1

Wir verfügen über eine API, die zum Bereitstellen bestimmter Ressourcen in AWS mithilfe von Cloud Formation verwendet wird. Dies beinhaltet eine Lambda-Funktion, die Ereignisse an S3 sendet, wobei der Bucket konfigurierbar ist. Die Sache ist, wir werden den Bucket-Namen kennen, wenn wir das Lambda bereitstellen, nicht innerhalb des Lambda-Codes selbst.Verwenden von Cloudformation zum Bereitstellen von Lambda, einschließlich eines Parameters, auf den die Funktion zugreifen kann

Soweit ich feststellen kann, gibt es keine Möglichkeit, den S3-Bucket-Namen zum Zeitpunkt der Bereitstellung in das Cloud-Formations-Template selbst zu injizieren. Ist das wahr?

Die einzige Lösung, die ich sehen kann, ist, den Funktionscode im laufenden Betrieb zu generieren und diesen in die Cloud-Formationsvorlage einzubetten. Dadurch können wir keine NPM-Abhängigkeiten zusammen mit dem Funktionscode verwenden. Gibt es eine bessere Option?

+0

Ihre Frage ist nicht klar. 'Lambda-Funktion, die Ereignisse an S3 sendet. Was meinst du damit? – helloV

Antwort

1

Also erkannte ich, dass ich diese Frage nie mit meiner eventuellen Lösung aktualisiert hatte. Ich habe schließlich eine Proxy-Lambda-Funktion in die Cloud-Templates eingebettet, die es mir ermöglicht, Template-Parameter zu injizieren.

Beispiel:

{ 
"AWSTemplateFormatVersion": "2010-09-09", 
"Description": "Creates a function to relay messages from a Kinesis instance to S3", 
"Parameters": { 
    "S3Bucket" : { 
     "Type": "String", 
     "Description": "The name of the S3 bucket where the data will be stored" 
    }, 
    "S3Key": { 
     "Type": "String", 
     "Description": "The key of the directory where the data will be stored" 
    } 
}, 

"Resources": { 
    "mainLambda": { 
     "Type" : "AWS::Lambda::Function", 
     "Properties" : { 
      "Handler" : "index.handler", 
      "Description" : "Writes events to S3", 
      "Role" : { "Ref": "LambdaRoleARN" }, 
      "Runtime" : "nodejs4.3", 
      "Code" : { 
       "S3Bucket": "streams-resources", 
       "S3Key": "astro-bass/${GIT_COMMIT}/lambda/astro-bass.zip" 
      } 
     } 
    }, 

    "lambdaProxy": { 
     "Type" : "AWS::Lambda::Function", 
     "Properties" : { 
      "Handler" : "index.handler", 
      "Runtime" : "nodejs", 
      "Code" : { 
       "ZipFile": { "Fn::Join": ["", [ 
        "var AWS = require('aws-sdk');", 
        "var lambda = new AWS.Lambda();", 
        "exports.handler = function(event, context) {", 
         "event.bundledParams = ['", 
          { "Ref": "S3Bucket" }, 
          "','", 
          { "Ref": "S3Key" }, 
         "'];", 
         "lambda.invoke({", 
          "FunctionName: '", 
          { "Ref": "mainLambda" }, 
          "',", 
          "Payload: JSON.stringify(event, null, 2),", 
          "InvocationType: 'Event'", 
         "}, function(err, data) {", 
          "if(err) {", 
           "context.fail(err);", 
          "}", 
          "context.done();", 
         "});", 
        "};" 
       ]]} 
      } 
     } 
    }, 
}, 

... 
} 

Die Proxy-Funktion hatte die in ihren Code injizierten Parameter (s3Bucket/key), und dann ruft es das Haupt Lambda mit einem modifizierten Ereignisobjekt. Es ist ein wenig unorthodox, aber mir erschien es viel sauberer als die anderen verfügbaren Lösungen, wie Parse Stacknamen/etc. Bis jetzt gut gearbeitet.

Beachten Sie, dass diese Lösung derzeit nur mit der Legacy-Knotenumgebung funktioniert. Kein Problem, aber beunruhigend in Bezug auf die Langlebigkeit dieser Lösung.

UPDATE: Wir stießen mit der vorherigen Lösung auf Einschränkungen und mussten noch eine weitere entwickeln. Am Ende haben wir das Beschreibungsfeld off-label verwendet, um Konfigurationswerte einzubetten. Hier ist unsere Lambda

'use strict'; 
var aws = require('aws-sdk'); 
var lambda = new aws.Lambda({apiVersion: '2014-11-11'}); 

let promise = lambda.getFunctionConfiguration({ FunctionName: process.env['AWS_LAMBDA_FUNCTION_NAME'] }).promise(); 

exports.handler = async function getTheConfig(event, context, cb) { 
    try { 
     let data = await promise; 
     cb(null, JSON.parse(data.Description).bucket); 
    } catch(e) { 
     cb(e); 
    } 
}; 

Dann im Beschreibungsfeld, können Sie eine einfache JSON einbetten wie so snipped:

{ 
    "bucket": "bucket-name" 
} 

Darüber hinaus ist diese Struktur, mit dem Versprechen außerhalb des Handlers begrenzt die Anforderung, nur dann zu erscheinen, wenn der Container erzeugt wird - nicht für jede einzelne Lambda-Ausführung.

Nicht ganz die sauberste Lösung, aber die funktionellste, die wir gefunden haben.

0

Es gibt keine Möglichkeit, Parameter an eine Lambda-Funktion neben dem Ereignis selbst zu übergeben.

Wenn Sie eine Lambda-Funktion mit Cloudformation Erstellen Sie die folgende Problemumgehung verwenden:

  • Verwenden Lambda-Funktion Name des Cloudformation Stapel Namen abzuleiten.
  • Verwenden Sie den CloudFormation-Stapelnamen, um beim Ausführen der Lambda-Funktion auf Ressourcen oder Parameter des Stapels zuzugreifen.
+0

Ich traue nicht wirklich, den Stapelnamen vom Funktionsnamen selbst abzuleiten, aber dennoch interessante Idee. Vielen Dank! – Dygerati