use of com.aws.greengrass.componentmanager.exceptions.NoAvailableComponentVersionException 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;
}
use of com.aws.greengrass.componentmanager.exceptions.NoAvailableComponentVersionException in project aws-greengrass-nucleus by aws-greengrass.
the class ComponentManager method resolveComponentVersion.
ComponentMetadata resolveComponentVersion(String componentName, Map<String, Requirement> versionRequirements) throws InterruptedException, PackagingException {
logger.atDebug().setEventType("resolve-component-version-start").kv(COMPONENT_STR, componentName).kv("versionRequirements", versionRequirements).log("Resolving component version starts");
// Find best local candidate
Optional<ComponentIdentifier> localCandidateOptional = findBestCandidateLocally(componentName, versionRequirements);
if (localCandidateOptional.isPresent()) {
logger.atInfo().kv("LocalCandidateId", localCandidateOptional.get()).log("Found the best local candidate that satisfies the requirement.");
} else {
logger.atInfo().log("Can't find a local candidate that satisfies the requirement.");
}
ComponentIdentifier resolvedComponentId;
if (versionRequirements.containsKey(DeploymentDocumentConverter.LOCAL_DEPLOYMENT_GROUP_NAME) && localCandidateOptional.isPresent()) {
// If local group has a requirement and a satisfying local version presents, use it and don't negotiate with
// cloud.
logger.atInfo().log("Local group has a requirement and found satisfying local candidate. Using the local" + " candidate as the resolved version without negotiating with cloud.");
resolvedComponentId = localCandidateOptional.get();
} else {
// Otherwise try to negotiate with cloud
if (deviceConfiguration.isDeviceConfiguredToTalkToCloud()) {
logger.atDebug().setEventType("negotiate-version-with-cloud-start").log("Negotiating version with cloud");
resolvedComponentId = negotiateVersionWithCloud(componentName, versionRequirements, localCandidateOptional.orElse(null));
logger.atDebug().setEventType("negotiate-version-with-cloud-end").log("Negotiated version with cloud");
} else {
// Device running offline. Use the local candidate if present, otherwise fails
if (localCandidateOptional.isPresent()) {
logger.atInfo().log("Device is running offline and found satisfying local candidate. Using the " + "local candidate as the resolved version without negotiating with cloud.");
resolvedComponentId = localCandidateOptional.get();
} else {
throw new NoAvailableComponentVersionException("Device is configured to run offline and no local component version satisfies the " + "requirements.", componentName, versionRequirements);
}
}
}
logger.atInfo().setEventType("resolve-component-version-end").kv("ResolvedComponent", resolvedComponentId).log("Resolved component version.");
return getComponentMetadata(resolvedComponentId);
}
use of com.aws.greengrass.componentmanager.exceptions.NoAvailableComponentVersionException in project aws-greengrass-nucleus by aws-greengrass.
the class ComponentServiceHelper method resolveComponentVersion.
/**
* Resolve a component version with greengrass cloud service. The dependency resolution algorithm goes through the
* dependencies node by node, so one component got resolve a time.
*
* @param componentName component name to be resolve
* @param localCandidateVersion component local candidate version if available
* @param versionRequirements component dependents version requirement map
* @return resolved component version and recipe
* @throws NoAvailableComponentVersionException if no applicable version available in cloud service
*/
@SuppressWarnings("PMD.PreserveStackTrace")
ResolvedComponentVersion resolveComponentVersion(String componentName, Semver localCandidateVersion, Map<String, Requirement> versionRequirements) throws NoAvailableComponentVersionException {
ComponentPlatform platform = ComponentPlatform.builder().attributes(platformResolver.getCurrentPlatform()).build();
Map<String, String> versionRequirementsInString = versionRequirements.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().toString()));
ComponentCandidate candidate = ComponentCandidate.builder().componentName(componentName).componentVersion(localCandidateVersion == null ? null : localCandidateVersion.getValue()).versionRequirements(versionRequirementsInString).build();
ResolveComponentCandidatesRequest request = ResolveComponentCandidatesRequest.builder().platform(platform).componentCandidates(Collections.singletonList(candidate)).build();
ResolveComponentCandidatesResponse result;
try {
result = clientFactory.getGreengrassV2DataClient().resolveComponentCandidates(request);
} catch (ResourceNotFoundException e) {
logger.atDebug().kv("componentName", componentName).kv("versionRequirements", versionRequirements).log("No applicable version found in cloud registry", e);
throw new NoAvailableComponentVersionException("No cloud component version satisfies the requirements.", componentName, versionRequirements);
}
Validate.isTrue(result.resolvedComponentVersions() != null && result.resolvedComponentVersions().size() == 1, "Component service returns invalid response. It should have one resolved component version");
return result.resolvedComponentVersions().get(0);
}
Aggregations