やったこと
Serverless Frameworkで条件ごとにbuildするリソースの分岐をしようと、
いくつか試したので記録として残しておきます
先にまとめ
resource:
に入れ子構造で- $file{xxxx}
を設定できない$file{(./xxxx.yml), ''}
で書けば、そのファイルが存在する場合はリソースが作られるし、ファイルが存在しない場合はリソースが作られないかつ、エラーも発生しない
改修前の状態
serverless.ymlからresourceへのpathを書いたファイルを読み込む
custom:
...
resources: ${file(./resources_shared.yml)}
...
- $file{(./SampleLambda/lambda.yml)}
- $file{(./SampleEventRule/rule.yml)}
これで現状問題なく動いていました
今回やりたかったこと
特定のServerlessのserviceでのみあるリソースのbuildが必要になりました
なのでserverless.ymlから複数のresourceへのpathを書いたファイルを読み込んで、環境ごとにbuildするリソースを分けることができるかな…と調査を開始したのがきっかけです
例としてここではserviceNameの値を使ってにリソースを分けるつもりで記載しておきます
「serviceNameがapple
の場合のみ特定のリソースをbuildしたい」想定です
custom:
serviceName: ${env:SERVICE_NAME, "apple"} #apple or orange
..
resources:
- ${file(./resources_shared.yml)}
- ${file(./resources_${self:custom.serviceName}.yml)}
...
# apple, orange共通で必要なリソース
- $file{(./SampleLambda/lambda.yml)}
- $file{(./SampleEventRule/rule.yml)}
# appleのみで必要なリソース
- $file{(./Resource/IAM.yml)}
- $file{(./Resource/S3.yml)}
# orangeの場合は追加でbuildしたいリソースは無い
結果
上記のようにファイル名のsufixを動的に変えて試すも、そもそもresources:
を配列にする場合は、
参照先のファイルで- $file{xxxx}
を記述することができなかった
つまり- $file{xxxx}
を入れ子にできない
対処
1. serverless.ymlのresources:には配列ではなく単一のymlを参照させる
custom:
serviceName: ${env:SERVICE_NAME, "apple"} #apple or orange
..
resources: ${file(./resources.yml)}
2. appleのみで必要なリソースファイルを/Resource/apple/配下に配置する
3. resources.yml内で下記のように書く
# apple, orange共通で必要なリソース
- $file{(./SampleLambda/lambda.yml)}
- $file{(./SampleEventRule/rule.yml)}
# appleのみで必要なリソース
- $file{(./Resource/${self:custom.serviceName}/IAM.yml), ''}
- $file{(./Resource/${self:custom.serviceName}/S3.yml), ''}
この記法であればファイルが存在しない場合は、''
が読み込まれ、
その結果何もリソースが作られない & エラーも発生しない
まとめ
分岐をするためのプラグインServerless Plugin IfElse もありますが、
後々repository内に分岐箇所が増殖していくことを避けたかったので、記法とフォルダ構成に頼りました
とはいえ力技でねじ伏せた感は残りますが…