AWS CodePipeline勉強メモ① ハローワールド


## はじめに

AWS CodePipeline 全然わからないので調査

## 参考

- [【AWS】CodePipelineから呼び出したLambdaがずっと進行中になっている問題と対応](https://qiita.com/hassoubeat/items/f2f89eae2c26cdc06433)
- [CodePipeline で パイプラインに AWS Lambda 関数を呼び出す](https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/actions-invoke-lambda-function.html)
- [CodePipelineからAWS Lambdaを呼び出してCloudFrontのキャッシュを削除(Invalidation)してみた](https://dev.classmethod.jp/articles/cloudfront-invalidation-using-codepipeline-custom-action/)


## 構成図

こんなの作る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/e563193b-7112-8526-e5d1-e49b8aac3bf5.png)

## やること

Code Pipelineの`Stage`にLambdaを登録してみる。ハローワールド的な動作確認までやる。`Source`と`Deploy`は適当に設定。
Stageで思った通りに（しょぼい）Lambdaが動くことを確認する

## 1.検証の準備

検証に必要な準備をする。いわゆる環境構築

#### 1-1.IAMポリシーを作る

作成するLambdaに与える権限`CodePipelineLambdaExecPolicy`を作る。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/89e77869-ef15-3e2c-e1f3-b35209946613.png" width="450">


```json:CodePipelineLambdaExecPolicy
{
  "Version": "2012-10-17", 
  "Statement": [
    {
      "Action": [ 
        "logs:*"
      ],
      "Effect": "Allow", 
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Action": [
        "codepipeline:PutJobSuccessResult",
        "codepipeline:PutJobFailureResult"
        ],
        "Effect": "Allow",
        "Resource": "*"
     }
  ]
} 
```

以下ができるポリシー

- codepipelineに、SuccessとFailureを返せるようにする
- CloudWatchにログ出力できるようにする

#### 1-2.IAMロールを作る

先ほど作成したIAMポリシー`CodePipelineLambdaExecPolicy`をLambdaに適用できるようIAMロール`CodePipelineLambdaExecPolicy`を作る。IAMポリシー作成時、AWSサービス `lambda` を選択する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/6b857e65-dec4-d94e-5b4e-a455d901e924.png" width="450">

#### 1-3.Lambdaを作る

Python3.8を選択し、Lambdaを作る。IAMロールは、`CodePipelineLambdaExecPolicy`を選択する ←重要。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/ba7d0f76-9816-a901-ee34-b03ddb3db491.png" width="450">


#### 1-4.CodePipelineを作る

`Stage`にLambdaを設定する以外は、適当に設定。今回は、CodeCommitのリポジトリ内のデータをS3にpushするように設定したけど、動くならなんでもいい。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/bbd9f174-b0ed-ca50-8852-2c473832c590.png" width="450">


## 2.検証(1) スクリプトの成功/失敗やってみる

Lambdaスクリプトの成功と失敗の動きをやってみる。

#### 2-1.成功を返すスクリプト

今回のメイン、Lambdaスクリプトを書いていく。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/b2a025ef-7a14-0bf9-1793-5c9c4f722cfb.png" width="450">


```python:成功を返す
import json
import boto3

def lambda_handler(event, context):
    codepipeline = boto3.client('codepipeline')

    # CodePipelineに結果(成功)を返す
    codepipeline.put_job_success_result(jobId = event['CodePipeline.job']['id'])

    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda! Error')
    }
```

CodePipelineの`変更をリリースする`を実行し、`成功しました`と表示されたら成功

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/f61382ed-ddff-984e-e87e-d04a7f459844.png)


#### 2-2.失敗を返すスクリプト

```python:失敗を返す
import json
import boto3

def lambda_handler(event, context):
    codepipeline = boto3.client('codepipeline')

    # CodePipelineに結果(失敗)を返す
    codepipeline.put_job_failure_result(
         jobId = event['CodePipeline.job']['id'],
         failureDetails={
             'type': 'JobFailed',
             'message': 'Failed test.'
         }
    )

    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda! Error')
    }
```

`失敗しました`と表示されれば成功

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/df33b1b0-d9ee-2201-c2f0-2648614266cc.png)


## 3.検証(2) CodePipelineアクションデータからの情報をLambdaで受け取ってログ出力

CodePipelineアクションデータからの情報をLambdaで受け取ってログ出力してみる

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/d33e8943-2869-78fd-a909-b1e2952afa42.png" width="450">

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/bb3a04d0-b827-7323-4421-c28f51182e99.png)


↑のユーザーパラメータに登録した内容がこれ↓　（ホントは改行してない）

```json
{
    "PipelineName": "example-pipeline",
    "DistributionId": "E1EVDTCEXAMPLE",
    "SnsTopicArn": "arn:aws:sns:ap-northeast-1:XXXXXXXXXXXX:example-topic"
}
```

Lambdaスクリプト(Python3.8)はこれ

```python:lambda-test02
import boto3
import json
import logging
import time
import traceback

logger = logging.getLogger()
logger.setLevel(logging.INFO)

cp = boto3.client('codepipeline')
cf = boto3.client('cloudfront')
sns = boto3.client('sns')

def lambda_handler(event, context):
    codepipeline = boto3.client('codepipeline')

    job_id = event['CodePipeline.job']['id']
    job_data = event['CodePipeline.job']['data']

    user_parameters = json.loads(
        job_data['actionConfiguration']['configuration']['UserParameters']
    )

    pipeline_name = user_parameters['PipelineName']
    distribution_id = user_parameters['DistributionId']
    sns_topic_arn = user_parameters['SnsTopicArn']


    logger.info('[TEST] job_id = %s', job_id)
    logger.info('[TEST] job_data = %s', job_data)
    logger.info('[TEST] pipeline_name = %s', pipeline_name)
    logger.info('[TEST] distribution_id = %s', distribution_id)
    logger.info('[TEST] sns_topic_arn = %s', sns_topic_arn)

    # CodePipelineに結果(成功)を返す
    codepipeline.put_job_success_result(jobId = event['CodePipeline.job']['id'])

    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda! Error')
    }
```

実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/6fa78d30-62a6-c4f1-d7f3-bd40bc8f14ed.png)

↑の`詳細`をクリックしてCloudWatchログを確認する

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/6ffc2ee2-ff31-1756-ee3d-fc997530d1b7.png" width="450">

ログに記録されてたら成功

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/4ef36252-1c76-28d5-4321-ce33f79172f7.png)


今回は、ここまででおわり。
ホントにハローワールドしかできなかった、調査はつづく
次は、Souceの情報をStageでチェックするスクリプトを作りたい