Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions samcli/commands/pipeline/bootstrap/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from samcli.cli.cli_config_file import configuration_option, TomlProvider
from samcli.cli.main import pass_context, common_options, aws_creds_options, print_cmdline_args
from samcli.lib.config.samconfig import SamConfig
from samcli.lib.pipeline.bootstrap.environment import Environment
from samcli.lib.pipeline.bootstrap.stage import Stage
from samcli.lib.telemetry.metric import track_command
from samcli.lib.utils.colors import Colored
from samcli.lib.utils.version_checker import check_newer_version
Expand All @@ -37,8 +37,8 @@
help="Disable interactive prompting for bootstrap parameters, and fail if any required arguments are missing.",
)
@click.option(
"--environment",
help="The name of the corresponding environment. It is used as a suffix for the created resources.",
"--stage",
help="The name of the corresponding stage. It is used as a suffix for the created resources.",
required=False,
)
@click.option(
Expand Down Expand Up @@ -90,7 +90,7 @@
def cli(
ctx: Any,
interactive: bool,
environment: Optional[str],
stage: Optional[str],
pipeline_user: Optional[str],
pipeline_execution_role: Optional[str],
cloudformation_execution_role: Optional[str],
Expand All @@ -108,7 +108,7 @@ def cli(
region=ctx.region,
profile=ctx.profile,
interactive=interactive,
environment_name=environment,
stage_name=stage,
pipeline_user_arn=pipeline_user,
pipeline_execution_role_arn=pipeline_execution_role,
cloudformation_execution_role_arn=cloudformation_execution_role,
Expand All @@ -125,7 +125,7 @@ def do_cli(
region: Optional[str],
profile: Optional[str],
interactive: bool,
environment_name: Optional[str],
stage_name: Optional[str],
pipeline_user_arn: Optional[str],
pipeline_execution_role_arn: Optional[str],
cloudformation_execution_role_arn: Optional[str],
Expand Down Expand Up @@ -159,7 +159,7 @@ def do_cli(

guided_context = GuidedContext(
profile=profile,
environment_name=environment_name,
stage_name=stage_name,
pipeline_user_arn=pipeline_user_arn,
pipeline_execution_role_arn=pipeline_execution_role_arn,
cloudformation_execution_role_arn=cloudformation_execution_role_arn,
Expand All @@ -169,7 +169,7 @@ def do_cli(
region=region,
)
guided_context.run()
environment_name = guided_context.environment_name
stage_name = guided_context.stage_name
pipeline_user_arn = guided_context.pipeline_user_arn
pipeline_execution_role_arn = guided_context.pipeline_execution_role_arn
cloudformation_execution_role_arn = guided_context.cloudformation_execution_role_arn
Expand All @@ -179,11 +179,11 @@ def do_cli(
region = guided_context.region
profile = guided_context.profile

if not environment_name:
raise click.UsageError("Missing required parameter '--environment'")
if not stage_name:
raise click.UsageError("Missing required parameter '--stage'")

environment: Environment = Environment(
name=environment_name,
environment: Stage = Stage(
name=stage_name,
aws_profile=profile,
aws_region=region,
pipeline_user_arn=pipeline_user_arn,
Expand Down
16 changes: 8 additions & 8 deletions samcli/commands/pipeline/bootstrap/guided_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class GuidedContext:
def __init__(
self,
profile: Optional[str] = None,
environment_name: Optional[str] = None,
stage_name: Optional[str] = None,
pipeline_user_arn: Optional[str] = None,
pipeline_execution_role_arn: Optional[str] = None,
cloudformation_execution_role_arn: Optional[str] = None,
Expand All @@ -33,7 +33,7 @@ def __init__(
region: Optional[str] = None,
) -> None:
self.profile = profile
self.environment_name = environment_name
self.stage_name = stage_name
self.pipeline_user_arn = pipeline_user_arn
self.pipeline_execution_role_arn = pipeline_execution_role_arn
self.cloudformation_execution_role_arn = cloudformation_execution_role_arn
Expand Down Expand Up @@ -76,7 +76,7 @@ def _prompt_account_id(self) -> None:

try:
account_id = get_current_account_id(self.profile)
click.echo(self.color.green(f"Associated account {account_id} with stage {self.environment_name}."))
click.echo(self.color.green(f"Associated account {account_id} with stage {self.stage_name}."))
except CredentialsError as ex:
click.echo(self.color.red(ex.message))
self._prompt_account_id()
Expand All @@ -85,9 +85,9 @@ def _prompt_stage_name(self) -> None:
click.echo(
"Enter a name for this stage. This will be referenced later when you use the sam pipeline init command:"
)
self.environment_name = click.prompt(
self.stage_name = click.prompt(
"Stage name",
default=self.environment_name,
default=self.stage_name,
type=click.STRING,
)

Expand Down Expand Up @@ -144,7 +144,7 @@ def _prompt_image_repository(self) -> None:
def _get_user_inputs(self) -> List[Tuple[str, Callable[[], None]]]:
return [
(f"Account: {get_current_account_id(self.profile)}", self._prompt_account_id),
(f"Stage name: {self.environment_name}", self._prompt_stage_name),
(f"Stage name: {self.stage_name}", self._prompt_stage_name),
(f"Region: {self.region}", self._prompt_region_name),
(
f"Pipeline user ARN: {self.pipeline_user_arn}"
Expand Down Expand Up @@ -185,8 +185,8 @@ def run(self) -> None: # pylint: disable=too-many-branches
and it will be created by the bootstrap command
"""
click.secho(self.color.bold("[1] Stage definition"))
if self.environment_name:
click.echo(f"Stage name: {self.environment_name}")
if self.stage_name:
click.echo(f"Stage name: {self.stage_name}")
else:
self._prompt_stage_name()
click.echo()
Expand Down
44 changes: 22 additions & 22 deletions samcli/commands/pipeline/init/interactive_init_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,16 @@ def _generate_from_custom_location(
)
return self._generate_from_pipeline_template(pipeline_template_local_dir)

def _prompt_run_bootstrap_within_pipeline_init(self, env_names: List[str], required_env_number: int) -> bool:
def _prompt_run_bootstrap_within_pipeline_init(self, stage_names: List[str], required_env_number: int) -> bool:
"""
Prompt bootstrap if `--bootstrap` flag is provided. Return True if bootstrap process is executed.
"""
if not env_names:
if not stage_names:
click.echo(Colored().yellow("No bootstrapped resources were detected."))
else:
click.echo(
Colored().yellow(
f"Only {len(env_names)} bootstrapped stage(s) were detected, "
f"Only {len(stage_names)} bootstrapped stage(s) were detected, "
f"fewer than what the template requires: {required_env_number}."
)
)
Expand All @@ -153,12 +153,12 @@ def _prompt_run_bootstrap_within_pipeline_init(self, env_names: List[str], requi
)
)

click.echo(Colored().bold(f"\nStage {len(env_names) + 1} Setup\n"))
click.echo(Colored().bold(f"\nStage {len(stage_names) + 1} Setup\n"))
do_bootstrap(
region=None,
profile=None,
interactive=True,
environment_name=None,
stage_name=None,
pipeline_user_arn=None,
pipeline_execution_role_arn=None,
cloudformation_execution_role_arn=None,
Expand Down Expand Up @@ -196,9 +196,9 @@ def _generate_from_pipeline_template(self, pipeline_template_dir: Path) -> List[
_draw_stage_diagram(required_env_number)
while True:
click.echo("Checking for bootstrapped resources...")
env_names, bootstrap_context = _load_pipeline_bootstrap_resources()
if len(env_names) < required_env_number and self._prompt_run_bootstrap_within_pipeline_init(
env_names, required_env_number
stage_names, bootstrap_context = _load_pipeline_bootstrap_resources()
if len(stage_names) < required_env_number and self._prompt_run_bootstrap_within_pipeline_init(
stage_names, required_env_number
):
# the customers just went through the bootstrap process,
# refresh the pipeline bootstrap resources and see whether bootstrap is still needed
Expand All @@ -219,26 +219,26 @@ def _load_pipeline_bootstrap_resources() -> Tuple[List[str], Dict[str, str]]:

config = SamConfig(PIPELINE_CONFIG_DIR, PIPELINE_CONFIG_FILENAME)
if not config.exists():
context[str(["environment_names_message"])] = ""
context[str(["stage_names_message"])] = ""
return [], context

# config.get_env_names() will return the list of
# bootstrapped env names and "default" which is used to store shared values
# config.get_stage_names() will return the list of
# bootstrapped stage names and "default" which is used to store shared values
# we don't want to include "default" here.
env_names = [env_name for env_name in config.get_env_names() if env_name != "default"]
for env in env_names:
for key, value in config.get_all(_get_bootstrap_command_names(), section, env).items():
context[str([env, key])] = value

# pre-load the list of env names detected from pipelineconfig.toml
environment_names_message = (
"Here are the environment names detected "
stage_names = [stage_name for stage_name in config.get_stage_names() if stage_name != "default"]
for stage in stage_names:
for key, value in config.get_all(_get_bootstrap_command_names(), section, stage).items():
context[str([stage, key])] = value

# pre-load the list of stage names detected from pipelineconfig.toml
stage_names_message = (
"Here are the stage names detected "
+ f"in {os.path.join(PIPELINE_CONFIG_DIR, PIPELINE_CONFIG_FILENAME)}:\n"
+ "\n".join([f"\t- {env_name}" for env_name in env_names])
+ "\n".join([f"\t- {stage_name}" for stage_name in stage_names])
)
context[str(["environment_names_message"])] = environment_names_message
context[str(["stage_names_message"])] = stage_names_message

return env_names, context
return stage_names, context


def _copy_dir_contents_to_cwd_fail_on_exist(source_dir: str) -> List[str]:
Expand Down
4 changes: 2 additions & 2 deletions samcli/lib/config/samconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ def __init__(self, config_dir, filename=None):
"""
self.filepath = Path(config_dir, filename or DEFAULT_CONFIG_FILE_NAME)

def get_env_names(self):
def get_stage_names(self):
self._read()
if isinstance(self.document, dict):
return [env for env, value in self.document.items() if isinstance(value, dict)]
return [stage for stage, value in self.document.items() if isinstance(value, dict)]
return []

def get_all(self, cmd_names, section, env=DEFAULT_ENV):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

CFN_TEMPLATE_PATH = str(pathlib.Path(os.path.dirname(__file__)))
STACK_NAME_PREFIX = "aws-sam-cli-managed"
ENVIRONMENT_RESOURCES_STACK_NAME_SUFFIX = "pipeline-resources"
ENVIRONMENT_RESOURCES_CFN_TEMPLATE = "environment_resources.yaml"
STAGE_RESOURCES_STACK_NAME_SUFFIX = "pipeline-resources"
STAGE_RESOURCES_CFN_TEMPLATE = "stage_resources.yaml"
PIPELINE_USER = "pipeline_user"
PIPELINE_EXECUTION_ROLE = "pipeline_execution_role"
CLOUDFORMATION_EXECUTION_ROLE = "cloudformation_execution_role"
Expand All @@ -26,9 +26,9 @@
REGION = "region"


class Environment:
class Stage:
"""
Represents an application environment: Beta, Gamma, Prod ...etc
Represents an application stage: Beta, Gamma, Prod ...etc

Attributes
----------
Expand Down Expand Up @@ -58,9 +58,9 @@ class Environment:
checks if all of the environment's required resources (pipeline_user, pipeline_execution_role,
cloudformation_execution_role, artifacts_bucket and image_repository) are provided by the user.
bootstrap(self, confirm_changeset: bool = True) -> None:
deploys the CFN template ./environment_resources.yaml to the AWS account identified by aws_profile and
deploys the CFN template ./stage_resources.yaml to the AWS account identified by aws_profile and
aws_region member fields. if aws_profile is not provided, it will fallback to default boto3 credentials'
resolving. Note that ./environment_resources.yaml template accepts the ARNs of already existing resources(if
resolving. Note that ./stage_resources.yaml template accepts the ARNs of already existing resources(if
any) as parameters and it will skip the creation of those resources but will use the ARNs to set the proper
permissions of other missing resources(resources created by the template)
save_config(self, config_dir: str, filename: str, cmd_names: List[str]):
Expand Down Expand Up @@ -122,7 +122,7 @@ def _get_non_user_provided_resources_msg(self) -> str:

def bootstrap(self, confirm_changeset: bool = True) -> bool:
"""
Deploys the CFN template(./environment_resources.yaml) which deploys:
Deploys the CFN template(./stage_resources.yaml) which deploys:
* Pipeline IAM User
* Pipeline execution IAM role
* CloudFormation execution IAM role
Expand All @@ -137,7 +137,7 @@ def bootstrap(self, confirm_changeset: bool = True) -> bool:
Parameters
----------
confirm_changeset: bool
if set to false, the environment_resources.yaml CFN template will directly be deployed, otherwise,
if set to false, the stage_resources.yaml CFN template will directly be deployed, otherwise,
the user will be prompted for confirmation

Returns True if bootstrapped, otherwise False
Expand All @@ -160,7 +160,7 @@ def bootstrap(self, confirm_changeset: bool = True) -> bool:
click.secho(self.color.red("Canceling pipeline bootstrap creation."))
return False

environment_resources_template_body = Environment._read_template(ENVIRONMENT_RESOURCES_CFN_TEMPLATE)
environment_resources_template_body = Stage._read_template(STAGE_RESOURCES_CFN_TEMPLATE)
output: StackOutput = manage_stack(
stack_name=self._get_stack_name(),
region=self.aws_region,
Expand All @@ -183,9 +183,7 @@ def bootstrap(self, confirm_changeset: bool = True) -> bool:
(
self.pipeline_user.access_key_id,
self.pipeline_user.secret_access_key,
) = Environment._get_pipeline_user_secret_pair(
pipeline_user_secret_sm_id, self.aws_profile, self.aws_region
)
) = Stage._get_pipeline_user_secret_pair(pipeline_user_secret_sm_id, self.aws_profile, self.aws_region)
self.pipeline_execution_role.arn = output.get("PipelineExecutionRole")
self.cloudformation_execution_role.arn = output.get("CloudFormationExecutionRole")
self.artifacts_bucket.arn = output.get("ArtifactsBucket")
Expand Down Expand Up @@ -326,5 +324,5 @@ def print_resources_summary(self) -> None:
click.secho(self.color.green(f"\tAWS_SECRET_ACCESS_KEY: {self.pipeline_user.secret_access_key}"))

def _get_stack_name(self) -> str:
sanitized_environment_name: str = re.sub("[^0-9a-zA-Z]+", "-", self.name)
return f"{STACK_NAME_PREFIX}-{sanitized_environment_name}-{ENVIRONMENT_RESOURCES_STACK_NAME_SUFFIX}"
sanitized_stage_name: str = re.sub("[^0-9a-zA-Z]+", "-", self.name)
return f"{STACK_NAME_PREFIX}-{sanitized_stage_name}-{STAGE_RESOURCES_STACK_NAME_SUFFIX}"
18 changes: 9 additions & 9 deletions tests/integration/pipeline/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import boto3
from botocore.exceptions import ClientError

from samcli.lib.pipeline.bootstrap.environment import Environment
from samcli.lib.pipeline.bootstrap.stage import Stage


class PipelineBase(TestCase):
Expand Down Expand Up @@ -69,7 +69,7 @@ def tearDown(self):
def get_bootstrap_command_list(
self,
no_interactive: bool = False,
env_name: Optional[str] = None,
stage_name: Optional[str] = None,
pipeline_user: Optional[str] = None,
pipeline_execution_role: Optional[str] = None,
cloudformation_execution_role: Optional[str] = None,
Expand All @@ -82,8 +82,8 @@ def get_bootstrap_command_list(

if no_interactive:
command_list += ["--no-interactive"]
if env_name:
command_list += ["--environment", env_name]
if stage_name:
command_list += ["--stage", stage_name]
if pipeline_user:
command_list += ["--pipeline-user", pipeline_user]
if pipeline_execution_role:
Expand Down Expand Up @@ -114,13 +114,13 @@ def _stack_exists(self, stack_name) -> bool:
return False
raise ex

def _get_env_and_stack_name(self, suffix: str = "") -> Tuple[str, str]:
def _get_stage_and_stack_name(self, suffix: str = "") -> Tuple[str, str]:
# Method expects method name which can be a full path. Eg: test.integration.test_bootstrap_command.method_name
method_name = self.id().split(".")[-1]
env_name = method_name.replace("_", "-") + suffix
stage_name = method_name.replace("_", "-") + suffix

mock_env = Mock()
mock_env.name = env_name
stack_name = Environment._get_stack_name(mock_env)
mock_env.name = stage_name
stack_name = Stage._get_stack_name(mock_env)

return env_name, stack_name
return stage_name, stack_name
Loading