/**
* 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 io.airlift.airship.integration;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Scopes;
import com.google.inject.util.Modules;
import io.airlift.airship.agent.Agent;
import io.airlift.airship.agent.AgentMainModule;
import io.airlift.airship.agent.DeploymentManagerFactory;
import io.airlift.airship.agent.LifecycleManager;
import io.airlift.airship.agent.MockDeploymentManagerFactory;
import io.airlift.airship.agent.MockLifecycleManager;
import io.airlift.airship.agent.Slot;
import io.airlift.airship.coordinator.HttpRemoteAgent;
import io.airlift.airship.coordinator.HttpRemoteSlot;
import io.airlift.airship.coordinator.RemoteSlot;
import io.airlift.airship.shared.AgentStatusRepresentation;
import io.airlift.airship.shared.Installation;
import io.airlift.airship.shared.InstallationRepresentation;
import io.airlift.airship.shared.SlotStatus;
import io.airlift.airship.shared.SlotStatusRepresentation;
import io.airlift.configuration.ConfigurationFactory;
import io.airlift.configuration.ConfigurationModule;
import io.airlift.discovery.client.ServiceDescriptorsRepresentation;
import io.airlift.event.client.EventModule;
import io.airlift.http.client.AsyncHttpClient;
import io.airlift.http.client.jetty.JettyHttpClient;
import io.airlift.http.server.testing.TestingHttpServer;
import io.airlift.http.server.testing.TestingHttpServerModule;
import io.airlift.jaxrs.JaxrsModule;
import io.airlift.json.JsonCodec;
import io.airlift.json.JsonModule;
import io.airlift.node.testing.TestingNodeModule;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.io.File;
import java.net.URI;
import java.util.Map;
import java.util.UUID;
import static io.airlift.airship.shared.AssignmentHelper.APPLE_ASSIGNMENT;
import static io.airlift.airship.shared.AssignmentHelper.BANANA_ASSIGNMENT;
import static io.airlift.airship.shared.FileUtils.createTempDir;
import static io.airlift.airship.shared.FileUtils.deleteRecursively;
import static io.airlift.airship.shared.SlotLifecycleState.RUNNING;
import static io.airlift.airship.shared.SlotLifecycleState.STOPPED;
import static io.airlift.airship.shared.SlotLifecycleState.TERMINATED;
import static io.airlift.airship.shared.SlotStatus.createSlotStatus;
import static io.airlift.testing.Closeables.closeQuietly;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
public class TestRemoteSlot
{
private static final Installation APPLE_INSTALLATION = new Installation("apple",
APPLE_ASSIGNMENT,
URI.create("fake://localhost/apple.tar.gz"),
URI.create("fake://localhost/apple.config"),
ImmutableMap.of("memory", 512));
private static final Installation BANANA_INSTALLATION = new Installation("banana",
BANANA_ASSIGNMENT,
URI.create("fake://localhost/banana.tar.gz"),
URI.create("fake://localhost/banana.config"),
ImmutableMap.of("cpu", 1));
private AsyncHttpClient client;
private TestingHttpServer server;
private Agent agent;
private File tempDir;
private Slot slot;
private HttpRemoteAgent remoteAgent;
@BeforeClass
public void startServer()
throws Exception
{
tempDir = createTempDir("agent");
Map<String, String> properties = ImmutableMap.<String, String>builder()
.put("agent.id", UUID.randomUUID().toString())
.put("agent.coordinator-uri", "http://localhost:9999/")
.put("agent.slots-dir", tempDir.getAbsolutePath())
.build();
Injector injector = Guice.createInjector(new TestingHttpServerModule(),
new TestingNodeModule(),
new JsonModule(),
new JaxrsModule(),
new EventModule(),
new ConfigurationModule(new ConfigurationFactory(properties)),
Modules.override(new AgentMainModule()).with(new Module()
{
@Override
public void configure(Binder binder)
{
binder.bind(DeploymentManagerFactory.class).to(MockDeploymentManagerFactory.class).in(Scopes.SINGLETON);
binder.bind(LifecycleManager.class).to(MockLifecycleManager.class).in(Scopes.SINGLETON);
}
}));
server = injector.getInstance(TestingHttpServer.class);
agent = injector.getInstance(Agent.class);
server.start();
client = new JettyHttpClient();
remoteAgent = new HttpRemoteAgent(
agent.getAgentStatus(),
"test",
client,
JsonCodec.jsonCodec(InstallationRepresentation.class),
JsonCodec.jsonCodec(AgentStatusRepresentation.class),
JsonCodec.jsonCodec(SlotStatusRepresentation.class),
JsonCodec.jsonCodec(ServiceDescriptorsRepresentation.class));
}
@BeforeMethod
public void resetState()
{
for (Slot slot : agent.getAllSlots()) {
if (slot.status().getAssignment() != null) {
slot.stop();
}
agent.terminateSlot(slot.getId());
}
assertTrue(agent.getAllSlots().isEmpty());
slot = agent.getSlot(agent.install(APPLE_INSTALLATION).getId());
}
@AfterClass
public void stopServer()
throws Exception
{
closeQuietly(client);
if (server != null) {
server.stop();
}
if (tempDir != null) {
deleteRecursively(tempDir);
}
}
@Test
public void testGetSlotStatus()
throws Exception
{
RemoteSlot remoteSlot = new HttpRemoteSlot(slot.status(), client, remoteAgent);
assertEquals(remoteSlot.status(), slot.status());
}
@Test
public void testAssign()
throws Exception
{
// setup
SlotStatus status1 = slot.status();
assertEquals(slot.status(), status1.changeAssignment(STOPPED, APPLE_ASSIGNMENT, status1.getResources()));
// test
remoteAgent.setStatus(agent.getAgentStatus());
RemoteSlot remoteSlot = new HttpRemoteSlot(slot.status(), client, remoteAgent);
SlotStatus actual = remoteSlot.assign(BANANA_INSTALLATION);
// verify
SlotStatus status = slot.status();
SlotStatus expected = status.changeAssignment(STOPPED, BANANA_ASSIGNMENT, status.getResources());
assertEquals(actual, expected);
}
@Test
public void testTerminate()
throws Exception
{
// setup
assertEquals(slot.assign(APPLE_INSTALLATION).getAssignment(), APPLE_ASSIGNMENT);
// test
remoteAgent.setStatus(agent.getAgentStatus());
RemoteSlot remoteSlot = new HttpRemoteSlot(slot.status(), client, remoteAgent);
SlotStatus actual = remoteSlot.terminate();
// verify
SlotStatus expected = createSlotStatus(slot.getId(),
slot.getSelf(),
slot.getExternalUri(),
slot.status().getInstanceId(),
slot.status().getLocation(),
TERMINATED,
null,
null,
ImmutableMap.<String, Integer>of());
assertEquals(actual, expected);
}
@Test
public void testStart()
throws Exception
{
// setup
assertEquals(slot.assign(APPLE_INSTALLATION).getState(), STOPPED);
// test
remoteAgent.setStatus(agent.getAgentStatus());
RemoteSlot remoteSlot = new HttpRemoteSlot(slot.status(), client, remoteAgent);
SlotStatus actual = remoteSlot.start();
// verify
SlotStatus status = slot.status();
SlotStatus expected = status.changeAssignment(RUNNING, APPLE_ASSIGNMENT, status.getResources());
assertEquals(actual, expected);
}
@Test
public void testStop()
throws Exception
{
// setup
slot.assign(APPLE_INSTALLATION);
assertEquals(slot.start().getState(), RUNNING);
// test
remoteAgent.setStatus(agent.getAgentStatus());
RemoteSlot remoteSlot = new HttpRemoteSlot(slot.status(), client, remoteAgent);
SlotStatus actual = remoteSlot.stop();
// verify
SlotStatus status = slot.status();
SlotStatus expected = status.changeAssignment(STOPPED, APPLE_ASSIGNMENT, status.getResources());
assertEquals(actual, expected);
}
@Test
public void testKill()
throws Exception
{
// setup
slot.assign(APPLE_INSTALLATION);
assertEquals(slot.start().getState(), RUNNING);
// test
remoteAgent.setStatus(agent.getAgentStatus());
RemoteSlot remoteSlot = new HttpRemoteSlot(slot.status(), client, remoteAgent);
SlotStatus actual = remoteSlot.kill();
// verify
SlotStatus status = slot.status();
SlotStatus expected = status.changeAssignment(STOPPED, APPLE_ASSIGNMENT, status.getResources());
assertEquals(actual, expected);
}
@Test
public void testRestart()
throws Exception
{
// setup
assertEquals(slot.assign(APPLE_INSTALLATION).getState(), STOPPED);
// test
remoteAgent.setStatus(agent.getAgentStatus());
RemoteSlot remoteSlot = new HttpRemoteSlot(slot.status(), client, remoteAgent);
SlotStatus actual = remoteSlot.restart();
// verify
SlotStatus status = slot.status();
SlotStatus expected = status.changeAssignment(RUNNING, APPLE_ASSIGNMENT, status.getResources());
assertEquals(actual, expected);
}
}