9
9
is_intrinsic_if ,
10
10
is_intrinsic_no_value ,
11
11
validate_intrinsic_if_items ,
12
+ make_combined_condition ,
13
+ ref ,
14
+ fnGetAtt ,
12
15
)
13
16
from samtranslator .model .update_policy import UpdatePolicy
14
17
from samtranslator .translator .arn_generator import ArnGenerator
27
30
"Linear10PercentEvery10Minutes" ,
28
31
"AllAtOnce" ,
29
32
]
33
+ CODE_DEPLOY_CONDITION_NAME = "ServerlessCodeDeployCondition"
30
34
31
35
32
36
class DeploymentPreferenceCollection (object ):
@@ -41,20 +45,19 @@ class DeploymentPreferenceCollection(object):
41
45
42
46
def __init__ (self ):
43
47
"""
44
- This collection stores an intenral dict of the deployment preferences for each function's
45
- deployment preference in the SAM Template.
48
+ This collection stores an internal dict of the deployment preferences for each function's
49
+ deployment preference in the SAM Template.
46
50
"""
47
51
self ._resource_preferences = {}
48
- self .codedeploy_application = self ._codedeploy_application ()
49
- self .codedeploy_iam_role = self ._codedeploy_iam_role ()
50
52
51
- def add (self , logical_id , deployment_preference_dict ):
53
+ def add (self , logical_id , deployment_preference_dict , condition = None ):
52
54
"""
53
55
Add this deployment preference to the collection
54
56
55
57
:raise ValueError if an existing logical id already exists in the _resource_preferences
56
58
:param logical_id: logical id of the resource where this deployment preference applies
57
59
:param deployment_preference_dict: the input SAM template deployment preference mapping
60
+ :param condition: the condition (if it exists) on the serverless function
58
61
"""
59
62
if logical_id in self ._resource_preferences :
60
63
raise ValueError (
@@ -63,7 +66,9 @@ def add(self, logical_id, deployment_preference_dict):
63
66
)
64
67
)
65
68
66
- self ._resource_preferences [logical_id ] = DeploymentPreference .from_dict (logical_id , deployment_preference_dict )
69
+ self ._resource_preferences [logical_id ] = DeploymentPreference .from_dict (
70
+ logical_id , deployment_preference_dict , condition
71
+ )
67
72
68
73
def get (self , logical_id ):
69
74
"""
@@ -85,18 +90,52 @@ def can_skip_service_role(self):
85
90
"""
86
91
return all (preference .role or not preference .enabled for preference in self ._resource_preferences .values ())
87
92
93
+ def needs_resource_condition (self ):
94
+ """
95
+ If all preferences have a condition, all code deploy resources need to be conditionally created
96
+ :return: True, if a condition needs to be created
97
+ """
98
+ # If there are any enabled deployment preferences without conditions, return false
99
+ return self ._resource_preferences and not any (
100
+ not preference .condition and preference .enabled for preference in self ._resource_preferences .values ()
101
+ )
102
+
103
+ def get_all_deployment_conditions (self ):
104
+ """
105
+ Returns a list of all conditions associated with the deployment preference resources
106
+ :return: List of condition names
107
+ """
108
+ conditions_set = set ([preference .condition for preference in self ._resource_preferences .values ()])
109
+ if None in conditions_set :
110
+ # None can exist if there are disabled deployment preference(s)
111
+ conditions_set .remove (None )
112
+ return list (conditions_set )
113
+
114
+ def create_aggregate_deployment_condition (self ):
115
+ """
116
+ Creates an aggregate deployment condition if necessary
117
+ :return: None if <2 conditions are found, otherwise a dictionary of new conditions to add to template
118
+ """
119
+ return make_combined_condition (self .get_all_deployment_conditions (), CODE_DEPLOY_CONDITION_NAME )
120
+
88
121
def enabled_logical_ids (self ):
89
122
"""
90
123
:return: only the logical id's for the deployment preferences in this collection which are enabled
91
124
"""
92
125
return [logical_id for logical_id , preference in self ._resource_preferences .items () if preference .enabled ]
93
126
94
- def _codedeploy_application (self ):
127
+ def get_codedeploy_application (self ):
95
128
codedeploy_application_resource = CodeDeployApplication (CODEDEPLOY_APPLICATION_LOGICAL_ID )
96
129
codedeploy_application_resource .ComputePlatform = "Lambda"
130
+ if self .needs_resource_condition ():
131
+ conditions = self .get_all_deployment_conditions ()
132
+ condition_name = CODE_DEPLOY_CONDITION_NAME
133
+ if len (conditions ) <= 1 :
134
+ condition_name = conditions .pop ()
135
+ codedeploy_application_resource .set_resource_attribute ("Condition" , condition_name )
97
136
return codedeploy_application_resource
98
137
99
- def _codedeploy_iam_role (self ):
138
+ def get_codedeploy_iam_role (self ):
100
139
iam_role = IAMRole (CODE_DEPLOY_SERVICE_ROLE_LOGICAL_ID )
101
140
iam_role .AssumeRolePolicyDocument = {
102
141
"Version" : "2012-10-17" ,
@@ -120,6 +159,12 @@ def _codedeploy_iam_role(self):
120
159
ArnGenerator .generate_aws_managed_policy_arn ("service-role/AWSCodeDeployRoleForLambda" )
121
160
]
122
161
162
+ if self .needs_resource_condition ():
163
+ conditions = self .get_all_deployment_conditions ()
164
+ condition_name = CODE_DEPLOY_CONDITION_NAME
165
+ if len (conditions ) <= 1 :
166
+ condition_name = conditions .pop ()
167
+ iam_role .set_resource_attribute ("Condition" , condition_name )
123
168
return iam_role
124
169
125
170
def deployment_group (self , function_logical_id ):
@@ -137,7 +182,7 @@ def deployment_group(self, function_logical_id):
137
182
except ValueError as e :
138
183
raise InvalidResourceException (function_logical_id , str (e ))
139
184
140
- deployment_group .ApplicationName = self . codedeploy_application . get_runtime_attr ( "name" )
185
+ deployment_group .ApplicationName = ref ( CODEDEPLOY_APPLICATION_LOGICAL_ID )
141
186
deployment_group .AutoRollbackConfiguration = {
142
187
"Enabled" : True ,
143
188
"Events" : ["DEPLOYMENT_FAILURE" , "DEPLOYMENT_STOP_ON_ALARM" , "DEPLOYMENT_STOP_ON_REQUEST" ],
@@ -149,13 +194,16 @@ def deployment_group(self, function_logical_id):
149
194
150
195
deployment_group .DeploymentStyle = {"DeploymentType" : "BLUE_GREEN" , "DeploymentOption" : "WITH_TRAFFIC_CONTROL" }
151
196
152
- deployment_group .ServiceRoleArn = self . codedeploy_iam_role . get_runtime_attr ( "arn " )
197
+ deployment_group .ServiceRoleArn = fnGetAtt ( CODE_DEPLOY_SERVICE_ROLE_LOGICAL_ID , "Arn " )
153
198
if deployment_preference .role :
154
199
deployment_group .ServiceRoleArn = deployment_preference .role
155
200
156
201
if deployment_preference .trigger_configurations :
157
202
deployment_group .TriggerConfigurations = deployment_preference .trigger_configurations
158
203
204
+ if deployment_preference .condition :
205
+ deployment_group .set_resource_attribute ("Condition" , deployment_preference .condition )
206
+
159
207
return deployment_group
160
208
161
209
def _convert_alarms (self , preference_alarms ):
@@ -240,7 +288,7 @@ def update_policy(self, function_logical_id):
240
288
deployment_preference = self .get (function_logical_id )
241
289
242
290
return UpdatePolicy (
243
- self . codedeploy_application . get_runtime_attr ( "name" ),
291
+ ref ( CODEDEPLOY_APPLICATION_LOGICAL_ID ),
244
292
self .deployment_group (function_logical_id ).get_runtime_attr ("name" ),
245
293
deployment_preference .pre_traffic_hook ,
246
294
deployment_preference .post_traffic_hook ,
0 commit comments