Gibt es eine Möglichkeit, Verknüpfungen für häufig verwendete Werte zu definieren, die aus CloudFormation-Vorlagenparametern abgeleitet wurden?
Zum Beispiel - Ich habe ein Skript, das einen Multi-AZ-Projektstapel mit dem ELB-Namen project
und zwei Instanzen hinter dem ELB mit dem Namen project-1
und erstellt project-2
. Ich übergebe nur ELBHostName
Parameter an die Vorlage und benutze sie später zum Konstruieren:
"Fn::Join": [
".", [
{ "Fn::Join": [ "", [ { "Ref": "ELBHostName" }, "-1" ] ] },
{ "Ref": "EnvironmentVersioned" },
{ "Ref": "HostedZone" }
]
]
Diese oder eine sehr ähnliche Konstruktion wird in der gesamten Vorlage mehrmals wiederholt, um den EC2-Hostnamen, Route53-Datensätze usw. zu erstellen.
Anstatt das immer wieder zu wiederholen, möchte ich die Ausgabe Fn::Join
einer Variablen zuweisen und nur darauf verweisen, so wie ich es mit "Ref":
Anweisung tun kann .
Idealerweise so etwas wie:
Var::HostNameFull = "Fn::Join": [ ... ]
...
{ "Name": { "Ref": "Var::HostNameFull" } }
oder etwas ähnlich Einfaches.
Ist das mit Amazon CloudFormation möglich?
Antworten:
Ich habe nach der gleichen Funktionalität gesucht. Es kam mir in den Sinn, einen verschachtelten Stapel zu verwenden, wie es SpoonMeiser vorschlug, aber dann wurde mir klar, dass ich tatsächlich benutzerdefinierte Funktionen benötigte. Zum Glück ermöglicht CloudFormation die Verwendung von AWS :: CloudFormation :: CustomResource , mit der man mit ein wenig Arbeit genau das tun kann. Dies fühlt sich wie ein Overkill für nur Variablen an (etwas, von dem ich behaupte, dass es ursprünglich in CloudFormation gewesen sein sollte), aber es erledigt die Aufgabe und ermöglicht darüber hinaus die gesamte Flexibilität von (wählen Sie Python / Node aus) /Java). Es sollte beachtet werden, dass Lambda-Funktionen Geld kosten, aber wir sprechen hier von Pennies, es sei denn, Sie erstellen / löschen Ihre Stapel mehrmals pro Stunde.
Der erste Schritt besteht darin, auf dieser Seite eine Lambda-Funktion zu erstellen , die nichts anderes tut, als den Eingabewert zu übernehmen und in die Ausgabe zu kopieren. Wir könnten die Lambda-Funktion alle möglichen verrückten Sachen machen lassen, aber sobald wir die Identitätsfunktion haben, ist alles andere einfach. Alternativ könnte die Lambda-Funktion im Stapel selbst erstellt werden. Da ich viele Stapel in einem Konto verwende, hätte ich eine ganze Reihe von Lambda-Funktionen und -Rollen übrig (und alle Stapel müssen mit erstellt werden
--capabilities=CAPABILITY_IAM
, da sie auch eine Rolle benötigen.Lambda-Funktion erstellen
index.handler
Dann kopieren Sie den unten stehenden Code und fügen ihn in das Codefeld ein. Die Spitze der Funktion ist der Code aus dem cfn-response-Python-Modul , der aus irgendeinem Grund nur dann automatisch installiert wird, wenn die Lambda-Funktion über CloudFormation erstellt wird. Die
handler
Funktion ist ziemlich selbsterklärend.Sie können nun die Lambda-Funktion testen, indem Sie auf die Schaltfläche "Test" klicken und "CloudFormation Create Request" als Beispielvorlage auswählen. Sie sollten in Ihrem Protokoll sehen, dass die ihm zugeführten Variablen zurückgegeben werden.
Verwenden Sie eine Variable in Ihrer CloudFormation-Vorlage
Nachdem wir diese Lambda-Funktion haben, können wir sie in CloudFormation-Vorlagen verwenden. Notieren Sie sich zunächst die Lambda-Funktion Arn (gehen Sie zur Lambda-Homepage , klicken Sie auf die gerade erstellte Funktion, die Arn sollte sich etwa oben rechts befinden
arn:aws:lambda:region:12345:function:CloudFormationIdentity
).Geben Sie nun in Ihrer Vorlage im Ressourcenbereich Ihre Variablen an, wie z.
Zuerst gebe ich eine
Identity
Variable an, die das Arn für die Lambda-Funktion enthält. Wenn ich das hier in eine Variable setze, muss ich es nur einmal angeben. Ich mache alle meine Variablen vom TypCustom::Variable
. Mit CloudFormation können Sie jeden Typnamen verwenden, der mitCustom::
benutzerdefinierten Ressourcen beginnt .Beachten Sie, dass die
Identity
Variable zweimal das Arn für die Lambda-Funktion enthält. Einmal, um die zu verwendende Lambda-Funktion anzugeben. Das zweite Mal als Wert der Variablen.Nun, da ich die
Identity
Variable habe, kann ich neue Variablen mit definierenServiceToken: !GetAtt [Identity, Arn]
(ich denke, JSON-Code sollte so ähnlich sein"ServiceToken": {"Fn::GetAtt": ["Identity", "Arn"]}
). Ich erstelle 2 neue Variablen mit jeweils 2 Feldern: Name und Arn. Im Rest meiner Vorlage kann ich!GetAtt [ClientBucketVar, Name]
oder!GetAtt [ClientBucketVar, Arn]
wann immer ich es brauche.Achtung!
Wenn Sie mit benutzerdefinierten Ressourcen arbeiten und die Lambda-Funktion abstürzt, müssen Sie zwischen 1 und 2 Stunden warten, da CloudFormation eine Stunde lang auf eine Antwort der (abgestürzten) Funktion wartet, bevor Sie aufgeben. Daher kann es sinnvoll sein, während der Entwicklung Ihrer Lambda-Funktion eine kurze Zeitüberschreitung für den Stack festzulegen.
quelle
cloudformation-tool
Gem), also packe ich die Lambda-Erstellung in die Vorlage und kann sie dann direkt verwenden, anstatt dieIdentity
benutzerdefinierte Ressource zu erstellen . Siehe hier für meinen Code: gist.github.com/guss77/2471e8789a644cac96992c4102936fb3Ich habe keine Antwort, wollte aber darauf hinweisen, dass Sie sich viel Schmerz ersparen können, indem Sie
Fn::Sub
anstelle vonFn::Join
Ersetzt
quelle
Nein, ich habe es versucht, kam aber leer. Für mich war es sinnvoll, einen Mappings-Eintrag mit dem Namen "CustomVariables" zu erstellen und alle meine Variablen in diesem Haus zu haben. Es funktioniert für einfache Strings, aber Sie können Intrinsics (Refs, Fn :: Joins usw.) nicht in Mappings verwenden .
Werke:
Wird nicht funktionieren:
Das ist nur ein Beispiel. Sie würden keinen eigenständigen Verweis in eine Variable einfügen.
quelle
Sie können einen verschachtelten Stapel verwenden, der alle Ihre Variablen in seinen Ausgaben auflöst und dann
Fn::GetAtt
zum Lesen der Ausgaben von diesem Stapel verwendetquelle
Sie können verschachtelte Vorlagen verwenden, in denen Sie alle Variablen in der äußeren Vorlage "auflösen" und an eine andere Vorlage übergeben.
quelle