use of com.aws.greengrass.config.Topics in project aws-greengrass-nucleus by aws-greengrass.
the class DynamicComponentConfigurationValidationTest method GIVEN_deployment_changes_component_config_WHEN_component_validates_config_THEN_deployment_is_successful.
@Test
void GIVEN_deployment_changes_component_config_WHEN_component_validates_config_THEN_deployment_is_successful() throws Throwable {
LogConfig.getRootLogConfig().setLevel(Level.DEBUG);
// Subscribe to config validation on behalf of the running service
CountDownLatch eventReceivedByClient = new CountDownLatch(1);
Topics servicePrivateConfig = kernel.getConfig().findTopics(SERVICES_NAMESPACE_TOPIC, "OldService", PRIVATE_STORE_NAMESPACE_TOPIC);
String authToken = Coerce.toString(servicePrivateConfig.find(SERVICE_UNIQUE_ID_KEY));
CountDownLatch subscriptionLatch = new CountDownLatch(1);
try (EventStreamRPCConnection clientConnection = IPCTestUtils.connectToGGCOverEventStreamIPC(socketOptions, authToken, kernel);
AutoCloseable l = TestUtils.createCloseableLogListener(m -> {
if (m.getMessage().contains("Config IPC subscribe to config validation request")) {
subscriptionLatch.countDown();
}
})) {
GreengrassCoreIPCClient greengrassCoreIPCClient = new GreengrassCoreIPCClient(clientConnection);
SubscribeToValidateConfigurationUpdatesRequest subscribe = new SubscribeToValidateConfigurationUpdatesRequest();
greengrassCoreIPCClient.subscribeToValidateConfigurationUpdates(subscribe, Optional.of(new StreamResponseHandler<ValidateConfigurationUpdateEvents>() {
@Override
public void onStreamEvent(ValidateConfigurationUpdateEvents events) {
assertNotNull(events);
assertNotNull(events.getValidateConfigurationUpdateEvent());
assertNotNull(events.getValidateConfigurationUpdateEvent().getConfiguration());
assertThat(events.getValidateConfigurationUpdateEvent().getConfiguration(), IsMapContaining.hasEntry("ConfigKey1", "ConfigValue2"));
eventReceivedByClient.countDown();
SendConfigurationValidityReportRequest reportRequest = new SendConfigurationValidityReportRequest();
ConfigurationValidityReport report = new ConfigurationValidityReport();
report.setStatus(ConfigurationValidityStatus.ACCEPTED);
report.setDeploymentId(events.getValidateConfigurationUpdateEvent().getDeploymentId());
reportRequest.setConfigurationValidityReport(report);
try {
greengrassCoreIPCClient.sendConfigurationValidityReport(reportRequest, Optional.empty()).getResponse().get(10, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
fail("received invalid update validate configuration event", e);
}
}
@Override
public boolean onStreamError(Throwable error) {
log.atError().log("Received stream error.", error);
return false;
}
@Override
public void onStreamClosed() {
}
}));
assertTrue(subscriptionLatch.await(20, TimeUnit.SECONDS));
// Attempt changing the configuration for the running service
Map<String, Object> newConfig = new HashMap<String, Object>() {
{
put(SERVICES_NAMESPACE_TOPIC, new HashMap<String, Object>() {
{
put("main", kernel.getMain().getServiceConfig().toPOJO());
put("OldService", new HashMap<String, Object>() {
{
put(CONFIGURATION_CONFIG_KEY, new HashMap<String, Object>() {
{
put("ConfigKey1", "ConfigValue2");
}
});
put(SERVICE_LIFECYCLE_NAMESPACE_TOPIC, new HashMap<String, Object>() {
{
put(LIFECYCLE_RUN_NAMESPACE_TOPIC, "echo Running OldService");
}
});
put(VERSION_CONFIG_KEY, DEFAULT_EXISTING_SERVICE_VERSION);
}
});
put(DEFAULT_NUCLEUS_COMPONENT_NAME, getNucleusConfig(kernel));
}
});
}
};
DeploymentResult result = deploymentConfigMerger.mergeInNewConfig(createTestDeployment(), newConfig).get(60, TimeUnit.SECONDS);
assertEquals(DeploymentResult.DeploymentStatus.SUCCESSFUL, result.getDeploymentStatus());
assertTrue(eventReceivedByClient.await(20, TimeUnit.SECONDS));
}
}
use of com.aws.greengrass.config.Topics in project aws-greengrass-nucleus by aws-greengrass.
the class DeploymentConfigMergingTest method GIVEN_kernel_running_with_some_config_WHEN_merge_simple_yaml_file_THEN_config_is_updated.
@Test
void GIVEN_kernel_running_with_some_config_WHEN_merge_simple_yaml_file_THEN_config_is_updated() throws Throwable {
// GIVEN
ConfigPlatformResolver.initKernelWithMultiPlatformConfig(kernel, getClass().getResource("config.yaml"));
CountDownLatch mainRunning = new CountDownLatch(1);
kernel.getContext().addGlobalStateChangeListener((service, oldState, newState) -> {
if (service.getName().equals("main") && newState.equals(State.RUNNING)) {
mainRunning.countDown();
}
});
kernel.launch();
// WHEN
CountDownLatch mainRestarted = new CountDownLatch(1);
kernel.getContext().addGlobalStateChangeListener((service, oldState, newState) -> {
if (service.getName().equals("main") && newState.equals(State.RUNNING) && oldState.equals(State.STARTING)) {
mainRestarted.countDown();
}
});
Topics t = kernel.findServiceTopic(FleetStatusService.FLEET_STATUS_SERVICE_TOPICS);
assertNotNull(t, "FSS Topics should not be null before merging");
Map<String, Object> newConfig = ConfigPlatformResolver.resolvePlatformMap(getClass().getResource("delta.yaml"));
((Map<String, Object>) newConfig.get(SERVICES_NAMESPACE_TOPIC)).put(DEFAULT_NUCLEUS_COMPONENT_NAME, getNucleusConfig());
deploymentConfigMerger.mergeInNewConfig(testDeployment(), newConfig).get(60, TimeUnit.SECONDS);
t = kernel.findServiceTopic(FleetStatusService.FLEET_STATUS_SERVICE_TOPICS);
assertNotNull(t, "FSS Topics should not be null after merging");
// THEN
assertTrue(mainRestarted.await(10, TimeUnit.SECONDS));
assertThat((String) kernel.findServiceTopic("main").find(SERVICE_LIFECYCLE_NAMESPACE_TOPIC, LIFECYCLE_RUN_NAMESPACE_TOPIC).getOnce(), containsString("echo Now we\\'re in phase 3"));
}
use of com.aws.greengrass.config.Topics in project aws-greengrass-nucleus by aws-greengrass.
the class MultipleGroupsDeploymentE2ETest method GIVEN_deployment_to_2_groups_WHEN_remove_service_from_1_group_THEN_service_is_removed.
@Timeout(value = 10, unit = TimeUnit.MINUTES)
@Test
void GIVEN_deployment_to_2_groups_WHEN_remove_service_from_1_group_THEN_service_is_removed() throws Exception {
CreateDeploymentRequest createDeploymentRequest1 = CreateDeploymentRequest.builder().targetArn(thingGroupArn).components(Utils.immutableMap("CustomerApp", ComponentDeploymentSpecification.builder().componentVersion("0.9.1").configurationUpdate(ComponentConfigurationUpdate.builder().merge("{\"sampleText\":\"FCS integ test\"}").build()).build(), "SomeService", ComponentDeploymentSpecification.builder().componentVersion("1.0.0").build())).build();
CreateDeploymentResponse result1 = draftAndCreateDeployment(createDeploymentRequest1);
IotJobsUtils.waitForJobExecutionStatusToSatisfy(iotClient, result1.iotJobId(), thingInfo.getThingName(), Duration.ofMinutes(5), s -> s.equals(JobExecutionStatus.SUCCEEDED));
Topics groupToRootMapping = kernel.getConfig().lookupTopics(DEPLOYMENT_SERVICE_TOPICS, GROUP_TO_ROOT_COMPONENTS_TOPICS);
logger.atInfo().log("Group to root mapping is: " + groupToRootMapping.toString());
CreateDeploymentRequest createDeploymentRequest2 = CreateDeploymentRequest.builder().targetArn(secondThingGroupResponse.thingGroupArn()).components(Utils.immutableMap("CustomerApp", ComponentDeploymentSpecification.builder().componentVersion("0.9.1").configurationUpdate(ComponentConfigurationUpdate.builder().merge("{\"sampleText\":\"FCS integ test\"}").build()).build())).build();
CreateDeploymentResponse result2 = draftAndCreateDeployment(createDeploymentRequest2);
IotJobsUtils.waitForJobExecutionStatusToSatisfy(iotClient, result2.iotJobId(), thingInfo.getThingName(), Duration.ofMinutes(5), s -> s.equals(JobExecutionStatus.SUCCEEDED));
CreateDeploymentRequest createDeploymentRequest3 = CreateDeploymentRequest.builder().targetArn(thingGroupArn).components(Utils.immutableMap("CustomerApp", ComponentDeploymentSpecification.builder().componentVersion("0.9.1").configurationUpdate(ComponentConfigurationUpdate.builder().merge("{\"sampleText\":\"FCS integ test\"}").build()).build())).build();
CreateDeploymentResponse result3 = draftAndCreateDeployment(createDeploymentRequest3);
IotJobsUtils.waitForJobExecutionStatusToSatisfy(iotClient, result3.iotJobId(), thingInfo.getThingName(), Duration.ofMinutes(5), s -> s.equals(JobExecutionStatus.SUCCEEDED));
assertThat(kernel.getMain()::getState, eventuallyEval(is(State.FINISHED)));
assertThrows(ServiceLoadException.class, () -> {
GreengrassService service = getCloudDeployedComponent("SomeService");
logger.atInfo().log("Service is " + service.getName());
});
}
use of com.aws.greengrass.config.Topics in project aws-greengrass-nucleus by aws-greengrass.
the class MultipleGroupsDeploymentE2ETest method GIVEN_deployment_to_2_groups_WHEN_both_deployments_have_same_service_different_version_THEN_second_deployment_fails_due_to_conflict.
@Timeout(value = 10, unit = TimeUnit.MINUTES)
@Test
void GIVEN_deployment_to_2_groups_WHEN_both_deployments_have_same_service_different_version_THEN_second_deployment_fails_due_to_conflict(ExtensionContext context) throws Exception {
ignoreExceptionOfType(context, ExecutionException.class);
ignoreExceptionOfType(context, // Expect this to happen due to conflict
NoAvailableComponentVersionException.class);
CreateDeploymentRequest createDeploymentRequest1 = CreateDeploymentRequest.builder().targetArn(thingGroupArn).components(Utils.immutableMap("CustomerApp", ComponentDeploymentSpecification.builder().componentVersion("0.9.1").configurationUpdate(ComponentConfigurationUpdate.builder().merge("{\"sampleText\":\"FCS integ test\"}").build()).build())).build();
CreateDeploymentResponse result1 = draftAndCreateDeployment(createDeploymentRequest1);
IotJobsUtils.waitForJobExecutionStatusToSatisfy(iotClient, result1.iotJobId(), thingInfo.getThingName(), Duration.ofMinutes(5), s -> s.equals(JobExecutionStatus.SUCCEEDED));
Topics groupToRootMapping = kernel.getConfig().lookupTopics(DEPLOYMENT_SERVICE_TOPICS, GROUP_TO_ROOT_COMPONENTS_TOPICS);
logger.atInfo().log("Group to root mapping is: " + groupToRootMapping.toString());
CreateDeploymentRequest createDeploymentRequest2 = CreateDeploymentRequest.builder().targetArn(secondThingGroupResponse.thingGroupArn()).components(Utils.immutableMap("CustomerApp", ComponentDeploymentSpecification.builder().componentVersion("1.0.0").configurationUpdate(ComponentConfigurationUpdate.builder().merge("{\"sampleText\":\"FCS integ test\"}").build()).build())).build();
CreateDeploymentResponse result2 = draftAndCreateDeployment(createDeploymentRequest2);
IotJobsUtils.waitForJobExecutionStatusToSatisfy(iotClient, result2.iotJobId(), thingInfo.getThingName(), Duration.ofMinutes(5), s -> s.equals(JobExecutionStatus.FAILED));
assertThat("Incorrect component version running", getCloudDeployedComponent("CustomerApp").getServiceConfig().find(VERSION_CONFIG_KEY).getOnce().toString(), is("0.9.1"));
}
use of com.aws.greengrass.config.Topics in project aws-greengrass-nucleus by aws-greengrass.
the class ShadowDeploymentE2ETest method GIVEN_kernel_running_WHEN_device_deployment_has_large_config_THEN_config_downloaded.
@Test
void GIVEN_kernel_running_WHEN_device_deployment_has_large_config_THEN_config_downloaded() throws Exception {
CountDownLatch cdlDeploymentFinished = new CountDownLatch(1);
Consumer<GreengrassLogMessage> listener = m -> {
if (m.getMessage() != null && m.getMessage().contains("Current deployment finished")) {
cdlDeploymentFinished.countDown();
}
};
// Threshold for triggering large config is 8 KB for shadow deployment. Using a 32000 bytes string.
String largeConfigValue = StringUtils.repeat("*", 32 * 1000);
try (AutoCloseable l = TestUtils.createCloseableLogListener(listener)) {
CreateDeploymentRequest createDeploymentRequest = CreateDeploymentRequest.builder().targetArn(thingInfo.getThingArn()).components(Utils.immutableMap("CustomerApp", ComponentDeploymentSpecification.builder().componentVersion("1.0.0").configurationUpdate(ComponentConfigurationUpdate.builder().merge("{\"largeConfigKey\":\"" + largeConfigValue + "\"}").build()).build())).build();
draftAndCreateDeployment(createDeploymentRequest);
assertThat(kernel.getMain()::getState, eventuallyEval(is(State.FINISHED)));
IotShadowClient shadowClient = new IotShadowClient(new WrapperMqttClientConnection(kernel.getContext().get(MqttClient.class)));
UpdateNamedShadowSubscriptionRequest req = new UpdateNamedShadowSubscriptionRequest();
req.shadowName = DEPLOYMENT_SHADOW_NAME;
req.thingName = thingInfo.getThingName();
CountDownLatch reportInProgressCdl = new CountDownLatch(1);
CountDownLatch reportSucceededCdl = new CountDownLatch(1);
shadowClient.SubscribeToUpdateNamedShadowAccepted(req, QualityOfService.AT_LEAST_ONCE, (response) -> {
try {
logger.info("Got shadow update: {}", new ObjectMapper().writeValueAsString(response));
} catch (JsonProcessingException e) {
// ignore
}
if (response.state.reported == null) {
return;
}
String reportedStatus = (String) response.state.reported.get(STATUS_KEY);
if (JobStatus.IN_PROGRESS.toString().equals(reportedStatus)) {
reportInProgressCdl.countDown();
} else if (JobStatus.SUCCEEDED.toString().equals(reportedStatus)) {
reportSucceededCdl.countDown();
}
});
// wait for the shadow's reported section to be updated
assertTrue(reportInProgressCdl.await(600, TimeUnit.SECONDS));
assertTrue(reportSucceededCdl.await(600, TimeUnit.SECONDS));
// deployment should succeed
assertTrue(cdlDeploymentFinished.await(30, TimeUnit.SECONDS));
Slf4jLogAdapter.removeGlobalListener(listener);
assertThat(getCloudDeployedComponent("CustomerApp")::getState, eventuallyEval(is(State.FINISHED)));
Topics customerApp = getCloudDeployedComponent("CustomerApp").getConfig();
assertEquals(largeConfigValue, Coerce.toString(customerApp.find("configuration", "largeConfigKey")));
}
}
Aggregations