in servicecatalog_factory/template_builder/builders.py [0:0]
def build(self, name, version, source, options, stages):
all_regions = config.get_regions()
factory_version = constants.VERSION
template_description = f'{{"version": "{factory_version}", "framework": "servicecatalog-factory", "role": "product-pipeline", "type": "cloudformation", "category": "stack"}}'
tpl = t.Template(Description=template_description)
build_input_artifact_name = base_template.SOURCE_OUTPUT_ARTIFACT
test_input_artifact_name = base_template.SOURCE_OUTPUT_ARTIFACT
package_input_artifact_name = base_template.SOURCE_OUTPUT_ARTIFACT
if options.get("ShouldParseAsJinja2Template"):
build_input_artifact_name = base_template.PARSE_OUTPUT_ARTIFACT
test_input_artifact_name = base_template.PARSE_OUTPUT_ARTIFACT
package_input_artifact_name = base_template.PARSE_OUTPUT_ARTIFACT
if stages.get("Build", {}).get("BuildSpec"):
test_input_artifact_name = base_template.BUILD_OUTPUT_ARTIFACT
package_input_artifact_name = base_template.BUILD_OUTPUT_ARTIFACT
deploy_input_artifact_name = "Package"
pipeline_stages = []
self.build_source_stage(tpl, pipeline_stages, source)
if options.get("ShouldParseAsJinja2Template"):
pipeline_stages.append(
codepipeline.Stages(
Name="Parse",
Actions=[
codepipeline.Actions(
RunOrder=1,
RoleArn=t.Sub(
"arn:${AWS::Partition}:iam::${AWS::AccountId}:role/servicecatalog-product-factory/SourceRole"
),
InputArtifacts=[
codepipeline.InputArtifacts(
Name=base_template.SOURCE_OUTPUT_ARTIFACT
),
],
ActionTypeId=codepipeline.ActionTypeId(
Category="Build",
Owner="AWS",
Version="1",
Provider="CodeBuild",
),
OutputArtifacts=[
codepipeline.OutputArtifacts(
Name=base_template.PARSE_OUTPUT_ARTIFACT
)
],
Configuration={
"ProjectName": shared_resources.JINJA_PROJECT_NAME,
"PrimarySource": base_template.SOURCE_OUTPUT_ARTIFACT,
"EnvironmentVariables": t.Sub(
json.dumps(
[
dict(
name="TEMPLATE_FORMAT",
value="yaml",
type="PLAINTEXT",
),
dict(
name="CATEGORY",
value="stack",
type="PLAINTEXT",
),
dict(
name="SOURCE_PATH",
value=source.get("Path", "."),
type="PLAINTEXT",
),
]
)
),
},
Name="Source",
)
],
)
)
if stages.get("Build", {}).get("BuildSpec"):
tpl.add_resource(
codebuild.Project(
"BuildProject",
Name=t.Sub("${AWS::StackName}-BuildProject"),
ServiceRole=t.Sub(
"arn:${AWS::Partition}:iam::${AWS::AccountId}:role/servicecatalog-product-factory/DeliveryCodeRole"
),
Tags=t.Tags.from_dict(
**{"ServiceCatalogPuppet:Actor": "Framework"}
),
Artifacts=codebuild.Artifacts(Type="CODEPIPELINE"),
TimeoutInMinutes=60,
Environment=codebuild.Environment(
ComputeType=constants.ENVIRONMENT_COMPUTE_TYPE_DEFAULT,
Image=stages.get("Build", {}).get(
"BuildSpecImage", constants.ENVIRONMENT_IMAGE_DEFAULT
),
Type=constants.ENVIRONMENT_TYPE_DEFAULT,
PrivilegedMode=stages.get("Build", {}).get(
"PrivilegedMode",
constants.GENERIC_BUILD_PROJECT_PRIVILEGED_MODE_DEFAULT,
),
EnvironmentVariables=[
codebuild.EnvironmentVariable(
Name="TEMPLATE_FORMAT", Type="PLAINTEXT", Value="yaml",
),
codebuild.EnvironmentVariable(
Name="CATEGORY", Type="PLAINTEXT", Value="stack",
),
codebuild.EnvironmentVariable(
Name="SOURCE_PATH", Type="PLAINTEXT", Value=".",
),
],
),
Source=codebuild.Source(
BuildSpec=stages.get("Build", {}).get("BuildSpec"),
Type="CODEPIPELINE",
),
Description=t.Sub("build project"),
)
)
pipeline_stages.append(
codepipeline.Stages(
Name="Build",
Actions=[
codepipeline.Actions(
Name="Build",
RunOrder=1,
RoleArn=t.Sub(
"arn:${AWS::Partition}:iam::${AWS::AccountId}:role/servicecatalog-product-factory/SourceRole"
),
InputArtifacts=[
codepipeline.InputArtifacts(
Name=build_input_artifact_name
),
],
ActionTypeId=codepipeline.ActionTypeId(
Category="Build",
Owner="AWS",
Version="1",
Provider="CodeBuild",
),
OutputArtifacts=[
codepipeline.OutputArtifacts(
Name=base_template.BUILD_OUTPUT_ARTIFACT
)
],
Configuration={
"ProjectName": t.Sub("${AWS::StackName}-BuildProject"),
"PrimarySource": build_input_artifact_name,
"EnvironmentVariables": t.Sub(
json.dumps(
[
dict(
name="TEMPLATE_FORMAT",
value="yaml",
type="PLAINTEXT",
),
dict(
name="CATEGORY",
value="stack",
type="PLAINTEXT",
),
dict(
name="SOURCE_PATH",
value=source.get("Path", "."),
type="PLAINTEXT",
),
]
)
),
},
)
],
)
)
pipeline_stages.append(
self.build_test_stage(
test_input_artifact_name, options, tpl, stages, source
)
)
if stages.get("Package", {}).get("BuildSpec"):
package_build_spec = stages.get("Package", {}).get("BuildSpec")
package_build_spec = jinja2.Template(package_build_spec).render(ALL_REGIONS=all_regions)
else:
package_build_spec = yaml.safe_dump(
{
"version": "0.2",
"phases": {
"install": {"runtime-versions": {"python": "3.8"}},
"build": {
"commands": ["cd $SOURCE_PATH",]
+ [
f"aws cloudformation package --region {region} --template $(pwd)/$CATEGORY.template.$TEMPLATE_FORMAT --s3-bucket sc-factory-artifacts-$ACCOUNT_ID-{region} --s3-prefix $STACK_NAME --output-template-file $CATEGORY.template-{region}.$TEMPLATE_FORMAT"
for region in all_regions
],
},
},
"artifacts": {"files": ["*", "**/*"],},
}
)
package_project_name = t.Sub("${AWS::StackName}-PackageProject")
tpl.add_resource(
codebuild.Project(
"PackageProject",
Name=package_project_name,
ServiceRole=t.Sub(
"arn:${AWS::Partition}:iam::${AWS::AccountId}:role/servicecatalog-product-factory/DeliveryCodeRole"
),
Tags=t.Tags.from_dict(**{"ServiceCatalogPuppet:Actor": "Framework"}),
Artifacts=codebuild.Artifacts(Type="CODEPIPELINE"),
TimeoutInMinutes=60,
Environment=codebuild.Environment(
ComputeType=constants.ENVIRONMENT_COMPUTE_TYPE_DEFAULT,
Image=stages.get("Build", {}).get(
"BuildSpecImage", constants.ENVIRONMENT_IMAGE_DEFAULT
),
Type=constants.ENVIRONMENT_TYPE_DEFAULT,
EnvironmentVariables=[
codebuild.EnvironmentVariable(
Name="TEMPLATE_FORMAT", Type="PLAINTEXT", Value="yaml",
),
codebuild.EnvironmentVariable(
Name="CATEGORY", Type="PLAINTEXT", Value="stack",
),
codebuild.EnvironmentVariable(
Name="ACCOUNT_ID",
Type="PLAINTEXT",
Value=t.Sub("${AWS::AccountId}"),
),
codebuild.EnvironmentVariable(
Name="STACK_NAME",
Type="PLAINTEXT",
Value=t.Sub("${AWS::StackName}"),
),
codebuild.EnvironmentVariable(
Name="SOURCE_PATH", Type="PLAINTEXT", Value=".",
),
codebuild.EnvironmentVariable(
Name="ALL_REGIONS", Type="PLAINTEXT", Value=" ".join(all_regions),
),
],
),
Source=codebuild.Source(
BuildSpec=package_build_spec, Type="CODEPIPELINE",
),
Description=t.Sub("build project"),
)
)
pipeline_stages.append(
codepipeline.Stages(
Name="Package",
Actions=[
codepipeline.Actions(
Name="Package",
RunOrder=1,
RoleArn=t.Sub(
"arn:${AWS::Partition}:iam::${AWS::AccountId}:role/servicecatalog-product-factory/SourceRole"
),
InputArtifacts=[
codepipeline.InputArtifacts(
Name=package_input_artifact_name
),
],
ActionTypeId=codepipeline.ActionTypeId(
Category="Build",
Owner="AWS",
Version="1",
Provider="CodeBuild",
),
OutputArtifacts=[
codepipeline.OutputArtifacts(
Name=base_template.PACKAGE_OUTPUT_ARTIFACT
)
],
Configuration={
"ProjectName": package_project_name,
"EnvironmentVariables": t.Sub(
json.dumps(
[
dict(
name="TEMPLATE_FORMAT",
value="yaml",
type="PLAINTEXT",
),
dict(
name="CATEGORY",
value="stack",
type="PLAINTEXT",
),
dict(
name="SOURCE_PATH",
value=source.get("Path", "."),
type="PLAINTEXT",
),
]
)
),
},
)
],
)
)
deploy_project_name = t.Sub("${AWS::StackName}-DeployProject")
tpl.add_resource(
codebuild.Project(
"DeployProject",
Name=deploy_project_name,
ServiceRole=t.Sub(
"arn:${AWS::Partition}:iam::${AWS::AccountId}:role/servicecatalog-product-factory/DeliveryCodeRole"
),
Tags=t.Tags.from_dict(**{"ServiceCatalogPuppet:Actor": "Framework"}),
Artifacts=codebuild.Artifacts(Type="CODEPIPELINE"),
TimeoutInMinutes=60,
Environment=codebuild.Environment(
ComputeType=constants.ENVIRONMENT_COMPUTE_TYPE_DEFAULT,
Image=constants.ENVIRONMENT_IMAGE_DEFAULT,
Type=constants.ENVIRONMENT_TYPE_DEFAULT,
EnvironmentVariables=[
codebuild.EnvironmentVariable(
Name="TEMPLATE_FORMAT", Type="PLAINTEXT", Value="yaml",
),
codebuild.EnvironmentVariable(
Name="CATEGORY", Type="PLAINTEXT", Value="stack",
),
codebuild.EnvironmentVariable(
Name="ACCOUNT_ID",
Type="PLAINTEXT",
Value=t.Sub("${AWS::AccountId}"),
),
codebuild.EnvironmentVariable(
Name="SOURCE_PATH", Type="PLAINTEXT", Value=".",
),
],
),
Source=codebuild.Source(
BuildSpec=yaml.safe_dump(
{
"version": "0.2",
"phases": {
"build": {
"commands": [
"cd $SOURCE_PATH",
f'aws s3 cp . s3://sc-puppet-stacks-repository-$ACCOUNT_ID/$CATEGORY/{name}/{version}/ --recursive --exclude "*" --include "$CATEGORY.template.$TEMPLATE_FORMAT" --include "$CATEGORY.template-*.$TEMPLATE_FORMAT"',
],
}
},
"artifacts": {"files": ["*", "**/*"],},
}
),
Type="CODEPIPELINE",
),
Description=t.Sub("deploy project"),
)
)
pipeline_stages.append(
codepipeline.Stages(
Name="Deploy",
Actions=[
codepipeline.Actions(
Name="Deploy",
RunOrder=1,
RoleArn=t.Sub(
"arn:${AWS::Partition}:iam::${AWS::AccountId}:role/servicecatalog-product-factory/SourceRole"
),
InputArtifacts=[
codepipeline.InputArtifacts(
Name=deploy_input_artifact_name
),
],
ActionTypeId=codepipeline.ActionTypeId(
Category="Build",
Owner="AWS",
Version="1",
Provider="CodeBuild",
),
OutputArtifacts=[
codepipeline.OutputArtifacts(
Name=base_template.DEPLOY_OUTPUT_ARTIFACT
)
],
Configuration={
"ProjectName": deploy_project_name,
"EnvironmentVariables": t.Sub(
json.dumps(
[
dict(
name="TEMPLATE_FORMAT",
value="yaml",
type="PLAINTEXT",
),
dict(
name="CATEGORY",
value="stack",
type="PLAINTEXT",
),
dict(
name="SOURCE_PATH",
value=source.get("Path", "."),
type="PLAINTEXT",
),
]
)
),
},
)
],
)
)
tpl.add_resource(
codepipeline.Pipeline(
"Pipeline",
RoleArn=t.Sub(
"arn:${AWS::Partition}:iam::${AWS::AccountId}:role/servicecatalog-product-factory/CodePipelineRole"
),
Stages=pipeline_stages,
Name=t.Sub("${AWS::StackName}-pipeline"),
ArtifactStore=codepipeline.ArtifactStore(
Type="S3",
Location=t.Sub(
"sc-factory-artifacts-${AWS::AccountId}-${AWS::Region}"
),
),
RestartExecutionOnUpdate=False,
),
)
return tpl