

終止支援通知：2026 年 10 月 7 日 AWS 將終止 的支援 AWS Proton。2026 年 10 月 7 日之後，您將無法再存取 AWS Proton 主控台或 AWS Proton 資源。您部署的基礎設施將保持不變。如需詳細資訊，請參閱[AWS Proton 服務棄用和遷移指南](https://docs.aws.amazon.com/proton/latest/userguide/proton-end-of-support.html)。

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 為 編寫範本和建立套件 AWS Proton
<a name="ag-template-authoring"></a>

AWS Proton 會根據基礎設施即程式碼 (IaC) 檔案為您佈建資源。您可以在可重複使用的 IaC 檔案中描述基礎設施。若要讓檔案可供不同環境和應用程式重複使用，您可以將它們編寫為*範本*、定義輸入參數，並在 IaC 定義中使用這些參數。當您稍後建立佈建資源 （環境、服務執行個體或元件） 時， AWS Proton 會使用轉譯引擎，將輸入值與範本結合，以建立準備好佈建的 IaC 檔案。

管理員將大多數範本撰寫為*範本套件*，然後將它們上傳並註冊到其中 AWS Proton。此頁面的其餘部分討論了這些 AWS Proton 範本套件。*直接定義的元件*是例外狀況：開發人員會建立元件，並直接提供 IaC 範本檔案。如需元件的詳細資訊，請參閱 [AWS Proton 元件](ag-components.md)。

**Topics**
+ [範本套件](#ag-template-bundles)
+ [AWS Proton 參數](parameters.md)
+ [AWS Proton 基礎設施即程式碼檔案](ag-infrastructure-tmp-files.md)
+ [結構描述檔案](ag-schema.md)
+ [後續處理 的範本檔案 AWS Proton](ag-wrap-up.md)
+ [範本套件考量事項](template-considerations.md)

## 範本套件
<a name="ag-template-bundles"></a>

身為管理員，您可以使用 [建立和註冊範本](template-create.md) AWS Proton。您可以使用這些範本來建立環境和服務。當您建立服務時， 會 AWS Proton 佈建和部署服務執行個體至選取的環境。如需詳細資訊，請參閱[AWS Proton 適用於平台團隊](Welcome.md#ag-admin)。

若要在 中建立和註冊範本 AWS Proton，您可以上傳範本套件，其中包含 AWS Proton 需要佈建 和環境或服務的基礎設施即程式碼 (IaC) 檔案。

*範本套件*包含下列項目：
+ [基礎設施即程式碼 (IaC) 檔案](ag-infrastructure-tmp-files.md)，其中包含列出 IaC [檔案的資訊清單 YAML](ag-wrap-up.md) 檔案。 *IaC *
+ IaC [檔案輸入參數定義的結構描述 YAML](ag-schema.md) 檔案。

CloudFormation 環境範本套件包含一個 IaC 檔案。

CloudFormation 服務範本套件包含一個用於服務執行個體定義的 IaC 檔案，以及另一個用於管道定義的選用 IaC 檔案。

Terraform 環境和服務範本套件可以包含多個 IaC 檔案。

AWS Proton 需要輸入參數結構描述檔案。當您使用 AWS CloudFormation 建立 IaC 檔案時，您可以使用 [Jinja](https://jinja.palletsprojects.com/en/2.11.x/) 語法來參考輸入參數。 AWS Proton 提供參數命名空間，可用來參考 IaC 檔案中的[參數](parameters.md)。

下圖顯示您可以用來建立*範本*的步驟範例 AWS Proton。

![\[描述如何為一組 AWS Proton 基礎設施資源建立範本套件的程序的圖表。\]](http://docs.aws.amazon.com/zh_tw/proton/latest/userguide/images/bundles.png)


 ![\[Red circle with the number 1 inside, typically used as a notification icon.\]](http://docs.aws.amazon.com/zh_tw/proton/latest/userguide/images/label-one.png) 識別[輸入參數](parameters.md)。

 ![\[Number 2 icon in a pink circle.\]](http://docs.aws.amazon.com/zh_tw/proton/latest/userguide/images/label-two.png) 建立[結構描述檔案](ag-schema.md)以定義您的輸入參數。

 ![\[Pink square icon with a white exclamation mark inside a circle.\]](http://docs.aws.amazon.com/zh_tw/proton/latest/userguide/images/label-three.png) 建立參考輸入參數的 [IaC 檔案](ag-infrastructure-tmp-files.md)。您可以參考環境 IaC 檔案*輸出*做為服務 IaC 檔案的*輸入*。

 ![\[Number 4 in a red circle icon, commonly used to indicate a notification count.\]](http://docs.aws.amazon.com/zh_tw/proton/latest/userguide/images/label-four.png) 向 [註冊範本版本，](template-create.md) AWS Proton 並上傳您的範本套件。

# AWS Proton 參數
<a name="parameters"></a>

您可以定義並使用基礎設施中的參數做為程式碼 (IaC) 檔案，讓它們具有彈性且可重複使用。您可以參考參數 AWS Proton *命名空間*中的參數名稱來讀取 IaC 檔案中的參數值。 會將參數值 AWS Proton 插入其在資源佈建期間產生的轉譯 IaC 檔案中。若要處理 AWS CloudFormation IaC 參數， AWS Proton 請使用 [Jinja](https://jinja.palletsprojects.com/en/2.11.x/)。若要處理 Terraform IaC 參數， AWS Proton 會產生 Terraform 參數值檔案，並依賴內建於 HCL 的參數化功能。

使用 [CodeBuild 佈建](ag-works-prov-methods.md#ag-works-prov-methods-codebuild)， AWS Proton 產生您的程式碼可以匯入的輸入檔案。檔案是 JSON 或 HCL 檔案，取決於範本資訊清單中的屬性。如需詳細資訊，請參閱[CodeBuild 佈建參數詳細資訊和範例](parameters-codebuild.md)。

您可以參考環境、服務和元件 IaC 檔案中的參數，或具有下列需求的佈建程式碼：
+ 每個參數名稱的長度不超過 100 個字元。
+ 合併的參數命名空間和資源名稱的長度不超過資源名稱的字元限制。

AWS Proton 如果超過這些配額，佈建會失敗。

## 參數類型
<a name="param-name-types"></a>

您可以在 AWS Proton IaC 檔案中參考下列參數類型：

**輸入參數**  
環境和服務執行個體可以採用您在與環境或服務範本建立關聯的[結構描述檔案中](ag-schema.md)定義的輸入參數。您可以在資源的 IaC 檔案中參考資源的輸入參數。元件 IaC 檔案可以參考元件所連接之服務執行個體的輸入參數。  
AWS Proton 會對照您的結構描述檔案檢查輸入參數名稱，並將其與 IaC 檔案中參考的參數相符，以在資源佈建期間注入您在規格檔案中提供的輸入值。

**輸出參數**  
您可以在任何 IaC 檔案中定義輸出。輸出可以是範本佈建之其中一個資源的名稱、ID 或 ARN，也可以是傳遞其中一個範本輸入的方式。您可以在其他資源的 IaC 檔案中參考這些輸出。  
在 CloudFormation IaC 檔案中，定義 `Outputs:`區塊中的輸出參數。在 Terraform IaC 檔案中，使用 `output`陳述式定義每個輸出參數。

**資源參數**  
AWS Proton 會自動建立 AWS Proton 資源參數。這些參數會公開 AWS Proton 資源物件的屬性。資源參數的範例為 `environment.name`。

## 在 IaC 檔案中使用 AWS Proton 參數
<a name="param-name-spaces"></a>

若要讀取 IaC 檔案中的參數值，您可以參考參數命名空間中的 AWS Proton 參數名稱。對於 AWS CloudFormation IaC 檔案，您可以使用 *Jinja* 語法，並將 參數包圍成對大括號和引號。

下表顯示每個支援範本語言的參考語法，其中包含 範例。


| 範本語言 | 語法 | 範例：名為 "VPC" 的環境輸入 | 
| --- | --- | --- | 
|  CloudFormation  |  `"{{ parameter-name }}"`  |  `"{{ environment.inputs.VPC }}"`  | 
|  Terraform  |  `var.parameter-name`  |  `var.environment.inputs.VPC` [產生的 Terraform 變數定義](ag-infrastructure-tmp-files-terraform.md#compiled-tform)  | 

**注意**  
如果您在 IaC 檔案中使用 [CloudFormation 動態參數](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html)，您必須[逸出這些](https://jinja.palletsprojects.com/en/2.11.x/templates/#escaping)參數，以防止 Jinja 錯誤解譯錯誤。如需詳細資訊，請參閱[故障診斷 AWS Proton](ag-troubleshooting.md)

下表列出所有 AWS Proton 資源參數的命名空間名稱。每個範本檔案類型都可以使用參數命名空間的不同子集。

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/proton/latest/userguide/parameters.html)

如需詳細資訊和範例，請參閱不同資源類型和範本語言的 IaC 範本檔案中參數的相關子主題。

**Topics**
+ [參數類型](#param-name-types)
+ [在 IaC 檔案中使用 AWS Proton 參數](#param-name-spaces)
+ [環境 CloudFormation IaC 檔案參數詳細資訊和範例](env-parameters.md)
+ [Service CloudFormation IaC 檔案參數詳細資訊和範例](svc-parameters.md)
+ [元件 CloudFormation IaC 檔案參數詳細資訊和範例](comp-parameters.md)
+ [CloudFormation IaC 檔案的參數篩選條件](parameter-filters.md)
+ [CodeBuild 佈建參數詳細資訊和範例](parameters-codebuild.md)
+ [Terraform 基礎設施即程式碼 (IaC) 檔案參數詳細資訊和範例](env-parameters-tform.md)

# 環境 CloudFormation IaC 檔案參數詳細資訊和範例
<a name="env-parameters"></a>

您可以在環境基礎設施中將參數定義為程式碼 (IaC) 檔案並加以參考。如需 AWS Proton 參數、參數類型、參數命名空間，以及如何在 IaC 檔案中使用參數的詳細說明，請參閱 [AWS Proton 參數](parameters.md)。

## 定義環境參數
<a name="env-parameters.define"></a>

您可以同時定義環境 IaC 檔案的輸入和輸出參數。
+ **輸入參數** – 在[結構描述檔案中](ag-schema.md)定義環境輸入參數。

  下列清單包含典型使用案例的環境輸入參數範例。
  + VPC CIDR 值
  + 負載平衡器設定
  + 資料庫設定
  + 運作狀態檢查逾時

  身為管理員，您可以在[建立環境](ag-create-env.md)時提供輸入參數的值：
  + 使用 主控台填寫 AWS Proton 提供的結構描述型表單。
  + 使用 CLI 提供包含值的規格。
+ **輸出參數** – 在環境 IaC 檔案中定義環境輸出。然後，您可以在其他資源的 IaC 檔案中參考這些輸出。

## 讀取環境 IaC 檔案中的參數值
<a name="env-parameters.refer"></a>

您可以在環境 IaC 檔案中讀取與環境相關的參數。您可以在參數命名空間中參考參數的名稱來讀取 AWS Proton 參數值。
+ **輸入參數** – 參考 讀取環境輸入值`environment.inputs.input-name`。
+ **資源參數** – 透過參考 等名稱讀取 AWS Proton 資源參數`environment.name`。

**注意**  
環境 IaC 檔案沒有其他資源的輸出參數。

## 具有參數的環境和服務 IaC 檔案範例
<a name="env-parameters.example"></a>

下列範例示範環境 IaC 檔案中的參數定義和參考。此範例會示範如何在服務 IaC 檔案中參考環境 IaC 檔案中定義的環境輸出參數。

**Example 環境 CloudFormation IaC 檔案**  
在此範例中，請注意下列事項：  
+ `environment.inputs.` 命名空間是指環境輸入參數。
+ Amazon EC2 Systems Manager (SSM) 參數`StoreInputValue`會串連環境輸入。
+ `MyEnvParameterValue` 輸出會公開與輸出參數相同的輸入參數串連。三個額外的輸出參數也會個別公開輸入參數。
+ 六個額外的輸出參數會公開環境佈建的資源。

```
Resources:
  StoreInputValue:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Value: "{{ environment.inputs.my_sample_input }} {{ environment.inputs.my_other_sample_input}} {{ environment.inputs.another_optional_input }}"
              # input parameter references

# These output values are available to service infrastructure as code files as outputs, when given the 
# the 'environment.outputs' namespace, for example, service_instance.environment.outputs.ClusterName.
Outputs:
  MyEnvParameterValue:                                        # output definition
    Value: !GetAtt StoreInputValue.Value
  MySampleInputValue:                                         # output definition
    Value: "{{ environment.inputs.my_sample_input }}"         #   input parameter reference
  MyOtherSampleInputValue:                                    # output definition
    Value: "{{ environment.inputs.my_other_sample_input }}"   #   input parameter reference
  AnotherOptionalInputValue:                                  # output definition
    Value: "{{ environment.inputs.another_optional_input }}"  #   input parameter reference
  ClusterName:                                                # output definition
    Description: The name of the ECS cluster
    Value: !Ref 'ECSCluster'                                  #   provisioned resource
  ECSTaskExecutionRole:                                       # output definition
    Description: The ARN of the ECS role
    Value: !GetAtt 'ECSTaskExecutionRole.Arn'                 #   provisioned resource
  VpcId:                                                      # output definition
    Description: The ID of the VPC that this stack is deployed in
    Value: !Ref 'VPC'                                         #   provisioned resource
  PublicSubnetOne:                                            # output definition
    Description: Public subnet one
    Value: !Ref 'PublicSubnetOne'                             #   provisioned resource
  PublicSubnetTwo:                                            # output definition
    Description: Public subnet two
    Value: !Ref 'PublicSubnetTwo'                             #   provisioned resource
  ContainerSecurityGroup:                                     # output definition
    Description: A security group used to allow Fargate containers to receive traffic
    Value: !Ref 'ContainerSecurityGroup'                      #   provisioned resource
```

**Example Service CloudFormation IaC 檔案**  
`environment.outputs.` 命名空間是指來自環境 IaC 檔案的環境輸出。例如，名稱會`environment.outputs.ClusterName`讀取`ClusterName`環境輸出參數的值。  

```
AWSTemplateFormatVersion: '2010-09-09'
Description: Deploy a service on AWS Fargate, hosted in a public subnet, and accessible via a public load balancer.
Mappings:
  TaskSize:
    x-small:
      cpu: 256
      memory: 512
    small:
      cpu: 512
      memory: 1024
    medium:
      cpu: 1024
      memory: 2048
    large:
      cpu: 2048
      memory: 4096
    x-large:
      cpu: 4096
      memory: 8192
Resources:
  # A log group for storing the stdout logs from this service's containers
  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: '{{service_instance.name}}' # resource parameter

  # The task definition. This is a simple metadata description of what
  # container to run, and what resource requirements it has.
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Family: '{{service_instance.name}}' # resource parameter
      Cpu: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, cpu] # input parameter
      Memory: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, memory] 
      NetworkMode: awsvpc
      RequiresCompatibilities:
        - FARGATE
      ExecutionRoleArn: '{{environment.outputs.ECSTaskExecutionRole}}'  # output reference to an environment infrastructure code file
      TaskRoleArn: !Ref "AWS::NoValue"
      ContainerDefinitions:
        - Name: '{{service_instance.name}}'  # resource parameter
          Cpu: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, cpu]
          Memory: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, memory]
          Image: '{{service_instance.inputs.image}}'
          PortMappings:
            - ContainerPort: '{{service_instance.inputs.port}}' # input parameter
          LogConfiguration:
            LogDriver: 'awslogs'
            Options:
              awslogs-group: '{{service_instance.name}}' # resource parameter
              awslogs-region: !Ref 'AWS::Region'
              awslogs-stream-prefix: '{{service_instance.name}}' # resource parameter

  # The service_instance. The service is a resource which allows you to run multiple
  # copies of a type of task, and gather up their logs and metrics, as well
  # as monitor the number of running tasks and replace any that have crashed
  Service:
    Type: AWS::ECS::Service
    DependsOn: LoadBalancerRule
    Properties:
      ServiceName: '{{service_instance.name}}'  # resource parameter
      Cluster: '{{environment.outputs.ClusterName}}' # output reference to an environment infrastructure as code file
      LaunchType: FARGATE
      DeploymentConfiguration:
        MaximumPercent: 200
        MinimumHealthyPercent: 75
      DesiredCount: '{{service_instance.inputs.desired_count}}'# input parameter
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: ENABLED
          SecurityGroups:
            - '{{environment.outputs.ContainerSecurityGroup}}' # output reference to an environment infrastructure as code file
          Subnets:
            - '{{environment.outputs.PublicSubnetOne}}' # output reference to an environment infrastructure as code file
            - '{{environment.outputs.PublicSubnetTwo}}' # output reference to an environment infrastructure as code file
      TaskDefinition: !Ref 'TaskDefinition'
      LoadBalancers:
        - ContainerName: '{{service_instance.name}}'  # resource parameter
          ContainerPort: '{{service_instance.inputs.port}}' # input parameter
          TargetGroupArn: !Ref 'TargetGroup'
[...]
```

# Service CloudFormation IaC 檔案參數詳細資訊和範例
<a name="svc-parameters"></a>

您可以在服務和管道基礎設施中將參數定義為程式碼 (IaC) 檔案並加以參考。如需參數、參數類型、參數命名空間，以及如何在 IaC 檔案中使用參數的 AWS Proton 詳細說明，請參閱 [AWS Proton 參數](parameters.md)。

## 定義服務參數
<a name="svc-parameters.define"></a>

您可以定義服務 IaC 檔案的輸入和輸出參數。
+ **輸入參數** – 在[結構描述檔案中](ag-schema.md)定義服務執行個體輸入參數。

  下列清單包含典型使用案例的服務輸入參數範例。
  + 連接埠
  + 任務大小
  + 映像
  + 所需計數
  + Docker 檔案
  + 單位測試命令

  [您在建立服務](ag-create-svc.md)時提供輸入參數的值：
  + 使用 主控台填寫 AWS Proton 提供的結構描述型表單。
  + 使用 CLI 提供包含值的規格。
+ **輸出參數** – 在服務 IaC 檔案中定義服務執行個體輸出。然後，您可以在其他資源的 IaC 檔案中參考這些輸出。

## 讀取服務 IaC 檔案中的參數值
<a name="svc-parameters.refer"></a>

您可以讀取與服務 IaC 檔案中其他資源相關的參數。您可以在參數命名空間中參考參數的名稱來讀取 AWS Proton 參數值。
+ **輸入參數** – 參考 讀取服務執行個體輸入值`service_instance.inputs.input-name`。
+ **資源參數** – 透過參考 `service.name`、 `service_instance.name`和 等名稱讀取 AWS Proton 資源參數`environment.name`。
+ **輸出參數** – 透過參考 `environment.outputs.output-name`或 讀取其他資源的輸出`service_instance.components.default.outputs.output-name`。

## 具有參數的服務 IaC 檔案範例
<a name="svc-parameters.example"></a>

下列範例是來自服務 CloudFormation IaC 檔案的程式碼片段。`environment.outputs.` 命名空間是指來自環境 IaC 檔案的輸出。`service_instance.inputs.` 命名空間是指服務執行個體輸入參數。`service_instance.name` 屬性是指 AWS Proton 資源參數。

```
Resources:
  StoreServiceInstanceInputValue:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Value: "{{ service.name }} {{ service_instance.name }} {{ service_instance.inputs.my_sample_service_instance_required_input }} {{ service_instance.inputs.my_sample_service_instance_optional_input }} {{ environment.outputs.MySampleInputValue }} {{ environment.outputs.MyOtherSampleInputValue }}"
              #  resource parameter references               # input parameter references                                                                                                                    # output references to an environment infrastructure as code file
Outputs:
  MyServiceInstanceParameter:                                                         # output definition
    Value: !Ref StoreServiceInstanceInputValue 
  MyServiceInstanceRequiredInputValue:                                                # output definition
    Value: "{{ service_instance.inputs.my_sample_service_instance_required_input }}"  # input parameter reference
  MyServiceInstanceOptionalInputValue:                                                # output definition
    Value: "{{ service_instance.inputs.my_sample_service_instance_optional_input }}"  # input parameter reference
  MyServiceInstancesEnvironmentSampleOutputValue:                                     # output definition
    Value: "{{ environment.outputs.MySampleInputValue }}"                             # output reference to an environment IaC file
  MyServiceInstancesEnvironmentOtherSampleOutputValue:                                # output definition
    Value: "{{ environment.outputs.MyOtherSampleInputValue }}"                        # output reference to an environment IaC file
```

# 元件 CloudFormation IaC 檔案參數詳細資訊和範例
<a name="comp-parameters"></a>

您可以在元件基礎設施中將參數定義為程式碼 (IaC) 檔案並加以參考。如需 AWS Proton 參數、參數類型、參數命名空間，以及如何在 IaC 檔案中使用參數的詳細說明，請參閱 [AWS Proton 參數](parameters.md)。如需元件的詳細資訊，請參閱 [AWS Proton 元件](ag-components.md)。

## 定義元件輸出參數
<a name="comp-parameters.define"></a>

您可以在元件 IaC 檔案中定義輸出參數。然後，您可以在服務 IaC 檔案中參考這些輸出。

**注意**  
您無法定義元件 IaC 檔案的輸入。連接的元件可以從其連接的服務執行個體取得輸入。分離的元件沒有輸入。

## 讀取元件 IaC 檔案中的參數值
<a name="comp-parameters.refer"></a>

您可以讀取與元件和元件 IaC 檔案中其他資源相關的參數。您可以在參數命名空間中參考參數的名稱來讀取 AWS Proton 參數值。
+ **輸入參數** – 透過參考 讀取附加的服務執行個體輸入值`service_instance.inputs.input-name`。
+ **資源參數** – 透過參考 `component.name`、`service_instance.name`、 `service.name`和 等名稱讀取 AWS Proton 資源參數`environment.name`。
+ **輸出參數** – 參考 讀取環境輸出`environment.outputs.output-name`。

## 具有參數的元件和服務 IaC 檔案範例
<a name="comp-parameters.example"></a>

下列範例顯示佈建 Amazon Simple Storage Service (Amazon S3) 儲存貯體和相關存取政策的元件，並將這兩個資源的 Amazon Resource Name (ARNs) 公開為元件輸出。服務 IaC 範本會將元件輸出新增為 Amazon Elastic Container Service (Amazon ECS) 任務的容器環境變數，讓輸出可供容器中執行的程式碼使用，並將儲存貯體存取政策新增至任務的角色。儲存貯體名稱是以環境、服務、服務執行個體和元件的名稱為基礎，這表示儲存貯體會與延伸特定服務執行個體之元件範本的特定執行個體結合。開發人員可以根據此元件範本建立多個自訂元件，為不同的服務執行個體和功能需求佈建 Amazon S3 儲存貯體。

此範例顯示如何使用 Jinja `{{ ... }}` 語法來參考服務 IaC 檔案中的元件和其他資源參數。您只能在元件連接至服務執行個體時，使用 `{% if ... %}` 陳述式來新增陳述式區塊。`proton_cfn_*` 關鍵字是可用來淨化和格式化輸出參數值的*篩選條件*。如需篩選條件的詳細資訊，請參閱[CloudFormation IaC 檔案的參數篩選條件](parameter-filters.md)。

 身為管理員，您會撰寫服務 IaC 範本檔案。

**Example 使用元件的服務 CloudFormation IaC 檔案**  

```
# service/instance_infrastructure/cloudformation.yaml

Resources: 
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      TaskRoleArn: !Ref TaskRole
      ContainerDefinitions:
        - Name: '{{service_instance.name}}'
          # ...
          {% if service_instance.components.default.outputs | length > 0 %}
          Environment:
            {{ service_instance.components.default.outputs |
                proton_cfn_ecs_task_definition_formatted_env_vars }}
          {% endif %}

  # ...

  TaskRole:
    Type: AWS::IAM::Role
    Properties:
      # ...
      ManagedPolicyArns:
        - !Ref BaseTaskRoleManagedPolicy
        {{ service_instance.components.default.outputs
            | proton_cfn_iam_policy_arns }}

  # Basic permissions for the task
  BaseTaskRoleManagedPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      # ...
```

身為開發人員，您撰寫元件 IaC 範本檔案。

**Example 元件 CloudFormation IaC 檔案**  

```
# cloudformation.yaml

# A component that defines an S3 bucket and a policy for accessing the bucket.
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: '{{environment.name}}-{{service.name}}-{{service_instance.name}}-{{component.name}}'
  S3BucketAccessPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      PolicyDocument:
        Version: "2012-10-17"		 	 	 
        Statement:
          - Effect: Allow
            Action:
              - 's3:Get*'
              - 's3:List*'
              - 's3:PutObject'
            Resource: !GetAtt S3Bucket.Arn
Outputs:
  BucketName:
    Description: "Bucket to access"
    Value: !GetAtt S3Bucket.Arn
  BucketAccessPolicyArn:
    Value: !Ref S3BucketAccessPolicy
```

當 AWS Proton 轉譯服務執行個體的 CloudFormation 範本，並將所有參數取代為實際值時，範本可能看起來像下列檔案。

**Example 服務執行個體 CloudFormation 轉譯 IaC 檔案**  

```
Resources: 
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      TaskRoleArn: !Ref TaskRole
      ContainerDefinitions:
        - Name: '{{service_instance.name}}'
          # ...
          Environment:
            - Name: BucketName
              Value: arn:aws:s3:us-east-1:123456789012:environment_name-service_name-service_instance_name-component_name
            - Name: BucketAccessPolicyArn
              Value: arn:aws:iam::123456789012:policy/cfn-generated-policy-name
  # ...

  TaskRole:
    Type: AWS::IAM::Role
    Properties:
      # ...
      ManagedPolicyArns:
        - !Ref BaseTaskRoleManagedPolicy
        - arn:aws:iam::123456789012:policy/cfn-generated-policy-name

  # Basic permissions for the task
  BaseTaskRoleManagedPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      # ...
```

# CloudFormation IaC 檔案的參數篩選條件
<a name="parameter-filters"></a>

當您參考 AWS CloudFormation IaC 檔案中的[AWS Proton 參數](parameters.md)時，您可以使用稱為*篩選條件*的 Jinja 修飾詞，在參數值插入轉譯範本之前對其進行驗證、篩選和格式化。篩選條件驗證在參考[元件](ag-components.md)輸出參數時特別有用，因為元件建立和連接是由開發人員完成，而且在服務執行個體範本中使用元件輸出的管理員可能想要驗證其存在和有效性。不過，您可以在任何 Jinja IaC 檔案中使用篩選條件。

下列各節說明和定義可用的參數篩選條件，並提供範例。 AWS Proton 定義這些篩選條件的大部分。`default` 篩選條件是 Jinja 內建篩選條件。

## 為 Amazon ECS 任務格式化環境屬性
<a name="parameter-filters.proton.cfn-ecs"></a>

**宣告**

```
dict → proton_cfn_ecs_task_definition_formatted_env_vars (raw: boolean = True) → YAML list of dicts
```

**描述**

此篩選條件會格式化 Amazon Elastic Container Service (Amazon ECS) 任務定義 `ContainerDefinition`區段中的 [Environment 屬性](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-containerdefinitions.html#cfn-ecs-taskdefinition-containerdefinition-environment)中使用的輸出清單。

`raw` 設定為 `False`以驗證參數值。在此情況下，需要 值才能符合規則表達式 `^[a-zA-Z0-9_-]*$`。如果值未通過此驗證，範本轉譯會失敗。

### 範例
<a name="parameter-filters.proton.cfn-ecs.example"></a>

使用下列自訂元件範本：

```
Resources:
  # ...
Outputs:
  Output1:
    Description: "Example component output 1"
    Value: hello
  Output2:
    Description: "Example component output 2"
    Value: world
```

以及下列服務範本：

```
Resources:
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      # ...
      ContainerDefinitions:
        - Name: MyServiceName
          # ...
          Environment:
            {{ service_instance.components.default.outputs
              | proton_cfn_ecs_task_definition_formatted_env_vars }}
```

轉譯的服務範本如下所示：

```
Resources:
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      # ...
      ContainerDefinitions:
        - Name: MyServiceName
          # ...
          Environment:
            - Name: Output1
              Value: hello
            - Name: Output2
              Value: world
```

## 格式化 Lambda 函數的環境屬性
<a name="parameter-filters.proton.cfn-lambda"></a>

**宣告**

```
dict → proton_cfn_lambda_function_formatted_env_vars (raw: boolean = True) → YAML dict
```

**描述**

此篩選條件會格式化要在 AWS Lambda 函數定義之 `Properties`區段的 [Environment 屬性](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html#cfn-lambda-function-environment)中使用的輸出清單。

`raw` 設定為 `False`以驗證參數值。在此情況下，需要 值才能符合規則表達式 `^[a-zA-Z0-9_-]*$`。如果值未通過此驗證，範本轉譯會失敗。

### 範例
<a name="parameter-filters.proton.cfn-lambda.example"></a>

使用下列自訂元件範本：

```
Resources:
  # ...
Outputs:
  Output1:
    Description: "Example component output 1"
    Value: hello
  Output2:
    Description: "Example component output 2"
    Value: world
```

以及下列服務範本：

```
Resources:
  Lambda:
    Type: AWS::Lambda::Function
    Properties:
      Environment:
        Variables:
          {{ service_instance.components.default.outputs
            | proton_cfn_lambda_function_formatted_env_vars }}
```

轉譯的服務範本如下所示：

```
Resources:
  Lambda:
    Type: AWS::Lambda::Function
    Properties:
      Environment:
        Variables:
          Output1: hello
          Output2: world
```

## 擷取要包含在 IAM 角色中的 IAM 政策 ARNs
<a name="parameter-filters.proton.cfn-policy-arns"></a>

**宣告**

```
dict → proton_cfn_iam_policy_arns → YAML list
```

**描述**

此篩選條件會格式化 AWS Identity and Access Management (IAM) 角色定義 `Properties`區段中要在 [ManagedPolicyArns 屬性](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html#cfn-iam-role-managepolicyarns)中使用的輸出清單。篩選條件使用規則表達`^arn:[a-zA-Z-]+:iam::\d{12}:policy/`式，從輸出參數清單中擷取有效的 IAM 政策 ARNs。您可以使用此篩選條件，將輸出參數值中的政策附加至服務範本中的 IAM 角色定義。

### 範例
<a name="parameter-filters.proton.cfn-policy-arns.example"></a>

使用下列自訂元件範本：

```
Resources:
  # ...
  ExamplePolicy1:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      # ...
  ExamplePolicy2:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      # ...

  # ...

Outputs:
  Output1:
    Description: "Example component output 1"
    Value: hello
  Output2:
    Description: "Example component output 2"
    Value: world
  PolicyArn1:
    Description: "ARN of policy 1"
    Value: !Ref ExamplePolicy1
  PolicyArn2:
    Description: "ARN of policy 2"
    Value: !Ref ExamplePolicy2
```

以及下列服務範本：

```
Resources: 

  # ...

  TaskRole:
    Type: AWS::IAM::Role
    Properties:
      # ...
      ManagedPolicyArns:
        - !Ref BaseTaskRoleManagedPolicy
        {{ service_instance.components.default.outputs
            | proton_cfn_iam_policy_arns }}

  # Basic permissions for the task
  BaseTaskRoleManagedPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      # ...
```

轉譯的服務範本如下所示：

```
Resources: 

  # ...

  TaskRole:
    Type: AWS::IAM::Role
    Properties:
      # ...
      ManagedPolicyArns:
        - !Ref BaseTaskRoleManagedPolicy
        - arn:aws:iam::123456789012:policy/cfn-generated-policy-name-1
        - arn:aws:iam::123456789012:policy/cfn-generated-policy-name-2

  # Basic permissions for the task
  BaseTaskRoleManagedPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      # ...
```

## 清理屬性值
<a name="parameter-filters.proton.cfn-sanitize"></a>

**宣告**

```
string → proton_cfn_sanitize → string
```

**描述**

這是一般用途篩選條件。使用它來驗證參數值的安全性。篩選條件會驗證該值是否符合規則表達式，`^[a-zA-Z0-9_-]*$`或是有效的 Amazon Resource Name (ARN)。如果值未通過此驗證，範本轉譯會失敗。

### 範例
<a name="parameter-filters.proton.cfn-sanitize.example"></a>

使用下列自訂元件範本：

```
Resources:
  # ...
Outputs:
  Output1:
    Description: "Example of valid output"
    Value: "This-is_valid_37"
  Output2:
    Description: "Example incorrect output"
    Value: "this::is::incorrect"
  SomeArn:
    Description: "Example ARN"
    Value: arn:aws:some-service::123456789012:some-resource/resource-name
```
+ 服務範本中的下列參考：

  ```
  # ...
    {{ service_instance.components.default.outputs.Output1
      | proton_cfn_sanitize }}
  ```

  轉譯方式如下：

  ```
  # ...
    This-is_valid_37
  ```
+ 服務範本中的下列參考：

  ```
  # ...
    {{ service_instance.components.default.outputs.Output2
      | proton_cfn_sanitize }}
  ```

  具有下列轉譯錯誤的結果：

  ```
  Illegal character(s) detected in "this::is::incorrect". Must match regex ^[a-zA-Z0-9_-]*$ or be a valid ARN
  ```
+ 服務範本中的下列參考：

  ```
  # ...
    {{ service_instance.components.default.outputs.SomeArn
      | proton_cfn_sanitize }}
  ```

  轉譯方式如下：

  ```
  # ...
    arn:aws:some-service::123456789012:some-resource/resource-name
  ```

## 為不存在的參考提供預設值
<a name="parameter-filters.proton.default"></a>

**描述**

當命名空間參考不存在時，`default`篩選條件會提供預設值。使用它來撰寫強大的範本，即使參考的參數遺失，也能在沒有失敗的情況下轉譯。

### 範例
<a name="parameter-filters.default.example"></a>

如果服務執行個體沒有直接定義的 （預設） 元件，或連接的元件沒有名為 的輸出，則服務範本中的下列參考會導致範本轉譯失敗`test`。

```
# ...
  {{ service_instance.components.default.outputs.test }}
```

若要避免此問題，請新增`default`篩選條件。

```
# ...
  {{ service_instance.components.default.outputs.test | default("[optional-value]") }}
```

# CodeBuild 佈建參數詳細資訊和範例
<a name="parameters-codebuild"></a>

您可以在 CodeBuild 型 AWS Proton 資源的範本中定義參數，並在佈建程式碼中參考這些參數。如需 AWS Proton 參數、參數類型、參數命名空間，以及如何在 IaC 檔案中使用參數的詳細說明，請參閱 [AWS Proton 參數](parameters.md)。

**注意**  
您可以搭配環境和服務使用 CodeBuild 佈建。目前您無法以這種方式佈建元件。

## 輸入參數
<a name="parameters-codebuild.input"></a>

當您建立 AWS Proton 資源時，例如環境或服務，您可以為範本[結構描述檔案中](ag-schema.md)定義的輸入參數提供值。當您建立的資源使用 時[CodeBuild 佈建](ag-works-prov-methods.md#ag-works-prov-methods-codebuild)， 會將這些輸入值 AWS Proton 轉譯為輸入檔案。您的佈建程式碼可以從此檔案匯入和取得參數值。

如需 CodeBuild 範本的範例，請參閱 [CodeBuild 佈建範本套件](ag-infrastructure-tmp-files-codebuild.md)。如需資訊清單檔案的相關資訊，請參閱[後續處理 的範本檔案 AWS Proton](ag-wrap-up.md)。

下列範例是在服務執行個體的 CodeBuild 型佈建期間產生的 JSON 輸入檔案。

### 範例： AWS CDK 搭配 CodeBuild 佈建使用
<a name="parameters-codebuild.example"></a>

```
{
  "service_instance": {
    "name": "my-service-staging",
    "inputs": {
      "port": "8080",
      "task_size": "medium"
    }
  },
  "service": {
    "name": "my-service"
  },
  "environment": {
    "account_id": "123456789012",
    "name": "my-env-staging",
    "outputs": {
      "vpc-id": "hdh2323423"
    }
  }
}
```

## 輸出參數
<a name="parameters-codebuild.output"></a>

若要將資源佈建輸出傳回給 AWS Proton，您的佈建程式碼可以產生名為 的 JSON 檔案`proton-outputs.json`，其中包含範本[結構描述檔案中](ag-schema.md)定義的輸出參數值。例如， `cdk deploy`命令具有 `--outputs-file`引數，指示 使用佈建輸出 AWS CDK 產生 JSON 檔案。如果您的資源使用 AWS CDK，請在 CodeBuild 範本資訊清單中指定下列命令：

```
aws proton notify-resource-deployment-status-change
```

AWS Proton 會尋找此 JSON 檔案。如果檔案在佈建程式碼成功完成之後存在， 會從中 AWS Proton 讀取輸出參數值。

# Terraform 基礎設施即程式碼 (IaC) 檔案參數詳細資訊和範例
<a name="env-parameters-tform"></a>

您可以在範本套件的`variable.tf`檔案中包含 Terraform 輸入變數。您也可以建立結構描述來建立 AWS Proton 受管變數。`.tf files`從結構描述檔案 AWS Proton 建立變數。如需詳細資訊，請參閱[Terraform IaC 檔案](ag-infrastructure-tmp-files-terraform.md)。

若要在基礎設施 中參考結構描述定義的 AWS Proton 變數`.tf files`，您可以使用 Terraform IaC 資料表的參數和命名 AWS Proton 空間中顯示的命名空間。 * IaC* 例如，您可以使用 `var.environment.inputs.vpc_cidr`. 在引號內，以單一括號括住這些變數，並在第一個括號前面加上貨幣符號 （例如 `“${var.environment.inputs.vpc_cidr}”`)。

下列範例示範如何使用 命名空間在環境 中包含 AWS Proton 參數`.tf file`。

```
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
  // This tells terraform to store the state file in s3 at the location
  // s3://terraform-state-bucket/tf-os-sample/terraform.tfstate
  backend "s3" {
    bucket = "terraform-state-bucket"
    key    = "tf-os-sample/terraform.tfstate"
    region = "us-east-1"
  }
}

// Configure the AWS Provider
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = var.proton_tags
  }
}

resource "aws_ssm_parameter" "my_ssm_parameter" {
  name  = "my_ssm_parameter"
  type  = "String"
  // Use the Proton environment.inputs. namespace
  value = var.environment.inputs.ssm_parameter_value
}
```

# AWS Proton 基礎設施即程式碼檔案
<a name="ag-infrastructure-tmp-files"></a>

範本套件的主要部分是*基礎設施即程式碼 (IaC) 檔案*，這些檔案會定義您要佈建的基礎設施資源和屬性。 AWS CloudFormation 其他基礎設施即程式碼引擎則使用這些類型的檔案來佈建基礎設施資源。

**注意**  
IaC 檔案也可以獨立於範本套件使用，做為*直接定義元件*的直接輸入。如需元件的詳細資訊，請參閱 [AWS Proton 元件](ag-components.md)。

AWS Proton 目前支援兩種 IaC 檔案類型：
+ *[CloudFormation](ag-infrastructure-tmp-files-cloudformation.md) 檔案* – 用於 *AWS受管佈建*。 在 CloudFormation 範本檔案格式的頂端 AWS Proton 使用 Jinja 進行參數化。
+ *[Terraform HCL](ag-infrastructure-tmp-files-terraform.md) 檔案* – 用於*自我管理佈建*。HCL 原生支援參數化。

您無法使用佈建方法的組合來佈建 AWS Proton 資源。您必須使用其中一個。您無法將 AWS受管佈建服務部署至自我管理的佈建環境，反之亦然。

如需詳細資訊，請參閱 [如何 AWS Proton 佈建基礎設施](ag-works-prov-methods.md)、[AWS Proton 環境](ag-environments.md)、[AWS Proton 服務](ag-services.md) 和 [AWS Proton 元件](ag-components.md)。

# CloudFormation IaC 檔案
<a name="ag-infrastructure-tmp-files-cloudformation"></a>

了解如何搭配 使用 AWS CloudFormation 基礎設施做為程式碼檔案 AWS Proton。 CloudFormation 是基礎設施做為程式碼 (IaC) 服務，可協助您模型化和設定 AWS 資源。您可以在 parametrization. AWS Proton expands 參數的 CloudFormation 範本檔案格式上，使用 Jinja 在範本中定義基礎設施資源，並轉譯完整的 CloudFormation 範本。CloudFormation 會將定義的資源佈建為 CloudFormation 堆疊。如需詳細資訊，請參閱*《 使用者指南》 CloudFormation *中的[什麼是 CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html) 。

AWS Proton 支援 CloudFormation IaC [AWS的 受管佈建](ag-works-prov-methods.md#ag-works-prov-methods-direct)。

## 從您現有的基礎設施做為程式碼檔案開始
<a name="iac-tmp-files"></a>

您可以調整*自己的現有*基礎設施做為程式碼 (IaC) 檔案，以搭配 使用 AWS Proton。

下列 CloudFormation 範例[範例 1](#ag-env-cfn-example) 和[範例 2](#ag-svc-cfn-example) 代表您*現有的* CloudFormation IaC 檔案。CloudFormation 可以使用這些檔案來建立兩個不同的 CloudFormation 堆疊。

在[範例 1](#ag-env-cfn-example) 中，CloudFormation IaC 檔案設定為佈建要在容器應用程式之間共用的基礎設施。在此範例中，會新增輸入參數，以便您可以使用相同的 IaC 檔案來建立多組佈建基礎設施。每個集合可以有不同的名稱，以及一組不同的 VPC 和子網路 CIDR 值。身為管理員或開發人員，當您使用 IaC 檔案搭配 CloudFormation 佈建基礎設施資源時，您可以提供這些參數的值。為了方便起見，這些輸入參數會以註解標記，並在範例中多次參考。*輸出*定義在範本的結尾。它們可以在其他 CloudFormation IaC 檔案中參考。

在[範例 2](#ag-svc-cfn-example) 中，CloudFormation IaC 檔案設定為將應用程式部署至從*範例 1 *佈建的基礎設施。為了您的方便，參數會加上註解。

### 範例 1：CloudFormation IaC 檔案
<a name="ag-env-cfn-example"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Description: AWS Fargate cluster running containers in a public subnet. Only supports
             public facing load balancer, and public service discovery namespaces.
Parameters:
   VpcCIDR:       # input parameter
        Description: CIDR for VPC
        Type: String
        Default: "10.0.0.0/16"
   SubnetOneCIDR: # input parameter
        Description: CIDR for SubnetOne
        Type: String
        Default: "10.0.0.0/24"
   SubnetTwoCIDR: # input parameters
        Description: CIDR for SubnetTwo
        Type: String
        Default: "10.0.1.0/24"
Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      EnableDnsSupport: true
      EnableDnsHostnames: true
      CidrBlock: 
        Ref: 'VpcCIDR'

  # Two public subnets, where containers will have public IP addresses
  PublicSubnetOne:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone:
         Fn::Select:
         - 0
         - Fn::GetAZs: {Ref: 'AWS::Region'}
      VpcId: !Ref 'VPC'
      CidrBlock:
         Ref: 'SubnetOneCIDR'
      MapPublicIpOnLaunch: true

  PublicSubnetTwo:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone:
         Fn::Select:
         - 1
         - Fn::GetAZs: {Ref: 'AWS::Region'}
      VpcId: !Ref 'VPC'
      CidrBlock:
        Ref: 'SubnetTwoCIDR'
      MapPublicIpOnLaunch: true

  # Setup networking resources for the public subnets. Containers
  # in the public subnets have public IP addresses and the routing table
  # sends network traffic via the internet gateway.
  InternetGateway:
    Type: AWS::EC2::InternetGateway
  GatewayAttachement:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref 'VPC'
      InternetGatewayId: !Ref 'InternetGateway'
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref 'VPC'
  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: GatewayAttachement
    Properties:
      RouteTableId: !Ref 'PublicRouteTable'
      DestinationCidrBlock: '0.0.0.0/0'
      GatewayId: !Ref 'InternetGateway'
  PublicSubnetOneRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetOne
      RouteTableId: !Ref PublicRouteTable
  PublicSubnetTwoRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetTwo
      RouteTableId: !Ref PublicRouteTable

  # ECS Resources
  ECSCluster:
    Type: AWS::ECS::Cluster

  # A security group for the containers we will run in Fargate.
  # Rules are added to this security group based on what ingress you
  # add for the cluster.
  ContainerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Access to the Fargate containers
      VpcId: !Ref 'VPC'

  # This is a role which is used by the ECS tasks themselves.
  ECSTaskExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: [ecs-tasks.amazonaws.com]
          Action: ['sts:AssumeRole']
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy'

# These output values will be available to other templates to use.
Outputs:
  ClusterName:                                               # output
    Description: The name of the ECS cluster
    Value: !Ref 'ECSCluster'
    Export:
      Name:
        Fn::Sub: "${AWS::StackName}-ECSCluster"
  ECSTaskExecutionRole:                                       # output
    Description: The ARN of the ECS role
    Value: !GetAtt 'ECSTaskExecutionRole.Arn'
    Export: 
      Name:
        Fn::Sub: "${AWS::StackName}-ECSTaskExecutionRole"
  VpcId:                                                      # output
    Description: The ID of the VPC that this stack is deployed in
    Value: !Ref 'VPC'
    Export: 
      Name: 
        Fn::Sub: "${AWS::StackName}-VPC"
  PublicSubnetOne:                                            # output
    Description: Public subnet one
    Value: !Ref 'PublicSubnetOne'
    Export: 
      Name:
        Fn::Sub: "${AWS::StackName}-PublicSubnetOne"
  PublicSubnetTwo:                                            # output
    Description: Public subnet two
    Value: !Ref 'PublicSubnetTwo'
    Export: 
      Name:
        Fn::Sub: "${AWS::StackName}-PublicSubnetTwo"
  ContainerSecurityGroup:                                     # output
    Description: A security group used to allow Fargate containers to receive traffic
    Value: !Ref 'ContainerSecurityGroup'
    Export: 
      Name:
        Fn::Sub: "${AWS::StackName}-ContainerSecurityGroup"
```

### 範例 2：CloudFormation IaC 檔案
<a name="ag-svc-cfn-example"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Description: Deploy a service on AWS Fargate, hosted in a public subnet, and accessible via a public load balancer.
Parameters:
    ContainerPortInput:  # input parameter
        Description: The port to route traffic to
        Type: Number
        Default: 80
    TaskCountInput:      # input parameter
        Description: The default number of Fargate tasks you want running
        Type: Number
        Default: 1
    TaskSizeInput:       # input parameter
        Description: The size of the task you want to run
        Type: String
        Default: x-small
    ContainerImageInput: # input parameter
        Description: The name/url of the container image
        Type: String
        Default: "public.ecr.aws/z9d2n7e1/nginx:1.19.5"
    TaskNameInput:       # input parameter
        Description: Name for your task
        Type: String
        Default: "my-fargate-instance"
    StackName:           # input parameter
        Description: Name of the environment stack to deploy to
        Type: String
        Default: "my-fargate-environment"
Mappings:
  TaskSizeMap:
    x-small:
      cpu: 256
      memory: 512
    small:
      cpu: 512
      memory: 1024
    medium:
      cpu: 1024
      memory: 2048
    large:
      cpu: 2048
      memory: 4096
    x-large:
      cpu: 4096
      memory: 8192
Resources:
  # A log group for storing the stdout logs from this service's containers
  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName:
        Ref: 'TaskNameInput' # input parameter

  # The task definition. This is a simple metadata description of what
  # container to run, and what resource requirements it has.
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Family: !Ref 'TaskNameInput'
      Cpu: !FindInMap [TaskSizeMap, !Ref 'TaskSizeInput', cpu]
      Memory: !FindInMap [TaskSizeMap, !Ref 'TaskSizeInput', memory]
      NetworkMode: awsvpc
      RequiresCompatibilities:
        - FARGATE
      ExecutionRoleArn:
        Fn::ImportValue:
          !Sub "${StackName}-ECSTaskExecutionRole"    # output parameter from another CloudFormation template
              awslogs-region: !Ref 'AWS::Region'
              awslogs-stream-prefix: !Ref 'TaskNameInput'
                

  # The service_instance. The service is a resource which allows you to run multiple
  # copies of a type of task, and gather up their logs and metrics, as well
  # as monitor the number of running tasks and replace any that have crashed
  Service:
    Type: AWS::ECS::Service
    DependsOn: LoadBalancerRule
    Properties:
      ServiceName: !Ref 'TaskNameInput'
      Cluster:
        Fn::ImportValue:
          !Sub "${StackName}-ECSCluster"  # output parameter from another CloudFormation template
      LaunchType: FARGATE
      DeploymentConfiguration:
        MaximumPercent: 200
        MinimumHealthyPercent: 75
      DesiredCount: !Ref 'TaskCountInput'
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: ENABLED
          SecurityGroups:
            - Fn::ImportValue:
                !Sub "${StackName}-ContainerSecurityGroup"    # output parameter from another CloudFormation template
          Subnets:
            - Fn::ImportValue:r CloudFormation template
      TaskRoleArn: !Ref "AWS::NoValue"
      ContainerDefinitions:        
        - Name: !Ref 'TaskNameInput'
          Cpu: !FindInMap [TaskSizeMap, !Ref 'TaskSizeInput', cpu]
          Memory: !FindInMap [TaskSizeMap, !Ref 'TaskSizeInput', memory]
          Image: !Ref 'ContainerImageInput'             # input parameter
          PortMappings:
            - ContainerPort: !Ref 'ContainerPortInput'  # input parameter
          
          LogConfiguration:
            LogDriver: 'awslogs'
            Options:
              awslogs-group: !Ref 'TaskNameInput'
                !Sub "${StackName}-PublicSubnetOne"    # output parameter from another CloudFormation template
            - Fn::ImportValue:
                !Sub "${StackName}-PublicSubnetTwo"    # output parameter from another CloudFormation template
      TaskDefinition: !Ref 'TaskDefinition'
      LoadBalancers:
        - ContainerName: !Ref 'TaskNameInput'
          ContainerPort: !Ref 'ContainerPortInput'  # input parameter
          TargetGroupArn: !Ref 'TargetGroup'

  # A target group. This is used for keeping track of all the tasks, and
  # what IP addresses / port numbers they have. You can query it yourself,
  # to use the addresses yourself, but most often this target group is just
  # connected to an application load balancer, or network load balancer, so
  # it can automatically distribute traffic across all the targets.
  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 6
      HealthCheckPath: /
      HealthCheckProtocol: HTTP
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 2
      TargetType: ip
      Name: !Ref 'TaskNameInput'
      Port: !Ref 'ContainerPortInput'
      Protocol: HTTP
      UnhealthyThresholdCount: 2
      VpcId:
        Fn::ImportValue:
          !Sub "${StackName}-VPC"    # output parameter from another CloudFormation template

  # Create a rule on the load balancer for routing traffic to the target group
  LoadBalancerRule:
    Type: AWS::ElasticLoadBalancingV2::ListenerRule
    Properties:
      Actions:
        - TargetGroupArn: !Ref 'TargetGroup'
          Type: 'forward'
      Conditions:
        - Field: path-pattern
          Values:
            - '*'
      ListenerArn: !Ref PublicLoadBalancerListener
      Priority: 1

  # Enable autoscaling for this service
  ScalableTarget:
    Type: AWS::ApplicationAutoScaling::ScalableTarget
    DependsOn: Service
    Properties:
      ServiceNamespace: 'ecs'
      ScalableDimension: 'ecs:service:DesiredCount'
      ResourceId:
        Fn::Join:
          - '/'
          - - service
            - Fn::ImportValue:
                !Sub "${StackName}-ECSCluster"
            - !Ref 'TaskNameInput'
      MinCapacity: 1
      MaxCapacity: 10
      RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService

  # Create scaling policies for the service
  ScaleDownPolicy:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    DependsOn: ScalableTarget
    Properties:
      PolicyName:
        Fn::Join:
          - '/'
          - - scale
            - !Ref 'TaskNameInput'
            - down
      PolicyType: StepScaling
      ResourceId:
        Fn::Join:
          - '/'
          - - service
            - Fn::ImportValue:
                !Sub "${StackName}-ECSCluster"  # output parameter from another CloudFormation template
            - !Ref 'TaskNameInput'
      ScalableDimension: 'ecs:service:DesiredCount'
      ServiceNamespace: 'ecs'
      StepScalingPolicyConfiguration:
        AdjustmentType: 'ChangeInCapacity'
        StepAdjustments:
          - MetricIntervalUpperBound: 0
            ScalingAdjustment: -1
        MetricAggregationType: 'Average'
        Cooldown: 60

  ScaleUpPolicy:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    DependsOn: ScalableTarget
    Properties:
      PolicyName:
        Fn::Join:
          - '/'
          - - scale
            - !Ref 'TaskNameInput'
            - up
      PolicyType: StepScaling
      ResourceId:
        Fn::Join:
          - '/'
          - - service
            - Fn::ImportValue:
                !Sub "${StackName}-ECSCluster"
            - !Ref 'TaskNameInput'
      ScalableDimension: 'ecs:service:DesiredCount'
      ServiceNamespace: 'ecs'
      StepScalingPolicyConfiguration:
        AdjustmentType: 'ChangeInCapacity'
        StepAdjustments:
          - MetricIntervalLowerBound: 0
            MetricIntervalUpperBound: 15
            ScalingAdjustment: 1
          - MetricIntervalLowerBound: 15
            MetricIntervalUpperBound: 25
            ScalingAdjustment: 2
          - MetricIntervalLowerBound: 25
            ScalingAdjustment: 3
        MetricAggregationType: 'Average'
        Cooldown: 60

  # Create alarms to trigger these policies
  LowCpuUsageAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName:
        Fn::Join:
          - '-'
          - - low-cpu
            - !Ref 'TaskNameInput'
      AlarmDescription:
        Fn::Join:
          - ' '
          - - "Low CPU utilization for service"
            - !Ref 'TaskNameInput'
      MetricName: CPUUtilization
      Namespace: AWS/ECS
      Dimensions:
        - Name: ServiceName
          Value: !Ref 'TaskNameInput'
        - Name: ClusterName
          Value:
            Fn::ImportValue:
              !Sub "${StackName}-ECSCluster"
      Statistic: Average
      Period: 60
      EvaluationPeriods: 1
      Threshold: 20
      ComparisonOperator: LessThanOrEqualToThreshold
      AlarmActions:
        - !Ref ScaleDownPolicy

  HighCpuUsageAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName:
        Fn::Join:
          - '-'
          - - high-cpu
            - !Ref 'TaskNameInput'
      AlarmDescription:
        Fn::Join:
          - ' '
          - - "High CPU utilization for service"
            - !Ref 'TaskNameInput'
      MetricName: CPUUtilization
      Namespace: AWS/ECS
      Dimensions:
        - Name: ServiceName
          Value: !Ref 'TaskNameInput'
        - Name: ClusterName
          Value:
            Fn::ImportValue:
              !Sub "${StackName}-ECSCluster"
      Statistic: Average
      Period: 60
      EvaluationPeriods: 1
      Threshold: 70
      ComparisonOperator: GreaterThanOrEqualToThreshold
      AlarmActions:
        - !Ref ScaleUpPolicy

  EcsSecurityGroupIngressFromPublicALB:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      Description: Ingress from the public ALB
      GroupId:
        Fn::ImportValue:
          !Sub "${StackName}-ContainerSecurityGroup"
      IpProtocol: -1
      SourceSecurityGroupId: !Ref 'PublicLoadBalancerSG'

  # Public load balancer, hosted in public subnets that is accessible
  # to the public, and is intended to route traffic to one or more public
  # facing services. This is used for accepting traffic from the public
  # internet and directing it to public facing microservices
  PublicLoadBalancerSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Access to the public facing load balancer
      VpcId:
        Fn::ImportValue:
          !Sub "${StackName}-VPC"
      SecurityGroupIngress:
          # Allow access to ALB from anywhere on the internet
          - CidrIp: 0.0.0.0/0
            IpProtocol: -1

  PublicLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Scheme: internet-facing
      LoadBalancerAttributes:
      - Key: idle_timeout.timeout_seconds
        Value: '30'
      Subnets:
        # The load balancer is placed into the public subnets, so that traffic
        # from the internet can reach the load balancer directly via the internet gateway
        - Fn::ImportValue:
            !Sub "${StackName}-PublicSubnetOne"
        - Fn::ImportValue:
            !Sub "${StackName}-PublicSubnetTwo"
      SecurityGroups: [!Ref 'PublicLoadBalancerSG']

  PublicLoadBalancerListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    DependsOn:
      - PublicLoadBalancer
    Properties:
      DefaultActions:
        - TargetGroupArn: !Ref 'TargetGroup'
          Type: 'forward'
      LoadBalancerArn: !Ref 'PublicLoadBalancer'
      Port: 80
      Protocol: HTTP
# These output values will be available to other templates to use.
Outputs:
  ServiceEndpoint:        # output
    Description: The URL to access the service
    Value: !Sub "http://${PublicLoadBalancer.DNSName}"
```

您可以調整這些檔案以搭配 使用 AWS Proton。

## 將您的基礎設施做為程式碼帶到 AWS Proton
<a name="proton-tmp-files"></a>

只要稍微修改，您就可以使用[範例 1](#ag-env-cfn-example) 做為環境範本套件的基礎設施做為程式碼 (IaC) 檔案，該套件 AWS Proton 使用 來部署環境 （如[範例 3](#ag-proton-env-cfn-example) 所示）。

您可以使用 [Jinja](https://jinja.palletsprojects.com/en/2.11.x/templates/) 語法來參考您在 [Open API](https://swagger.io/docs/specification/data-models/) 型[結構描述檔案中](ag-schema.md)定義的參數，而不是使用 CloudFormation 參數。為了方便起見，系統會對這些輸入參數進行註解，並在 IaC 檔案中多次參考。如此一來， AWS Proton 就可以稽核和檢查參數值。它也可以將一個 IaC 檔案中的輸出參數值比對並插入另一個 IaC 檔案中的參數。

身為管理員，您可以將命名空間新增至 AWS Proton `environment.inputs.`輸入參數。當您在服務 IaC 檔案中參考環境 IaC 檔案輸出時，您可以將`environment.outputs.`命名空間新增至輸出 （例如，`environment.outputs.ClusterName`)。最後，用大括號和引號括住它們。

透過這些修改，您的 CloudFormation IaC 檔案可供 使用 AWS Proton。

### 範例 3：作為程式碼檔案 AWS Proton 的環境基礎設施
<a name="ag-proton-env-cfn-example"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Description: AWS Fargate cluster running containers in a public subnet. Only supports
             public facing load balancer, and public service discovery prefixes.
Mappings:
  # The VPC and subnet configuration is passed in via the environment spec.
  SubnetConfig:
    VPC:
      CIDR: '{{ environment.inputs.vpc_cidr}}'        # input parameter
    PublicOne:
      CIDR: '{{ environment.inputs.subnet_one_cidr}}' # input parameter
    PublicTwo:
      CIDR: '{{ environment.inputs.subnet_two_cidr}}' # input parameter
Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      EnableDnsSupport: true
      EnableDnsHostnames: true
      CidrBlock: !FindInMap ['SubnetConfig', 'VPC', 'CIDR']

  # Two public subnets, where containers will have public IP addresses
  PublicSubnetOne:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone:
         Fn::Select:
         - 0
         - Fn::GetAZs: {Ref: 'AWS::Region'}
      VpcId: !Ref 'VPC'
      CidrBlock: !FindInMap ['SubnetConfig', 'PublicOne', 'CIDR']
      MapPublicIpOnLaunch: true

  PublicSubnetTwo:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone:
         Fn::Select:
         - 1
         - Fn::GetAZs: {Ref: 'AWS::Region'}
      VpcId: !Ref 'VPC'
      CidrBlock: !FindInMap ['SubnetConfig', 'PublicTwo', 'CIDR']
      MapPublicIpOnLaunch: true

  # Setup networking resources for the public subnets. Containers
  # in the public subnets have public IP addresses and the routing table
  # sends network traffic via the internet gateway.
  InternetGateway:
    Type: AWS::EC2::InternetGateway
  GatewayAttachement:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref 'VPC'
      InternetGatewayId: !Ref 'InternetGateway'
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref 'VPC'
  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: GatewayAttachement
    Properties:
      RouteTableId: !Ref 'PublicRouteTable'
      DestinationCidrBlock: '0.0.0.0/0'
      GatewayId: !Ref 'InternetGateway'
  PublicSubnetOneRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetOne
      RouteTableId: !Ref PublicRouteTable
  PublicSubnetTwoRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetTwo
      RouteTableId: !Ref PublicRouteTable

  # ECS Resources
  ECSCluster:
    Type: AWS::ECS::Cluster

  # A security group for the containers we will run in Fargate.
  # Rules are added to this security group based on what ingress you
  # add for the cluster.
  ContainerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Access to the Fargate containers
      VpcId: !Ref 'VPC'

  # This is a role which is used by the ECS tasks themselves.
  ECSTaskExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: [ecs-tasks.amazonaws.com]
          Action: ['sts:AssumeRole']
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy'

# These output values are available to service infrastructure as code files as outputs, when given the 
# the 'service_instance.environment.outputs.' namespace, for example, service_instance.environment.outputs.ClusterName.

Outputs:
  ClusterName:                                            # output
    Description: The name of the ECS cluster
    Value: !Ref 'ECSCluster'
  ECSTaskExecutionRole:                                   # output
    Description: The ARN of the ECS role
    Value: !GetAtt 'ECSTaskExecutionRole.Arn'
  VpcId:                                                  # output
    Description: The ID of the VPC that this stack is deployed in
    Value: !Ref 'VPC'
  PublicSubnetOne:                                        # output
    Description: Public subnet one
    Value: !Ref 'PublicSubnetOne'
  PublicSubnetTwo:                                        # output
    Description: Public subnet two
    Value: !Ref 'PublicSubnetTwo'
  ContainerSecurityGroup:                                 # output
    Description: A security group used to allow Fargate containers to receive traffic
    Value: !Ref 'ContainerSecurityGroup'
```

[範例 1 ](#ag-env-cfn-example)和範例 3 中的 IaC 檔案會產生略有不同的 CloudFormation 堆疊。 [範例 3：作為程式碼檔案 AWS Proton 的環境基礎設施](#ag-proton-env-cfn-example)參數在堆疊範本檔案中顯示的方式不同。*範例 1* CloudFormation 堆疊範本檔案會在堆疊範本檢視中顯示參數標籤 （索引鍵）。*範例 3* AWS Proton CloudFormation 基礎設施堆疊範本檔案會顯示參數值。 AWS Proton 輸入參數*不*會顯示在主控台 CloudFormation 堆疊參數檢視中。

在[範例 4](#ag-proton-svc-cfn-example) 中， AWS Proton 服務 IaC 檔案對應於[範例 2](#ag-svc-cfn-example)。

### 範例 4： AWS Proton 服務執行個體 IaC 檔案
<a name="ag-proton-svc-cfn-example"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Description: Deploy a service on AWS Fargate, hosted in a public subnet, and accessible via a public load balancer.
Mappings:
  TaskSize:
    x-small:
      cpu: 256
      memory: 512
    small:
      cpu: 512
      memory: 1024
    medium:
      cpu: 1024
      memory: 2048
    large:
      cpu: 2048
      memory: 4096
    x-large:
      cpu: 4096
      memory: 8192
Resources:
  # A log group for storing the stdout logs from this service's containers
  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: '{{service_instance.name}}' # resource parameter

  # The task definition. This is a simple metadata description of what
  # container to run, and what resource requirements it has.
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Family: '{{service_instance.name}}'
      Cpu: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, cpu] # input parameter
      Memory: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, memory] 
      NetworkMode: awsvpc
      RequiresCompatibilities:
        - FARGATE
      ExecutionRoleArn: '{{environment.outputs.ECSTaskExecutionRole}}' # output from an environment infrastructure as code file
      TaskRoleArn: !Ref "AWS::NoValue"
      ContainerDefinitions:
        - Name: '{{service_instance.name}}'
          Cpu: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, cpu]
          Memory: !FindInMap [TaskSize, {{service_instance.inputs.task_size}}, memory]
          Image: '{{service_instance.inputs.image}}'
          PortMappings:
            - ContainerPort: '{{service_instance.inputs.port}}' # input parameter
          LogConfiguration:
            LogDriver: 'awslogs'
            Options:
              awslogs-group: '{{service_instance.name}}'
              awslogs-region: !Ref 'AWS::Region'
              awslogs-stream-prefix: '{{service_instance.name}}'

  # The service_instance. The service is a resource which allows you to run multiple
  # copies of a type of task, and gather up their logs and metrics, as well
  # as monitor the number of running tasks and replace any that have crashed
  Service:
    Type: AWS::ECS::Service
    DependsOn: LoadBalancerRule
    Properties:
      ServiceName: '{{service_instance.name}}'
      Cluster: '{{environment.outputs.ClusterName}}' # output from an environment infrastructure as code file
      LaunchType: FARGATE
      DeploymentConfiguration:
        MaximumPercent: 200
        MinimumHealthyPercent: 75
      DesiredCount: '{{service_instance.inputs.desired_count}}'       # input parameter
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: ENABLED
          SecurityGroups:
            - '{{environment.outputs.ContainerSecurityGroup}}' # output from an environment infrastructure as code file
          Subnets:
            - '{{environment.outputs.PublicSubnetOne}}'        # output from an environment infrastructure as code file
            - '{{environment.outputs.PublicSubnetTwo}}'
      TaskDefinition: !Ref 'TaskDefinition'
      LoadBalancers:
        - ContainerName: '{{service_instance.name}}'
          ContainerPort: '{{service_instance.inputs.port}}'
          TargetGroupArn: !Ref 'TargetGroup'

  # A target group. This is used for keeping track of all the tasks, and
  # what IP addresses / port numbers they have. You can query it yourself,
  # to use the addresses yourself, but most often this target group is just
  # connected to an application load balancer, or network load balancer, so
  # it can automatically distribute traffic across all the targets.
  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 6
      HealthCheckPath: /
      HealthCheckProtocol: HTTP
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 2
      TargetType: ip
      Name: '{{service_instance.name}}'
      Port: '{{service_instance.inputs.port}}'
      Protocol: HTTP
      UnhealthyThresholdCount: 2
      VpcId: '{{environment.outputs.VpcId}}' # output from an environment infrastructure as code file

  # Create a rule on the load balancer for routing traffic to the target group
  LoadBalancerRule:
    Type: AWS::ElasticLoadBalancingV2::ListenerRule
    Properties:
      Actions:
        - TargetGroupArn: !Ref 'TargetGroup'
          Type: 'forward'
      Conditions:
        - Field: path-pattern
          Values:
            - '*'
      ListenerArn: !Ref PublicLoadBalancerListener
      Priority: 1

  # Enable autoscaling for this service
  ScalableTarget:
    Type: AWS::ApplicationAutoScaling::ScalableTarget
    DependsOn: Service
    Properties:
      ServiceNamespace: 'ecs'
      ScalableDimension: 'ecs:service:DesiredCount'
      ResourceId:
        Fn::Join:
          - '/'
          - - service
            - '{{environment.outputs.ClusterName}}' # output from an environment infrastructure as code file
            - '{{service_instance.name}}'
      MinCapacity: 1
      MaxCapacity: 10
      RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService

  # Create scaling policies for the service
  ScaleDownPolicy:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    DependsOn: ScalableTarget
    Properties:
      PolicyName:
        Fn::Join:
          - '/'
          - - scale
            - '{{service_instance.name}}'
            - down
      PolicyType: StepScaling
      ResourceId:
        Fn::Join:
          - '/'
          - - service
            - '{{environment.outputs.ClusterName}}'
            - '{{service_instance.name}}'
      ScalableDimension: 'ecs:service:DesiredCount'
      ServiceNamespace: 'ecs'
      StepScalingPolicyConfiguration:
        AdjustmentType: 'ChangeInCapacity'
        StepAdjustments:
          - MetricIntervalUpperBound: 0
            ScalingAdjustment: -1
        MetricAggregationType: 'Average'
        Cooldown: 60

  ScaleUpPolicy:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    DependsOn: ScalableTarget
    Properties:
      PolicyName:
        Fn::Join:
          - '/'
          - - scale
            - '{{service_instance.name}}'
            - up
      PolicyType: StepScaling
      ResourceId:
        Fn::Join:
          - '/'
          - - service
            - '{{environment.outputs.ClusterName}}'
            - '{{service_instance.name}}'
      ScalableDimension: 'ecs:service:DesiredCount'
      ServiceNamespace: 'ecs'
      StepScalingPolicyConfiguration:
        AdjustmentType: 'ChangeInCapacity'
        StepAdjustments:
          - MetricIntervalLowerBound: 0
            MetricIntervalUpperBound: 15
            ScalingAdjustment: 1
          - MetricIntervalLowerBound: 15
            MetricIntervalUpperBound: 25
            ScalingAdjustment: 2
          - MetricIntervalLowerBound: 25
            ScalingAdjustment: 3
        MetricAggregationType: 'Average'
        Cooldown: 60

  # Create alarms to trigger these policies
  LowCpuUsageAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName:
        Fn::Join:
          - '-'
          - - low-cpu
            - '{{service_instance.name}}'
      AlarmDescription:
        Fn::Join:
          - ' '
          - - "Low CPU utilization for service"
            - '{{service_instance.name}}'
      MetricName: CPUUtilization
      Namespace: AWS/ECS
      Dimensions:
        - Name: ServiceName
          Value: '{{service_instance.name}}'
        - Name: ClusterName
          Value:
            '{{environment.outputs.ClusterName}}'
      Statistic: Average
      Period: 60
      EvaluationPeriods: 1
      Threshold: 20
      ComparisonOperator: LessThanOrEqualToThreshold
      AlarmActions:
        - !Ref ScaleDownPolicy

  HighCpuUsageAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName:
        Fn::Join:
          - '-'
          - - high-cpu
            - '{{service_instance.name}}'
      AlarmDescription:
        Fn::Join:
          - ' '
          - - "High CPU utilization for service"
            - '{{service_instance.name}}'
      MetricName: CPUUtilization
      Namespace: AWS/ECS
      Dimensions:
        - Name: ServiceName
          Value: '{{service_instance.name}}'
        - Name: ClusterName
          Value:
            '{{environment.outputs.ClusterName}}'
      Statistic: Average
      Period: 60
      EvaluationPeriods: 1
      Threshold: 70
      ComparisonOperator: GreaterThanOrEqualToThreshold
      AlarmActions:
        - !Ref ScaleUpPolicy

  EcsSecurityGroupIngressFromPublicALB:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      Description: Ingress from the public ALB
      GroupId: '{{environment.outputs.ContainerSecurityGroup}}'
      IpProtocol: -1
      SourceSecurityGroupId: !Ref 'PublicLoadBalancerSG'

  # Public load balancer, hosted in public subnets that is accessible
  # to the public, and is intended to route traffic to one or more public
  # facing services. This is used for accepting traffic from the public
  # internet and directing it to public facing microservices
  PublicLoadBalancerSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Access to the public facing load balancer
      VpcId: '{{environment.outputs.VpcId}}'
      SecurityGroupIngress:
          # Allow access to ALB from anywhere on the internet
          - CidrIp: 0.0.0.0/0
            IpProtocol: -1

  PublicLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Scheme: internet-facing
      LoadBalancerAttributes:
      - Key: idle_timeout.timeout_seconds
        Value: '30'
      Subnets:
        # The load balancer is placed into the public subnets, so that traffic
        # from the internet can reach the load balancer directly via the internet gateway
        - '{{environment.outputs.PublicSubnetOne}}'
        - '{{environment.outputs.PublicSubnetTwo}}'
      SecurityGroups: [!Ref 'PublicLoadBalancerSG']

  PublicLoadBalancerListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    DependsOn:
      - PublicLoadBalancer
    Properties:
      DefaultActions:
        - TargetGroupArn: !Ref 'TargetGroup'
          Type: 'forward'
      LoadBalancerArn: !Ref 'PublicLoadBalancer'
      Port: 80
      Protocol: HTTP
Outputs:
  ServiceEndpoint:         # output
    Description: The URL to access the service
    Value: !Sub "http://${PublicLoadBalancer.DNSName}"
```

在[範例 5](#ag-proton-pipeline-cfn-example) 中， AWS Proton 管道 IaC 檔案佈建管道基礎設施，以支援[範例 4 ](#ag-proton-svc-cfn-example)佈建的服務執行個體。

### 範例 5： AWS Proton 服務管道 IaC 檔案
<a name="ag-proton-pipeline-cfn-example"></a>

```
Resources:
  ECRRepo:
    Type: AWS::ECR::Repository
    DeletionPolicy: Retain
  BuildProject:
    Type: AWS::CodeBuild::Project
    Properties:
      Artifacts:
        Type: CODEPIPELINE
      Environment:
        ComputeType: BUILD_GENERAL1_SMALL
        Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0
        PrivilegedMode: true
        Type: LINUX_CONTAINER
        EnvironmentVariables:
        - Name: repo_name
          Type: PLAINTEXT
          Value: !Ref ECRRepo
        - Name: service_name
          Type: PLAINTEXT
          Value: '{{ service.name }}'    # resource parameter
      ServiceRole:
        Fn::GetAtt:
          - PublishRole
          - Arn
      Source:
        BuildSpec:
          Fn::Join:
            - ""
            - - >-
                {
                  "version": "0.2",
                  "phases": {
                    "install": {
                      "runtime-versions": {
                        "docker": 18
                      },
                      "commands": [
                        "pip3 install --upgrade --user awscli",
                        "echo 'f6bd1536a743ab170b35c94ed4c7c4479763356bd543af5d391122f4af852460  yq_linux_amd64' > yq_linux_amd64.sha",
                        "wget https://github.com/mikefarah/yq/releases/download/3.4.0/yq_linux_amd64",
                        "sha256sum -c yq_linux_amd64.sha",
                        "mv yq_linux_amd64 /usr/bin/yq",
                        "chmod +x /usr/bin/yq"
                      ]
                    },
                    "pre_build": {
                      "commands": [
                        "cd $CODEBUILD_SRC_DIR",
                        "$(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)",
                        "{{ pipeline.inputs.unit_test_command }}",    # input parameter
                      ]
                    },
                    "build": {
                      "commands": [
                        "IMAGE_REPO_NAME=$repo_name",
                        "IMAGE_TAG=$CODEBUILD_BUILD_NUMBER",
                        "IMAGE_ID=
              - Ref: AWS::AccountId
              - >-
                .dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG",
                        "docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG -f {{ pipeline.inputs.dockerfile }} .",     # input parameter
                        "docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $IMAGE_ID;",
                        "docker push $IMAGE_ID"
                      ]
                    },
                    "post_build": {
                      "commands": [
                        "aws proton --region $AWS_DEFAULT_REGION get-service --name $service_name | jq -r .service.spec > service.yaml",
                        "yq w service.yaml 'instances[*].spec.image' \"$IMAGE_ID\" > rendered_service.yaml"
                      ]
                    }
                  },
                  "artifacts": {
                    "files": [
                      "rendered_service.yaml"
                    ]
                  }
                }
        Type: CODEPIPELINE
      EncryptionKey:
        Fn::GetAtt:
          - PipelineArtifactsBucketEncryptionKey
          - Arn
{% for service_instance in service_instances %}
  Deploy{{loop.index}}Project:
    Type: AWS::CodeBuild::Project
    Properties:
      Artifacts:
        Type: CODEPIPELINE
      Environment:
        ComputeType: BUILD_GENERAL1_SMALL
        Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0
        PrivilegedMode: false
        Type: LINUX_CONTAINER
        EnvironmentVariables:
        - Name: service_name
          Type: PLAINTEXT
          Value:  '{{service.name}}'          # resource parameter
        - Name: service_instance_name
          Type: PLAINTEXT
          Value: '{{service_instance.name}}'  # resource parameter
      ServiceRole:
        Fn::GetAtt:
          - DeploymentRole
          - Arn
      Source:
        BuildSpec: >-
          {
            "version": "0.2",
            "phases": {
              "build": {
                "commands": [
                  "pip3 install --upgrade --user awscli",
                  "aws proton --region $AWS_DEFAULT_REGION update-service-instance --deployment-type CURRENT_VERSION --name $service_instance_name --service-name $service_name --spec file://rendered_service.yaml",
                  "aws proton --region $AWS_DEFAULT_REGION wait service-instance-deployed --name $service_instance_name --service-name $service_name"
                ]
              }
            }
          }
        Type: CODEPIPELINE
      EncryptionKey:
        Fn::GetAtt:
          - PipelineArtifactsBucketEncryptionKey
          - Arn
{% endfor %}
  # This role is used to build and publish an image to ECR
  PublishRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: codebuild.amazonaws.com
        Version: "2012-10-17"		 	 	 
  PublishRoleDefaultPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Action:
              - logs:CreateLogGroup
              - logs:CreateLogStream
              - logs:PutLogEvents
            Effect: Allow
            Resource:
              - Fn::Join:
                  - ""
                  - - "arn:"
                    - Ref: AWS::Partition
                    - ":logs:"
                    - Ref: AWS::Region
                    - ":"
                    - Ref: AWS::AccountId
                    - :log-group:/aws/codebuild/
                    - Ref: BuildProject
              - Fn::Join:
                  - ""
                  - - "arn:"
                    - Ref: AWS::Partition
                    - ":logs:"
                    - Ref: AWS::Region
                    - ":"
                    - Ref: AWS::AccountId
                    - :log-group:/aws/codebuild/
                    - Ref: BuildProject
                    - :*
          - Action:
              - codebuild:CreateReportGroup
              - codebuild:CreateReport
              - codebuild:UpdateReport
              - codebuild:BatchPutTestCases
            Effect: Allow
            Resource:
              Fn::Join:
                - ""
                - - "arn:"
                  - Ref: AWS::Partition
                  - ":codebuild:"
                  - Ref: AWS::Region
                  - ":"
                  - Ref: AWS::AccountId
                  - :report-group/
                  - Ref: BuildProject
                  - -*
          - Action:
              - ecr:GetAuthorizationToken
            Effect: Allow
            Resource: "*"
          - Action:
              - ecr:BatchCheckLayerAvailability
              - ecr:CompleteLayerUpload
              - ecr:GetAuthorizationToken
              - ecr:InitiateLayerUpload
              - ecr:PutImage
              - ecr:UploadLayerPart
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - ECRRepo
                - Arn
          - Action:
              - proton:GetService
            Effect: Allow
            Resource: "*"
          - Action:
              - s3:GetObject*
              - s3:GetBucket*
              - s3:List*
              - s3:DeleteObject*
              - s3:PutObject*
              - s3:Abort*
            Effect: Allow
            Resource:
              - Fn::GetAtt:
                  - PipelineArtifactsBucket
                  - Arn
              - Fn::Join:
                  - ""
                  - - Fn::GetAtt:
                        - PipelineArtifactsBucket
                        - Arn
                    - /*
          - Action:
              - kms:Decrypt
              - kms:DescribeKey
              - kms:Encrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - PipelineArtifactsBucketEncryptionKey
                - Arn
          - Action:
              - kms:Decrypt
              - kms:Encrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - PipelineArtifactsBucketEncryptionKey
                - Arn
        Version: "2012-10-17"		 	 	 
      PolicyName: PublishRoleDefaultPolicy
      Roles:
        - Ref: PublishRole

  DeploymentRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: codebuild.amazonaws.com
        Version: "2012-10-17"		 	 	 
  DeploymentRoleDefaultPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Action:
              - logs:CreateLogGroup
              - logs:CreateLogStream
              - logs:PutLogEvents
            Effect: Allow
            Resource:
              - Fn::Join:
                  - ""
                  - - "arn:"
                    - Ref: AWS::Partition
                    - ":logs:"
                    - Ref: AWS::Region
                    - ":"
                    - Ref: AWS::AccountId
                    - :log-group:/aws/codebuild/Deploy*Project*
              - Fn::Join:
                  - ""
                  - - "arn:"
                    - Ref: AWS::Partition
                    - ":logs:"
                    - Ref: AWS::Region
                    - ":"
                    - Ref: AWS::AccountId
                    - :log-group:/aws/codebuild/Deploy*Project:*
          - Action:
              - codebuild:CreateReportGroup
              - codebuild:CreateReport
              - codebuild:UpdateReport
              - codebuild:BatchPutTestCases
            Effect: Allow
            Resource:
              Fn::Join:
                - ""
                - - "arn:"
                  - Ref: AWS::Partition
                  - ":codebuild:"
                  - Ref: AWS::Region
                  - ":"
                  - Ref: AWS::AccountId
                  - :report-group/Deploy*Project
                  - -*
          - Action:
              - proton:UpdateServiceInstance
              - proton:GetServiceInstance
            Effect: Allow
            Resource: "*"
          - Action:
              - s3:GetObject*
              - s3:GetBucket*
              - s3:List*
            Effect: Allow
            Resource:
              - Fn::GetAtt:
                  - PipelineArtifactsBucket
                  - Arn
              - Fn::Join:
                  - ""
                  - - Fn::GetAtt:
                        - PipelineArtifactsBucket
                        - Arn
                    - /*
          - Action:
              - kms:Decrypt
              - kms:DescribeKey
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - PipelineArtifactsBucketEncryptionKey
                - Arn
          - Action:
              - kms:Decrypt
              - kms:Encrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - PipelineArtifactsBucketEncryptionKey
                - Arn
        Version: "2012-10-17"		 	 	 
      PolicyName: DeploymentRoleDefaultPolicy
      Roles:
        - Ref: DeploymentRole
  PipelineArtifactsBucketEncryptionKey:
    Type: AWS::KMS::Key
    Properties:
      KeyPolicy:
        Statement:
          - Action:
              - kms:Create*
              - kms:Describe*
              - kms:Enable*
              - kms:List*
              - kms:Put*
              - kms:Update*
              - kms:Revoke*
              - kms:Disable*
              - kms:Get*
              - kms:Delete*
              - kms:ScheduleKeyDeletion
              - kms:CancelKeyDeletion
              - kms:GenerateDataKey
              - kms:TagResource
              - kms:UntagResource
            Effect: Allow
            Principal:
              AWS:
                Fn::Join:
                  - ""
                  - - "arn:"
                    - Ref: AWS::Partition
                    - ":iam::"
                    - Ref: AWS::AccountId
                    - :root
            Resource: "*"
          - Action:
              - kms:Decrypt
              - kms:DescribeKey
              - kms:Encrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
            Effect: Allow
            Principal:
              AWS:
                Fn::GetAtt:
                  - PipelineRole
                  - Arn
            Resource: "*"
          - Action:
              - kms:Decrypt
              - kms:DescribeKey
              - kms:Encrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
            Effect: Allow
            Principal:
              AWS:
                Fn::GetAtt:
                  - PublishRole
                  - Arn
            Resource: "*"
          - Action:
              - kms:Decrypt
              - kms:Encrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
            Effect: Allow
            Principal:
              AWS:
                Fn::GetAtt:
                  - PublishRole
                  - Arn
            Resource: "*"
          - Action:
              - kms:Decrypt
              - kms:DescribeKey
            Effect: Allow
            Principal:
              AWS:
                Fn::GetAtt:
                  - DeploymentRole
                  - Arn
            Resource: "*"
          - Action:
              - kms:Decrypt
              - kms:Encrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
            Effect: Allow
            Principal:
              AWS:
                Fn::GetAtt:
                  - DeploymentRole
                  - Arn
            Resource: "*"
        Version: "2012-10-17"		 	 	 
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
  PipelineArtifactsBucket:
    Type: AWS::S3::Bucket
    Properties:
      VersioningConfiguration:
        Status: Enabled
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              KMSMasterKeyID:
                Fn::GetAtt:
                  - PipelineArtifactsBucketEncryptionKey
                  - Arn
              SSEAlgorithm: aws:kms
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
  PipelineArtifactsBucketEncryptionKeyAlias:
    Type: AWS::KMS::Alias
    Properties:
      AliasName: 'alias/codepipeline-encryption-key-{{ service.name }}'
      TargetKeyId:
        Fn::GetAtt:
          - PipelineArtifactsBucketEncryptionKey
          - Arn
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
  PipelineRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: codepipeline.amazonaws.com
        Version: "2012-10-17"		 	 	 
  PipelineRoleDefaultPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Action:
              - s3:GetObject*
              - s3:GetBucket*
              - s3:List*
              - s3:DeleteObject*
              - s3:PutObject*
              - s3:Abort*
            Effect: Allow
            Resource:
              - Fn::GetAtt:
                  - PipelineArtifactsBucket
                  - Arn
              - Fn::Join:
                  - ""
                  - - Fn::GetAtt:
                        - PipelineArtifactsBucket
                        - Arn
                    - /*
          - Action:
              - kms:Decrypt
              - kms:DescribeKey
              - kms:Encrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - PipelineArtifactsBucketEncryptionKey
                - Arn
          - Action: codestar-connections:*
            Effect: Allow
            Resource: "*"
          - Action: sts:AssumeRole
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - PipelineBuildCodePipelineActionRole
                - Arn
          - Action: sts:AssumeRole
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - PipelineDeployCodePipelineActionRole
                - Arn
        Version: "2012-10-17"		 	 	 
      PolicyName: PipelineRoleDefaultPolicy
      Roles:
        - Ref: PipelineRole
  Pipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      RoleArn:
        Fn::GetAtt:
          - PipelineRole
          - Arn
      Stages:
        - Actions:
            - ActionTypeId:
                Category: Source
                Owner: AWS
                Provider: CodeStarSourceConnection
                Version: "1"
              Configuration:
                ConnectionArn: '{{ service.repository_connection_arn }}'
                FullRepositoryId: '{{ service.repository_id }}'
                BranchName: '{{ service.branch_name }}'
              Name: Checkout
              OutputArtifacts:
                - Name: Artifact_Source_Checkout
              RunOrder: 1
          Name: Source
        - Actions:
            - ActionTypeId:
                Category: Build
                Owner: AWS
                Provider: CodeBuild
                Version: "1"
              Configuration:
                ProjectName:
                  Ref: BuildProject
              InputArtifacts:
                - Name: Artifact_Source_Checkout
              Name: Build
              OutputArtifacts:
                - Name: BuildOutput
              RoleArn:
                Fn::GetAtt:
                  - PipelineBuildCodePipelineActionRole
                  - Arn
              RunOrder: 1
          Name: Build {%- for service_instance in service_instances %}
        - Actions:
            - ActionTypeId:
                Category: Build
                Owner: AWS
                Provider: CodeBuild
                Version: "1"
              Configuration:
                ProjectName:
                  Ref: Deploy{{loop.index}}Project
              InputArtifacts:
                - Name: BuildOutput
              Name: Deploy
              RoleArn:
                Fn::GetAtt:
                  - PipelineDeployCodePipelineActionRole
                  - Arn
              RunOrder: 1
          Name: 'Deploy{{service_instance.name}}'
{%- endfor %}
      ArtifactStore:
        EncryptionKey:
          Id:
            Fn::GetAtt:
              - PipelineArtifactsBucketEncryptionKey
              - Arn
          Type: KMS
        Location:
          Ref: PipelineArtifactsBucket
        Type: S3
    DependsOn:
      - PipelineRoleDefaultPolicy
      - PipelineRole
  PipelineBuildCodePipelineActionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              AWS:
                Fn::Join:
                  - ""
                  - - "arn:"
                    - Ref: AWS::Partition
                    - ":iam::"
                    - Ref: AWS::AccountId
                    - :root
        Version: "2012-10-17"		 	 	 
  PipelineBuildCodePipelineActionRoleDefaultPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Action:
              - codebuild:BatchGetBuilds
              - codebuild:StartBuild
              - codebuild:StopBuild
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - BuildProject
                - Arn
        Version: "2012-10-17"		 	 	 
      PolicyName: PipelineBuildCodePipelineActionRoleDefaultPolicy
      Roles:
        - Ref: PipelineBuildCodePipelineActionRole
  PipelineDeployCodePipelineActionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              AWS:
                Fn::Join:
                  - ""
                  - - "arn:"
                    - Ref: AWS::Partition
                    - ":iam::"
                    - Ref: AWS::AccountId
                    - :root
        Version: "2012-10-17"		 	 	 
  PipelineDeployCodePipelineActionRoleDefaultPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Action:
              - codebuild:BatchGetBuilds
              - codebuild:StartBuild
              - codebuild:StopBuild
            Effect: Allow
            Resource:
              Fn::Join:
                - ""
                - - "arn:"
                  - Ref: AWS::Partition
                  - ":codebuild:"
                  - Ref: AWS::Region
                  - ":"
                  - Ref: AWS::AccountId
                  - ":project/Deploy*"
        Version: "2012-10-17"		 	 	 
      PolicyName: PipelineDeployCodePipelineActionRoleDefaultPolicy
      Roles:
        - Ref: PipelineDeployCodePipelineActionRole
Outputs:
  PipelineEndpoint:
    Description: The URL to access the pipeline
    Value: !Sub "https://${AWS::Region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${Pipeline}/view?region=${AWS::Region}"

                ]
              }
            }
          }
        Type: CODEPIPELINE
      EncryptionKey:
        Fn::GetAtt:
          - PipelineArtifactsBucketEncryptionKey
          - Arn
{% endfor %}
  # This role is used to build and publish an image to ECR
  PublishRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: codebuild.amazonaws.com
        Version: "2012-10-17"		 	 	 
  PublishRoleDefaultPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Action:
              - logs:CreateLogGroup
              - logs:CreateLogStream
              - logs:PutLogEvents
            Effect: Allow
            Resource:
              - Fn::Join:
                  - ""
                  - - "arn:"
                    - Ref: AWS::Partition
                    - ":logs:"
                    - Ref: AWS::Region
                    - ":"
                    - Ref: AWS::AccountId
                    - :log-group:/aws/codebuild/
                    - Ref: BuildProject
              - Fn::Join:
                  - ""
                  - - "arn:"
                    - Ref: AWS::Partition
                    - ":logs:"
                    - Ref: AWS::Region
                    - ":"
                    - Ref: AWS::AccountId
                    - :log-group:/aws/codebuild/
                    - Ref: BuildProject
                    - :*
          - Action:
              - codebuild:CreateReportGroup
              - codebuild:CreateReport
              - codebuild:UpdateReport
              - codebuild:BatchPutTestCases
            Effect: Allow
            Resource:
              Fn::Join:
                - ""
                - - "arn:"
                  - Ref: AWS::Partition
                  - ":codebuild:"
                  - Ref: AWS::Region
                  - ":"
                  - Ref: AWS::AccountId
                  - :report-group/
                  - Ref: BuildProject
                  - -*
          - Action:
              - ecr:GetAuthorizationToken
            Effect: Allow
            Resource: "*"
          - Action:
              - ecr:BatchCheckLayerAvailability
              - ecr:CompleteLayerUpload
              - ecr:GetAuthorizationToken
              - ecr:InitiateLayerUpload
              - ecr:PutImage
              - ecr:UploadLayerPart
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - ECRRepo
                - Arn
          - Action:
              - proton:GetService
            Effect: Allow
            Resource: "*"
          - Action:
              - s3:GetObject*
              - s3:GetBucket*
              - s3:List*
              - s3:DeleteObject*
              - s3:PutObject*
              - s3:Abort*
            Effect: Allow
            Resource:
              - Fn::GetAtt:
                  - PipelineArtifactsBucket
                  - Arn
              - Fn::Join:
                  - ""
                  - - Fn::GetAtt:
                        - PipelineArtifactsBucket
                        - Arn
                    - /*
          - Action:
              - kms:Decrypt
              - kms:DescribeKey
              - kms:Encrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - PipelineArtifactsBucketEncryptionKey
                - Arn
          - Action:
              - kms:Decrypt
              - kms:Encrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - PipelineArtifactsBucketEncryptionKey
                - Arn
        Version: "2012-10-17"		 	 	 
      PolicyName: PublishRoleDefaultPolicy
      Roles:
        - Ref: PublishRole

  DeploymentRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: codebuild.amazonaws.com
        Version: "2012-10-17"		 	 	 
  DeploymentRoleDefaultPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Action:
              - logs:CreateLogGroup
              - logs:CreateLogStream
              - logs:PutLogEvents
            Effect: Allow
            Resource:
              - Fn::Join:
                  - ""
                  - - "arn:"
                    - Ref: AWS::Partition
                    - ":logs:"
                    - Ref: AWS::Region
                    - ":"
                    - Ref: AWS::AccountId
                    - :log-group:/aws/codebuild/Deploy*Project*
              - Fn::Join:
                  - ""
                  - - "arn:"
                    - Ref: AWS::Partition
                    - ":logs:"
                    - Ref: AWS::Region
                    - ":"
                    - Ref: AWS::AccountId
                    - :log-group:/aws/codebuild/Deploy*Project:*
          - Action:
              - codebuild:CreateReportGroup
              - codebuild:CreateReport
              - codebuild:UpdateReport
              - codebuild:BatchPutTestCases
            Effect: Allow
            Resource:
              Fn::Join:
                - ""
                - - "arn:"
                  - Ref: AWS::Partition
                  - ":codebuild:"
                  - Ref: AWS::Region
                  - ":"
                  - Ref: AWS::AccountId
                  - :report-group/Deploy*Project
                  - -*
          - Action:
              - proton:UpdateServiceInstance
              - proton:GetServiceInstance
            Effect: Allow
            Resource: "*"
          - Action:
              - s3:GetObject*
              - s3:GetBucket*
              - s3:List*
            Effect: Allow
            Resource:
              - Fn::GetAtt:
                  - PipelineArtifactsBucket
                  - Arn
              - Fn::Join:
                  - ""
                  - - Fn::GetAtt:
                        - PipelineArtifactsBucket
                        - Arn
                    - /*
          - Action:
              - kms:Decrypt
              - kms:DescribeKey
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - PipelineArtifactsBucketEncryptionKey
                - Arn
          - Action:
              - kms:Decrypt
              - kms:Encrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - PipelineArtifactsBucketEncryptionKey
                - Arn
        Version: "2012-10-17"		 	 	 
      PolicyName: DeploymentRoleDefaultPolicy
      Roles:
        - Ref: DeploymentRole
  PipelineArtifactsBucketEncryptionKey:
    Type: AWS::KMS::Key
    Properties:
      KeyPolicy:
        Statement:
          - Action:
              - kms:Create*
              - kms:Describe*
              - kms:Enable*
              - kms:List*
              - kms:Put*
              - kms:Update*
              - kms:Revoke*
              - kms:Disable*
              - kms:Get*
              - kms:Delete*
              - kms:ScheduleKeyDeletion
              - kms:CancelKeyDeletion
              - kms:GenerateDataKey
              - kms:TagResource
              - kms:UntagResource
            Effect: Allow
            Principal:
              AWS:
                Fn::Join:
                  - ""
                  - - "arn:"
                    - Ref: AWS::Partition
                    - ":iam::"
                    - Ref: AWS::AccountId
                    - :root
            Resource: "*"
          - Action:
              - kms:Decrypt
              - kms:DescribeKey
              - kms:Encrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
            Effect: Allow
            Principal:
              AWS:
                Fn::GetAtt:
                  - PipelineRole
                  - Arn
            Resource: "*"
          - Action:
              - kms:Decrypt
              - kms:DescribeKey
              - kms:Encrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
            Effect: Allow
            Principal:
              AWS:
                Fn::GetAtt:
                  - PublishRole
                  - Arn
            Resource: "*"
          - Action:
              - kms:Decrypt
              - kms:Encrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
            Effect: Allow
            Principal:
              AWS:
                Fn::GetAtt:
                  - PublishRole
                  - Arn
            Resource: "*"
          - Action:
              - kms:Decrypt
              - kms:DescribeKey
            Effect: Allow
            Principal:
              AWS:
                Fn::GetAtt:
                  - DeploymentRole
                  - Arn
            Resource: "*"
          - Action:
              - kms:Decrypt
              - kms:Encrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
            Effect: Allow
            Principal:
              AWS:
                Fn::GetAtt:
                  - DeploymentRole
                  - Arn
            Resource: "*"
        Version: "2012-10-17"		 	 	 
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
  PipelineArtifactsBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              KMSMasterKeyID:
                Fn::GetAtt:
                  - PipelineArtifactsBucketEncryptionKey
                  - Arn
              SSEAlgorithm: aws:kms
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
  PipelineArtifactsBucketEncryptionKeyAlias:
    Type: AWS::KMS::Alias
    Properties:
      AliasName: 'alias/codepipeline-encryption-key-{{ service.name }}'     # resource parameter
      TargetKeyId:
        Fn::GetAtt:
          - PipelineArtifactsBucketEncryptionKey
          - Arn
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
  PipelineRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service: codepipeline.amazonaws.com
        Version: "2012-10-17"		 	 	 
  PipelineRoleDefaultPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Action:
              - s3:GetObject*
              - s3:GetBucket*
              - s3:List*
              - s3:DeleteObject*
              - s3:PutObject*
              - s3:Abort*
            Effect: Allow
            Resource:
              - Fn::GetAtt:
                  - PipelineArtifactsBucket
                  - Arn
              - Fn::Join:
                  - ""
                  - - Fn::GetAtt:
                        - PipelineArtifactsBucket
                        - Arn
                    - /*
          - Action:
              - kms:Decrypt
              - kms:DescribeKey
              - kms:Encrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - PipelineArtifactsBucketEncryptionKey
                - Arn
          - Action: codestar-connections:*
            Effect: Allow
            Resource: "*"
          - Action: sts:AssumeRole
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - PipelineBuildCodePipelineActionRole
                - Arn
          - Action: sts:AssumeRole
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - PipelineDeployCodePipelineActionRole
                - Arn
        Version: "2012-10-17"		 	 	 
      PolicyName: PipelineRoleDefaultPolicy
      Roles:
        - Ref: PipelineRole
  Pipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      RoleArn:
        Fn::GetAtt:
          - PipelineRole
          - Arn
      Stages:
        - Actions:
            - ActionTypeId:
                Category: Source
                Owner: AWS
                Provider: CodeStarSourceConnection
                Version: "1"
              Configuration:
                ConnectionArn: '{{ service.repository_connection_arn }}'   # resource parameter
                FullRepositoryId: '{{ service.repository_id }}'            # resource parameter
                BranchName: '{{ service.branch_name }}'                    # resource parameter
              Name: Checkout
              OutputArtifacts:
                - Name: Artifact_Source_Checkout
              RunOrder: 1
          Name: Source
        - Actions:
            - ActionTypeId:
                Category: Build
                Owner: AWS
                Provider: CodeBuild
                Version: "1"
              Configuration:
                ProjectName:
                  Ref: BuildProject
              InputArtifacts:
                - Name: Artifact_Source_Checkout
              Name: Build
              OutputArtifacts:
                - Name: BuildOutput
              RoleArn:
                Fn::GetAtt:
                  - PipelineBuildCodePipelineActionRole
                  - Arn
              RunOrder: 1
          Name: Build {%- for service_instance in service_instances %}
        - Actions:
            - ActionTypeId:
                Category: Build
                Owner: AWS
                Provider: CodeBuild
                Version: "1"
              Configuration:
                ProjectName:
                  Ref: Deploy{{loop.index}}Project
              InputArtifacts:
                - Name: BuildOutput
              Name: Deploy
              RoleArn:
                Fn::GetAtt:
                  - PipelineDeployCodePipelineActionRole
                  - Arn
              RunOrder: 1
          Name: 'Deploy{{service_instance.name}}'         # resource parameter
{%- endfor %}
      ArtifactStore:
        EncryptionKey:
          Id:
            Fn::GetAtt:
              - PipelineArtifactsBucketEncryptionKey
              - Arn
          Type: KMS
        Location:
          Ref: PipelineArtifactsBucket
        Type: S3
    DependsOn:
      - PipelineRoleDefaultPolicy
      - PipelineRole
  PipelineBuildCodePipelineActionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              AWS:
                Fn::Join:
                  - ""
                  - - "arn:"
                    - Ref: AWS::Partition
                    - ":iam::"
                    - Ref: AWS::AccountId
                    - :root
        Version: "2012-10-17"		 	 	 
  PipelineBuildCodePipelineActionRoleDefaultPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Action:
              - codebuild:BatchGetBuilds
              - codebuild:StartBuild
              - codebuild:StopBuild
            Effect: Allow
            Resource:
              Fn::GetAtt:
                - BuildProject
                - Arn
        Version: "2012-10-17"		 	 	 
      PolicyName: PipelineBuildCodePipelineActionRoleDefaultPolicy
      Roles:
        - Ref: PipelineBuildCodePipelineActionRole
  PipelineDeployCodePipelineActionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              AWS:
                Fn::Join:
                  - ""
                  - - "arn:"
                    - Ref: AWS::Partition
                    - ":iam::"
                    - Ref: AWS::AccountId
                    - :root
        Version: "2012-10-17"		 	 	 
  PipelineDeployCodePipelineActionRoleDefaultPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Statement:
          - Action:
              - codebuild:BatchGetBuilds
              - codebuild:StartBuild
              - codebuild:StopBuild
            Effect: Allow
            Resource:
              Fn::Join:
                - ""
                - - "arn:"
                  - Ref: AWS::Partition
                  - ":codebuild:"
                  - Ref: AWS::Region
                  - ":"
                  - Ref: AWS::AccountId
                  - ":project/Deploy*"
        Version: "2012-10-17"		 	 	 
      PolicyName: PipelineDeployCodePipelineActionRoleDefaultPolicy
      Roles:
        - Ref: PipelineDeployCodePipelineActionRole
Outputs:
  PipelineEndpoint:
    Description: The URL to access the pipeline
    Value: !Sub "https://${AWS::Region}.console.aws.amazon.com/codesuite/codepipeline/pipelines/${Pipeline}/view?region=${AWS::Region}"
```

# CodeBuild 佈建範本套件
<a name="ag-infrastructure-tmp-files-codebuild"></a>

使用 CodeBuild 佈建，而不是使用 IaC 範本轉譯 IaC 檔案並使用 IaC 佈建引擎執行它們， AWS Proton 只需執行您的 shell 命令。若要這樣做， 會在環境帳戶中為環境 AWS Proton 建立 AWS CodeBuild 專案，並啟動任務，以針對每個 AWS Proton 資源建立或更新執行您的命令。當您撰寫範本套件時，您會提供資訊清單，指定基礎設施佈建和取消佈建命令，以及這些命令可能需要的任何程式、指令碼和其他檔案。您的命令可以讀取 AWS Proton 提供的輸入，並負責佈建或取消佈建基礎設施和產生輸出值。

資訊清單也會指定 AWS Proton 應如何轉譯您的程式碼可以輸入的輸入檔案，並從中取得輸入值。它可以轉譯為 JSON 或 HCL。如需輸入參數的詳細資訊，請參閱 [CodeBuild 佈建參數詳細資訊和範例](parameters-codebuild.md)。如需資訊清單檔案的相關資訊，請參閱[後續處理 的範本檔案 AWS Proton](ag-wrap-up.md)。

**注意**  
您可以搭配環境和服務使用 CodeBuild 佈建。目前您無法以這種方式佈建元件。

## 範例： AWS CDK 搭配 CodeBuild 佈建使用
<a name="ag-infrastructure-tmp-files-codebuild.example"></a>

使用 CodeBuild 佈建的範例包括使用 AWS Cloud Development Kit (AWS CDK) 佈建 (*部署*) 和取消佈建 (*destroy*) AWS 資源的程式碼，以及安裝 CDK 並執行 CDK 程式碼的資訊清單。

下列各節列出您可以包含在 CodeBuild 佈建範本套件中的範例檔案，該套件使用 佈建環境 AWS CDK。

### 資訊清單
<a name="ag-infrastructure-tmp-files-codebuild.example.manifest"></a>

下列資訊清單檔案會指定 CodeBuild 佈建，並包含安裝和使用 AWS CDK、輸出檔案處理和回報輸出所需的命令 AWS Proton。

**Example infrastructure/manifest.yaml**  

```
infrastructure:
  templates:
    - rendering_engine: codebuild
      settings:
        image: aws/codebuild/amazonlinux2-x86_64-standard:4.0
        runtimes:
          nodejs: 16
        provision:
          - npm install
          - npm run build
          - npm run cdk bootstrap
          - npm run cdk deploy -- --require-approval never --outputs-file proton-outputs.json
          - jq 'to_entries | map_values(.value) | add | to_entries | map({key:.key, valueString:.value})' < proton-outputs.json > outputs.json
          - aws proton notify-resource-deployment-status-change --resource-arn $RESOURCE_ARN --status IN_PROGRESS --outputs file://./outputs.json
        deprovision:
          - npm install
          - npm run build
          - npm run cdk destroy
        project_properties:
          VpcConfig:
            VpcId: "{{ environment.inputs.codebuild_vpc_id }}"
            Subnets: "{{ environment.inputs.codebuild_subnets }}"
            SecurityGroupIds: "{{ environment.inputs.codebuild_security_groups }}"
```

### 結構描述
<a name="ag-infrastructure-tmp-files-codebuild.example.schema"></a>

下列結構描述檔案定義 環境的參數。您的 AWS CDK 程式碼可以在部署期間參考這些參數的值。

**Example 結構描述/結構描述.yaml**  

```
schema:
  format:
    openapi: "3.0.0"
  environment_input_type: "MyEnvironmentInputType"
  types:
    MyEnvironmentInputType:
      type: object
      description: "Input properties for my environment"
      properties:
        my_sample_input:
          type: string
          description: "This is a sample input"
          default: "hello world"
        my_other_sample_input:
          type: string
          description: "Another sample input"
      required:
        - my_other_sample_input
```

### AWS CDK 檔案
<a name="ag-infrastructure-tmp-files-codebuild.example.cdkcode"></a>

以下是 Node.js CDK 專案的範例。

**Example infrastructure/package.json**  

```
{
  "name": "ProtonEnvironment",
  "version": "0.1.0",
  "bin": {
    "ProtonEnvironmente": "bin/ProtonEnvironment.js"
  },
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "test": "jest",
    "cdk": "cdk"
  },
  "devDependencies": {
    "@types/jest": "^28.1.7",
    "@types/node": "18.7.6",
    "jest": "^28.1.3",
    "ts-jest": "^28.0.8",
    "aws-cdk": "2.37.1",
    "ts-node": "^10.9.1",
    "typescript": "~4.7.4"
  },
  "dependencies": {
    "aws-cdk-lib": "2.37.1",
    "constructs": "^10.1.77",
    "source-map-support": "^0.5.21"
  }
}
```

**Example infrastructure/tsconfig.json**  

```
{
  "compilerOptions": {
    "target": "ES2018",
    "module": "commonjs",
    "lib": [
      "es2018"
    ],
    "declaration": true,
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "noImplicitThis": true,
    "alwaysStrict": true,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": false,
    "inlineSourceMap": true,
    "inlineSources": true,
    "experimentalDecorators": true,
    "strictPropertyInitialization": false,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "typeRoots": [
      "./node_modules/@types"
    ]
  },
  "exclude": [
    "node_modules",
    "cdk.out"
  ]
}
```

**Example infrastructure/cdk.json**  

```
{
  "app": "npx ts-node --prefer-ts-exts bin/ProtonEnvironment.ts",
  "outputsFile": "proton-outputs.json",
  "watch": {
    "include": [
      "**"
    ],
    "exclude": [
      "README.md",
      "cdk*.json",
      "**/*.d.ts",
      "**/*.js",
      "tsconfig.json",
      "package*.json",
      "yarn.lock",
      "node_modules",
      "test"
    ]
  },
  "context": {
    "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true,
    "@aws-cdk/core:stackRelativeExports": true,
    "@aws-cdk/aws-rds:lowercaseDbIdentifier": true,
    "@aws-cdk/aws-lambda:recognizeVersionProps": true,
    "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true,
    "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
    "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
    "@aws-cdk/core:target-partitions": [
      "aws",
      "aws-cn"
    ]
  }
}
```

**Example infrastructure/bin/ProtonEnvironment.ts**  

```
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { ProtonEnvironmentStack } from '../lib/ProtonEnvironmentStack';

const app = new cdk.App();
new ProtonEnvironmentStack(app, 'ProtonEnvironmentStack', {});
```

**Example infrastructure/lib/ProtonEnvironmentStack.ts**  

```
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as cdk from 'aws-cdk-lib';
import * as ssm from 'aws-cdk-lib/aws-ssm';
import input from '../proton-inputs.json';

export class ProtonEnvironmentStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, { ...props, stackName: process.env.STACK_NAME });

    const ssmParam = new ssm.StringParameter(this, "ssmParam", {
      stringValue: input.environment.inputs.my_sample_input,
      parameterName: `${process.env.STACK_NAME}-Param`,
      tier: ssm.ParameterTier.STANDARD
    })

    new cdk.CfnOutput(this, 'ssmParamOutput', {
      value: ssmParam.parameterName,
      description: 'The name of the ssm parameter',
      exportName: `${process.env.STACK_NAME}-Param`
    });
  }
}
```

### 轉譯的輸入檔案
<a name="ag-infrastructure-tmp-files-codebuild.example.manifest"></a>

當您使用 CodeBuild 型佈建範本建立環境時， AWS Proton 會使用您提供的輸入[參數值轉譯輸入](https://docs.aws.amazon.com/proton/latest/userguide/parameters.html)檔案。您的程式碼可以參考這些值。下列檔案是轉譯輸入檔案的範例。

**Example infrastructure/proton-inputs.json**  

```
{
  "environment": {
    "name": "myenv",
    "inputs": {
      "my_sample_input": "10.0.0.0/16",
      "my_other_sample_input": "11.0.0.0/16"
    }
  }
}
```

# Terraform IaC 檔案
<a name="ag-infrastructure-tmp-files-terraform"></a>

了解如何搭配 使用 Terraform 基礎設施做為程式碼 (IaC) 檔案 AWS Proton。[Terraform](https://www.terraform.io/) 是由 [HashiCorp](https://www.hashicorp.com/) 開發的廣泛使用開放原始碼 IaC 引擎。Terraform 模組是以 HashiCorp 的 HCL 語言開發，並支援數個後端基礎設施供應商，包括 Amazon Web Services。

AWS Proton 支援 Terraform IaC [的自我管理佈建](ag-works-prov-methods.md#ag-works-prov-methods-self)。

如需回應提取請求並實作基礎設施佈建的佈建儲存庫完整範例，請參閱 [ GitHub 上適用於 的 Terraform OpenSource GitHub Actions 自動化範本 AWS Proton](https://github.com/aws-samples/aws-proton-terraform-github-actions-sample)。 GitHub

**自我管理佈建如何與 Terraform IaC 範本套件檔案搭配使用：**

1. 當您從 Terraform 範本套件[建立環境](ag-create-env.md)時， 會使用主控台或`spec file`輸入參數 AWS Proton 編譯您的`.tf`檔案。

1. 它提出提取請求，將編譯的 IaC 檔案合併到[您已向 註冊的儲存庫 AWS Proton](ag-create-repo.md)。

1. 如果請求獲得核准， 會 AWS Proton 等待您提供的佈建狀態。

1. 如果請求遭到拒絕，則會取消環境建立。

1. 如果提取請求逾時，則環境建立*未完成*。

**AWS Proton 搭配 Terraform IaC 考量：**
+ AWS Proton 不會管理您的 Terraform 佈建。
+ 您必須在此[儲存庫上向 .makes 提取請求註冊佈建](ag-create-repo.md)儲存庫。 AWS Proton AWS Proton 
+ 您必須[建立 CodeStar 連線](setting-up-for-service.md#setting-up-vcontrol)，才能 AWS Proton 與您的佈建儲存庫連線。
+ 若要從 AWS Proton 編譯的 IaC 檔案佈建，您必須回應 AWS Proton pull request. AWS Proton makes 在環境和服務建立和更新動作之後提取請求。如需詳細資訊，請參閱[AWS Proton 環境](ag-environments.md)及[AWS Proton 服務](ag-services.md)。
+ 若要從 AWS Proton 編譯的 IaC 檔案佈建管道，您必須[建立 CI/CD 管道儲存庫](setting-up-for-service.md#setting-up-pr-repo)。
+ 您的提取請求型佈建自動化必須包含通知 AWS Proton 任何佈建 AWS Proton 資源狀態變更的步驟。您可以使用 AWS Proton [NotifyResourceDeploymentStatusChange API](https://docs.aws.amazon.com/proton/latest/APIReference/API_NotifyResourceDeploymentStatusChange.html)。
+ 您無法將從 CloudFormation IaC 檔案建立的服務、管道和元件部署至從 Terraform IaC 檔案建立的環境。
+ 您無法將從 Terraform IaC 檔案建立的服務、管道和元件部署至從 CloudFormation IaC 檔案建立的環境。

準備 Terraform IaC 檔案時 AWS Proton，您可以將命名空間連接至輸入變數，如下列範例所示。如需詳細資訊，請參閱[參數](parameters.md)。

## 範例 1： AWS Proton environment Terraform IaC 檔案
<a name="ag-env-tform-example"></a>

```
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
  // This tells terraform to store the state file in s3 at the location
  // s3://terraform-state-bucket/tf-os-sample/terraform.tfstate
  backend "s3" {
    bucket = "terraform-state-bucket"
    key    = "tf-os-sample/terraform.tfstate"
    region = "us-east-1"
  }
}

// Configure the AWS Provider
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = var.proton_tags
  }
}

resource "aws_ssm_parameter" "my_ssm_parameter" {
  name  = "my_ssm_parameter"
  type  = "String"
  // Use the Proton environment.inputs. namespace
  value = var.environment.inputs.ssm_parameter_value
}
```

## 編譯的基礎設施做為程式碼
<a name="compiled-tform"></a>

當您建立環境或服務時， 會使用主控台或`spec file`輸入將基礎設施 AWS Proton 編譯為程式碼檔案。它會為您的輸入建立 `proton.resource-type.variables.tf`和 `proton.auto.tfvars.json` 檔案，供 Terraform 使用，如下列範例所示。這些檔案位於與環境或服務執行個體名稱相符的資料夾中指定的儲存庫中。

此範例顯示 如何在變數定義和變數值中 AWS Proton 包含標籤，以及如何將這些 AWS Proton 標籤傳播到佈建的資源。如需詳細資訊，請參閱[將標籤傳播至佈建的資源](resources.md#auto-tags-prop)。

### 範例 2：為名為 "dev" 的環境編譯 IaC 檔案。
<a name="ag-compiled-example"></a>

**dev/environment.tf：**

```
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
  // This tells terraform to store the state file in s3 at the location
  // s3://terraform-state-bucket/tf-os-sample/terraform.tfstate
  backend "s3" {
    bucket = "terraform-state-bucket"
    key    = "tf-os-sample/terraform.tfstate"
    region = "us-east-1"
  }
}

// Configure the AWS Provider
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = var.proton_tags
  }
}

resource "aws_ssm_parameter" "my_ssm_parameter" {
  name  = "my_ssm_parameter"
  type  = "String"
  // Use the Proton environment.inputs. namespace
  value = var.environment.inputs.ssm_parameter_value
}
```

**dev/proton.environment.variables.tf：**

```
variable "environment" {
  type = object({
    inputs = map(string)
    name = string
  })
}

variable "proton_tags" {
  type = map(string)
  default = null
}
```

**dev/proton.auto.tfvars.json：**

```
{
  "environment": {
    "name": "dev",
    "inputs": {
      "ssm_parameter_value": "MyNewParamValue"
    }
  }

  "proton_tags" : {
    "proton:account" : "123456789012",
    "proton:template" : "arn:aws:proton:us-east-1:123456789012:environment-template/fargate-env",
    "proton:environment" : "arn:aws:proton:us-east-1:123456789012:environment/dev"
  }
}
```

## 儲存庫路徑
<a name="repo-dir"></a>

AWS Proton 使用來自環境或服務建立動作的主控台或規格輸入來尋找儲存庫，以及尋找編譯 IaC 檔案的路徑。輸入值會傳遞至[命名空間輸入參數](parameters.md)。

AWS Proton 支援兩種儲存庫路徑配置。在下列範例中，路徑會以來自兩個環境的命名空間資源參數命名。每個環境都有兩個 服務的服務執行個體，而其中一個服務的服務執行個體具有直接定義的元件。

<a name="limits-table"></a>[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/proton/latest/userguide/ag-infrastructure-tmp-files-terraform.html)

------
#### [ Layout 1 ]

如果 AWS Proton 找到具有 `environments` 資料夾的指定儲存庫，它會建立包含編譯 IaC 檔案的資料夾，並使用 命名`environment.name`。

如果 AWS Proton 找到具有資料夾`environments`的指定儲存庫，其中包含與服務執行個體相容環境名稱相符的資料夾名稱，它會建立資料夾，其中包含編譯的執行個體 IaC 檔案，並以 命名`service_instance.name`。

```
/repo
    /environments
        /env-prod                             # environment folder
            main.tf
            proton.environment.variables.tf
            proton.auto.tfvars.json
          
            /service-one-instance-one-prod    # instance folder
                main.tf
                proton.service_instance.variables.tf
                proton.auto.tfvars.json
              
            /service-two-instance-two-prod    # instance folder
                main.tf
                proton.service_instance.variables.tf
                proton.auto.tfvars.json
              
            /component-prod                   # component folder
                main.tf
                proton.component.variables.tf
                proton.auto.tfvars.json
              
        /env-staged                           # environment folder
            main.tf
            proton.variables.tf
            proton.auto.tfvars.json         
          
            /service-one-instance-one-staged  # instance folder
                main.tf
                proton.service_instance.variables.tf
                proton.auto.tfvars.json
              
            /service-two-instance-two-staged  # instance folder
                main.tf
                proton.service_instance.variables.tf
                proton.auto.tfvars.json
              
            /component-staged                 # component folder
                main.tf
                proton.component.variables.tf
                proton.auto.tfvars.json
```

------
#### [ Layout 2 ]

如果 AWS Proton 找到沒有 `environments` 資料夾的指定儲存庫，它會建立資料夾`environment.name`，找到編譯的環境 IaC 檔案。

如果 AWS Proton 找到具有與服務執行個體相容環境名稱相符之資料夾名稱的指定儲存庫，它會建立`service_instance.name`資料夾來尋找編譯的執行個體 IaC 檔案。

```
/repo
    /env-prod                             # environment folder
        main.tf
        proton.environment.variables.tf
        proton.auto.tfvars.json
      
        /service-one-instance-one-prod    # instance folder
            main.tf
            proton.service_instance.variables.tf
            proton.auto.tfvars.json
          
        /service-two-instance-two-prod    # instance folder
            main.tf
            proton.service_instance.variables.tf
            proton.auto.tfvars.json
          
        /component-prod                   # component folder
            main.tf
            proton.component.variables.tf
            proton.auto.tfvars.json
          
    /env-staged                           # environment folder
        main.tf
        proton.variables.tf
        proton.auto.tfvars.json         
      
        /service-one-instance-one-staged  # instance folder
            main.tf
            proton.service_instance.variables.tf
            proton.auto.tfvars.json
          
        /service-two-instance-two-staged  # instance folder
            main.tf
            proton.service_instance.variables.tf
            proton.auto.tfvars.json
          
        /component-staged                 # component folder
            main.tf
            proton.component.variables.tf
            proton.auto.tfvars.json
```

------

# 結構描述檔案
<a name="ag-schema"></a>

身為管理員，當您使用 Open API [Data Models （結構描述） 區段](https://swagger.io/docs/specification/data-models/)來定義範本套件的參數結構描述 YAML 檔案時， AWS Proton 可以根據您在結構描述中定義的需求驗證參數值輸入。

如需格式和可用關鍵字的詳細資訊，請參閱 OpenAPI 的[結構描述物件](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#schemaObject)區段。

## 環境範本套件的結構描述需求
<a name="schema-req-env"></a>

您的結構描述必須遵循 YAML 格式 OpenAPI [的資料模型 （結構描述） 區段](https://swagger.io/docs/specification/data-models/)。它也必須是環境範本套件的一部分。

對於您的環境結構描述，您必須包含格式化的標頭，以確定您正在使用 Open API 的資料模型 （結構描述） 區段。在下列環境結構描述範例中，這些標頭會出現在前三行中。

`environment_input_type` 必須包含並定義您提供的名稱。在下列範例中，這在第 5 行定義。透過定義此參數，您可以將其與 AWS Proton 環境資源建立關聯。

若要遵循 Open API 結構描述模型，您必須包含 `types`。在下列範例中，這是第 6 行。

在 之後`types`，您必須定義 `environment_input_type`類型。您可以將環境的輸入參數定義為 的屬性`environment_input_type`。您必須包含至少一個名稱與環境基礎設施中列出的至少一個參數相符的屬性，做為與結構描述相關聯的程式碼 (IaC) 檔案。

當您建立環境並提供自訂參數值時， AWS Proton 會使用結構描述檔案來比對、驗證和插入至相關聯 CloudFormation IaC 檔案中的大括號參數。針對每個屬性 （參數），提供 `name`和 `type`。或者，也提供 `description`、 `default`和 `pattern`。

下列範例*標準*環境範本結構描述的定義參數包括 `vpc_cidr`、 和 `subnet_one_cidr`，`subnet_two_cidr`以及`default`關鍵字和預設值。當您使用此環境範本套件結構描述建立環境時，您可以接受預設值或提供自己的值。如果參數*沒有*預設值並列為`required`屬性 （參數），您必須在建立環境時為其提供值。

第二個範例*標準*環境範本結構描述會列出 `required` 參數 `my_other_sample_input`。

您可以為兩種類型的環境範本建立結構描述。如需詳細資訊，請參閱[註冊和發佈範本](template-create.md)。
+ ***標準*環境範本**

  在下列範例中，使用描述和輸入屬性定義環境輸入類型。此結構描述範例可與[範例 3 ](ag-infrastructure-tmp-files-cloudformation.md#ag-proton-env-cfn-example)中顯示的 AWS Proton CloudFormation IaC 檔案搭配使用。

  *標準*環境範本的範例結構描述：

  ```
  schema:                            # required
    format:                          # required
      openapi: "3.0.0"               # required
    # required              defined by administrator
    environment_input_type: "PublicEnvironmentInput"
    types:                           # required
      # defined by administrator
      PublicEnvironmentInput:
        type: object
        description: "Input properties for my environment"
        properties:
          vpc_cidr:                   # parameter
            type: string
            description: "This CIDR range for your VPC"
            default: 10.0.0.0/16
            pattern: ([0-9]{1,3}\.){3}[0-9]{1,3}($|/(16|24))
          subnet_one_cidr:            # parameter
            type: string
            description: "The CIDR range for subnet one"
            default: 10.0.0.0/24
            pattern: ([0-9]{1,3}\.){3}[0-9]{1,3}($|/(16|24))
          subnet_two_cidr:            # parameter
            type: string
            description: "The CIDR range for subnet one"
            default: 10.0.1.0/24
            pattern: ([0-9]{1,3}\.){3}[0-9]{1,3}($|/(16|24))
  ```

  包含 `required` 參數*的標準*環境範本範例結構描述：

  ```
  schema:                            # required
    format:                          # required
      openapi: "3.0.0"               # required
    # required              defined by administrator
    environment_input_type: "MyEnvironmentInputType"
    types:                           # required
      # defined by administrator
      MyEnvironmentInputType:
        type: object
        description: "Input properties for my environment"
        properties:
          my_sample_input:           # parameter
            type: string
            description: "This is a sample input"
            default: "hello world"
          my_other_sample_input:     # parameter
            type: string
            description: "Another sample input"
          another_optional_input:    # parameter
            type: string
            description: "Another optional input"
            default: "!"
        required:
          - my_other_sample_input
  ```
+ ***客戶受*管環境範本**

  在下列範例中，結構描述只會包含輸出清單，這些輸出會複寫您用來佈建*客戶受*管基礎設施的 IaC 輸出。您需要將輸出值類型定義為*僅字串 *(*而非*清單、陣列或其他類型）。例如，下一個程式碼片段會顯示外部 CloudFormation 範本的輸出區段。這是來自[範例 1 ](ag-infrastructure-tmp-files-cloudformation.md#ag-env-cfn-example)中顯示的範本。它可用於為從[範例 4](ag-infrastructure-tmp-files-cloudformation.md#ag-proton-svc-cfn-example) 建立的 AWS Proton Fargate 服務建立外部*客戶受*管基礎設施。
**重要**  
身為管理員，您必須確保佈建和管理的基礎設施和所有輸出參數與相關聯的*客戶受*管環境範本相容。 AWS Proton 無法代表您考慮變更，因為這些變更不可見 AWS Proton。不一致會導致失敗。

  *客戶受*管環境範本的範例 CloudFormation IaC 檔案輸出：

  ```
  // Cloudformation Template Outputs
  [...]
  Outputs:
    ClusterName:
      Description: The name of the ECS cluster
      Value: !Ref 'ECSCluster'
    ECSTaskExecutionRole:
      Description: The ARN of the ECS role
      Value: !GetAtt 'ECSTaskExecutionRole.Arn'
    VpcId:
      Description: The ID of the VPC that this stack is deployed in
      Value: !Ref 'VPC'
  [...]
  ```

  對應 AWS Proton *客戶受*管環境範本套件的結構描述如下列範例所示。每個輸出值都定義為字串。

  *客戶受*管環境範本的範例結構描述：

  ```
  schema:                            # required
    format:                          # required
      openapi: "3.0.0"               # required
    # required              defined by administrator
    environment_input_type: "EnvironmentOutput"
    types:                           # required
      # defined by administrator
      EnvironmentOutput:
        type: object
        description: "Outputs of the environment"
        properties:
          ClusterName:               # parameter
            type: string
            description: "The name of the ECS cluster"
          ECSTaskExecutionRole:      # parameter
            type: string
            description: "The ARN of the ECS role"
          VpcId:                     # parameter
            type: string
            description: "The ID of the VPC that this stack is deployed in"
  [...]
  ```

## 服務範本套件的結構描述需求
<a name="schema-req-svc"></a>

您的結構描述必須遵循 YAML 格式 OpenAPI [的資料模型 （結構描述） 區段](https://swagger.io/docs/specification/data-models/)，如下列範例所示。您必須在服務範本套件中提供結構描述檔案。

在下列服務結構描述範例中，您必須包含格式化的標頭。在下列範例中，這位於前三行。這是為了確認您使用的是 Open API 的資料模型 （結構描述） 區段。

`service_input_type` 必須包含和定義您提供的名稱。在下列範例中，這是第 5 行。這會將參數與服務 AWS Proton 資源建立關聯。

當您使用主控台或 CLI 建立 AWS Proton 服務時，預設會包含服務管道。當您包含服務的服務管道時，您必須`pipeline_input_type`包含您提供的名稱。在下列範例中，這是第 7 行。如果您*未*包含 AWS Proton 服務管道，*請勿*包含此參數。如需詳細資訊，請參閱[註冊和發佈範本](template-create.md)。

若要遵循 Open API 結構描述模型，您必須包含`types`下列範例中的第 9 行。

在 之後`types`，您必須定義`service_input_type`類型。您可以將服務的輸入參數定義為 的屬性`service_input_type`。您必須包含至少一個屬性，其名稱至少符合服務基礎設施中列出的至少一個參數做為與結構描述相關聯的程式碼 (IaC) 檔案。

若要定義服務管道，請在`service_input_type`定義下方定義 `pipeline_input_type`。如上所述，您必須包含至少一個屬性，其名稱至少符合與結構描述相關聯的管道 IaC 檔案中列出的至少一個參數。如果您*不包含* AWS Proton 服務管道，*請勿*包含此定義。

身為管理員或開發人員，當您建立服務並提供自訂參數值時， AWS Proton 會使用結構描述檔案來比對、驗證和插入相關聯的 CloudFormation IaC 檔案的大括號參數。針對每個屬性 （參數），提供 `name`和 `type`。或者，您也可以提供 `description`、 `default`和 `pattern`。

範例結構描述的定義參數包括 `port`、 `task_size`和 `desired_count`，`image`以及`default`關鍵字和預設值。當您使用此服務範本套件結構描述建立服務時，您可以接受預設值或提供自己的值。參數`unique_name`也包含在範例中，*而且沒有*預設值。它被列為`required`屬性 （參數）。身為管理員或開發人員，您必須在建立服務時提供`required`參數的值。

如果您想要使用服務管道建立服務範本，請在結構描述`pipeline_input_type`中包含 。

**包含 服務 AWS Proton 管道之服務的服務結構描述檔案範例。**

 此結構描述範例可與[範例 4 ](ag-infrastructure-tmp-files-cloudformation.md#ag-proton-svc-cfn-example)和[範例 5 ](ag-infrastructure-tmp-files-cloudformation.md#ag-proton-pipeline-cfn-example)中顯示的 AWS Proton IaC 檔案搭配使用。包含服務管道。

```
schema:                            # required
  format:                          # required
    openapi: "3.0.0"               # required
  # required           defined by administrator
  service_input_type: "LoadBalancedServiceInput"
  # only include if including AWS Proton service pipeline, defined by administrator
  pipeline_input_type: "PipelineInputs"

  types:                           # required
    # defined by administrator
    LoadBalancedServiceInput:
      type: object
      description: "Input properties for a loadbalanced Fargate service"
      properties:
        port:                      # parameter
          type: number
          description: "The port to route traffic to"
          default: 80
          minimum: 0
          maximum: 65535
        desired_count:             # parameter
          type: number
          description: "The default number of Fargate tasks you want running"
          default: 1
          minimum: 1
        task_size:                 # parameter
          type: string
          description: "The size of the task you want to run"
          enum: ["x-small", "small", "medium", "large", "x-large"]
          default: "x-small"
        image:                     # parameter
          type: string
          description: "The name/url of the container image"
          default: "public.ecr.aws/z9d2n7e1/nginx:1.19.5"
          minLength: 1
          maxLength: 200
        unique_name:               # parameter
          type: string
          description: "The unique name of your service identifier. This will be used to name your log group, task definition and ECS service"
          minLength: 1
          maxLength: 100
      required:
        - unique_name
    # defined by administrator
    PipelineInputs:
      type: object
      description: "Pipeline input properties"
      properties:
        dockerfile:                # parameter
          type: string
          description: "The location of the Dockerfile to build"
          default: "Dockerfile"
          minLength: 1
          maxLength: 100
        unit_test_command:         # parameter
          type: string
          description: "The command to run to unit test the application code"
          default: "echo 'add your unit test command here'"
          minLength: 1
          maxLength: 200
```

如果您想要在沒有服務管道的情況下建立服務範本，*請不要*在結構描述`pipeline_input_type`中包含 ，如下列範例所示。

***不包含*服務 AWS Proton 管道之服務的服務結構描述檔案範例**

```
schema:                            # required
  format:                          # required
    openapi: "3.0.0"               # required
  # required            defined by administrator  
  service_input_type: "MyServiceInstanceInputType"

  types:                           # required
    # defined by administrator
    MyServiceInstanceInputType:
      type: object
      description: "Service instance input properties"
      required:
        - my_sample_service_instance_required_input
      properties:
        my_sample_service_instance_optional_input:   # parameter
          type: string
          description: "This is a sample input"
          default: "hello world"
        my_sample_service_instance_required_input:   # parameter
          type: string
          description: "Another sample input"
```

# 後續處理 的範本檔案 AWS Proton
<a name="ag-wrap-up"></a>

準備環境和服務基礎設施做為程式碼 (IaC) 檔案及其個別結構描述檔案之後，您必須在目錄中組織它們。您也必須建立資訊清單 YAML 檔案。資訊清單檔案會列出目錄中的 IaC 檔案、轉譯引擎，以及用於在此範本中開發 IaC 的範本語言。

**注意**  
資訊清單檔案也可以獨立於範本套件使用，做為*直接定義元件*的直接輸入。在這種情況下，它一律會為 CloudFormation 和 Terraform 指定單一 IaC 範本檔案。如需元件的詳細資訊，請參閱 [AWS Proton 元件](ag-components.md)。

資訊清單檔案需要遵循下列範例中顯示的格式和內容。

**CloudFormation 資訊清單檔案格式：**

使用 CloudFormation，您可以列出單一檔案。

```
infrastructure:
  templates:
    - file: "cloudformation.yaml"
      rendering_engine: jinja
      template_language: cloudformation
```

**Terraform 資訊清單檔案格式：**

透過 terraform，您可以明確列出單一檔案，或使用萬用字元`*`列出目錄中的每個檔案。

**注意**  
萬用字元只包含名稱結尾為 的檔案`.tf`。會忽略其他檔案。

```
infrastructure:
  templates:
    - file: "*"
      rendering_engine: hcl
      template_language: terraform
```

**CodeBuild 型佈建資訊清單檔案格式：**

使用 CodeBuild 型佈建，您可以指定佈建和取消佈建 shell 命令。

**注意**  
除了資訊清單之外，您的套件還應該包含命令依賴的任何檔案。

下列範例資訊清單使用 CodeBuild 型佈建來使用 () 佈建 AWS Cloud Development Kit (AWS CDK) (*部署*) 和取消佈建 (*銷毀*) 資源AWS CDK。範本套件也應包含 CDK 程式碼。

在佈建期間，AWS Proton 會建立輸入檔案，其中包含您在範本結構描述中以名稱 定義的輸入參數值`proton-input.json`。

```
infrastructure:
  templates:
    - rendering_engine: codebuild
      settings:
        image: aws/codebuild/amazonlinux2-x86_64-standard:4.0
        runtimes:
          nodejs: 16
        provision:
          - npm install
          - npm run build
          - npm run cdk bootstrap
          - npm run cdk deploy -- --require-approval never --outputs-file proton-outputs.json
          - jq 'to_entries | map_values(.value) | add | to_entries | map({key:.key, valueString:.value})' < proton-outputs.json > outputs.json
          - aws proton notify-resource-deployment-status-change --resource-arn $RESOURCE_ARN --status IN_PROGRESS --outputs file://./outputs.json
        deprovision:
          - npm install
          - npm run build
          - npm run cdk destroy
        project_properties:
          VpcConfig:
            VpcId: "{{ environment.inputs.codebuild_vpc_id }}"
            Subnets: "{{ environment.inputs.codebuild_subnets }}"
            SecurityGroupIds: "{{ environment.inputs.codebuild_security_groups }}"
```

為您的環境或服務範本套件設定目錄和資訊清單檔案後，您可以將目錄壓縮為 tar 球，並將其上傳到 Amazon Simple Storage Service (Amazon S3) 儲存貯體，其中 AWS Proton 可以擷取它們，或[範本同步 Git 儲存庫](ag-template-sync-configs.md)。

當您建立 環境的次要版本或註冊的服務範本時 AWS Proton，您會提供 S3 儲存貯體中環境或服務範本套件 tar 球的路徑。 AWS Proton 會使用新的範本次要版本來儲存它。您可以選擇新的範本次要版本來建立或更新環境或服務 AWS Proton。

## 環境範本套件後續處理
<a name="environment-wrap-up"></a>

您建立的環境範本套件有兩種類型 AWS Proton。
+ 若要為*標準*環境範本建立環境範本套件，請在目錄中組織結構描述、基礎設施即程式碼 (IaC) 檔案和資訊清單檔案，如下列環境範本套件目錄結構所示。
+ 若要為客戶*受管*環境範本建立環境範本套件，請僅提供結構描述檔案和目錄。*請勿*包含基礎設施目錄和檔案。如果包含基礎設施目錄和檔案， 會 AWS Proton 擲回錯誤。

如需詳細資訊，請參閱[註冊和發佈範本](template-create.md)。

CloudFormation 環境範本套件目錄結構：

```
 /schema
   schema.yaml
 /infrastructure
   manifest.yaml
   cloudformation.yaml
```

Terraform 環境範本套件目錄結構：

```
 /schema
   schema.yaml
 /infrastructure
   manifest.yaml
   environment.tf
```

## 服務範本套件後續處理
<a name="service-wrap-up"></a>

若要建立服務範本套件，您必須將結構描述、基礎設施即程式碼 (IaC) 檔案和資訊清單檔案組織到目錄中，如服務範本套件目錄結構範例所示。

如果您*未在*範本套件中包含服務管道，*請勿*在建立要與此範本套件相關聯的服務範本`"pipelineProvisioning": "CUSTOMER_MANAGED"`時包含管道目錄和檔案並設定 。

**注意**  
建立服務範本`pipelineProvisioning`後，您無法修改 。

如需詳細資訊，請參閱[註冊和發佈範本](template-create.md)。

CloudFormation 服務範本套件目錄結構：

```
 /schema
   schema.yaml
 /instance_infrastructure
   manifest.yaml
   cloudformation.yaml
 /pipeline_infrastructure
   manifest.yaml
   cloudformation.yaml
```

Terraform 服務範本套件目錄結構：

```
 /schema
   schema.yaml
 /instance_infrastructure
   manifest.yaml
   instance.tf
 /pipeline_infrastructure
   manifest.yaml
   pipeline.tf
```

# 範本套件考量事項
<a name="template-considerations"></a>


+ **基礎設施即程式碼 (IaC) 檔案**

  AWS Proton 稽核範本的檔案格式是否正確。不過， AWS Proton 不會檢查範本開發、相依性和邏輯錯誤。例如，假設您已在服務或環境範本中指定在 CloudFormation IaC 檔案中建立 Amazon S3 儲存貯體。服務會根據這些範本建立。現在，假設您想要在某個時間點刪除服務。如果指定的 S3 儲存貯*體不是*空的，且 CloudFormation IaC 檔案*未在* `Retain`中將其標記為 `DeletionPolicy`，則服務刪除操作會 AWS Proton 失敗。
+ **套件檔案大小限制和格式**
  + 套件檔案大小、計數和名稱大小限制可在 找到[AWS Proton 配額](ag-limits.md)。
  + 檔案的範本套件目錄會壓縮為 tar 球，並位於 Amazon Simple Storage Service (Amazon S3) 儲存貯體中。
  + 套件中的每個檔案都必須是有效的格式化 YAML 檔案。
+ **S3 儲存貯體範本套件加密**

  如果您想要加密 S3 儲存貯體中靜態範本套件中的敏感資料，請使用 SSE-S3 或 SSE-KMS 金鑰 AWS Proton 來允許 擷取這些資料。