示例#1
0
    def the_lot(self, skip_zip, skip_build, skip_upload):

        if skip_build:
            print(warn('Skipping building of lambdas'))
        else:
            self.do_work('build', self.build_one)

        if skip_zip:
            print(warn('Skipping zipping of lambdas'))
        else:
            self.do_work('zip', self.zip_one)

        if skip_upload:
            print(warn('Skipping uploading of lambdas'))
            print('using latest versions of zips currently in S3')
            lambdas = self.list_local_lambdas()
            with Pool(3) as p:
                versions_raw = p.map(self.latest_version, lambdas)
            versions = [{
                'name': lam,
                'S3Version': v
            } for (lam, v) in zip(lambdas, versions_raw)]
        else:

            # check code bucket exists

            client = boto3.client('s3')
            response = client.list_buckets()
            buckets = [b['Name'] for b in response['Buckets']]
            if self.code_bucket not in buckets:
                print('Bucket %s does not exist, creating it now' %
                      self.code_bucket)
                response = client.create_bucket(ACL='private',
                                                Bucket=self.code_bucket,
                                                CreateBucketConfiguration={
                                                    'LocationConstraint':
                                                    self.region
                                                })

                print('Created bucket %s' % self.code_bucket)

                response = client.put_bucket_versioning(
                    Bucket=self.code_bucket,
                    VersioningConfiguration={
                        'MFADelete': 'Disabled',
                        'Status': 'Enabled'
                    })

                print('Versioning turned on for bucket %s' % self.code_bucket)

            # list of {'name':x,'return_val':s3version}
            results = self.do_work('upload', self.upload_one)
            versions = [{
                'name': x['name'],
                'S3Version': x['return_val']
            } for x in results]

        assert (not any([x['S3Version'] == None for x in versions]))
        self.versions = versions
示例#2
0
 def test_lambdas(self, skip_test, stack_name):
     if skip_test:
         print(warn('Skipping testing of lambdas'))
     else:
         self.stack_name = stack_name
         self.do_work('test', self.test_one)
示例#3
0
    def deploy(self, lambda_versions):

        assert (not any([x['S3Version'] == None for x in lambda_versions]))
        self.lambda_versions = lambda_versions

        client = boto3.client('cloudformation')

        stack_name_short = 'stack'
        fname = os.path.join('data', 'cloudformation',
                             '%s.yaml' % stack_name_short)

        if not os.path.isfile(fname):
            print(error('Error: I expect a yaml template at %s' % fname))

        self.stack_name = self.project_name + '-' + self.stage
        print('About to deploy file %s as stack %s' % (fname, self.stack_name))

        client = boto3.client('cloudformation')

        print('Checking template file %s' % fname)
        with open(fname, "rb") as f:
            response = client.validate_template(
                TemplateBody=f.read().decode("utf-8"))

        print(good('Template %s is valid' % fname))

        params = [{
            'ParameterKey': 'prjName',
            'ParameterValue': self.project_name
        }, {
            'ParameterKey': 'codebucket',
            'ParameterValue': self.code_bucket
        }, {
            'ParameterKey': 'stage',
            'ParameterValue': self.stage
        }]

        # versions of S3 zips
        version_params = [{'ParameterKey':'%sS3Version' % v['name'], \
                           'ParameterValue':v['S3Version'] \
                          } \
                          for v in self.lambda_versions]
        assert (not any([x['ParameterValue'] == None for x in version_params]))
        params.extend(version_params)
        if any([x['ParameterValue'] == None for x in params]):
            print(error('Error: some parameters are None'))
            pp.pprint([
                x['ParameterKey'] for x in params
                if x['ParameterValue'] == None
            ])
            exit(1)

        if self.stack_exists(self.stack_name):
            # update stack
            print('Stack %s already exists. Updating it' % self.stack_name)

            change_set_name = 'update-%d' % int(time.time())
            with open(fname, "rb") as f:
                print('Creating change set for %s' % self.stack_name)
                response = client.create_change_set(
                    StackName=self.stack_name,
                    TemplateBody=f.read().decode("utf-8"),
                    Parameters=params,
                    Capabilities=['CAPABILITY_NAMED_IAM'],
                    ChangeSetName=change_set_name,
                    Description='Update of %s' % fname,
                    ChangeSetType='UPDATE')

                try:
                    waiter = client.get_waiter('change_set_create_complete')
                    waiter.wait(StackName=self.stack_name,
                                ChangeSetName=change_set_name,
                                WaiterConfig={
                                    'Delay': 10,
                                    'MaxAttempts': 100
                                })
                except Exception as e:
                    response = client.describe_change_set(
                        ChangeSetName=change_set_name,
                        StackName=self.stack_name)
                    pp.pprint(response)
                    expected = 'The submitted information didn\'t contain changes.'
                    if (response['Status']
                            == 'FAILED') and (expected
                                              in response['StatusReason']):
                        print('No changes to make to stack %s' %
                              self.stack_name)
                        response = client.delete_change_set(
                            ChangeSetName=change_set_name,
                            StackName=self.stack_name)
                        return ()
                    pp.pprint(e)
                    print(
                        err('Could not create change set %s for stack %s' %
                            (change_set_name, self.stack_name)))
                    raise (e)

                print(
                    good('change set created sucessfully for %s' %
                         self.stack_name))

                print('Applying change set to stack %s' % self.stack_name)
                response = client.execute_change_set(
                    ChangeSetName=change_set_name,
                    StackName=self.stack_name,
                )

                waiter = client.get_waiter('stack_update_complete')
                waiter.wait(StackName=self.stack_name,
                            WaiterConfig={
                                'Delay': 10,
                                'MaxAttempts': 100
                            })

                print(good('Stack %s updated sucessfully' % self.stack_name))

        else:
            print('Stack %s does not exist. Creating it' % self.stack_name)
            # create stack
            with open(fname, "rb") as f:
                response = client.create_stack(
                    StackName=self.stack_name,
                    TemplateBody=f.read().decode("utf-8"),
                    Parameters=params,
                    Capabilities=['CAPABILITY_NAMED_IAM'])

            stack_id = response['StackId']

            waiter = client.get_waiter('stack_create_complete')
            waiter.wait(StackName=self.stack_name,
                        WaiterConfig={
                            'Delay': 10,
                            'MaxAttempts': 20
                        })

            response = client.describe_stacks(StackName=self.stack_name)
            assert (len(response['Stacks']) == 1)
            assert (response['Stacks'][0]['StackName'] == self.stack_name)

            status = response['Stacks'][0]['StackStatus']

            if status in ['CREATE_COMPLETE']:
                print(good('Stack %s sucessfully created' % self.stack_name))
            else:
                print(error('Failed to create stack %s'))
                print(warn('status %s' % status))
                print(
                    'Check cloudformation in the browser to see what went wrong'
                )
                # TODO: add option to delete stack
                exit(1)