use of com.aws.greengrass.lifecyclemanager.GlobalStateChangeListener in project aws-greengrass-nucleus by aws-greengrass.
the class DeploymentConfigMergingTest method GIVEN_kernel_running_single_service_WHEN_merge_same_doc_happens_twice_THEN_second_merge_should_not_restart_services.
@Test
void GIVEN_kernel_running_single_service_WHEN_merge_same_doc_happens_twice_THEN_second_merge_should_not_restart_services() throws Throwable {
// GIVEN
ConfigPlatformResolver.initKernelWithMultiPlatformConfig(kernel, getClass().getResource("single_service.yaml"));
// launch Nucleus
CountDownLatch mainRunning = new CountDownLatch(1);
kernel.getContext().addGlobalStateChangeListener((service, oldState, newState) -> {
if (service.getName().equals("main") && newState.equals(State.RUNNING)) {
mainRunning.countDown();
}
});
kernel.launch();
assertTrue(mainRunning.await(5, TimeUnit.SECONDS));
Map<String, Object> nucleusConfig = getNucleusConfig();
HashMap<String, Object> newConfig = new HashMap<String, Object>() {
{
put(SERVICES_NAMESPACE_TOPIC, new HashMap<String, Object>() {
{
put("main", new HashMap<String, Object>() {
{
put(SERVICE_DEPENDENCIES_NAMESPACE_TOPIC, Arrays.asList("new_service", DEFAULT_NUCLEUS_COMPONENT_NAME));
}
});
put("new_service", new HashMap<String, Object>() {
{
put(SERVICE_LIFECYCLE_NAMESPACE_TOPIC, new HashMap<String, Object>() {
{
put(LIFECYCLE_RUN_NAMESPACE_TOPIC, "echo done");
}
});
put(SERVICE_DEPENDENCIES_NAMESPACE_TOPIC, Arrays.asList("new_service2"));
}
});
put("new_service2", new HashMap<String, Object>() {
{
put(SERVICE_LIFECYCLE_NAMESPACE_TOPIC, new HashMap<String, Object>() {
{
put(LIFECYCLE_RUN_NAMESPACE_TOPIC, "echo done");
}
});
}
});
put(DEFAULT_NUCLEUS_COMPONENT_NAME, nucleusConfig);
}
});
}
};
// do first merge
CountDownLatch mainRestarted = new CountDownLatch(1);
AtomicBoolean newService2Started = new AtomicBoolean(false);
AtomicBoolean newServiceStarted = new AtomicBoolean(false);
GlobalStateChangeListener listener = (service, oldState, newState) -> {
if (service.getName().equals("new_service2") && newState.equals(State.RUNNING)) {
newService2Started.set(true);
}
if (newService2Started.get() && service.getName().equals("new_service") && newState.equals(State.RUNNING)) {
newServiceStarted.set(true);
}
// Only count main as started if its dependency (new_service) has already been started
if (newServiceStarted.get() && service.getName().equals("main") && newState.equals(State.FINISHED) && oldState.equals(State.STARTING)) {
mainRestarted.countDown();
}
};
kernel.getContext().addGlobalStateChangeListener(listener);
GreengrassService main = kernel.locate("main");
deploymentConfigMerger.mergeInNewConfig(testDeployment(), newConfig).get(60, TimeUnit.SECONDS);
// Verify that first merge succeeded.
assertTrue(newService2Started.get());
assertTrue(newServiceStarted.get());
assertTrue(mainRestarted.await(10, TimeUnit.SECONDS));
assertThat(kernel.orderedDependencies().stream().map(GreengrassService::getName).collect(Collectors.toList()), containsInRelativeOrder("new_service2", "new_service", "main"));
// Wait for main to finish before continuing, otherwise the state change listner may cause a failure
assertThat(main::getState, eventuallyEval(is(State.FINISHED)));
// WHEN
AtomicBoolean stateChanged = new AtomicBoolean(false);
listener = (service, oldState, newState) -> {
System.err.println("State shouldn't change in merging the same config: " + service.getName() + " " + oldState + " => " + newState);
stateChanged.set(true);
};
kernel.getContext().addGlobalStateChangeListener(listener);
// THEN
// merge in the same config the second time
// merge shouldn't block
deploymentConfigMerger.mergeInNewConfig(testDeployment(), newConfig).get(60, TimeUnit.SECONDS);
// main should be finished
assertEquals(State.FINISHED, main.getState());
assertFalse(stateChanged.get(), "State shouldn't change in merging the same config.");
// remove listener
kernel.getContext().removeGlobalStateChangeListener(listener);
}
use of com.aws.greengrass.lifecyclemanager.GlobalStateChangeListener in project aws-greengrass-cli by aws-greengrass.
the class IPCCliTest method GIVEN_kernel_running_WHEN_CLI_authorized_groups_updated_THEN_old_token_revoked_and_new_token_accepted.
@Test
@Order(10)
void GIVEN_kernel_running_WHEN_CLI_authorized_groups_updated_THEN_old_token_revoked_and_new_token_accepted(ExtensionContext context) throws Exception {
ignoreExceptionOfType(context, RuntimeException.class);
String oldAuthToken = getAuthTokenFromInfoFile();
CountDownLatch awaitIpcServiceLatch = new CountDownLatch(1);
GlobalStateChangeListener listener = getListenerForServiceRunning(awaitIpcServiceLatch, CLI_SERVICE);
kernel.getContext().addGlobalStateChangeListener(listener);
String validGid;
if (PlatformResolver.isWindows) {
// GG_NEEDS_REVIEW: TODO support windows
validGid = "0";
} else {
validGid = selectAValidGid();
}
assertNotNull(validGid, "Failed to find a single valid GID on this test instance");
kernel.locate(CLI_SERVICE).getConfig().lookup(CONFIGURATION_CONFIG_KEY, AUTHORIZED_POSIX_GROUPS).withValue(validGid);
assertTrue(awaitIpcServiceLatch.await(10, TimeUnit.SECONDS));
kernel.getContext().removeGlobalStateChangeListener(listener);
ExecutionException executionException = assertThrows(ExecutionException.class, () -> IPCTestUtils.connectToGGCOverEventStreamIPC(TestUtils.getSocketOptionsForIPC(), oldAuthToken, kernel));
assertEquals(AccessDeniedException.class, executionException.getCause().getClass());
try (EventStreamRPCConnection eventStreamRPCConnection = IPCTestUtils.connectToGGCOverEventStreamIPC(TestUtils.getSocketOptionsForIPC(), getAuthTokenFromInfoFile(), kernel)) {
GreengrassCoreIPCClient client = new GreengrassCoreIPCClient(eventStreamRPCConnection);
ListComponentsResponse listComponentsResponse = client.listComponents(new ListComponentsRequest(), Optional.empty()).getResponse().get(DEFAULT_TIMEOUT_IN_SEC, TimeUnit.SECONDS);
assertTrue(listComponentsResponse.getComponents().size() > 0);
}
}
use of com.aws.greengrass.lifecyclemanager.GlobalStateChangeListener in project aws-greengrass-cli by aws-greengrass.
the class IPCCliTest method prepareKernelFromConfigFile.
public static Kernel prepareKernelFromConfigFile(String configFile, Class testClass, String... serviceNames) throws InterruptedException, IOException {
Kernel kernel = new Kernel();
NoOpPathOwnershipHandler.register(kernel);
ConfigPlatformResolver.initKernelWithMultiPlatformConfig(kernel, testClass.getResource(configFile));
CountDownLatch awaitIpcServiceLatch = new CountDownLatch(serviceNames.length);
GlobalStateChangeListener listener = getListenerForServiceRunning(awaitIpcServiceLatch, serviceNames);
kernel.getContext().addGlobalStateChangeListener(listener);
kernel.launch();
Assertions.assertTrue(awaitIpcServiceLatch.await(60L, TimeUnit.SECONDS));
kernel.getContext().removeGlobalStateChangeListener(listener);
return kernel;
}
use of com.aws.greengrass.lifecyclemanager.GlobalStateChangeListener in project aws-greengrass-nucleus by aws-greengrass.
the class IPCTestUtils method prepareKernelFromConfigFile.
public static Kernel prepareKernelFromConfigFile(String configFile, Class testClass, String... serviceNames) throws InterruptedException, IOException {
Kernel kernel = new Kernel();
NoOpPathOwnershipHandler.register(kernel);
ConfigPlatformResolver.initKernelWithMultiPlatformConfig(kernel, testClass.getResource(configFile));
// ensure awaitIpcServiceLatch starts
CountDownLatch awaitIpcServiceLatch = new CountDownLatch(serviceNames.length);
GlobalStateChangeListener listener = getListenerForServiceRunning(awaitIpcServiceLatch, serviceNames);
kernel.getContext().addGlobalStateChangeListener(listener);
kernel.launch();
assertTrue(awaitIpcServiceLatch.await(10, TimeUnit.SECONDS));
kernel.getContext().removeGlobalStateChangeListener(listener);
return kernel;
}
use of com.aws.greengrass.lifecyclemanager.GlobalStateChangeListener in project aws-greengrass-nucleus by aws-greengrass.
the class ServiceDependencyLifecycleTest method testRoutine.
@SuppressWarnings({ "PMD.LooseCoupling", "PMD.CloseResource" })
private static void testRoutine(long timeoutSeconds, Kernel kernel, Crashable action, String actionName, LinkedList<ExpectedStateTransition> expectedStateTransitions, Set<ExpectedStateTransition> unexpectedStateTransitions) throws Throwable {
Context context = kernel.getContext();
CountDownLatch assertionLatch = new CountDownLatch(1);
List<ExpectedStateTransition> unexpectedSeenInOrder = new LinkedList<>();
GlobalStateChangeListener listener = (GreengrassService service, State oldState, State newState) -> {
if (!expectedStateTransitions.isEmpty()) {
ExpectedStateTransition expected = expectedStateTransitions.peek();
if (service.getName().equals(expected.serviceName) && oldState.equals(expected.was) && newState.equals(expected.current)) {
logger.atWarn().kv("expected", expected).log("Just saw expected state event for service");
expectedStateTransitions.pollFirst();
}
if (expectedStateTransitions.isEmpty()) {
assertionLatch.countDown();
}
}
ExpectedStateTransition actual = new ExpectedStateTransition(service.getName(), oldState, newState);
logger.atInfo().kv("actual", actual).log("Actual state event");
if (unexpectedStateTransitions.contains(actual)) {
unexpectedSeenInOrder.add(actual);
}
};
context.addGlobalStateChangeListener(listener);
action.run();
assertionLatch.await(timeoutSeconds, TimeUnit.SECONDS);
context.removeGlobalStateChangeListener(listener);
if (!expectedStateTransitions.isEmpty()) {
logger.atError().kv("expected", expectedStateTransitions).kv("action", actionName).log("Fail to see state events");
fail("Didn't see all expected state transitions for " + actionName);
}
if (!unexpectedSeenInOrder.isEmpty()) {
logger.atError().kv("unexpected", unexpectedSeenInOrder).kv("action", actionName).log("Saw unexpected state events");
fail("Saw unexpected state transitions for " + actionName);
}
logger.atWarn().log("End of " + actionName);
}
Aggregations