2016-01-05 8 views
10

Zadanie, które należy zrobić, to CDN powinien zależeć od zasobnika S3, ale możemy również użyć istniejącego wiadra zamiast tworzyć nowy.CloudFormation, Apply Condition on DependsOn

Oto przykładowy kod, że walczę z:

"Parameters" : { 
    "UseExistingBucket" : { 
    "Description" : "Yes/No", 
    "Default" : "yes", 
    "Type" : "String", 
    "AllowedValues" : [ "yes", "no" ] 
    } 
}, 
"Conditions" : { 
    "CreateS3Resources" : {"Fn::Equals" : [{"Ref" : "UseExistingBucket"}, "no"]} 
}, 
"Resources" : { 
    "StaticBucket" : { 
    "Type" : "AWS::S3::Bucket", 
    "Condition" : "CreateS3Resources", 
    "Properties" : { 
     "BucketName" : { "Fn::Join": [ "-", [ "app", { "Ref": "EnvType" }, "static" ] ] } 
    }, 
    "DeletionPolicy": "Retain" 
    }, 
    "MyStaticDistribution": { 
    "Type": "AWS::CloudFront::Distribution", 
    "Properties": { 
     "DistributionConfig": { 
     "Origins": [ 
      { 
      "DomainName": { 
       "Fn::If" : [ 
       "CreateS3Resources", 
       { "Fn::Join": [ "-", [ "app", { "Ref": "EnvType" }, "static" ] ] }, 
       {"Fn::GetAtt": [ "StaticBucket", "DomainName" ] } 
       ] 
      }, 
      "Id": "S3Origin", 
      } 
     ] 
     } 
    }, 
    "DependsOn": [{ 
     "Fn::If" : [ 
     "CreateS3Resources", 
     { "Fn::Join": [ "-", [ "app", { "Ref": "EnvType" }, "static" ] ] }, 
     "" 
     ] 
    }] 
    } 
} 

Proszę zasugerować mi żadnych więcej szczegółów w razie potrzeby (conajmniej stackoverflow nie chce więcej szczegółów, ale nie podając żadnych :-P)

Odpowiedz

0

Walczę z tym samym. Błąd jest:

A client error (ValidationError) occurred when calling the ValidateTemplate operation: Template format error: DependsOn must be a string or list of strings.

nie wydaje się możliwe, aby umieścić warunkowa w DependsOn.

Zacząłem szukać innych sposobów, aby to wyrazić. Może umieszczenie zależnego kodu w 2 różnych szablonach potomnych. Wykryj warunek na zewnątrz i przekaż odpowiednią nazwę zagnieżdżonego szablonu do parametru szablonu nadrzędnego. Tak więc DependsOn widzi parametr, który przekazuję jako szablon zależny.

Wydaje się, że zbytnio wykrzywiona logika.

Musi być lepszy sposób.

7

Możesz to zrobić, używając Fn:GetAtt w opakowaniu warunkowym Fn:If. Korzystanie z Fn: GetAtt implikuje zależność, więc CloudFormation automatycznie zaczeka, gdy osiągnie tę funkcję, tak samo jak w przypadku DependsOn.

Przykład

Fragment kodu poniżej pokazuje to poprzez warunkowo pobierania nazwę zagnieżdżonego stos, który nie został jeszcze utworzony, ale nie tylko, więc jeśli UseNestedStack stan jest ustawiony na true. Jeśli UseNestedStack ma wartość false, nie będzie czekać i zamiast tego pobierze nazwę zmiennej lokalnej.

{ 
"Fn::If": ["UseNestedStack", { 
    "Fn::GetAtt": ["NestedStack", "Outputs.Name"] 
}, { 
    "Ref": "LocalName" 
}] 

Skąd mam wiedzieć? (Inny przykład)

Niestety nie ma oficjalnej dokumentacji oficjalnie stwierdzającej, ale to AWS kazało mi zrobić to w ten sposób, a w ich przykładach kodu widać, że gdy zamówienie ma znaczenie, używają Fn: GetAtt. Próbowałem tego wiele razy i działa za każdym razem. Wypróbuj sam na prostym stosie. Oto jeszcze jeden pseudo dowód z przykładu AWS z AWS, który zmodyfikowałem i wykorzystałem. Poniższy stos nie mógłby działać, gdyby funkcja AMI została utworzona po informacji o AMI zasobu, AMI Info potrzebuje wyjścia funkcji AMI, więc AWS połączył je razem za pomocą Fn: GetAtt. Aby zobaczyć ten przewinięcie do dołu i przyjrzeć się zasobowi AMIInfo, a zobaczysz, że odwołuje się do funkcji AMIFunction przez fn: Gett. CloudFormation widzi to i wraca do AMIFunction, aby je najpierw utworzyć.

"AMIInfoFunction": { 
    "DependsOn":"SourceStack", 
    "Type": "AWS::Lambda::Function", 
    "Properties": { 
    "Code": { 
     "S3Bucket": { "Ref": "DeploymentBucket" }, 
     "S3Key": {"Fn::Join": [ 
     "", 
     [ 
      { 
      "Ref": "ApplicationName" 
      }, 
      "/amilookup.zip" 
     ] 
     ]} 
    }, 
    "Handler": "amilookup.handler", 
    "Runtime": "nodejs", 
    "Timeout": "30", 
    "Role": { "Fn::GetAtt" : ["LambdaExecutionRole", "Arn"] }, 
    "VpcConfig": { 
     "SecurityGroupIds": [ {"Ref": "InstanceSecurityGroup"}], 
     "SubnetIds": [ {"Ref":"PrivateSubnetA"},{"Ref":"PrivateSubnetB"} ] 
    } 
    } 
}, 
"AMIInfo": { 
    "Type": "Custom::AMIInfo", 
    "Properties": { 
    "ServiceToken": { "Fn::GetAtt" : ["AMIInfoFunction", "Arn"] }, 
    "StackName": { "Ref":"SourceStack" } 
    } 
} 
+0

Czy istnieje dokumentacja gdzieś, że mówi, że GetAtt automatycznie czekać na zakończenie drugiego zasobu przed przejściem do przodu? – doeiqts

+2

@doeiqts Dobre pytanie. Niestety nie widziałem tego udokumentowanego, ale jestem przekonany, że jest to prawdą od jego wykorzystania w przykładach AWS, tego, że widziałem to już wiele razy, oraz od inżynierów AWS, którzy pouczają mnie, że robię to w ten sposób. Dodałem przykład lambda z AWS, w którym opóźniają tworzenie w ten sposób. Ale tak, oficjalna dokumentacja byłaby czystsza. –

0

W szablonie nie trzeba dodać atrybut DependsOn do zasobu MyStaticDistribution jak masz już odwołanie do zasobu StaticBucket.

Jest to udokumentowane w Określanie Zależności części Optymalizacja AWS CloudFormation Szablony blogu: https://aws.amazon.com/blogs/devops/optimize-aws-cloudformation-templates/

When you need CloudFormation to wait to provision one resource until another one has been provisioned, you can use the DependsOn attribute.

You can also introduce references between elements by using either the { "Ref": "MyResource" } or the { "Fn::GetAtt" : [ "MyResource" , "MyAttribute" ] } functions. When you use one of these functions, CloudFormation behaves as if you’ve added a DependsOn attribute to the resource.

Powiązane problemy