def _update_product_constraint()

in control-tower-account-factory/src/common.py [0:0]


    def _update_product_constraint(self, product_id, porfolio_name, regions, destination_account):
        """Delete Launch contraint, if exists. Add/update StackSet contraint for product"""

        # get porfolio id
        porfolio_id = self.__get_product_portfolio(product_id, porfolio_name)

        if not porfolio_id:
            self._log_error(f'Portfolio id for product {product_id} could not be determined. Product deployment skipped')
            self._send_notification('Portfolio issue', f'Portfolio id for product {product_id} could not be determined. Product deployment skipped')
            return False

        try:
            # get list of constraints associate with product
            constraint_list = self.sc_client.list_constraints_for_portfolio(
                PortfolioId=porfolio_id,
                ProductId=product_id
            )

            stack_set_constraint_id = None

            # iterate through constraints
            for constraint in  constraint_list['ConstraintDetails']:
                # if product has Launch constraint, it has to be deleted as
                # Service Catalog does not allow both Launch and StackSet contraints
                # attach to product
                if constraint['Type'] == 'LAUNCH':
                    self._log_info(f'Deleting LAUNCH contraint id: {constraint["ConstraintId"]}')
                    self.sc_client.delete_constraint(Id=constraint['ConstraintId'])
                elif constraint['Type'] == 'STACKSET':
                    stack_set_constraint_id = constraint['ConstraintId']
            # if no StackSet constraint create one
            if not stack_set_constraint_id:
                admin_role = f'arn:aws:iam::{self.master_account}:role/service-role/AWSControlTowerStackSetRole'
                constraint_config = {"Version": "2.0", "Properties": {"AccountList": [destination_account], "RegionList": regions, "AdminRole": admin_role, "ExecutionRole": "AWSControlTowerExecution"}}

                self.sc_client.create_constraint(
                    PortfolioId=porfolio_id,
                    ProductId=product_id,
                    Parameters=json.dumps(constraint_config),
                    Type='STACKSET',
                    Description='Control-Tower-Account-Baseline',
                    IdempotencyToken=f'ct-baseline-constraint-{datetime.utcnow().strftime("%Y%m%d%H%M%S%f")}'
                )
            # if product has StackSet constraint add the new account and region, if needed
            else:
                constraint_info = self.sc_client.describe_constraint(
                    Id=stack_set_constraint_id
                )

                constraint_config = json.loads(constraint_info['ConstraintParameters'])

                if destination_account not in constraint_config['Properties']['AccountList']:
                    (constraint_config['Properties']['AccountList']).append(destination_account)

                for region in regions:
                    if region not in constraint_config['Properties']['RegionList']:
                        (constraint_config['Properties']['RegionList']).append(region)

                self.sc_client.update_constraint(
                    Id=stack_set_constraint_id,
                    Parameters=json.dumps(constraint_config)
                )

            return True
        except ClientError as error:
            self._log_error(f'Error adding account to contraint: Error: {error.response["Error"]}')
            self._send_notification('Error adding account to contraint', f'Error: {error.response["Error"]}')
            return False