Пример #1
0
    def update_stack(self, service_name, cloudformation_template, changeset_id,
                     cf_stack):
        try:
            cs_response = self.cloudformation_client.create_change_set(
                StackName=cf_stack.stack_name,
                TemplateBody=cloudformation_template,
                Capabilities=["CAPABILITY_IAM"],
                ChangeSetName=changeset_id)
            cs_id = cs_response['Id']
            changes = self.cloudformation_client.describe_change_set(
                StackName=cf_stack.stack_name, ChangeSetName=cs_id)

            # delay for 2 seconds while waiting for changeset to create
            time.sleep(2)

            print(
                colored("The following stack update changes to be applied:",
                        'cyan'))
            print(
                colored(
                    "================================================================================",
                    'cyan'))
            print(colored(changes, 'yellow'))
            print(
                colored(
                    "================================================================================",
                    'cyan'))
            perform_update = query_yes_no("Perform changes?")
            if perform_update:
                self.cloudformation_client.execute_change_set(
                    ChangeSetName=changeset_id, StackName=cf_stack.stack_name)

                waiter = CloudformationWaiter(self.cloudformation)
                print(
                    colored(
                        'Cloudformation stack update in progress. Please check the AWS console!',
                        color='green'))
                print(colored('Waiting on stack update...', color='magenta'))
                waiter.waiter.wait(StackName=service_name)
                print(colored('Stack update finished!', color='green'))
            else:
                self.cloudformation_client.delete_change_set(
                    StackName=cf_stack.stack_name, ChangeSetName=cs_id)
        except ClientError as e:
            raise NovaError(str(e))
        except WaiterError as e:
            raise NovaError(str(e))
Пример #2
0
 def kms_generate_data_key(self, kms_key, context):
     try:
         return self.kms_client.generate_data_key(KeyId=kms_key,
                                                  EncryptionContext=context,
                                                  NumberOfBytes=64)
     except:
         raise NovaError("Could not generate key using KMS key %s: %s" %
                         (kms_key, str(sys.exc_info()[0])))
Пример #3
0
 def find_image(self, looking_for_tag):
     matching_images = [
         d for d in self.docker_client.images()
         if d['RepoTags'] is not None and looking_for_tag in d['RepoTags']
     ]
     if not len(matching_images) == 1:
         raise NovaError(
             "Could not find a docker image with a tag for: '%s'" %
             looking_for_tag)
     else:
         return matching_images[0]
Пример #4
0
 def kms_decrypt(self, cipher, context):
     try:
         return self.kms_client.decrypt(CiphertextBlob=cipher,
                                        EncryptionContext=context)
     except ClientError as e:
         if e.response["Error"]["Code"] == "InvalidCiphertextException":
             if context is None:
                 msg = (
                     "Could not decrypt hmac key with KMS. The credential may "
                     "require that an encryption context be provided to decrypt it."
                 )
             else:
                 msg = (
                     "Could not decrypt hmac key with KMS. The encryption "
                     "context provided may not match the one used when the "
                     "credential was stored.")
         else:
             msg = "Decryption error %s" % e
         raise NovaError(msg)
     except Exception as e:
         raise NovaError("Decryption error %s" % e)
Пример #5
0
    def __add_stack(self,
                    cft,
                    service,
                    template_bucket,
                    aws_manager,
                    include_docker=True):
        other_params = self.extra_parameters.copy()

        if 'DNS' in other_params and other_params.get(
                'HostedZoneName') is None:
            record = other_params.get('DNS')
            hostedzones = aws_manager.get_hosted_zone_names()
            hostedzone = next((z for z in hostedzones
                               if (z in record) or (z[:len(z) - 1] in record)),
                              None)
            if hostedzone is not None:
                other_params['HostedZoneName'] = hostedzone
            else:
                raise NovaError(
                    "Unable to determine 'HostedZoneName' from DNS record '%s'"
                    % record)

        other_params.update([('StackType', self.stack_type),
                             ('Port', service.port),
                             ('ApplicationName', service.name),
                             ('TeamName', service.team_name),
                             ('HealthcheckUrl', service.healthcheck_url),
                             ('LogsList',
                              self.serialize_logs_settings(service.logs))])

        if include_docker:
            other_params.update([
                ('DockerDeploymentOptions',
                 self.pickle_encode(self.deployment_options)),
                ('DockerDeploymentVariables',
                 self.pickle_encode(self.deployment_variables)),
                ('DockerDeploymentVolumes',
                 self.pickle_encode(self.deployment_volumes)),
                ('DockerDeploymentArguments',
                 self.pickle_encode(self.deployment_arguments))
            ])

        parameters = {
            'TemplateURL': self.template_url_to_use(service, template_bucket),
            'TimeoutInMinutes': 60,
            'Parameters': other_params
        }
        cft.resources.add(
            Resource(self.name.title(), 'AWS::CloudFormation::Stack',
                     parameters))
Пример #6
0
    def create_and_upload_stack_template(self, s3_bucket, service,
                                         environment):
        bucket = self.create_bucket(
            s3_bucket,
            'Common Nova service templates bucket does not exist, creating...')

        for s, template in environment.get_stack_templates_used(
                service, s3_bucket).items():
            if 's3_key' in template:
                template_file = template['filename']
                template_s3_key = template['s3_key']
            else:
                template_version = template['version']
                template_filename = '%s.json' % template['name']
                user_home_dir = os.path.join(os.path.expanduser('~'), '.nova')

                if not os.path.exists(user_home_dir):
                    raise NovaError(
                        "Unable to find NOVA templates. Please create templates under '~/.nova'."
                    )

                repo = git.Repo(user_home_dir)
                # If repo is dirty or has un-pushed commits we want to fail here
                if repo.is_dirty() or bool(
                        repo.git.rev_list("origin/master..master")):
                    raise NovaError(
                        "You have local modifications to '~/.nova'. These are shared templates! Please create a pull request!"
                    )

                template_file = os.path.join(user_home_dir, template_version,
                                             template_filename)
                template_s3_key = '%s/%s' % (template_version,
                                             template_filename)

            existing_file = None
            if bucket:
                print(
                    colored(
                        'Found common Nova service templates bucket. Verifying contents...',
                        color='cyan'))
                checksum = self.__md5(template_file)
                try:
                    existing_file = self.s3_client.head_object(
                        Bucket=s3_bucket,
                        Key=template_s3_key,
                        IfMatch=checksum)
                except ClientError:
                    pass

            if not existing_file:
                print(
                    colored(
                        'Common Nova service templates not found. Uploading...',
                        color='cyan'))
                with open(template_file, 'rb') as template_data:
                    self.s3_client.put_object(Bucket=s3_bucket,
                                              Key=template_s3_key,
                                              Body=template_data)
                print(colored('Contents uploaded!', color='green'))
            else:
                print(colored('Contents verified!', color='green'))

        print(
            colored('All required templates have been uploaded & verified!',
                    color='green'))