Reputation: 17441
I want to create an Elastic Beanstalk using CloudFormation template. I want to define an environment variable ENV_VAR_1
and set it's value to value of template parameter var1
. But don't want ENV_VAR_1
to exist at all if var1
is an empty string. I.e. I don't want ENV_VAR_1
with no value.
First I tried the Conditions
, but I get "Encountered unsupported property Condition"
during creation of ElasticBeanstalkEnvironment
resource.
Parameters:
var1:
Type: String
Conditions:
isVar1Empty: !Equals [ !Ref var1, "" ]
Resources:
ElasticBeanstalkEnvironment:
Type: 'AWS::ElasticBeanstalk::Environment'
Properties:
OptionSettings:
- Namespace: 'aws:elasticbeanstalk:application:environment'
Condition: isVar1Empty
OptionName: ENV_VAR_1
Value: !Ref var1
Then I tried AWS::NoValue
Parameters:
var1:
Type: String
Resources:
ElasticBeanstalkEnvironment:
Type: 'AWS::ElasticBeanstalk::Environment'
Properties:
OptionSettings:
- Namespace: 'aws:elasticbeanstalk:application:environment'
OptionName: ENV_VAR_1
Value: !If [[!Equals [ !Ref var1, "" ]], !Ref 'AWS::NoValue', !Ref var1]
and many permutation combinations of this. With the same result: When var1
is empty, Elastic Beanstalk gets created with ENV_VAR_1
set to ""
Upvotes: 6
Views: 1279
Reputation: 14255
Yet another option is to use ConfigurationTemplate
"inheritance", using the SourceConfiguration
property.
Basically, you create a parent configuration template with all desired properties except the environment property, and you conditionally create a child template that specifies the parent as its SourceConfiguration
. The child template just adds the desired environment property. Then you use the same condition to assign the appropriate template to the environment.
Here it is applied to the OP's example :
Parameters:
var1:
Type: String
Conditions:
Var1NotEmpty: !Not [!Equals [ !Ref var1, "" ]]
Resources:
ElasticBeanstalkEnvironment:
Type: 'AWS::ElasticBeanstalk::Environment'
Properties:
ApplicationName: !Ref ApplicationName
TemplateName: !If [Var1NotEmpty, !Ref TemplateWithVar, !Ref TemplateWithoutVar]
TemplateWithoutVar:
Type: AWS::ElasticBeanstalk::ConfigurationTemplate
Properties:
ApplicationName: !Ref ApplicationName
Description: "specifies all configuration settings except the optional ENV_VAR_1"
SolutionStackName: "64bit Amazon Linux 2023 v4.1.0 running Python 3.11"
OptionSettings:
- Namespace: "aws:autoscaling:launchconfiguration"
OptionName: "IamInstanceProfile"
Value: "aws-elasticbeanstalk-ec2-role"
TemplateWithVar:
Type: AWS::ElasticBeanstalk::ConfigurationTemplate
Condition: Var1NotEmpty
Properties:
ApplicationName: !Ref ApplicationName
Description: "only adds the optional ENV_VAR_1"
SourceConfiguration:
ApplicationName: !Ref ApplicationName
TemplateName: !Ref TemplateWithoutVar
OptionSettings:
- Namespace: 'aws:elasticbeanstalk:application:environment'
OptionName: ENV_VAR_1
Value: !Ref var1
Clearly this becomes too cumbersome if you've got multiple optional variables.
An interesting use-case would be the implementation of an optional SSH key, as in
...
- Namespace: "aws:autoscaling:launchconfiguration"
OptionName: "EC2KeyName"
Value: !Ref KeyName
where KeyName
can be an empty String
.
Upvotes: 1
Reputation: 66
Another workaround to handle conditions at option level:
Conditions:
CreateProdResources: !Equals [!Ref Env, "prod"]
EBEnvironment:
Type: AWS::ElasticBeanstalk::Environment
Properties:
OptionSettings:
- Namespace : "aws:elasticbeanstalk:command"
OptionName: Timeout
Value : 1200
- Namespace : !If [CreateProdResources, "aws:elbv2:listener:443", "aws:elasticbeanstalk:command"]
OptionName: !If [CreateProdResources, Protocol, Timeout]
Value : !If [CreateProdResources, HTTPS, 1200]
- Namespace : !If [CreateProdResources, "aws:elbv2:listener:443", "aws:elasticbeanstalk:command"]
OptionName: !If [CreateProdResources, SSLPolicy, Timeout]
Value : !If [CreateProdResources, "ELBSecurityPolicy-2016-08", 1200]
- Namespace : !If [CreateProdResources, "aws:elbv2:listener:443", "aws:elasticbeanstalk:command"]
OptionName: !If [CreateProdResources, SSLCertificateArns, Timeout]
Value : !If [CreateProdResources, !Ref ACMCertificate, 1200]
Repeated options are considered only once in Elastic Beanstalk.
Upvotes: 3
Reputation: 42849
Conditions are going to be applied at the Resource level...currently, you cannot apply a condition to a specific property.
What you could do to satisfy these exact requirements (and this is a bit ugly), is create two conditions, one negating the other. Then with these two conditions, have them conditionally create the specific resource.
Parameters:
var1:
Type: String
Conditions:
isVar1Empty: !Equals [ !Ref var1, "" ]
isVar1NonEmpty: !Not [ !Equals [ !Ref var1, "" ] ]
Resources:
ElasticBeanstalkEnvironmentWithVar1:
Type: 'AWS::ElasticBeanstalk::Environment'
Condition: isVar1NonEmpty
Properties:
OptionSettings:
- Namespace: 'aws:elasticbeanstalk:application:environment'
OptionName: ENV_VAR_1
Value: !Ref var1
ElasticBeanstalkEnvironmentWithoutVar1:
Type: 'AWS::ElasticBeanstalk::Environment'
Condition: isVar1Empty
Properties:
OptionSettings:
- Namespace: 'aws:elasticbeanstalk:application:environment'
Like I said...a bit ugly. Note that this will only really work well if you have one or two variables like this. As soon as you add a second or third 'optional' parameter, this quickly starts spiraling out of control.
A better option might be to generate your CloudFormation template using a templating library like mustache.
Upvotes: 5