use of software.amazon.awssdk.services.greengrassv2data.model.ResolvedComponentVersion in project aws-greengrass-nucleus by aws-greengrass.
the class ComponentManagerTest method GIVEN_requirement_is_from_local_group_and_has_no_local_version_WHEN_resolve_version_THEN_use_cloud_version.
@Test
void GIVEN_requirement_is_from_local_group_and_has_no_local_version_WHEN_resolve_version_THEN_use_cloud_version() throws Exception {
ComponentIdentifier componentA_1_0_0 = new ComponentIdentifier(componentA, v1_0_0);
ComponentMetadata componentA_1_0_0_md = new ComponentMetadata(componentA_1_0_0, Collections.emptyMap());
// no local version
when(componentStore.findBestMatchAvailableComponent(eq(componentA), any())).thenReturn(Optional.empty());
// has cloud version
com.amazon.aws.iot.greengrass.component.common.ComponentRecipe recipe = com.amazon.aws.iot.greengrass.component.common.ComponentRecipe.builder().componentName(componentA).componentVersion(v1_0_0).componentType(ComponentType.GENERIC).recipeFormatVersion(RecipeFormatVersion.JAN_25_2020).build();
ResolvedComponentVersion resolvedComponentVersion = ResolvedComponentVersion.builder().componentName(componentA).componentVersion(v1_0_0.getValue()).recipe(SdkBytes.fromByteArray(MAPPER.writeValueAsBytes(recipe))).arn(TEST_ARN).build();
when(componentManagementServiceHelper.resolveComponentVersion(anyString(), any(), any())).thenReturn(resolvedComponentVersion);
// mock return metadata from the id
when(componentStore.getPackageMetadata(any())).thenReturn(componentA_1_0_0_md);
// WHEN
ComponentMetadata componentMetadata = componentManager.resolveComponentVersion(componentA, Collections.singletonMap(DeploymentDocumentConverter.LOCAL_DEPLOYMENT_GROUP_NAME, Requirement.buildNPM("^1.0")));
// THEN
assertThat(componentMetadata, is(componentA_1_0_0_md));
verify(componentStore).findBestMatchAvailableComponent(componentA, Requirement.buildNPM("^1.0"));
verify(componentManagementServiceHelper).resolveComponentVersion(componentA, null, Collections.singletonMap(DeploymentDocumentConverter.LOCAL_DEPLOYMENT_GROUP_NAME, Requirement.buildNPM("^1.0")));
verify(componentStore).getPackageMetadata(componentA_1_0_0);
verify(componentStore).saveComponentRecipe(recipe);
verify(componentStore).saveRecipeMetadata(componentA_1_0_0, new RecipeMetadata(TEST_ARN));
}
use of software.amazon.awssdk.services.greengrassv2data.model.ResolvedComponentVersion in project aws-greengrass-nucleus by aws-greengrass.
the class ComponentManagerTest method GIVEN_component_is_local_active_WHEN_cloud_returns_a_recipe_THEN_use_cloud_recipe.
@Test
void GIVEN_component_is_local_active_WHEN_cloud_returns_a_recipe_THEN_use_cloud_recipe() throws Exception {
ComponentIdentifier componentA_1_0_0 = new ComponentIdentifier(componentA, v1_0_0);
ComponentMetadata componentA_1_0_0_md = new ComponentMetadata(componentA_1_0_0, Collections.emptyMap());
Topics serviceConfigTopics = mock(Topics.class);
Topic versionTopic = mock(Topic.class);
Topics runtimeTopics = mock(Topics.class);
Topic digestTopic = mock(Topic.class);
com.amazon.aws.iot.greengrass.component.common.ComponentRecipe newRecipe = com.amazon.aws.iot.greengrass.component.common.ComponentRecipe.builder().componentName("SampleComponent2").componentVersion(new Semver("2.0.0")).componentType(ComponentType.PLUGIN).recipeFormatVersion(RecipeFormatVersion.JAN_25_2020).build();
GreengrassService mockKernelService = mock(GreengrassService.class);
when(kernel.findServiceTopic(componentA)).thenReturn(mock(Topics.class));
when(kernel.locate(componentA)).thenReturn(mockService);
when(kernel.getMain()).thenReturn(mockKernelService);
when(mockKernelService.getRuntimeConfig()).thenReturn(runtimeTopics);
when(runtimeTopics.lookup(any())).thenReturn(digestTopic);
when(mockService.getServiceConfig()).thenReturn(serviceConfigTopics);
when(serviceConfigTopics.findLeafChild(VERSION_CONFIG_KEY)).thenReturn(versionTopic);
when(versionTopic.getOnce()).thenReturn(v1_0_0.getValue());
ResolvedComponentVersion resolvedComponentVersion = ResolvedComponentVersion.builder().componentName(componentA).componentVersion(v1_0_0.getValue()).recipe(SdkBytes.fromByteArray(MAPPER.writeValueAsBytes(newRecipe))).arn(TEST_ARN).build();
when(componentManagementServiceHelper.resolveComponentVersion(anyString(), any(), any())).thenReturn(resolvedComponentVersion);
when(componentStore.getPackageMetadata(any())).thenReturn(componentA_1_0_0_md);
String recipeString = SerializerFactory.getRecipeSerializer().writeValueAsString(newRecipe);
when(componentStore.saveComponentRecipe(any())).thenReturn(recipeString);
ComponentMetadata componentMetadata = componentManager.resolveComponentVersion(componentA, Collections.singletonMap("X", Requirement.buildNPM("^1.0")));
assertThat(componentMetadata, is(componentA_1_0_0_md));
verify(componentManagementServiceHelper).resolveComponentVersion(componentA, v1_0_0, Collections.singletonMap("X", Requirement.buildNPM("^1.0")));
verify(componentStore).saveComponentRecipe(newRecipe);
verify(componentStore).getPackageMetadata(componentA_1_0_0);
verify(componentStore).saveRecipeMetadata(componentA_1_0_0, new RecipeMetadata(TEST_ARN));
verify(digestTopic).withValue(Digest.calculate(recipeString));
}
use of software.amazon.awssdk.services.greengrassv2data.model.ResolvedComponentVersion in project aws-greengrass-nucleus by aws-greengrass.
the class ComponentManagerTest method GIVEN_component_no_local_version_WHEN_cloud_service_client_exception_THEN_retry.
@Test
void GIVEN_component_no_local_version_WHEN_cloud_service_client_exception_THEN_retry(ExtensionContext context) throws Exception {
ignoreExceptionOfType(context, SdkClientException.class);
componentManager.setClientExceptionRetryConfig(RetryUtils.RetryConfig.builder().initialRetryInterval(Duration.ofSeconds(1)).maxRetryInterval(Duration.ofSeconds(1)).maxAttempt(Integer.MAX_VALUE).retryableExceptions(Arrays.asList(SdkClientException.class)).build());
ComponentIdentifier componentA_1_0_0 = new ComponentIdentifier(componentA, v1_0_0);
ComponentMetadata componentA_1_0_0_md = new ComponentMetadata(componentA_1_0_0, Collections.emptyMap());
// no local version
when(componentStore.findBestMatchAvailableComponent(eq(componentA), any())).thenReturn(Optional.empty());
// has cloud version
com.amazon.aws.iot.greengrass.component.common.ComponentRecipe recipe = com.amazon.aws.iot.greengrass.component.common.ComponentRecipe.builder().componentName(componentA).componentVersion(v1_0_0).componentType(ComponentType.GENERIC).recipeFormatVersion(RecipeFormatVersion.JAN_25_2020).build();
ResolvedComponentVersion resolvedComponentVersion = ResolvedComponentVersion.builder().componentName(componentA).componentVersion(v1_0_0.getValue()).recipe(SdkBytes.fromByteArray(MAPPER.writeValueAsBytes(recipe))).arn(TEST_ARN).build();
// Retry succeeds
when(componentManagementServiceHelper.resolveComponentVersion(anyString(), any(), any())).thenThrow(SdkClientException.class).thenReturn(resolvedComponentVersion);
// mock return metadata from the id
when(componentStore.getPackageMetadata(any())).thenReturn(componentA_1_0_0_md);
ComponentMetadata componentMetadata = componentManager.resolveComponentVersion(componentA, Collections.singletonMap("X", Requirement.buildNPM("^1.0")));
assertThat(componentMetadata, is(componentA_1_0_0_md));
verify(componentManagementServiceHelper, times(2)).resolveComponentVersion(componentA, null, Collections.singletonMap("X", Requirement.buildNPM("^1.0")));
verify(componentStore, never()).findComponentRecipeContent(any());
verify(componentStore).saveComponentRecipe(any());
verify(componentStore).getPackageMetadata(componentA_1_0_0);
}
use of software.amazon.awssdk.services.greengrassv2data.model.ResolvedComponentVersion in project aws-greengrass-nucleus by aws-greengrass.
the class ComponentServiceHelperTest method GIVEN_component_version_requirements_WHEN_resolve_component_version_THEN_send_service_request.
@Test
void GIVEN_component_version_requirements_WHEN_resolve_component_version_THEN_send_service_request() throws Exception {
Map<String, Requirement> versionRequirements = new HashMap<>();
versionRequirements.put("X", Requirement.buildNPM("^1.0"));
versionRequirements.put("Y", Requirement.buildNPM("^1.5"));
ResolvedComponentVersion componentVersion = ResolvedComponentVersion.builder().componentName(COMPONENT_A).componentVersion(v1_0_0.getValue()).recipe(SdkBytes.fromByteArray("new recipe".getBytes(Charsets.UTF_8))).build();
ResolveComponentCandidatesResponse result = ResolveComponentCandidatesResponse.builder().resolvedComponentVersions(Collections.singletonList(componentVersion)).build();
when(client.resolveComponentCandidates(any(ResolveComponentCandidatesRequest.class))).thenReturn(result);
ResolvedComponentVersion componentVersionReturn = helper.resolveComponentVersion(COMPONENT_A, v1_0_0, versionRequirements);
assertThat(componentVersionReturn, is(componentVersion));
ArgumentCaptor<ResolveComponentCandidatesRequest> requestArgumentCaptor = ArgumentCaptor.forClass(ResolveComponentCandidatesRequest.class);
verify(client).resolveComponentCandidates(requestArgumentCaptor.capture());
ResolveComponentCandidatesRequest request = requestArgumentCaptor.getValue();
assertThat(request.platform(), notNullValue());
assertThat(request.platform().attributes(), notNullValue());
Map<String, String> attributes = request.platform().attributes();
assertThat(attributes, hasKey(PlatformResolver.OS_KEY));
assertThat(attributes, hasKey(PlatformResolver.ARCHITECTURE_KEY));
assertThat(request.componentCandidates().size(), is(1));
ComponentCandidate candidate = request.componentCandidates().get(0);
assertThat(candidate.componentName(), is(COMPONENT_A));
assertThat(candidate.componentVersion(), is("1.0.0"));
assertThat(candidate.versionRequirements(), IsMapContaining.hasEntry("X", ">=1.0.0 <2.0.0"));
assertThat(candidate.versionRequirements(), IsMapContaining.hasEntry("Y", ">=1.5.0 <2.0.0"));
}
use of software.amazon.awssdk.services.greengrassv2data.model.ResolvedComponentVersion in project aws-greengrass-nucleus by aws-greengrass.
the class ComponentManager method negotiateVersionWithCloud.
@SuppressWarnings({ "PMD.AvoidCatchingGenericException", "PMD.AvoidRethrowingException", "PMD.NullAssignment", "PMD.AvoidInstanceofChecksInCatchClause", "PMD.PreserveStackTrace" })
private ComponentIdentifier negotiateVersionWithCloud(String componentName, Map<String, Requirement> versionRequirements, ComponentIdentifier localCandidate) throws PackagingException, InterruptedException {
ResolvedComponentVersion resolvedComponentVersion;
if (localCandidate == null) {
try {
resolvedComponentVersion = RetryUtils.runWithRetry(clientExceptionRetryConfig, () -> componentServiceHelper.resolveComponentVersion(componentName, null, versionRequirements), "resolve-component-version", logger);
} catch (InterruptedException e) {
throw e;
} catch (Exception e) {
// Don't bother logging the full stacktrace when it is NoAvailableComponentVersionException since we
// know the reason for that error
logger.atError().setCause(e instanceof NoAvailableComponentVersionException ? null : e).kv(COMPONENT_NAME, componentName).kv("versionRequirement", versionRequirements).log("Failed to negotiate version with cloud and no local version to fall back to");
// know what the cause is.
if (e instanceof NoAvailableComponentVersionException) {
throw new NoAvailableComponentVersionException("No local or cloud component version satisfies the requirements.", componentName, versionRequirements);
} else {
throw new NoAvailableComponentVersionException("No local or cloud component version satisfies the requirements.", componentName, versionRequirements, e);
}
}
} else {
try {
resolvedComponentVersion = componentServiceHelper.resolveComponentVersion(componentName, localCandidate.getVersion(), versionRequirements);
} catch (Exception e) {
// Don't bother logging the full stacktrace when it is NoAvailableComponentVersionException since we
// know the reason for that error
logger.atInfo().setCause(e instanceof NoAvailableComponentVersionException ? null : e).kv(COMPONENT_NAME, componentName).kv("versionRequirement", versionRequirements).kv("localVersion", localCandidate).log("Failed to negotiate version with cloud and fall back to use the local version");
return localCandidate;
}
}
ComponentIdentifier resolvedComponentId = new ComponentIdentifier(resolvedComponentVersion.componentName(), new Semver(resolvedComponentVersion.componentVersion()));
String downloadedRecipeContent = StandardCharsets.UTF_8.decode(resolvedComponentVersion.recipe().asByteBuffer()).toString();
com.amazon.aws.iot.greengrass.component.common.ComponentRecipe cloudResolvedRecipe = // cloud sends JSON
RecipeLoader.parseRecipe(downloadedRecipeContent, RecipeLoader.RecipeFormat.JSON);
// Persist the recipe
String savedRecipeContent = componentStore.saveComponentRecipe(cloudResolvedRecipe);
// Since plugin runs in the same JVM as Nucleus does, we need to calculate the digest for its recipe and
// persist it, so that we can use it to detect and prevent a tampered plugin (recipe) gets loaded
storeRecipeDigestInConfigStoreForPlugin(cloudResolvedRecipe, savedRecipeContent);
// Save the arn to the recipe meta data file
componentStore.saveRecipeMetadata(resolvedComponentId, new RecipeMetadata(resolvedComponentVersion.arn()));
return resolvedComponentId;
}
Aggregations