[PYTHON] [AWS] Résolution d'un problème où Lambda appelé depuis CodePipeline est toujours en cours

problème

** L'indicateur tourne tout le temps **

スクリーンショット 2019-11-08 23.47.25.png (Debout pendant 10 minutes tel quel) Je suis fou! !! !!

J'ai trébuché lorsque j'ai voulu appeler Lambda pour effacer le cache CloudFront une fois le déploiement sur S3 terminé, alors je l'ai résumé.

Cause

** Parce que codepipeline: PutJobSuccessResult (*) n'est pas retourné **

  • En cas d'échec, codepipeline: PutJobFailedResult

Qu'est-ce que PutJobSuccessResult?

PutJobSuccessResult Obligatoire pour signaler le succès du travail renvoyé par le travailleur du travail au pipeline. Utilisé uniquement pour les actions personnalisées. Extrait de https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/permissions-reference.html

images.png

En résumé

CodePipeline ne reçoit que les résultats des ** actions personnalisées (telles que Lambda) qu'il appelle dans un format fixe **, PutJobSuccessResult et PutJobFailedResult. ** Même s'il est renvoyé dans d'autres formats, il sera ignoré, de sorte que l'indicateur tourne autour ** que le résultat ne provient pas de Lambda depuis longtemps.

Lorsque PutJobSuccessResult est renvoyé

スクリーンショット 2019-11-08 23.56.48.png

Lorsque PutJobFailedResult est retourné

スクリーンショット 2019-11-09 0.09.46.png スクリーンショット 2019-11-09 0.09.58.png

Je l'ai fait. </ font>

Correspondance

** OK en écrivant du code qui renvoie PutJobSuccessResult et PutJobFailedResult sur Lambda. ** **

Comment renvoyer réellement «PutJobSuccessResult» et «PutJobFailedResult» dans Lambda par langue.

Python

Runtime Lambda_Python3.7


import json
import boto3

def lambda_handler(event, context):
    codepipeline = boto3.client('codepipeline')
    
    #Résultats sur CodePipeline(Succès)rends le
    codepipeline.put_job_success_result(jobId = event['CodePipeline.job']['id'])
    
    #Résultats sur CodePipeline(Échec)rends le
    # 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!')
    }

Ruby

Runtime Lambda_Ruby2.5


require 'json'
require 'aws-sdk'

def lambda_handler(event:, context:)
    codepipeline = Aws::CodePipeline::Client.new()
    
    #Résultats sur CodePipeline(Succès)rends le
    codepipeline.put_job_success_result({job_id: event["CodePipeline.job"]['id']})
    
    #Résultats sur CodePipeline(Échec)rends le
    # codepipeline.put_job_failure_result({
    #    job_id: event["CodePipeline.job"]['id'], 
    #    failure_details: {
    #        type: "JobFailed", # accepts {JobFailed, ConfigurationError, PermissionError, RevisionOutOfSync, RevisionUnavailable, SystemUnavailable}
    #        message: "Failed test."
    #    }
    # })
    
    { statusCode: 200, body: JSON.generate('Hello from Lambda!') }
end

Node.js

javascript:Runtime Lambda_Node.js10.x


var AWS = require('aws-sdk');

exports.handler = function(event, context) {
    var codepipeline = new AWS.CodePipeline();
    
    //Résultats sur CodePipeline(Succès)rends le
    codepipeline.putJobSuccessResult({jobId: event["CodePipeline.job"].id}, function(err, data) {
        if(err) {
            context.fail(err);
        } else {
            context.succeed('Success test.');
        }
    });
    
    //Résultats sur CodePipeline(Échec)rends le
    // var params = {
    //     jobId: event["CodePipeline.job"].id,
    //     failureDetails: {
    //         message: JSON.stringify('Failed test.'),
    //         type: 'JobFailed',
    //     }
    // };
    // codepipeline.putJobFailureResult(params, function(err, data) {
    //     context.fail('Failed test.');
    // });
    
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};

Je n'écris généralement pas Node.js, donc je ne sais pas si c'est le code minimum requis. </ Font>

Même si j'ai copié le code, il tourne toujours!

Tout d'abord, examinons le journal CloudWatch de Lambda.

AccessDeniedException

Suite à l'exécution de Lambda, CloudWatch Log affiche quelque chose comme ceci.

{
   "errorType": "AccessDeniedException",
   "errorMessage": "User: arn:aws:sts::1111111111111:assumed-role/codetest-role-xxxxxxxxx/codetest is not authorized to perform: codepipeline:PutJobSuccessResult",
    ...etc
}

Vous êtes également autorisé à renvoyer les résultats de Lambda à CodePipeline ...

La stratégie IAM suivante doit être ajoutée au rôle IAM attribué à Lambda.

Politique IAM


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

Veuillez me faire savoir si vous faites des erreurs.