def __init__(self, paco_ctx, netenv_ctl, netenv, env, env_region): self.paco_ctx = paco_ctx self.netenv_ctl = netenv_ctl self.netenv = netenv self.env = env self.env_region = env_region self.region = env_region.name self.network_stack_grp = None self.application_stack_grps = {} self.iam_stack_grps = {} self.stack_grps = [] self.account_ctx = paco_ctx.get_account_context( account_ref=self.env_region.network.aws_account ) self.init_done = False self.resource_yaml_filename = "{}-{}-{}.yaml".format( self.netenv.name, self.env.name, self.env_region.name, ) self.resource_yaml_path = self.paco_ctx.outputs_path / 'NetworkEnvironments' self.resource_yaml = self.resource_yaml_path / self.resource_yaml_filename self.stack_tags = StackTags() self.stack_tags.add_tag('paco.netenv.name', self.netenv.name) self.stack_tags.add_tag('paco.env.name', self.env.name)
def init_app_monitoring(self): "Application level Alarms are not specific to any Resource" if getattr(self.config, 'monitoring', None) == None: return # If health_checks exist, init them if getattr(self.config.monitoring, 'health_checks', None) != None and \ len(self.config.monitoring.health_checks.values()) > 0: for health_check in self.config.monitoring.health_checks.values(): stack_tags = StackTags(self.stack_tags) stack_tags.add_tag('Paco-Application-HealthCheck-Name', health_check.name) health_check.resolve_ref_obj = self # ToDo: enable other types when there is more than one if health_check.type == 'Route53HealthCheck': self.stack_group.add_new_stack( 'us-east-1', # Route53 Health Check only runs in us-east-1 self.config, paco.cftemplates.Route53HealthCheck, stack_tags=stack_tags, extra_context={ 'health_check': health_check, 'app_aws_region': self.aws_region, }, ) # If alarm_sets exist init their alarms stack if getattr(self.config.monitoring, 'alarm_sets', None) != None and \ len(self.config.monitoring.alarm_sets.values()) > 0: self.stack_group.add_new_stack(self.aws_region, self.config, paco.cftemplates.CWAlarms, change_protected=False, support_resource_ref_ext='alarms', stack_tags=self.stack_tags)
def init(self, command=None, model_obj=None): "Initialize controller" if self.init_done: return # inject the controller into the model self.groups.resolve_ref_obj = self stack_tags = StackTags() # there is no snstopics.yaml for this project if self.groups.account == None: self.init_done = True return self.account_ctx = self.paco_ctx.get_account_context( account_ref=self.groups.account) if self.groups.regions == ['ALL']: self.active_regions = self.paco_ctx.project.active_regions else: self.active_regions = self.groups.regions # create a SNSTopicsGroup stack group for each active region self.ng_stackgroups = {} for region in self.active_regions: config_ref = self.groups[region].paco_ref_parts stackgroup = SNSTopicsStackGroup(self.paco_ctx, self.account_ctx, region, 'SNS', self, config_ref, self.groups[region], StackTags(stack_tags)) self.ng_stackgroups[region] = stackgroup stackgroup.init() self.init_done = True
def __init__( self, account_ctx, region, resource, role_id, role, stack_group, stack_tags, template_params, ): self.account_ctx = account_ctx self.region = region self.resource = resource self.role_id = role_id self.role = role self.role_ref = role.paco_ref_parts self.stack_group = stack_group self.stack_tags = stack_tags self.template_params = template_params self.role_name = None self.role_template = None self.role_stack = None self.policy_context = {} # Create a Role stack and add it to the StackGroup role_stack_tags = StackTags(self.stack_tags) role_stack_tags.add_tag('Paco-IAM-Resource-Type', 'Role') # set the resolve_ref_obj on the model self.role.resolve_ref_obj = self # Resources such as a service might not have change_protected change_protected = getattr(self.resource, 'change_protected', False) role_ext = get_support_resource_ref_ext(self.resource, self.role) self.role_stack = self.stack_group.add_new_stack( self.region, self.resource, IAMRoles, account_ctx=self.account_ctx, stack_tags=role_stack_tags, change_protected=change_protected, extra_context={ 'template_params': self.template_params, 'role': self.role, }, support_resource_ref_ext=role_ext, ) self.role_template = self.role_stack.template role_id = self.resource.name + '-' + self.role.name self.role_name = self.role_template.gen_iam_role_name( "Role", self.role.paco_ref_parts, role_id) self.role_arn = "arn:aws:iam::{0}:role/{1}".format( self.account_ctx.get_id(), self.role_name) role_profile_name = self.role_template.gen_iam_role_name( "Profile", self.role.paco_ref_parts, role_id) self.role_profile_arn = "arn:aws:iam::{0}:instance-profile/{1}".format( self.account_ctx.get_id(), role_profile_name)
def add_managed_policy( self, resource, policy_name, policy_config_yaml, template_params=None, change_protected=False, extra_ref_names=None, ): "Adds a Managed Policy stack that is attached to this Role" # create a Policy object from YAML and add it to the model policy_dict = yaml.load(policy_config_yaml) policy_dict['roles'] = [self.role_name] # extra_ref_names adds extra parts to the Policy paco.ref # This is because the paco.ref is used to generate the a Policy hash used in the AWS # Policy name. The ref should not change otherwise the Policy names change. parent = resource for name in extra_ref_names: container = Named(name, parent) parent = container policy = paco.models.iam.ManagedPolicy(policy_name, parent) paco.models.loader.apply_attributes_from_config(policy, policy_dict) if policy.paco_ref_parts in self.policy_context.keys(): print(f"Managed policy already exists: {policy.paco_ref_parts}") raise StackException(PacoErrorCode.Unknown) # set the resolve_ref_obj to this RoleContext policy.resolve_ref_obj = self policy_context = { 'id': policy_name, 'config': policy, 'ref': policy.paco_ref_parts, 'template_params': template_params, } policy_stack_tags = StackTags(self.stack_tags) policy_stack_tags.add_tag('Paco-IAM-Resource-Type', 'ManagedPolicy') policy_ext = get_support_resource_ref_ext(resource, policy) policy_context['stack'] = self.stack_group.add_new_stack( self.region, resource, IAMManagedPolicies, stack_tags=policy_stack_tags, extra_context={ 'policy': policy, 'template_params': template_params }, support_resource_ref_ext=policy_ext) policy_context['template'] = policy_context['stack'].template self.policy_context['name'] = policy_context[ 'template'].gen_policy_name(policy.name) self.policy_context['arn'] = "arn:aws:iam::{0}:policy/{1}".format( self.account_ctx.get_id(), self.policy_context['name']) self.policy_context[policy.paco_ref_parts] = policy_context
def init(self): if self.init_done: return self.init_done = True self.paco_ctx.log_start('Init', self.env_region) # Secrets Manager self.secrets_stack_grp = SecretsManagerStackGroup( self.paco_ctx, self.account_ctx, self, self.env_region.secrets_manager, StackTags(self.stack_tags) ) self.secrets_stack_grp.init() self.stack_grps.append(self.secrets_stack_grp) # Network Stack: VPC, Subnets, Etc self.network_stack_grp = NetworkStackGroup( self.paco_ctx, self.account_ctx, self, StackTags(self.stack_tags) ) self.stack_grps.append(self.network_stack_grp) self.network_stack_grp.init() # Application Engine Stacks for app_name in self.ordered_application_names(): application_stack_grp = ApplicationStackGroup( self.paco_ctx, self.account_ctx, self, self.env_region['applications'][app_name], StackTags(self.stack_tags) ) self.application_stack_grps[app_name] = application_stack_grp self.stack_grps.append(application_stack_grp) application_stack_grp.init() # Backup if self.env_region.backup_vaults: self.backup_stack_grp = BackupVaultsStackGroup( self.paco_ctx, self.account_ctx, self, self.env_region.backup_vaults, StackTags(self.stack_tags) ) self.backup_stack_grp.init() self.stack_grps.append(self.backup_stack_grp) self.paco_ctx.log_finish('Init', self.env_region)
def __init__(self, paco_ctx, account_ctx, region, group_name, controller, resource, topics, stack_tags): aws_name = group_name super().__init__(paco_ctx, account_ctx, group_name, aws_name, controller) self.paco_ctx.log_start('Init', resource) stack = self.add_new_stack( region, resource, paco.cftemplates.SNS, stack_tags=StackTags(stack_tags), extra_context={ 'grp_id': account_ctx.name, 'topics': topics }, set_resource_stack=True, ) hook_arg = {'resource': resource, 'account_ctx': account_ctx} # Hook to create and upload imageDefinitions.json S3 source artifact stack.hooks.add(name='StoreResourceSNSState.' + resource.name, stack_action='update', stack_timing='post', hook_method=self.store_resource_sns_state, cache_method=self.store_resource_sns_state_cache, hook_arg=hook_arg) stack.hooks.add(name='StoreResourceSNSState.' + resource.name, stack_action='create', stack_timing='post', hook_method=self.store_resource_sns_state, cache_method=self.store_resource_sns_state_cache, hook_arg=hook_arg) self.paco_ctx.log_finish('Init', resource)
def init(self): # Initialize resolve_ref_obj and accounts accounts = {} for app_config in self.config.values(): for grp_config in app_config.values(): for secret in grp_config.values(): secret.resolve_ref_obj = self if secret.account != None: secret._account_ref = secret.account accounts[secret._account_ref] = True self.secret_account_lookup[ secret.paco_ref] = secret._account_ref else: secret._account_ref = self.account_ctx.paco_ref accounts[secret._account_ref] = True self.secret_account_lookup[ secret.paco_ref] = secret._account_ref for account_ref in accounts.keys(): self.secrets_stack[account_ref] = self.add_new_stack( self.region, self.config, paco.cftemplates.SecretsManager, account_ctx=self.paco_ctx.get_account_context(account_ref), stack_tags=StackTags(self.stack_tags), )
def init(self): "init" self.paco_ctx.log_start('Init', self.config) sns_topics_config = [topic for topic in self.config.values()] stack = self.add_new_stack(self.region, self.config, paco.cftemplates.SNSTopics, stack_tags=StackTags(self.stack_tags), extra_context={'grp_id': 'NG'}) self.paco_ctx.log_finish('Init', self.config)
def init(self, command=None, model_obj=None): "Initialize SNS Controller" if self.init_done: return stack_tags = StackTags() # aggregate SNS Topics grouped by account/region and apply to the computed attr default_locations = self.sns.default_locations sns_computed = self.sns.computed for snstopic in self.sns.topics.values(): if len(snstopic.locations) == 0: locations = default_locations else: locations = snstopic.locations for location in locations: account_name = location.account.split('.')[-1] if not account_name in sns_computed: sns_computed[account_name] = AccountContainer( account_name, sns_computed) sns_computed[account_name].stackgroups = [] for region in location.regions: if region not in sns_computed[account_name]: sns_computed[account_name][region] = RegionContainer( region, sns_computed[account_name]) snstopic = deepcopy_except_parent(snstopic) snstopic.__parent__ = sns_computed[account_name][region] sns_computed[account_name][region][ snstopic.name] = snstopic # create a SNSTopicsGroup stack group for each active region for account in sns_computed.keys(): account_ctx = self.paco_ctx.get_account_context( account_name=account) sns_computed[account].account_ctx = account_ctx for region in sns_computed[account].keys(): topics = sns_computed[account][region].values() stackgroup = SNSTopicsStackGroup(self.paco_ctx, account_ctx, region, 'SNS', self, sns_computed[account][region], topics, StackTags(stack_tags)) sns_computed[account].stackgroups.append(stackgroup) self.init_done = True
def init(self): self.log_init_status('Backup', '', True) role = self.create_iam_role() for backup_vault in self.config.values(): backup_vault.resolve_ref_obj = self stack = self.add_new_stack(self.region, backup_vault, paco.cftemplates.BackupVault, stack_tags=StackTags(self.stack_tags), extra_context={'role': role}) self.stack_list.append(stack)
def init(self): # Initialize resolve_ref_obj for app_config in self.config.values(): for grp_config in app_config.values(): for secret_config in grp_config.values(): secret_config.resolve_ref_obj = self self.secrets_stack = self.add_new_stack( self.region, self.config, paco.cftemplates.SecretsManager, stack_tags=StackTags(self.stack_tags), )
def create_iam_role(self, bucket_name, account_ctx, aws_region): "IAM Role for AWS Config" iam_role_id = 'AWSConfig-{}'.format(account_ctx.name) statements = [{ 'effect': "Allow", 'action': ["s3:PutObject"], 'resource': [f"arn:aws:s3:::{bucket_name}/AWSLogs/{account_ctx.id}/*"], 'condition': { "StringLike": { "s3:x-amz-acl": "bucket-owner-full-control" } } }, { 'effect': "Allow", 'action': ["s3:GetBucketAcl"], 'resource': f"arn:aws:s3:::{bucket_name}" }] role_dict = { 'enabled': True, 'path': '/', 'role_name': iam_role_id, 'assume_role_policy': { 'effect': 'Allow', 'service': ['config.amazonaws.com'] }, 'policies': [{ 'name': 'AllowS3BucketWriteAccess', 'statement': statements }], 'managed_policy_arns': ['arn:aws:iam::aws:policy/service-role/AWSConfigRole'], } role = paco.models.iam.Role(iam_role_id, self.config) role.apply_config(role_dict) iam_ctl = self.paco_ctx.get_controller('IAM') iam_ctl.add_role(region=aws_region, resource=self.config, role=role, iam_role_id=iam_role_id, stack_group=self, stack_tags=StackTags()) return role
def __init__(self, paco_ctx, account_ctx, region, group_name, controller, resource, topics, stack_tags): aws_name = group_name super().__init__(paco_ctx, account_ctx, group_name, aws_name, controller) self.paco_ctx.log_start('Init', resource) stack = self.add_new_stack( region, resource, paco.cftemplates.SNS, stack_tags=StackTags(stack_tags), extra_context={ 'grp_id': account_ctx.name, 'topics': topics }, set_resource_stack=True, ) self.paco_ctx.log_finish('Init', resource)
def __init__(self, paco_ctx, account_ctx, aws_region, app, stack_group, ref_type, stack_tags=StackTags(), env_ctx=None): self.paco_ctx = paco_ctx self.config = app self.app = app self.account_ctx = account_ctx self.aws_region = aws_region self.stack_group = stack_group self.ref_type = ref_type self.env_ctx = env_ctx self.stack_tags = stack_tags self.stack_tags.add_tag('Paco-Application-Name', self.app.name)
def create_iam_role(self): "Backup service Role" # if at least one vault is enabled, create an IAM Role # BackupVault will create one IAM Role for each NetworkEnvironment/Environment combination, # this way a netenv/env can be created, have it's own Role, then a different netenv/env with a second Role # if the first netenv/env is deleted, the second one will not be impacted. vaults_enabled = False for vault in self.config.values(): if vault.is_enabled(): vaults_enabled = True if not vaults_enabled: return None netenv = get_parent_by_interface(self.config, schemas.INetworkEnvironment) iam_role_id = 'Backup-{}-{}'.format(netenv.name, self.env_ctx.env.name) policy_arns = [ 'arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup', 'arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores' ] role_dict = { 'enabled': True, 'path': '/', 'role_name': iam_role_id, 'managed_policy_arns': policy_arns, 'assume_role_policy': { 'effect': 'Allow', 'service': ['backup.amazonaws.com'] } } role = paco.models.iam.Role(iam_role_id, self.config) role.apply_config(role_dict) iam_ctl = self.paco_ctx.get_controller('IAM') iam_ctl.add_role(region=self.env_ctx.region, resource=self.config, role=role, iam_role_id=iam_role_id, stack_group=self, stack_tags=StackTags(self.stack_tags)) return role
def init(self): """ Initializes an Application. Creates an EC2LaunchManager then iterates through the Application's ResourceGroups in order, then each Resource in that group in order, and calls an init specific to each Resource type. This will allow each Resource for an Application to do what it needs to be initialized, typically creating a CFTemplate for the Resource and adding it to the Application's StackGroup, and any supporting CFTemplates needed such as Alarms or IAM Policies. """ self.paco_ctx.log_start('Init', self.config) self.ec2_launch_manager = EC2LaunchManager( self.paco_ctx, self, self.config, self.account_ctx, self.aws_region, self.stack_group, self.stack_tags) # Resource Groups for grp_id, grp_config in self.config.groups_ordered(): for res_id, resource in grp_config.resources_ordered(): # initial resource stack_tags = StackTags(self.stack_tags) stack_tags.add_tag('Paco-Application-Group-Name', grp_id) stack_tags.add_tag('Paco-Application-Resource-Name', res_id) resource.resolve_ref_obj = self # Create a resource_engine object and initialize it resource_engine = getattr(paco.application, resource.type + 'ResourceEngine', None)( self, grp_id, res_id, resource, StackTags(stack_tags), ) #resource_engine.log_init_status() resource_engine.init_resource() resource_engine.init_monitoring() self.init_app_monitoring() self.paco_ctx.log_finish('Init', self.config)
def init(self): # Network Stack Templates # VPC Stack vpc_config = self.env_ctx.env_region.network.vpc if vpc_config == None: # NetworkEnvironment with no network - serverless return network_config = get_parent_by_interface(vpc_config, schemas.INetwork) vpc_config.resolve_ref_obj = self vpc_config.private_hosted_zone.resolve_ref_obj = self self.vpc_stack = self.add_new_stack( self.region, vpc_config, paco.cftemplates.VPC, stack_tags=StackTags(self.stack_tags), ) # Segments self.segment_list = [] self.segment_dict = {} segments = network_config.vpc.segments for segment in segments.values(): segment.resolve_ref_obj = self segment_stack = self.add_new_stack( self.region, segment, paco.cftemplates.Segment, stack_tags=StackTags(self.stack_tags), stack_orders=[StackOrder.PROVISION], extra_context={'env_ctx': self.env_ctx}, ) self.segment_dict[segment.name] = segment_stack self.segment_list.append(segment_stack) # Security Groups sg_config = network_config.vpc.security_groups self.sg_list = [] self.sg_dict = {} # EC2 NATGateway Security Groups # Creates a security group for each Availability Zone in the segment sg_nat_id = 'bastion_nat_' + utils.md5sum(str_data='gateway')[:8] for nat_config in vpc_config.nat_gateway.values(): if nat_config.is_enabled() == False: continue if nat_config.type == 'EC2': sg_nat_config_dict = {} if sg_nat_id not in sg_config.keys(): sg_config[sg_nat_id] = paco.models.networks.SecurityGroups( sg_nat_id, sg_config) for az_idx in range(1, network_config.availability_zones + 1): sg_nat_config_dict['enabled'] = True sg_nat_config_dict['ingress'] = [] for route_segment in nat_config.default_route_segments: route_segment_id = route_segment.split('.')[-1] az_cidr = getattr( vpc_config.segments[route_segment_id], f"az{az_idx}_cidr") sg_nat_config_dict['ingress'].append({ 'name': 'SubnetAZ', 'cidr_ip': az_cidr, 'protocol': '-1' }) sg_nat_config_dict['egress'] = [{ 'name': 'ANY', 'cidr_ip': '0.0.0.0/0', 'protocol': '-1' }] sg_nat_rule_id = nat_config.name + '_az' + str(az_idx) sg_config[sg_nat_id][ sg_nat_rule_id] = paco.models.networks.SecurityGroup( sg_nat_rule_id, vpc_config) paco.models.loader.apply_attributes_from_config( sg_config[sg_nat_id][sg_nat_rule_id], sg_nat_config_dict) # Declared Security Groups for sg_id in sg_config: # Set resolve_ref_obj for sg_obj_id in sg_config[sg_id]: sg_config[sg_id][sg_obj_id].resolve_ref_obj = self sg_stack = self.add_new_stack( self.region, sg_config[sg_id], paco.cftemplates.SecurityGroups, stack_tags=StackTags(self.stack_tags), extra_context={ 'env_ctx': self.env_ctx, 'template_type': 'Groups' }, ) self.sg_list.append(sg_stack) self.sg_dict[sg_id] = sg_stack # Ingress/Egress Stacks for sg_id in sg_config: self.add_new_stack(self.region, sg_config[sg_id], paco.cftemplates.SecurityGroups, stack_tags=StackTags(self.stack_tags), extra_context={ 'env_ctx': self.env_ctx, 'template_type': 'Rules' }) # Wait for Segment Stacks for segment_stack in self.segment_list: self.add_stack_order(segment_stack, [StackOrder.WAIT]) # VPC Peering Stack if vpc_config.peering != None: peering_config = self.env_ctx.env_region.network.vpc.peering for peer_id in peering_config.keys(): peer_config = vpc_config.peering[peer_id] peer_config.resolve_ref_obj = self # Add role to the target network account if peer_config.network_environment != None and peer_config.peer_type == 'accepter': netenv_ref = Reference(peer_config.network_environment + '.network') requester_netenv_config = netenv_ref.resolve( self.paco_ctx.project) requester_account_id = self.paco_ctx.get_ref( requester_netenv_config.aws_account + '.id') accepter_vpc_id = self.paco_ctx.get_ref( vpc_config.paco_ref + '.id') # Only create the role if we are cross account if self.account_ctx.id != requester_account_id: self.gen_vpc_peering_accepter_role( peer_config, vpc_config, accepter_vpc_id, requester_account_id) self.peering_stack = self.add_new_stack( self.region, vpc_config.peering, paco.cftemplates.VPCPeering, stack_tags=StackTags(self.stack_tags), ) # NAT Gateway self.nat_list = [] for nat_config in vpc_config.nat_gateway.values(): if sg_nat_id in sg_config.keys(): nat_sg_config = sg_config[sg_nat_id] else: nat_sg_config = None # We now disable the NAT Gateway in the template so that we can delete it and recreate it when disabled. nat_stack = self.add_new_stack( self.region, nat_config, paco.cftemplates.NATGateway, stack_tags=StackTags(self.stack_tags), stack_orders=[StackOrder.PROVISION], extra_context={'nat_sg_config': nat_sg_config}, ) self.nat_list.append(nat_stack) for nat_stack in self.nat_list: self.add_stack_order(nat_stack, [StackOrder.WAIT]) # VPC Endpoints vpc_endpoints_stack = self.add_new_stack( self.region, vpc_config, paco.cftemplates.VPCEndpoints, stack_tags=StackTags(self.stack_tags), stack_orders=[StackOrder.PROVISION]) self.add_stack_order(vpc_endpoints_stack, [StackOrder.WAIT])
class EnvironmentRegionContext(): "EnvironmentRegion Controller-ish" def __init__(self, paco_ctx, netenv_ctl, netenv, env, env_region): self.paco_ctx = paco_ctx self.netenv_ctl = netenv_ctl self.netenv = netenv self.env = env self.env_region = env_region self.region = env_region.name self.network_stack_grp = None self.application_stack_grps = {} self.iam_stack_grps = {} self.stack_grps = [] self.account_ctx = paco_ctx.get_account_context( account_ref=self.env_region.network.aws_account ) self.init_done = False self.resource_yaml_filename = "{}-{}-{}.yaml".format( self.netenv.name, self.env.name, self.env_region.name, ) self.resource_yaml_path = self.paco_ctx.outputs_path / 'NetworkEnvironments' self.resource_yaml = self.resource_yaml_path / self.resource_yaml_filename self.stack_tags = StackTags() self.stack_tags.add_tag('paco.netenv.name', self.netenv.name) self.stack_tags.add_tag('paco.env.name', self.env.name) @property def stack_group_filter(self): # The stack_group_filter can change so we need to get it from the network environment itself return self.netenv_ctl.stack_group_filter def init(self): if self.init_done: return self.init_done = True self.paco_ctx.log_start('Init', self.env_region) # Secrets Manager self.secrets_stack_grp = SecretsManagerStackGroup( self.paco_ctx, self.account_ctx, self, self.env_region.secrets_manager, StackTags(self.stack_tags) ) self.secrets_stack_grp.init() self.stack_grps.append(self.secrets_stack_grp) # Network Stack: VPC, Subnets, Etc self.network_stack_grp = NetworkStackGroup( self.paco_ctx, self.account_ctx, self, StackTags(self.stack_tags) ) self.stack_grps.append(self.network_stack_grp) self.network_stack_grp.init() # Application Engine Stacks for app_name in self.ordered_application_names(): application_stack_grp = ApplicationStackGroup( self.paco_ctx, self.account_ctx, self, self.env_region['applications'][app_name], StackTags(self.stack_tags) ) self.application_stack_grps[app_name] = application_stack_grp self.stack_grps.append(application_stack_grp) application_stack_grp.init() # Backup if self.env_region.backup_vaults: self.backup_stack_grp = BackupVaultsStackGroup( self.paco_ctx, self.account_ctx, self, self.env_region.backup_vaults, StackTags(self.stack_tags) ) self.backup_stack_grp.init() self.stack_grps.append(self.backup_stack_grp) self.paco_ctx.log_finish('Init', self.env_region) def get_aws_name(self): aws_name = '-'.join([self.netenv_ctl.get_aws_name(), self.env.name]) return aws_name def get_vpc_stack(self): return self.network_stack_grp.get_vpc_stack() def ordered_application_names(self): "List of application names sorted according to their order" ordered_config_list = [] ordered_id_list = [] for app_id, app_config in self.env_region['applications'].items(): new_app_config = [app_id, app_config] insert_idx = 0 for ordered_config in ordered_config_list: if app_config.order < ordered_config[1].order: ordered_config_list.insert(insert_idx, new_app_config) ordered_id_list.insert(insert_idx, app_id) break insert_idx += 1 else: ordered_config_list.append(new_app_config) ordered_id_list.append(app_id) return ordered_id_list def save_stack_output_config(self): merged_config = {} for stack_grp in self.stack_grps: for stack in stack_grp.stacks: if isinstance(stack, StackGroup): continue config_dict = stack.output_config_dict if config_dict == None: continue merged_config = utils.dict_of_dicts_merge(merged_config, config_dict) # Save merged_config to yaml file if 'netenv' in merged_config.keys(): utils.write_to_file( folder=self.resource_yaml_path, filename=self.resource_yaml_filename, data= merged_config['netenv'][self.netenv.name][self.env.name][self.env_region.name] ) def validate(self): for stack_grp in self.stack_grps: stack_grp.validate() def provision(self): self.paco_ctx.log_start('Provision', self.env_region) # provision EC2LM SSM Document first if self.env_region.has_ec2lm_resources(): ssm_ctl = self.paco_ctx.get_controller('SSM') ssm_ctl.provision(f'resource.ssm.ssm_documents.paco_ec2lm_update_instance.{self.account_ctx.name}.{self.env_region.name}') if 'paco_ecs_docker_exec' in self.paco_ctx.project['resource']['ssm'].ssm_documents: ssm_ctl.provision(f'resource.ssm.ssm_documents.paco_ecs_docker_exec.{self.account_ctx.name}.{self.env_region.name}') if len(self.stack_grps) > 0: for stack_grp in self.stack_grps: stack_grp.provision() self.save_stack_output_config() else: self.paco_ctx.log_action_col("Provision", "Nothing to provision.") self.paco_ctx.log_finish('Provision', self.env_region) def delete(self): for stack_grp in reversed(self.stack_grps): stack_grp.delete()