/* * Copyright 2017 ThoughtWorks, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.thoughtworks.go.server.domain; import com.thoughtworks.go.config.AgentConfig; import com.thoughtworks.go.config.Agents; import com.thoughtworks.go.domain.AgentInstance; import com.thoughtworks.go.domain.AgentStatus; import com.thoughtworks.go.domain.NullAgentInstance; import com.thoughtworks.go.domain.exception.MaxPendingAgentsLimitReachedException; import com.thoughtworks.go.helper.AgentInstanceMother; import com.thoughtworks.go.server.service.AgentRuntimeInfo; import com.thoughtworks.go.util.SystemEnvironment; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Mock; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Set; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.assertThat; import static org.junit.matchers.JUnitMatchers.hasItems; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; public class AgentInstancesTest { @Rule public ExpectedException thrown = ExpectedException.none(); private AgentInstance idle; private AgentInstance building; private AgentInstance pending; private AgentInstance disabled; private AgentInstance local; @Mock private SystemEnvironment systemEnvironment; @Before public void setUp() throws Exception { initMocks(this); idle = AgentInstanceMother.idle(new Date(), "CCeDev01", systemEnvironment); AgentInstanceMother.updateOS(idle, "linux"); building = AgentInstanceMother.building("buildLocator", systemEnvironment); AgentInstanceMother.updateOS(building, "macOS"); pending = AgentInstanceMother.pending(systemEnvironment); AgentInstanceMother.updateOS(pending, "windows"); disabled = AgentInstanceMother.disabled("10.18.5.4", systemEnvironment); local = AgentInstanceMother.local(systemEnvironment); } @Test public void shouldUnderstandFilteringAgentListBasedOnUuid() { AgentInstances instances = new AgentInstances(null); AgentRuntimeInfo agent1 = AgentRuntimeInfo.fromServer(new AgentConfig("uuid-1", "host-1", "192.168.1.2"), true, "/foo/bar", 100l, "linux", false); AgentRuntimeInfo agent2 = AgentRuntimeInfo.fromServer(new AgentConfig("uuid-2", "host-2", "192.168.1.3"), true, "/bar/baz", 200l, "linux", false); AgentRuntimeInfo agent3 = AgentRuntimeInfo.fromServer(new AgentConfig("uuid-3", "host-3", "192.168.1.4"), true, "/baz/quux", 300l, "linux", false); AgentInstance instance1 = AgentInstance.createFromLiveAgent(agent1, systemEnvironment); instances.add(instance1); instances.add(AgentInstance.createFromLiveAgent(agent2, systemEnvironment)); AgentInstance instance3 = AgentInstance.createFromLiveAgent(agent3, systemEnvironment); instances.add(instance3); List<AgentInstance> agents = instances.filter(Arrays.asList("uuid-1", "uuid-3")); assertThat(agents, hasItems(instance1, instance3)); assertThat(agents.size(), is(2)); } @Test public void shouldFindEnabledAgents() { AgentInstances agentInstances = sample(); AgentInstances enabledAgents = agentInstances.findEnabledAgents(); assertThat(enabledAgents.size(), is(2)); assertThat(enabledAgents.findAgentAndRefreshStatus("uuid2"), is(idle)); assertThat(enabledAgents.findAgentAndRefreshStatus("uuid3"), is(building)); } @Test public void shouldFindRegisteredAgents() { AgentInstances agentInstances = sample(); AgentInstances agents = agentInstances.findRegisteredAgents(); assertThat(agents.size(), is(3)); assertThat(agents.findAgentAndRefreshStatus("uuid2"), is(idle)); assertThat(agents.findAgentAndRefreshStatus("uuid3"), is(building)); assertThat(agents.findAgentAndRefreshStatus("uuid5"), is(disabled)); } @Test public void shouldFindAgentsByItHostName() throws Exception { AgentInstance idle = AgentInstanceMother.idle(new Date(), "ghost-name"); AgentInstances agentInstances = new AgentInstances(null, systemEnvironment, idle, AgentInstanceMother.building()); AgentInstance byHostname = agentInstances.findFirstByHostname("ghost-name"); assertThat(byHostname, is(idle)); } @Test public void shouldReturnNullAgentsWhenHostNameIsNotFound() throws Exception { AgentInstances agentInstances = new AgentInstances(null, systemEnvironment, AgentInstanceMother.building()); agentInstances.add(idle); agentInstances.add(building); AgentInstance byHostname = agentInstances.findFirstByHostname("not-exist"); assertThat(byHostname, is(instanceOf(NullAgentInstance.class))); } @Test public void shouldReturnFirstMatchedAgentsWhenHostNameHasMoreThanOneMatch() throws Exception { AgentInstance agent = AgentInstance.createFromConfig(new AgentConfig("uuid20", "CCeDev01", "10.18.5.20"), systemEnvironment); AgentInstance duplicatedAgent = AgentInstance.createFromConfig(new AgentConfig("uuid21", "CCeDev01", "10.18.5.20"), systemEnvironment); AgentInstances agentInstances = new AgentInstances(null, systemEnvironment, agent, duplicatedAgent); AgentInstance byHostname = agentInstances.findFirstByHostname("CCeDev01"); assertThat(byHostname, is(agent)); } @Test public void shouldAddAgentIntoMemoryAfterAgentIsManuallyAddedInConfigFile() throws Exception { AgentInstances agentInstances = new AgentInstances(null); AgentConfig agentConfig = new AgentConfig("uuid20", "CCeDev01", "10.18.5.20"); agentInstances.sync(new Agents(agentConfig)); assertThat(agentInstances.size(), is(1)); assertThat(agentInstances.findAgentAndRefreshStatus("uuid20").agentConfig(), is(agentConfig)); } @Test public void shouldRemoveAgentWhenAgentIsRemovedFromConfigFile() throws Exception { AgentInstances agentInstances = new AgentInstances(null, systemEnvironment, idle, building); Agents oneAgentIsRemoved = new Agents(new AgentConfig("uuid2", "CCeDev01", "10.18.5.1")); agentInstances.sync(oneAgentIsRemoved); assertThat(agentInstances.size(), is(1)); assertThat(agentInstances.findAgentAndRefreshStatus("uuid2"), is(idle)); assertThat(agentInstances.findAgentAndRefreshStatus("uuid1"), is(new NullAgentInstance("uuid1"))); } @Test public void shouldSyncAgent() throws Exception { AgentInstances agentInstances = new AgentInstances(null, systemEnvironment, AgentInstanceMother.building(), idle); AgentConfig agentConfig = new AgentConfig("uuid2", "CCeDev01", "10.18.5.1"); agentConfig.setDisabled(true); Agents oneAgentIsRemoved = new Agents(agentConfig); agentInstances.sync(oneAgentIsRemoved); assertThat(agentInstances.findAgentAndRefreshStatus("uuid2").getStatus(), is(AgentStatus.Disabled)); } @Test public void shouldNotRemovePendingAgentDuringSync() throws Exception { AgentInstances agentInstances = new AgentInstances(null, systemEnvironment, AgentInstanceMother.building()); agentInstances.add(pending); Agents agents = new Agents(); agentInstances.sync(agents); assertThat(agentInstances.size(), is(1)); assertThat(agentInstances.findAgentAndRefreshStatus("uuid4").getStatus(), is(AgentStatus.Pending)); } @Test public void agentHostnameShouldBeUnique() { AgentConfig agentConfig = new AgentConfig("uuid2", "CCeDev01", "10.18.5.1"); AgentInstances agentInstances = new AgentInstances(null); agentInstances.register(AgentRuntimeInfo.fromServer(agentConfig, false, "/var/lib", 0L, "linux", false)); agentInstances.register(AgentRuntimeInfo.fromServer(agentConfig, false, "/var/lib", 0L, "linux", false)); } @Test(expected = MaxPendingAgentsLimitReachedException.class) public void registerShouldErrorOutIfMaxPendingAgentsLimitIsReached() { AgentConfig agentConfig = new AgentConfig("uuid2", "CCeDev01", "10.18.5.1"); AgentInstances agentInstances = new AgentInstances(null, systemEnvironment, AgentInstanceMother.pending()); when(systemEnvironment.get(SystemEnvironment.MAX_PENDING_AGENTS_ALLOWED)).thenReturn(1); agentInstances.register(AgentRuntimeInfo.fromServer(agentConfig, false, "/var/lib", 0L, "linux", false)); } @Test public void shouldRemovePendingAgentThatIsTimedOut() { when(systemEnvironment.getAgentConnectionTimeout()).thenReturn(-1); AgentInstances agentInstances = new AgentInstances(null, systemEnvironment, pending, building, disabled); agentInstances.refresh(); assertThat(agentInstances.findAgentAndRefreshStatus("uuid4"), is(instanceOf(NullAgentInstance.class))); } @Test public void shouldSupportConcurrentOperations() throws Exception { final AgentInstances agentInstances = new AgentInstances(null); // register 100 agents for (int i = 0; i < 100; i++) { AgentConfig agentConfig = new AgentConfig("uuid" + i, "CCeDev_" + i, "10.18.5." + i); agentInstances.register(AgentRuntimeInfo.fromServer(agentConfig, false, "/var/lib", Long.MAX_VALUE, "linux", false)); } thrown.expect(MaxPendingAgentsLimitReachedException.class); thrown.expectMessage("Max pending agents allowed 100, limit reached"); AgentConfig agentConfig = new AgentConfig("uuid" + 200, "CCeDev_" + 200, "10.18.5." + 200); agentInstances.register(AgentRuntimeInfo.fromServer(agentConfig, false, "/var/lib", Long.MAX_VALUE, "linux", false)); } @Test public void shouldReturnAllAgentHostnames() { AgentInstances agentInstances = sample(); Set<String> names = agentInstances.getAllHostNames(); assertThat(names, hasItems("CCeDev01", "CCeDev03", "CCeDev04")); } @Test public void shouldReturnAllAgentIPAddresses() { AgentInstances agentInstances = sample(); Set<String> names = agentInstances.getAllIpAddresses(); assertThat(names, hasItems("10.18.5.1", "10.18.5.3", "10.18.5.4")); } @Test public void shouldReturnAllAgentOperatingSystems() { AgentInstances agentInstances = sample(); Set<String> names = agentInstances.getAllOperatingSystems(); assertThat(names, hasItems("linux", "macOS", "windows")); } private AgentInstances sample() { AgentInstances agentInstances = new AgentInstances(null); agentInstances.add(idle); agentInstances.add(building); agentInstances.add(pending); agentInstances.add(disabled); return agentInstances; } private static class AgentAdder implements Runnable { private final AgentInstances agentInstances; private boolean stop; public static AgentAdder startAdding(AgentInstances agentInstances) { AgentAdder agentAdder = new AgentAdder(agentInstances); Thread thread = new Thread(agentAdder); thread.setDaemon(true); thread.start(); return agentAdder; } private AgentAdder(AgentInstances agentInstances) { this.agentInstances = agentInstances; } public void run() { int count = 0; while (!stop) { AgentConfig agentConfig = new AgentConfig("uuid" + count, "CCeDev_" + count, "10.18.5." + count); agentInstances.register(AgentRuntimeInfo.fromServer(agentConfig, false, "/var/lib", Long.MAX_VALUE, "linux", false)); count++; } } public void stop() { this.stop = true; } } }