Пример #1
0
 def _upload_templates(self):
     """Upload all templates to artifacts bucket."""
     self._upload_single_template("Inputs", self._templates.inputs)
     self._upload_single_template("Iam", self._templates.iam)
     self._upload_single_template("Pipeline", self._templates.pipeline)
     for name, stage in self._templates.codebuild.items():
         self._upload_single_template(VALUE_SEPARATOR.join(("CodeBuild", "Stage", name)), stage)
Пример #2
0
def _wait_condition(
    type_name: str, base_name: str
) -> (cloudformation.WaitCondition, cloudformation.WaitConditionHandle):
    """Construct a wait condition and handle.

    :param type_name:
    :param base_name:
    :return:
    """
    handle = cloudformation.WaitConditionHandle(
        VALUE_SEPARATOR.join(("Upload", type_name, base_name)))
    condition = cloudformation.WaitCondition(VALUE_SEPARATOR.join(
        ("WaitFor", handle.title)),
                                             Handle=handle.ref(),
                                             Count=1,
                                             Timeout=3600)
    return condition, handle
Пример #3
0
def reference_name(name: str, value_type: str) -> str:
    """Build the reference name for a resource. Used in stack outputs and parameters.

    :param name: Resource name
    :param value_type: Value type
    :return: Specific reference name
    """
    return VALUE_SEPARATOR.join((name, value_type))
Пример #4
0
def resource_name(resource_type: AWSObject, name: str) -> str:
    """Build the resource logical name for use in stacks.

    :param resource_type: Resource type
    :param name: Naive logical name
    :return: Specific logical name
    """
    type_name = resource_type.resource_type.split("::")[-1]
    return VALUE_SEPARATOR.join((type_name, name))
Пример #5
0
    def _upload_single_template(self, template_type: str, template: Template):
        """Upload one template to the artifacts bucket.

        :param template_type: Template type name
        :param template: Template to upload
        """
        bucket_name = self._cache.physical_resource_name(self._artifacts_bucket_logical_name())
        _LOGGER.debug('Uploading %s template to bucket "%s"', template_type, bucket_name)
        key = f"templates/{uuid.uuid4()}"
        body = template.to_json()
        self._s3.put_object(Bucket=bucket_name, Key=key, Body=body)
        self._template_urls[VALUE_SEPARATOR.join(("Upload", "Template", template_type))] = key
Пример #6
0
def build(project: Config, inputs_template: Template, iam_template: Template,
          pipeline_templates: Pipeline) -> Template:
    """Construct a core stack template for a stand-alone deployment.

    :param project: PipeFormer config
    :param inputs_template: Inputs stack template
    :param iam_template: IAM stack template
    :param pipeline_templates: CodePipeline templates
    :return: Core stack template
    """
    default_tags = project_tags(project)

    core = Template(
        Description=
        f"Core resources for pipeformer-managed project: {project.name}")

    # Project CMK
    cmk = core.add_resource(_project_key(project))

    # Artifacts Bucket
    artifacts_bucket = core.add_resource(
        _bucket(name="Artifacts",
                cmk_arn=cmk.get_att("Arn"),
                tags=default_tags))
    # Project Bucket
    project_bucket = core.add_resource(
        _bucket(name="ProjectResources",
                cmk_arn=cmk.get_att("Arn"),
                tags=default_tags))

    # Inputs Stack
    inputs_stack = _wait_condition_stack(
        base_name="Inputs",
        parameters={reference_name(cmk.title, "Arn"): cmk.get_att("Arn")},
        artifacts_bucket=artifacts_bucket,
        tags=default_tags,
    )
    core.add_resource(inputs_stack.condition)
    core.add_resource(inputs_stack.handle)
    core.add_resource(inputs_stack.stack)

    # IAM Stack
    iam_stack = _wait_condition_stack(
        base_name="Iam",
        parameters={
            reference_name(artifacts_bucket.title, "Arn"):
            artifacts_bucket.get_att("Arn"),
            reference_name(project_bucket.title, "Arn"):
            project_bucket.get_att("Arn"),
            reference_name(cmk.title, "Arn"):
            cmk.get_att("Arn"),
        },
        artifacts_bucket=artifacts_bucket,
        tags=default_tags,
    )
    core.add_resource(iam_stack.condition)
    core.add_resource(iam_stack.handle)
    core.add_resource(iam_stack.stack)

    # Pipeline Stack and Prerequisites
    pipeline_parameters = {
        # Buckets
        reference_name(artifacts_bucket.title, "Name"):
        artifacts_bucket.ref(),
        reference_name(project_bucket.title, "Name"):
        project_bucket.ref(),
    }

    pipeline_depends_on = []

    # Pass on Inputs and Roles
    for nested_template, nested_stack in ((inputs_template, inputs_stack),
                                          (iam_template, iam_stack)):
        pipeline_depends_on.append(nested_stack.stack.title)
        for name in nested_template.outputs.keys():
            pipeline_parameters[name] = GetAtt(nested_stack.stack.title,
                                               f"Outputs.{name}")

    # Add waiters for each pipeline stage resource stack template
    for name in pipeline_templates.stage_templates:
        stage_name = VALUE_SEPARATOR.join(("CodeBuild", "Stage", name))
        condition, handle = _wait_condition("Template", stage_name)

        core.add_resource(condition)
        core.add_resource(handle)

        pipeline_depends_on.append(condition.title)
        pipeline_parameters[reference_name(
            VALUE_SEPARATOR.join(("Template", stage_name)),
            "Url")] = _wait_condition_data_to_s3_url(condition,
                                                     artifacts_bucket)

    input_condition, input_handle = _wait_condition("Input", "Values")
    pipeline_depends_on.append(input_condition.title)
    core.add_resource(input_condition)
    core.add_resource(input_handle)

    pipeline_stack = _wait_condition_stack(
        base_name="Pipeline",
        parameters=pipeline_parameters,
        artifacts_bucket=artifacts_bucket,
        tags=default_tags,
        depends_on=pipeline_depends_on,
    )
    core.add_resource(pipeline_stack.condition)
    core.add_resource(pipeline_stack.handle)
    core.add_resource(pipeline_stack.stack)

    return core
Пример #7
0
 def _report_input_values_saved(self):
     """Report that the input values have all been saved."""
     self._succeed_wait_condition(VALUE_SEPARATOR.join(("Upload", "Input", "Values")), "Inputs saved", "complete")
Пример #8
0
 def _wait_for_inputs_stack(self):
     """Wait until the inputs stack is created."""
     self._cache.wait_until_resource_is_complete(VALUE_SEPARATOR.join(("WaitFor", "Upload", "Template", "Inputs")))
     self._cache.wait_until_resource_is_complete(self._inputs_stack_logical_name())