def deploy(self): """ [option] option: stack-name: CloudFormation stack name template-path: CloudFormation template file path params-path: CloudFormation template parameters file path. allowed file type: json, jsonnet """ client = boto3.client('cloudformation') if not os.path.isfile(self.template_path): raise exceptions.InvalidTemplatePathError(template_path=self.template_path) with open(self.template_path, "r") as f: template_str = f.read() params = self.__load_cfn_params(self.params_path) tags = [] s3_uploader = None deployer = Deployer(client) self.__deploy(deployer, self.stack_name, template_str, params, ['CAPABILITY_IAM', 'CAPABILITY_AUTO_EXPAND'], True, None, None, s3_uploader, tags, False)
def setUp(self): self.session = mock.Mock() self.session.get_scoped_config.return_value = {} self.parsed_args = FakeArgs( template_file='./foo', stack_name="some_stack_name", parameter_overrides=["Key1=Value1", "Key2=Value2"], no_execute_changeset=False, execute_changeset=True, capabilities=None, role_arn=None, notification_arns=[], fail_on_empty_changeset=True, s3_bucket=None, s3_prefix="some prefix", kms_key_id="some kms key id", force_upload=True, tags=["tagkey1=tagvalue1"]) self.parsed_globals = FakeArgs(region="us-east-1", endpoint_url=None, verify_ssl=None) self.deploy_command = DeployCommand(self.session) self.deployer = Deployer(Mock()) self.deployer.create_and_wait_for_changeset = Mock() self.deployer.execute_changeset = Mock() self.deployer.wait_for_execute = Mock()
def test_wait_for_execute_no_changes(self): stack_name = "stack_name" changeset_type = "CREATE" mock_client = mock.Mock() mock_deployer = Deployer(mock_client) mock_waiter = mock.Mock() mock_client.get_waiter.return_value = mock_waiter waiter_error = botocore.exceptions.WaiterError(name="name", reason="reason", last_response={}) mock_waiter.wait.side_effect = waiter_error with self.assertRaises(exceptions.DeployFailedError): mock_deployer.wait_for_execute(stack_name, changeset_type) waiter_config = { 'Delay': 30, 'MaxAttempts': 120, } mock_waiter.wait.assert_called_once_with(StackName=stack_name, WaiterConfig=waiter_config) mock_client.get_waiter.assert_called_once_with("stack_create_complete")
def _run_main(self, parsed_args, parsed_globals): cloudformation_client = \ self._session.create_client( 'cloudformation', region_name=parsed_globals.region, endpoint_url=parsed_globals.endpoint_url, verify=parsed_globals.verify_ssl) template_path = parsed_args.template_file if not os.path.isfile(template_path): raise exceptions.InvalidTemplatePathError( template_path=template_path) # Parse parameters with open(template_path, "r") as handle: template_str = handle.read() stack_name = parsed_args.stack_name parameter_overrides = self.parse_parameter_arg( parsed_args.parameter_overrides) template_dict = yaml_parse(template_str) parameters = self.merge_parameters(template_dict, parameter_overrides) deployer = Deployer(cloudformation_client) return self.deploy(deployer, stack_name, template_str, parameters, parsed_args.capabilities, parsed_args.execute_changeset, parsed_args.role_arn, parsed_args.notification_arns, parsed_args.fail_on_empty_changeset)
def setUp(self): client = botocore.session.get_session().create_client( 'cloudformation', region_name="us-east-1") self.stub_client = Stubber(client) self.changeset_prefix = "some-changeset-prefix" self.deployer = Deployer(client, self.changeset_prefix)
def test_wait_for_changeset_failed_to_create_changeset(self): stack_name = "stack_name" changeset_id = "changeset-id" mock_client = mock.Mock() mock_deployer = Deployer(mock_client) mock_waiter = mock.Mock() mock_client.get_waiter.return_value = mock_waiter response = {"Status": "FAILED", "StatusReason": "some reason"} waiter_error = botocore.exceptions.WaiterError(name="name", reason="reason", last_response=response) mock_waiter.wait.side_effect = waiter_error with self.assertRaises(RuntimeError): mock_deployer.wait_for_changeset(changeset_id, stack_name) waiter_config = {'Delay': 5} mock_waiter.wait.assert_called_once_with(ChangeSetName=changeset_id, StackName=stack_name, WaiterConfig=waiter_config) mock_client.get_waiter.assert_called_once_with( "change_set_create_complete")
def test_wait_for_changeset_no_changes(self): stack_name = "stack_name" changeset_id = "changeset-id" mock_client = Mock() mock_deployer = Deployer(mock_client) mock_waiter = Mock() mock_client.get_waiter.return_value = mock_waiter response = { "Status": "FAILED", "StatusReason": "No updates are to be performed" } waiter_error = botocore.exceptions.WaiterError(name="name", reason="reason", last_response=response) mock_waiter.wait.side_effect = waiter_error with self.assertRaises(exceptions.ChangeEmptyError): mock_deployer.wait_for_changeset(changeset_id, stack_name) mock_waiter.wait.assert_called_once_with(ChangeSetName=changeset_id, StackName=stack_name) mock_client.get_waiter.assert_called_once_with( "change_set_create_complete")
def publish(self, stack_name): d = Deployer(boto3.client('cloudformation')) result = d.create_and_wait_for_changeset( stack_name=stack_name, cfn_template=self.get_template(), parameter_values=[], capabilities=['CAPABILITY_IAM']) d.execute_changeset(result.changeset_id, stack_name) d.wait_for_execute(stack_name, result.changeset_type)
def _run_main(self, parsed_args, parsed_globals): cloudformation_client = \ self._session.create_client( 'cloudformation', region_name=parsed_globals.region, endpoint_url=parsed_globals.endpoint_url, verify=parsed_globals.verify_ssl) template_path = parsed_args.template_file if not os.path.isfile(template_path): raise exceptions.InvalidTemplatePathError( template_path=template_path) # Parse parameters with open(template_path, "r") as handle: template_str = handle.read() stack_name = parsed_args.stack_name parameter_overrides = self.parse_key_value_arg( parsed_args.parameter_overrides, self.PARAMETER_OVERRIDE_CMD) tags_dict = self.parse_key_value_arg(parsed_args.tags, self.TAGS_CMD) tags = [{"Key": key, "Value": value} for key, value in tags_dict.items()] template_dict = yaml_parse(template_str) parameters = self.merge_parameters(template_dict, parameter_overrides) template_size = os.path.getsize(parsed_args.template_file) if template_size > 51200 and not parsed_args.s3_bucket: raise exceptions.DeployBucketRequiredError() bucket = parsed_args.s3_bucket if bucket: s3_client = self._session.create_client( "s3", config=Config(signature_version='s3v4'), region_name=parsed_globals.region, verify=parsed_globals.verify_ssl) s3_uploader = S3Uploader(s3_client, bucket, parsed_args.s3_prefix, parsed_args.kms_key_id, parsed_args.force_upload) else: s3_uploader = None deployer = Deployer(cloudformation_client) return self.deploy(deployer, stack_name, template_str, parameters, parsed_args.capabilities, parsed_args.execute_changeset, parsed_args.role_arn, parsed_args.notification_arns, s3_uploader, tags, parsed_args.fail_on_empty_changeset)
def deploy_template(session, config, packaged_yaml, approve=False): success = True print('\nDeploying...') client = session.create_client('cloudformation') stack_name = conventions.generate_stack_name(config['Parameters']) deployer = Deployer(client) tags = conventions.merge_tags(config.get('Tags', {}), config['Parameters']) try: result = deployer.create_and_wait_for_changeset( stack_name=stack_name, cfn_template=packaged_yaml, parameter_values=deploy_template_parameters_builder( config['Parameters']), capabilities=['CAPABILITY_NAMED_IAM'], role_arn=None, notification_arns=None, s3_uploader=None, tags=deploy_template_tags_builder(tags)) display_changeset(session, stack_name, result.changeset_id) if not approve: utils.get_confirmation() execute_changeset_token = str(uuid.uuid4()) client.execute_change_set(ChangeSetName=result.changeset_id, StackName=stack_name, ClientRequestToken=execute_changeset_token) deployer.wait_for_execute(stack_name, result.changeset_type) except exceptions.ChangeEmptyError as ex: logging.error(ex) success = False except exceptions.DeployFailedError as ex: logging.error(ex) # print(colored(ex.response['Error']['Message'], 'red')) stack_events = get_stack_events(session, stack_name, execute_changeset_token) aws.display_cfn_stack_events(stack_events) success = False except botocore.exceptions.ClientError as ex: logging.error(ex) success = False print('Done.') return success
def setUp(self): self.session = mock.Mock() self.session.get_scoped_config.return_value = {} self.parsed_args = FakeArgs( template_file='./foo', stack_name="some_stack_name", parameter_overrides=["Key1=Value1", "Key2=Value2"], no_execute_changeset=False, execute_changeset=True, capabilities=None) self.parsed_globals = FakeArgs(region="us-east-1", endpoint_url=None, verify_ssl=None) self.deploy_command = DeployCommand(self.session) self.deployer = Deployer(Mock()) self.deployer.create_and_wait_for_changeset = Mock() self.deployer.execute_changeset = Mock() self.deployer.wait_for_execute = Mock()