Skip to content

(gdk): Publish overwrites existing S3 objects, leading to ConflictException and ARTIFACT_CHECKSUM_MISMATCH #300

@gergely-peidl

Description

@gergely-peidl

Problem Statement
The gdk component publish command does not check for the existence of a component's artifact version in the S3 bucket before uploading. This behavior results in the command overwriting the S3 object (or creating a new version if versioning is enabled). While the S3 upload itself might succeed, the subsequent CreateComponentVersion call fails, and any deployments using the component version result in an ARTIFACT_CHECKSUM_MISMATCH error.

This happens because the gdk-cli first uploads the artifact to S3 and then attempts to create the Greengrass component version using the CreateComponentVersion API. If a component with the same name and version already exists in the AWS account, the API call will fail, but the S3 artifact has already been overwritten, corrupting the link between the S3 object and the Greengrass component.

To Reproduce
Run gdk component publish for a component with a specific version (e.g., 1.0.0).
Run gdk component publish again for the exact same component and version.

Observe the following error in the terminal:

botocore.errorfactory.ConflictException: An error occurred (ConflictException) when calling the CreateComponentVersion operation: Component [component_name : version] for account [AWS_ACCOUNT_ID] already exists with state: [DEPLOYABLE]

If a Greengrass deployment is attempted with this component version, it will fail with an ARTIFACT_CHECKSUM_MISMATCH error.

Expected Behavior
The gdk component publish command should check if the component version already exists in the S3 bucket before attempting to upload. If it exists, the command should either:
Fail gracefully with a clear message indicating the version already exists.
Provide a flag (e.g., --overwrite) to explicitly allow the user to overwrite the object.

Actual Behavior
The command overwrites the existing S3 artifact, causing an inconsistency between the S3 object and the Greengrass component. The subsequent CreateComponentVersion API call fails, and deployments fail with a botocore.errorfactory.ConflictException followed by an ARTIFACT_CHECKSUM_MISMATCH error.

Proposed Solutions
Pre-upload Check: Before uploading the artifact, use the head_object method to check if the file already exists in the S3 bucket. If it does, and a --force or --overwrite flag is not present, skip the upload and provide a user-friendly error message.
Relevant code location: https://github.com/aws-greengrass/aws-greengrass-gdk-cli/blob/main/gdk/commands/component/PublishCommand.py#L84-L87

Conditional Writes: Investigate using S3 conditional write headers, such as if-none-match or if-match.
Note: As per the boto3 documentation, these headers are not directly supported by the S3Transfer class used for uploads. This may require a different approach or a custom implementation using the put_object API call directly.

Relevant Links

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions