diff --git a/src/integrationtests/java/com/aws/greengrass/integrationtests/lifecyclemanager/PluginComponentTest.java b/src/integrationtests/java/com/aws/greengrass/integrationtests/lifecyclemanager/PluginComponentTest.java index a6a880c656..7690101c07 100644 --- a/src/integrationtests/java/com/aws/greengrass/integrationtests/lifecyclemanager/PluginComponentTest.java +++ b/src/integrationtests/java/com/aws/greengrass/integrationtests/lifecyclemanager/PluginComponentTest.java @@ -37,6 +37,7 @@ import com.aws.greengrass.lifecyclemanager.Kernel; import com.aws.greengrass.lifecyclemanager.KernelAlternatives; import com.aws.greengrass.lifecyclemanager.KernelCommandLine; +import com.aws.greengrass.lifecyclemanager.exceptions.CustomPluginNotSupportedException; import com.aws.greengrass.lifecyclemanager.exceptions.ServiceLoadException; import com.aws.greengrass.logging.impl.LogManager; import com.aws.greengrass.util.Coerce; @@ -149,7 +150,7 @@ private void launchAndWait(Kernel k) throws InterruptedException { @Test void GIVEN_kernel_WHEN_locate_plugin_without_digest_THEN_plugin_is_not_loaded_into_JVM(ExtensionContext context) throws Exception { - ignoreExceptionOfType(context, ServiceLoadException.class); + ignoreExceptionOfType(context, CustomPluginNotSupportedException.class); ConfigPlatformResolver.initKernelWithMultiPlatformConfig(kernel, this.getClass().getResource("plugin.yaml")); setupPackageStore(kernel, componentId); kernel.launch(); diff --git a/src/integrationtests/java/com/aws/greengrass/integrationtests/lifecyclemanager/UnloadableServiceIntegTest.java b/src/integrationtests/java/com/aws/greengrass/integrationtests/lifecyclemanager/UnloadableServiceIntegTest.java index a8e0a9b332..fe0597b88b 100644 --- a/src/integrationtests/java/com/aws/greengrass/integrationtests/lifecyclemanager/UnloadableServiceIntegTest.java +++ b/src/integrationtests/java/com/aws/greengrass/integrationtests/lifecyclemanager/UnloadableServiceIntegTest.java @@ -100,7 +100,7 @@ void GIVEN_unloadable_plugin_missing_jar_WHEN_nucleus_launch_THEN_nucleus_starts @Test void GIVEN_unloadable_plugin_digest_missing_WHEN_nucleus_launch_THEN_nucleus_starts_and_other_services_running( ExtensionContext context) throws Exception { - ignoreExceptionWithMessage(context, "Custom plugins is not supported by this greengrass version"); + ignoreExceptionWithMessageSubstring(context, "Locally deployed plugin components are not supported"); ConfigPlatformResolver.initKernelWithMultiPlatformConfig(kernel, this.getClass().getResource("unloadable_plugin.yaml")); setupPackageStore(kernel, componentId); diff --git a/src/main/java/com/aws/greengrass/componentmanager/ComponentManager.java b/src/main/java/com/aws/greengrass/componentmanager/ComponentManager.java index 2397ae736d..8f3cc201b1 100644 --- a/src/main/java/com/aws/greengrass/componentmanager/ComponentManager.java +++ b/src/main/java/com/aws/greengrass/componentmanager/ComponentManager.java @@ -83,8 +83,6 @@ public class ComponentManager implements InjectionActions { private static final long DEFAULT_MIN_DISK_AVAIL_BYTES = 20 * ONE_MB; protected static final String COMPONENT_NAME = "componentName"; - public static final String INSTALLED_COMPONENT_NOT_FOUND_FAILURE_MESSAGE = - "No active component version satisfies the requirements of non-target groups"; public static final String VERSION_NOT_FOUND_FAILURE_MESSAGE = "No local or cloud component version satisfies the requirements"; diff --git a/src/main/java/com/aws/greengrass/deployment/errorcode/DeploymentErrorCode.java b/src/main/java/com/aws/greengrass/deployment/errorcode/DeploymentErrorCode.java index bf6c22a732..cbedeb0211 100644 --- a/src/main/java/com/aws/greengrass/deployment/errorcode/DeploymentErrorCode.java +++ b/src/main/java/com/aws/greengrass/deployment/errorcode/DeploymentErrorCode.java @@ -8,7 +8,7 @@ import lombok.Getter; public enum DeploymentErrorCode { - // Generic types + /* Generic types */ DEPLOYMENT_FAILURE(DeploymentErrorType.NONE), DEPLOYMENT_REJECTED(DeploymentErrorType.NONE), DEPLOYMENT_INTERRUPTED(DeploymentErrorType.NONE), @@ -16,7 +16,7 @@ public enum DeploymentErrorCode { NO_AVAILABLE_COMPONENT_VERSION(DeploymentErrorType.NONE), COMPONENT_PACKAGE_LOADING_ERROR(DeploymentErrorType.NONE), - // Deployment request error + /* Deployment request errors */ REJECTED_STALE_DEPLOYMENT(DeploymentErrorType.NONE), NUCLEUS_MISSING_REQUIRED_CAPABILITIES(DeploymentErrorType.REQUEST_ERROR), COMPONENT_CIRCULAR_DEPENDENCY_ERROR(DeploymentErrorType.REQUEST_ERROR), @@ -27,7 +27,7 @@ public enum DeploymentErrorCode { // deployment resolved multiple nucleus types MULTIPLE_NUCLEUS_RESOLVED_ERROR(DeploymentErrorType.REQUEST_ERROR), - // Greengrass cloud service errors + /* Greengrass cloud service errors */ CLOUD_API_ERROR(DeploymentErrorType.NONE), BAD_REQUEST(DeploymentErrorType.NUCLEUS_ERROR), ACCESS_DENIED(DeploymentErrorType.PERMISSION_ERROR), @@ -39,14 +39,14 @@ public enum DeploymentErrorCode { GET_COMPONENT_VERSION_ARTIFACT_ACCESS_DENIED(DeploymentErrorType.PERMISSION_ERROR), RESOLVE_COMPONENT_CANDIDATES_ACCESS_DENIED(DeploymentErrorType.PERMISSION_ERROR), - // Network / http + /* Network / http */ NETWORK_ERROR(DeploymentErrorType.NETWORK_ERROR), HTTP_REQUEST_ERROR(DeploymentErrorType.HTTP_ERROR), DOWNLOAD_DEPLOYMENT_DOCUMENT_ERROR(DeploymentErrorType.HTTP_ERROR), GET_GREENGRASS_ARTIFACT_SIZE_ERROR(DeploymentErrorType.HTTP_ERROR), DOWNLOAD_GREENGRASS_ARTIFACT_ERROR(DeploymentErrorType.HTTP_ERROR), - // IO errors + /* IO errors */ IO_ERROR(DeploymentErrorType.NONE), // it could be both recipe parse error or deployment doc error IO_MAPPING_ERROR(DeploymentErrorType.NONE), @@ -57,18 +57,16 @@ public enum DeploymentErrorCode { SET_PERMISSION_ERROR(DeploymentErrorType.DEVICE_ERROR), IO_UNZIP_ERROR(DeploymentErrorType.DEVICE_ERROR), - // Local file issues + /* Local file issues */ LOCAL_RECIPE_NOT_FOUND(DeploymentErrorType.DEVICE_ERROR), LOCAL_RECIPE_CORRUPTED(DeploymentErrorType.DEVICE_ERROR), LOCAL_RECIPE_METADATA_NOT_FOUND(DeploymentErrorType.DEVICE_ERROR), - + // JVM hashing issue + HASHING_ALGORITHM_UNAVAILABLE(DeploymentErrorType.DEVICE_ERROR), // Could be a local file issue or a Nucleus issue; we will categorize as the latter for visibility LAUNCH_DIRECTORY_CORRUPTED(DeploymentErrorType.NUCLEUS_ERROR), - // Hashing issue - HASHING_ALGORITHM_UNAVAILABLE(DeploymentErrorType.DEVICE_ERROR), - - // Component recipe error + /* Component recipe errors */ RECIPE_PARSE_ERROR(DeploymentErrorType.COMPONENT_RECIPE_ERROR), RECIPE_METADATA_PARSE_ERROR(DeploymentErrorType.COMPONENT_RECIPE_ERROR), ARTIFACT_URI_NOT_VALID(DeploymentErrorType.COMPONENT_RECIPE_ERROR), @@ -83,14 +81,14 @@ public enum DeploymentErrorCode { COMPONENT_DEPENDENCY_NOT_VALID(DeploymentErrorType.COMPONENT_RECIPE_ERROR), CONFIG_INTERPOLATE_ERROR(DeploymentErrorType.COMPONENT_RECIPE_ERROR), - // Config issues + /* Config issues */ DEVICE_CONFIG_NOT_VALID_FOR_ARTIFACT_DOWNLOAD(DeploymentErrorType.DEVICE_ERROR), RUN_WITH_CONFIG_NOT_VALID(DeploymentErrorType.REQUEST_ERROR), UNSUPPORTED_REGION(DeploymentErrorType.REQUEST_ERROR), IOT_CRED_ENDPOINT_FORMAT_NOT_VALID(DeploymentErrorType.REQUEST_ERROR), IOT_DATA_ENDPOINT_FORMAT_NOT_VALID(DeploymentErrorType.REQUEST_ERROR), - // Docker + /* Docker issues */ DOCKER_ERROR(DeploymentErrorType.DEPENDENCY_ERROR), GET_ECR_CREDENTIAL_ERROR(DeploymentErrorType.PERMISSION_ERROR), USER_NOT_AUTHORIZED_FOR_DOCKER(DeploymentErrorType.PERMISSION_ERROR), @@ -100,7 +98,7 @@ public enum DeploymentErrorCode { DOCKER_PULL_ERROR(DeploymentErrorType.DEPENDENCY_ERROR), DOCKER_IMAGE_NOT_VALID(DeploymentErrorType.DEPENDENCY_ERROR), - // S3 + /* S3 issues */ S3_ERROR(DeploymentErrorType.DEPENDENCY_ERROR), S3_RESOURCE_NOT_FOUND(DeploymentErrorType.DEPENDENCY_ERROR), S3_ACCESS_DENIED(DeploymentErrorType.PERMISSION_ERROR), @@ -113,12 +111,13 @@ public enum DeploymentErrorCode { S3_GET_OBJECT_ACCESS_DENIED(DeploymentErrorType.PERMISSION_ERROR), S3_GET_OBJECT_RESOURCE_NOT_FOUND(DeploymentErrorType.REQUEST_ERROR), - // Cloud service errors + /* Cloud service errors */ // resolve component candidates returned more than one version RESOLVE_COMPONENT_CANDIDATES_BAD_RESPONSE(DeploymentErrorType.CLOUD_SERVICE_ERROR), DEPLOYMENT_DOCUMENT_SIZE_EXCEEDED(DeploymentErrorType.CLOUD_SERVICE_ERROR), GREENGRASS_ARTIFACT_SIZE_NOT_FOUND(DeploymentErrorType.CLOUD_SERVICE_ERROR), + /* Errors that could be cloud errors OR nucleus errors */ // An invalid deployment doc is received // it's a nucleus error if local deployment // a cloud service error is cloud deployment @@ -129,12 +128,13 @@ public enum DeploymentErrorCode { DEPLOYMENT_TYPE_NOT_VALID(DeploymentErrorType.UNKNOWN_ERROR), COMPONENT_METADATA_NOT_VALID_IN_DEPLOYMENT(DeploymentErrorType.NONE), - // Nucleus errors + /* Nucleus errors */ NUCLEUS_VERSION_NOT_FOUND(DeploymentErrorType.NUCLEUS_ERROR), NUCLEUS_RESTART_FAILURE(DeploymentErrorType.NUCLEUS_ERROR), - INSTALLED_COMPONENT_NOT_FOUND(DeploymentErrorType.NUCLEUS_ERROR), + COMPONENT_LOAD_FAILURE(DeploymentErrorType.NUCLEUS_ERROR), - // Component issues + /* Component issues */ + CUSTOM_PLUGIN_NOT_SUPPORTED(DeploymentErrorType.USER_COMPONENT_ERROR), COMPONENT_UPDATE_ERROR(DeploymentErrorType.NONE), COMPONENT_BROKEN(DeploymentErrorType.NONE), REMOVE_COMPONENT_ERROR(DeploymentErrorType.NONE), diff --git a/src/main/java/com/aws/greengrass/deployment/errorcode/DeploymentErrorCodeUtils.java b/src/main/java/com/aws/greengrass/deployment/errorcode/DeploymentErrorCodeUtils.java index 49515ab44e..51f8ed84a9 100644 --- a/src/main/java/com/aws/greengrass/deployment/errorcode/DeploymentErrorCodeUtils.java +++ b/src/main/java/com/aws/greengrass/deployment/errorcode/DeploymentErrorCodeUtils.java @@ -15,6 +15,7 @@ import com.aws.greengrass.deployment.model.Deployment; import com.aws.greengrass.lifecyclemanager.GreengrassService; import com.aws.greengrass.lifecyclemanager.Kernel; +import com.aws.greengrass.lifecyclemanager.exceptions.CustomPluginNotSupportedException; import com.aws.greengrass.lifecyclemanager.exceptions.ServiceLoadException; import com.aws.greengrass.logging.api.Logger; import com.aws.greengrass.logging.impl.LogManager; @@ -50,9 +51,10 @@ import static com.aws.greengrass.deployment.errorcode.DeploymentErrorCode.ACCESS_DENIED; import static com.aws.greengrass.deployment.errorcode.DeploymentErrorCode.BAD_REQUEST; import static com.aws.greengrass.deployment.errorcode.DeploymentErrorCode.CLOUD_API_ERROR; +import static com.aws.greengrass.deployment.errorcode.DeploymentErrorCode.COMPONENT_LOAD_FAILURE; import static com.aws.greengrass.deployment.errorcode.DeploymentErrorCode.CONFLICTED_REQUEST; +import static com.aws.greengrass.deployment.errorcode.DeploymentErrorCode.CUSTOM_PLUGIN_NOT_SUPPORTED; import static com.aws.greengrass.deployment.errorcode.DeploymentErrorCode.DEPLOYMENT_INTERRUPTED; -import static com.aws.greengrass.deployment.errorcode.DeploymentErrorCode.INSTALLED_COMPONENT_NOT_FOUND; import static com.aws.greengrass.deployment.errorcode.DeploymentErrorCode.IO_ERROR; import static com.aws.greengrass.deployment.errorcode.DeploymentErrorCode.IO_MAPPING_ERROR; import static com.aws.greengrass.deployment.errorcode.DeploymentErrorCode.IO_WRITE_ERROR; @@ -156,7 +158,11 @@ private static void translateExceptionToErrorCode(Set error } else if (e instanceof S3Exception) { collectErrorCodesFromS3Exception(errorCodeSet, (S3Exception) e); } else if (e instanceof ServiceLoadException) { - collectErrorCodesFromServiceLoadException(errorCodeSet); + if (e instanceof CustomPluginNotSupportedException) { + collectErrorCodesFromCustomPluginNotSupportedException(errorCodeSet); + } else { + collectErrorCodesFromServiceLoadException(errorCodeSet); + } } else if (NETWORK_OFFLINE_EXCEPTION.stream().anyMatch(c -> c.isInstance(e))) { errorCodeSet.add(NETWORK_ERROR); } else if (e instanceof InterruptedException) { @@ -210,8 +216,12 @@ private static void collectErrorCodesFromS3Exception(Set er } } + private static void collectErrorCodesFromCustomPluginNotSupportedException(Set errorCodeSet) { + errorCodeSet.add(CUSTOM_PLUGIN_NOT_SUPPORTED); + } + private static void collectErrorCodesFromServiceLoadException(Set errorCodeSet) { - errorCodeSet.add(INSTALLED_COMPONENT_NOT_FOUND); + errorCodeSet.add(COMPONENT_LOAD_FAILURE); } /** diff --git a/src/main/java/com/aws/greengrass/lifecyclemanager/Kernel.java b/src/main/java/com/aws/greengrass/lifecyclemanager/Kernel.java index 600bf18d22..38a7fa8fa6 100644 --- a/src/main/java/com/aws/greengrass/lifecyclemanager/Kernel.java +++ b/src/main/java/com/aws/greengrass/lifecyclemanager/Kernel.java @@ -28,6 +28,7 @@ import com.aws.greengrass.deployment.exceptions.ServiceUpdateException; import com.aws.greengrass.deployment.model.Deployment; import com.aws.greengrass.deployment.model.Deployment.DeploymentStage; +import com.aws.greengrass.lifecyclemanager.exceptions.CustomPluginNotSupportedException; import com.aws.greengrass.lifecyclemanager.exceptions.InputValidationException; import com.aws.greengrass.lifecyclemanager.exceptions.ServiceLoadException; import com.aws.greengrass.logging.api.Logger; @@ -536,7 +537,8 @@ private Class locateExternalPlugin(String name, Topics serviceRootTopics) thr if (storedDigest == null || storedDigest.getOnce() == null) { logger.atError("plugin-load-error").kv(GreengrassService.SERVICE_NAME_KEY, name) .log("Local external plugin is not supported by this greengrass version"); - throw new ServiceLoadException("Custom plugins is not supported by this greengrass version"); + throw new CustomPluginNotSupportedException("Locally deployed plugin components are not supported. " + + "Plugins must be deployed via a cloud-based deployment."); } ComponentStore componentStore = context.get(ComponentStore.class); diff --git a/src/main/java/com/aws/greengrass/lifecyclemanager/exceptions/CustomPluginNotSupportedException.java b/src/main/java/com/aws/greengrass/lifecyclemanager/exceptions/CustomPluginNotSupportedException.java new file mode 100644 index 0000000000..d315122b7e --- /dev/null +++ b/src/main/java/com/aws/greengrass/lifecyclemanager/exceptions/CustomPluginNotSupportedException.java @@ -0,0 +1,22 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.aws.greengrass.lifecyclemanager.exceptions; + +public class CustomPluginNotSupportedException extends ServiceLoadException { + static final long serialVersionUID = -3387516993124229948L; + + public CustomPluginNotSupportedException(String message) { + super(message); + } + + public CustomPluginNotSupportedException(String message, Throwable cause) { + super(message, cause); + } + + public CustomPluginNotSupportedException(Throwable cause) { + super(cause); + } +}