samcli/commands/publish/command.py (93 lines of code) (raw):
"""CLI command for "publish" command."""
import json
import logging
import boto3
import click
from samcli.cli.cli_config_file import ConfigProvider, configuration_option, save_params_option
from samcli.cli.main import aws_creds_options, pass_context, print_cmdline_args
from samcli.cli.main import common_options as cli_framework_options
from samcli.commands._utils.command_exception_handler import command_exception_handler
from samcli.commands._utils.options import template_common_option
from samcli.commands._utils.template import TemplateFailedParsingException, TemplateNotFoundException, get_template_data
from samcli.lib.telemetry.metric import track_command
from samcli.lib.utils.version_checker import check_newer_version
from samcli.vendor.serverlessrepo.publish import CREATE_APPLICATION
LOG = logging.getLogger(__name__)
SAM_PUBLISH_DOC = "https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-template-publishing-applications.html" # pylint: disable=line-too-long # noqa
SAM_PACKAGE_DOC = "https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-package.html" # pylint: disable=line-too-long # noqa
HELP_TEXT = """
Use this command to publish a packaged AWS SAM template to
the AWS Serverless Application Repository to share within your team,
across your organization, or with the community at large.\n
\b
This command expects the template's Metadata section to contain an
AWS::ServerlessRepo::Application section with application metadata
for publishing. For more details on this metadata section, see
{}
\b
Examples
--------
To publish an application
$ sam publish -t packaged.yaml --region <region>
""".format(
SAM_PUBLISH_DOC
)
SHORT_HELP = "Publish a packaged AWS SAM template to the AWS Serverless Application Repository."
SERVERLESSREPO_CONSOLE_URL = "https://console.aws.amazon.com/serverlessrepo/home?region={}#/published-applications/{}"
SEMANTIC_VERSION_HELP = "Optional. The value provided here overrides SemanticVersion in the template metadata."
SEMANTIC_VERSION = "SemanticVersion"
FAIL_ON_SAME_VERSION = """
If set, AWS SAM CLI will prevent a publish and return a non-zero exit code
if the publish is attempted with a semantic version that already exists on the SAR application.
Default is False.
"""
@click.command("publish", help=HELP_TEXT, short_help=SHORT_HELP)
@configuration_option(provider=ConfigProvider(section="parameters"))
@template_common_option
@click.option("--semantic-version", help=SEMANTIC_VERSION_HELP)
@click.option("--fail-on-same-version", default=False, required=False, is_flag=True, help=FAIL_ON_SAME_VERSION)
@aws_creds_options
@cli_framework_options
@save_params_option
@pass_context
@track_command
@check_newer_version
@print_cmdline_args
@command_exception_handler
def cli(
ctx,
template_file,
semantic_version,
fail_on_same_version,
save_params,
config_file,
config_env,
):
# All logic must be implemented in the ``do_cli`` method. This helps with easy unit testing
do_cli(ctx, template_file, semantic_version, fail_on_same_version) # pragma: no cover
def do_cli(ctx, template, semantic_version, fail_on_same_version):
"""Publish the application based on command line inputs."""
from samcli.commands.exceptions import UserException
from samcli.vendor.serverlessrepo import publish_application
from samcli.vendor.serverlessrepo.exceptions import (
InvalidS3UriError,
ServerlessRepoError,
)
from samcli.vendor.serverlessrepo.parser import METADATA, SERVERLESS_REPO_APPLICATION
try:
template_data = get_template_data(template)
except (TemplateFailedParsingException, TemplateNotFoundException) as ex:
click.secho("Publish Failed", fg="red")
raise ex
# Override SemanticVersion in template metadata when provided in command input
if semantic_version and SERVERLESS_REPO_APPLICATION in template_data.get(METADATA, {}):
template_data.get(METADATA).get(SERVERLESS_REPO_APPLICATION)[SEMANTIC_VERSION] = semantic_version
try:
publish_output = publish_application(template=template_data, fail_on_same_version=fail_on_same_version)
click.secho("Publish Succeeded", fg="green")
click.secho(_gen_success_message(publish_output))
except InvalidS3UriError as ex:
click.secho("Publish Failed", fg="red")
raise UserException(
"Your SAM template contains invalid S3 URIs. Please make sure that you have uploaded application "
"artifacts to S3 by packaging the template. See more details in {}".format(SAM_PACKAGE_DOC),
wrapped_from=ex.__class__.__name__,
) from ex
except ServerlessRepoError as ex:
click.secho("Publish Failed", fg="red")
LOG.debug("Failed to publish application to serverlessrepo", exc_info=True)
error_msg = "{}\nPlease follow the instructions in {}".format(str(ex), SAM_PUBLISH_DOC)
raise UserException(error_msg, wrapped_from=ex.__class__.__name__) from ex
application_id = publish_output.get("application_id")
_print_console_link(ctx.region, application_id)
def _gen_success_message(publish_output):
"""
Generate detailed success message for published applications.
Parameters
----------
publish_output : dict
Output from serverlessrepo publish_application
Returns
-------
str
Detailed success message
"""
application_id = publish_output.get("application_id")
details = json.dumps(publish_output.get("details"), indent=2)
if CREATE_APPLICATION in publish_output.get("actions"):
return "Created new application with the following metadata:\n{}".format(details)
return 'The following metadata of application "{}" has been updated:\n{}'.format(application_id, details)
def _print_console_link(region, application_id):
"""
Print link for the application in AWS Serverless Application Repository console.
Parameters
----------
region : str
AWS region name
application_id : str
The Amazon Resource Name (ARN) of the application
"""
if not region:
region = boto3.Session().region_name
console_link = SERVERLESSREPO_CONSOLE_URL.format(region, application_id.replace("/", "~"))
msg = "Click the link below to view your application in AWS console:\n{}".format(console_link)
click.secho(msg, fg="yellow")