web-dev-qa-db-fra.com

Mise à jour Terraform lambda source_code_hash avec le même code

J'ai déployé avec succès une AWS Lambda avec Terraform:

resource "aws_lambda_function" "lambda" {
  filename                       = "dist/subscriber-lambda.Zip"
  function_name                  = "test_get-code"
  role                           = <my_role>
  handler                        = "main.handler"
  timeout                        = 14
  reserved_concurrent_executions = 50
  memory_size                    = 128
  runtime                        = "python3.6"
  tags                           = <my map of tags>
  source_code_hash               = "${base64sha256(file("../modules/lambda/lambda-code/main.py"))}"
  kms_key_arn                    = <my_kms_arn>
  vpc_config {
    subnet_ids         = <my_list_of_private_subnets>
    security_group_ids = <my_list_of_security_groups>
  }
  environment {
    variables = {
      environment = "dev"
    }
  }
}

Maintenant, quand je lance terraform plan commande, il indique que ma ressource lambda doit être mise à jour car le source_code_hash a changé, mais je n'ai pas mis à jour lambda Python codebase (qui est versionné dans un dossier du même dépôt):

  ~ module.app.module.lambda.aws_lambda_function.lambda
  last_modified:                     "2018-10-05T07:10:35.323+0000" => <computed>
  source_code_hash:                  "jd6U44lfe4124vR0VtyGiz45HFzDHCH7+yTBjvr400s=" => "JJIv/AQoPvpGIg01Ze/YRsteErqR0S6JsqKDNShz1w78"

Je suppose que c'est parce qu'il compresse mes sources Python à chaque fois et que la source change. Comment puis-je éviter cela s'il n'y a pas de changement dans le code Python? Mon hypothèse est-elle cohérente si je ne change pas la base de code Python (je veux dire, pourquoi le hachage change-t-il))?

6
Arcones

C'est parce que vous hachez juste main.py mais que vous téléchargez dist/subscriber-lambda.Zip. Terraform compare le hachage au hachage qu'il calcule lorsque le fichier est téléchargé sur lambda. Étant donné que le hachage est effectué sur deux fichiers différents, vous vous retrouvez avec des hachages différents. Essayez d'exécuter le hachage sur le même fichier en cours de téléchargement.

1
ODYN-Kon

Je vais ajouter ma réponse pour contraster avec celle fournie par @ ODYN-Kon.

Le champ de hachage du code source dans la ressource "aws_lambda_function" n'est pas comparé à un hachage du Zip que vous téléchargez. Au lieu de cela, le hachage est simplement comparé à l'état enregistré de Terraform lors de sa dernière exécution. Ainsi, la prochaine fois que vous exécutez Terraform, il calcule le hachage du fichier python réel pour voir s'il a changé. Si tel est le cas, il suppose que le Zip a été modifié et la fonction Lambda La ressource doit être exécutée à nouveau. Le code_source_hash peut avoir la valeur que vous souhaitez lui donner ou il peut être omis complètement. Vous pouvez le définir sur une constante d'une chaîne arbitraire, puis il ne changera jamais sauf si vous modifiez votre configuration Terraform.

Maintenant, le problème est que Terraform suppose que vous avez mis à jour le fichier Zip. En supposant que vous ne disposez que d'un répertoire ou d'un fichier dans l'archive Zip, vous pouvez utiliser la source de données Terraform archive_file pour créer le fichier Zip. J'ai un cas où je ne peux pas l'utiliser parce que j'ai besoin d'un répertoire et d'un fichier (monde JS: source + node_modules /). Mais voici comment vous pouvez l'utiliser:

data "archive_file" "lambdaCode" {
  type = "Zip"
  source_file = "lambda_process_firewall_updates.js"
  output_path = "${var.lambda_Zip}"
}

Alternativement, vous pouvez archiver un répertoire entier, si vous remplacez l'instruction "source_file" par source_dir = "node_modules"

Une fois cela fait, vous pouvez référencer le code de hachage du fichier d'archive Zip pour l'insertion dans le bloc resource "aws_lambda_function" "lambda" { En tant que "${data.archive_file.lambdaCode.output_base64sha256}" Pour le champ source_hash. Ensuite, chaque fois que le Zip change, la fonction lambda est mise à jour. Et, le fichier d'archive de source de données sait que chaque fois que le fichier source change, il doit régénérer le Zip.

Maintenant, je n'ai pas exploré une cause profonde dans votre cas, mais j'espère avoir donné de l'aide pour arriver à un meilleur endroit. Vous pouvez vérifier l'état enregistré de Terraform via: tf state list - qui répertorie les éléments de l'état enregistré. Vous pouvez trouver celui qui correspond à votre bloc fonction lambda, puis exécuter tf state show <state-name>. Par exemple, pour celui sur lequel je travaille:

tf state show aws_lambda_function.test-lambda-networking Donne environ 30 lignes de sortie, dont:

code_source_hash = 2fKX9v/duluQF0H6O9 + iRnID2gokhfpXIXpxyeVBUM0 =

Vous pouvez comparer le hachage via les commandes de ligne de commande. Exemple sur MacOS: sha256sum my-lambda.Zip, Où sha256sum a été installé par brew install coreutils.

Comme mentionné, l'utilisation de archive_file ne fonctionne pas lorsque vous avez plusieurs éléments du Zip qui ne sont pas isolés dans un seul répertoire. Je pense que cela arrive souvent, donc je souhaite que les gars de Hashicorp étendent archive_file pour en supporter plusieurs. Je suis même allé voir le code Go, mais c'est un projet de jour de pluie. Une variante que j'utilise est de prendre le source_code_hash pour être "${base64sha256(file("my-lambda.Zip"))}". Mais cela nécessite encore que je lance deux fois tf.

1
Kevin Buchs

Comme d'autres l'ont dit, votre Zip doit être utilisé dans votre nom de fichier et votre hachage.

Je tiens à mentionner que vous pouvez également obtenir des problèmes de loisirs similaires si vous utilisez la mauvaise fonction de hachage dans vos définitions lambda. Par exemple, filesha256 (.Zip) recréera également vos lambdas à chaque fois. Vous devez utiliser filebase64sha256 ("file.Zip") (terraform 0.11.12+) ou base64sha256 (file ("file.Zip")) comme mentionné sous source_code_hash ici

1
adavea