def execute(self): Oprint.info('Start tear down service', 'lmdo') self._dispatcher.run(DeleteCommand(self._apigateway)) self._dispatcher.run(DeleteCommand(self._lambda)) self._dispatcher.run(DeleteCommand(self._cloudformation)) self._dispatcher.run(DeleteCommand(self._cloudwatchevent)) Oprint.info('Service has been destroy', 'lmdo')
def execute(self): Oprint.info('Start deploying service', 'lmdo') self._dispatcher.run(CreateCommand(self._cloudformation)) self._dispatcher.run(CreateCommand(self._lambda)) self._dispatcher.run(CreateCommand(self._apigateway)) self._dispatcher.run(CreateCommand(self._cloudwatchevent)) Oprint.info('Complete deploying service', 'lmdo')
def add_permission(self, func_name, principal, principal_id, action='lambda:InvokeFunction'): """Add permission to Lambda function""" try: response = self._client.add_permission( FunctionName=self.get_lmdo_format_name(func_name), StatementId=self.get_statement_id(func_name, principal_id), Action=action, Principal=principal) Oprint.info( 'Permission {} has been added for {} with principal {}'.format( action, self.get_lmdo_format_name(func_name), principal), 'lambda') except Exception as e: Oprint.err(e, 'lambda') if response.get('Statement') is None: Oprint.err( 'Create lambda permission {} for {}'.format(action, principal), 'lambda') return response
def upsert_targets(self, rule_name, targets=None): """ Add target to a rule Targets can be a single ARN or a list of ARNs """ try: if not self.delete_rule_targets(rule_name=rule_name): Oprint.err( 'Cannot delete rule {} due to deleting its targets failed'. format(rule_name), self.NAME) response = self._client.put_targets( Rule=rule_name, Targets=self.format_targets(targets)) if response['FailedEntryCount'] > 0: Oprint.err( 'Failed to update targets for rule {}'.format(rule_name), self.NAME) else: Oprint.info('Targets created for rule {}'.format(rule_name), self.NAME) self.add_lambda_permission_to_targets(targets) except Exception as e: Oprint.err(e, self.NAME) return True
def create_wsgi_api(self): """Create/Update api definition for wsgi app""" swagger_api = False # If there is already an exsiting swagger api template, # fetch it so we won't duplicate it #if os.path.isfile(self.get_swagger_template()) and self.get_apigateway_name(): swagger_api = self.if_api_exist_by_name(self.get_apigateway_name()) iam = IAM() for lm_func in self._config.get('Lambda'): if lm_func.get('Type') != AWSLambda.FUNCTION_TYPE_WSGI or lm_func.get('DisableApiGateway'): continue function_name = self.get_lmdo_format_name(lm_func.get('FunctionName')) role = iam.get_lambda_apigateway_default_role(function_name) Oprint.info('Create/Update API Gateway for wsgi function {}'.format(lm_func.get('FunctionName')), 'apigateway') to_replace = { "$title": self.get_apigateway_name(), "$version": str(datetime.datetime.utcnow()), "$basePath": lm_func.get('ApiBasePath') or '/res', "$apiRegion": self.get_region(), "$functionRegion": self.get_region(), "$accountId": self.get_account_id(), "$functionName": function_name, "$credentials": role['Role'].get('Arn') } # Enable cognito user pool as authorizer if lm_func.get('CognitoUserPoolId'): se_replace = { "$apiRegion": self.get_region(), "$accountId": self.get_account_id(), "$userPoolId": lm_func.get('CognitoUserPoolId'), "$CognitoUserPool": 'CognitoUserPool-{}'.format(lm_func.get('FunctionName')) } to_replace["$securityDefinitions"] = self.get_apigateway_authorizer(se_replace) to_replace["$authorizer"] = '{"' + str(se_replace['$CognitoUserPool'])+'":[]}' else: to_replace["$securityDefinitions"] = '' to_replace["$authorizer"] = '' template_dir = get_template(APIGATEWAY_SWAGGER_WSGI) if not template_dir: Oprint.err('Template {} for creating wsgi APIGateway hasn\'t been installed or missing'.format(APIGATEWAY_SWAGGER_WSGI), 'apigateway') with open(template_dir, 'r') as outfile: body = update_template(outfile.read(), to_replace) if not swagger_api: swagger_api = self.import_rest_api(body) else: # Always overwrite for update self.put_rest_api(swagger_api.get('id'), body, 'merge') return swagger_api
def upload_file(self, bucket_name, file_path, key, **kwargs): """Upload file to S3, provide network progress bar""" # Check if bucket exist, create one if user agrees if not self.if_bucket_exist(bucket_name): sys_pause( 'Bucket {} doesn\'t exist! Do you want to create it? [yes/no]'. format(bucket_name), 'yes') self.create_bucket(bucket_name) file_size = os.path.getsize(file_path) / 1000000 if round(file_size) <= 0: file_size = 'size:{}B'.format(os.path.getsize(file_path)) else: file_size = 'size:{}MB'.format(file_size) Oprint.info( 'Start uploading {} to S3 bucket {}. ({})'.format( key, bucket_name, file_size), 's3') #waiter = S3WaiterObjectCreate(self._client) self._client.upload_file(file_path, bucket_name, key, Callback=FileUploadProgress(file_path), **kwargs) #waiter.wait(bucket_name, key) Oprint.info('Complete uploading {}. ({})'.format(key, file_size), 's3') return True
def create(self): """Create/Update stack""" # Don't run if we don't have templates if not self._config.get('CloudFormation'): Oprint.info('No cloudformation found, skip', self.NAME) return True self.process()
def wait(self, stack_name): try: Oprint.info('Start deleting stack {}'.format(stack_name), self._client_type) spinner.start() self._stack_delete.wait(StackName=stack_name) spinner.stop() Oprint.info('Stack {} delete completed'.format(stack_name), self._client_type) except Exception as e: spinner.stop()
def wait(self, change_set_name, stack_name): try: Oprint.info('Start creating change set {} for stack {}'.format(change_set_name, stack_name), self._client_type) spinner.start() self._change_set_create.wait(StackName=stack_name, ChangeSetName=change_set_name) spinner.stop() Oprint.info('Change set {} creation completed'.format(change_set_name), self._client_type) except Exception as e: spinner.stop()
def delete_domain_name(self, domain_name): """delete custom domain""" try: Oprint.info('Deleting custom domain {}'.format(domain_name), 'apigateway') response = self._client.delete_domain_name(domainName=domain_name) Oprint.info('Complete deleting custom domain {}'.format(domain_name), 'apigateway') except Exception as e: Oprint.err(e, 'apigateway') return True
def delete_api_stage(self, api_id, stage_name, api_name=None): """delete a stage""" try: Oprint.info('Deleting stage: {} deployment for API {}'.format(stage_name, api_name or self.get_apigateway_name()), 'apigateway') response = self._client.delete_stage(restApiId=api_id, stageName=stage_name) Oprint.info('Complete deleting stage: {} deployment for API {}'.format(stage_name, api_name or self.get_apigateway_name()), 'apigateway') except Exception as e: Oprint.err(e, 'apigateway') return True
def create_api_stage(self, api_id, stage_name, deployment_id, api_name=None, **kwargs): """Create a stage""" try: Oprint.info('Creating stage: {} for API {}'.format(stage_name, api_name or self.get_apigateway_name()), 'apigateway') response = self._client.create_stage(restApiId=api_id, stageName=stage_name, deploymentId=deployment_id, **kwargs) Oprint.info('Complete creating stage: {} for API {}'.format(stage_name, api_name or self.get_apigateway_name()), 'apigateway') except Exception as e: Oprint.err(e, 'apigateway') return response
def put_rest_api(self, api_id, body, mode='merge', api_name=None): """Update rest api via Swagger""" try: Oprint.info('Start updating rest api definition via Swagger file for API {}'.format(api_name or self.get_apigateway_name()), 'apigateway') response = self._client.put_rest_api(restApiId=api_id, mode=mode, body=body) Oprint.info('Finish updating rest api', 'apigateway') except Exception as e: Oprint.err(e, 'apigateway') return response
def create(self): """Create""" if not self.get_apigateway_name(): Oprint.info('No action for api gateway, skip...', 'apigateway') sys.exit(0) swagger_api = self.create_api_by_swagger() swagger_api = self.create_wsgi_api() if swagger_api: self.create_deployment(swagger_api.get('id'), self._config.get('Stage'), swagger_api.get('name'))
def create_deployment(self, api_id, stage_name='dev', api_name=None, **kwargs): """Create a stage deployment to internet""" try: Oprint.info('Deploying {} stage: {} to internet'.format(api_name or self.get_apigateway_name(), stage_name), 'apigateway') response = self._client.create_deployment(restApiId=api_id, stageName=stage_name, **kwargs) Oprint.info('Complete deploying {} stage: {}'.format(api_name or self.get_apigateway_name(), stage_name), 'apigateway') except Exception as e: Oprint.err(e, 'apigateway') return response
def subscribe(self, topic, protocol, endpoint): """Subscription""" topic_arn = self.get_sns_topic_arn(topic) self._client.subscribe(TopicArn=topic_arn, Protocol=protocol, Endpoint=endpoint) Oprint.info( 'Endpoint {} has subscribed to SNS topic {}'.format( endpoint, topic), self.NAME) return True
def delete_deployment(self, api_id, deployment_id, api_name=None): """Delete a deployments of an API""" try: Oprint.info('Deleting stage: {} for API {}'.format(stage_name, api_name or self.get_apigateway_name()), 'apigateway') response = self._client.delete_deployment(restApiId=api_id, deploymentId=deployment_id) Oprint.info('Complete deleting stage: {} for API {}'.format(stage_name, api_name or self.get_apigateway_name()), 'apigateway') except Exception as e: Oprint.err(e, 'apigateway') return response
def import_rest_api(self, body, api_name=None): """Import rest api via Swagger""" try: Oprint.info('Start creating rest api definition via Swagger file for API {}'.format(api_name or self.get_apigateway_name()), 'apigateway') response = self._client.import_rest_api(body=body) Oprint.info('Finish creating rest api', 'apigateway') except Exception as e: Oprint.err(e, 'apigateway') return response
def create_role(self, role_name, policy): """Create an IAM role""" try: Oprint.info('Creating role {}'.format(role_name), 'iam') response = self._client.create_role( RoleName=role_name, AssumeRolePolicyDocument=policy) Oprint.info('Complete creating role {}'.format(role_name), 'iam') except Exception as e: Oprint.err(str(e.response['Error']['Message']), 'iam') return response
def upsert_rule(self, **kwargs): """Create or update rule""" try: name = kwargs.get('Name') Oprint.info('Creating Cloudwatch Event rule {}'.format(name), self.NAME) response = self._client.put_rule(**kwargs) except Exception as e: Oprint.err(e, self.NAME) return response['RuleArn']
def wait(self, bucket_name): try: Oprint.info('Bucket {} delete starts'.format(bucket_name), self._client_type) spinner.start() self._bucket_not_exist.wait(Bucket=bucket_name) spinner.stop() Oprint.info('Bucket {} delete completed'.format(bucket_name), self._client_type) except Exception as e: spinner.stop()
def delete_rule(self, name): """Delete a cloudwatch event rule""" try: self.delete_rule_targets(rule_name=name) response = self._client.delete_rule(Name=name) Oprint.info( 'CloudWatchEvent rule {} has been deleted'.format(name), self.NAME) except Exception as e: Oprint.err(e, self.NAME) return True
def update_function_code(self, func_name, bucket_name, s3_key): """Update lambda code""" try: response = self._client.update_function_code( FunctionName=func_name, S3Bucket=bucket_name, S3Key=s3_key) Oprint.info( 'Lambda function {} codes has been updated'.format(func_name), 'lambda') except Exception as e: Oprint.err(e, 'lambda') return response
def wait(self, bucket_name, key, **kwargs): try: Oprint.info( 'Object {} creation in bucket {} starts'.format( key, bucket_name), self._client_type) #spinner.start() self._object_exist.wait(Bucket=bucket_name, key=key, **kwargs) #spinner.stop() Oprint.info('Object {} creation completed'.format(key), self._client_type) except Exception as e: spinner.stop()
def remove_permission(self, func_name, principal_id): """Remove permission from Lambda function""" try: response = self._client.remove_permission( FunctionName=func_name, StatementId=self.get_statement_id(func_name, principal_id)) Oprint.info( 'Permission has been removed for {}'.format( self.get_lmdo_format_name(func_name)), 'lambda') except Exception as e: Oprint.err(e, 'lambda') return response
def delete_role(self, role_name): """Delete an IAM role""" try: # In case role doesn't exist response = False Oprint.info('Deleting role {}'.format(role_name), 'iam') response = self._client.delete_role(RoleName=role_name) Oprint.info('Complete deleting role {}'.format(role_name), 'iam') except Exception as e: Oprint.err(str(e.response['Error']['Message']), 'iam', exit=False) return response
def process(self): """Process cloudwatch events""" if not self._config.get('CloudWatchEvent'): Oprint.info('No CloudWatch Events to process', self.NAME) return True rules = self.get_deployment_data(self._config.get('CloudWatchEvent')) for rule in rules: targets = rule.pop('Targets') self.upsert_rule(**rule) self.upsert_targets(rule_name=rule['Name'], targets=targets) return True
def delete(self): if not self._config.get('CloudWatchEvent'): Oprint.info('No CloudWatch Events to process', self.NAME) return True rules = self.get_deployment_data(self._config.get('CloudWatchEvent')) for rule in rules: self.delete_rule(name=rule['Name']) self.delete_default_role() return True
def delete_base_path_mapping(self, domain_name, base_path): """Delete API mapping to customer domain""" try: Oprint.info('Deleting path {} mapping to {}'.format(base_path, domain_name), 'apigateway') response = self._client.delete_base_path_mapping( domainName=domain_name, basePath=base_path, ) Oprint.info('Complete deleting path {} mapping to {}'.format(base_path, domain_name), 'apigateway') except Exception as e: Oprint.err(e, 'apigateway') return response
def process(self, package_only=False): """Prepare function before creation/update""" config_data = self.convert_config() # Dont run if doesn't exist if not config_data: Oprint.info('No Lambda function configured, skip...', 'lambda') return True # Create all functions for lm in config_data: self.function_update_or_create(lm, package_only) return True