line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Cfn::TypeLibrary { |
2
|
22
|
|
|
22
|
|
2657309
|
use Moose::Util::TypeConstraints; |
|
22
|
|
|
|
|
4903821
|
|
|
22
|
|
|
|
|
207
|
|
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
sub try_function { |
5
|
7786
|
|
|
7786
|
|
14129
|
my $arg = shift; |
6
|
7786
|
|
|
|
|
28487
|
my @keys = keys %$arg; |
7
|
7786
|
|
|
|
|
13811
|
my $first_key = $keys[0]; |
8
|
7786
|
100
|
100
|
|
|
55351
|
if (@keys == 1 and (substr($first_key,0,4) eq 'Fn::' or $first_key eq 'Ref' or $first_key eq 'Condition')){ |
|
|
|
100
|
|
|
|
|
9
|
4941
|
100
|
|
|
|
18210
|
if ($first_key eq 'Fn::GetAtt') { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
10
|
397
|
|
|
|
|
3382
|
return Cfn::Value::Function::GetAtt->new(Function => $first_key, Value => $arg->{ $first_key }); |
11
|
|
|
|
|
|
|
} elsif ($keys[0] eq 'Ref'){ |
12
|
3530
|
|
|
|
|
11036
|
my $psdparam = Moose::Util::TypeConstraints::find_type_constraint('Cfn::PseudoParameterValue'); |
13
|
3530
|
|
|
|
|
332115
|
my $value = $arg->{ $first_key }; |
14
|
3530
|
100
|
|
|
|
13010
|
my $class = $psdparam->check($value) ? |
15
|
|
|
|
|
|
|
'Cfn::Value::Function::PseudoParameter' : |
16
|
|
|
|
|
|
|
'Cfn::Value::Function::Ref'; |
17
|
|
|
|
|
|
|
|
18
|
3530
|
|
|
|
|
252687
|
return $class->new( Function => $first_key, Value => $value); |
19
|
|
|
|
|
|
|
} elsif ($keys[0] eq 'Condition'){ |
20
|
7
|
|
|
|
|
66
|
return Cfn::Value::Function::Condition->new( Function => $first_key, Value => $arg->{ $first_key }); |
21
|
|
|
|
|
|
|
} else { |
22
|
1007
|
|
|
|
|
5911
|
return Cfn::Value::Function->new(Function => $first_key, Value => $arg->{ $first_key }); |
23
|
|
|
|
|
|
|
} |
24
|
|
|
|
|
|
|
} else { |
25
|
2845
|
|
|
|
|
11384
|
return undef; |
26
|
|
|
|
|
|
|
} |
27
|
|
|
|
|
|
|
} |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
coerce 'Cfn::Resource::UpdatePolicy', |
30
|
|
|
|
|
|
|
from 'HashRef', |
31
|
|
|
|
|
|
|
via { Cfn::Resource::UpdatePolicy->new( %$_ ) }; |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
coerce 'Cfn::Resource::UpdatePolicy::AutoScalingReplacingUpdate', |
34
|
|
|
|
|
|
|
from 'HashRef', |
35
|
|
|
|
|
|
|
via { Cfn::Resource::UpdatePolicy::AutoScalingReplacingUpdate->new( %$_ ) }; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
coerce 'Cfn::Resource::UpdatePolicy::AutoScalingRollingUpdate', |
38
|
|
|
|
|
|
|
from 'HashRef', |
39
|
|
|
|
|
|
|
via { Cfn::Resource::UpdatePolicy::AutoScalingRollingUpdate->new( %$_ ) }; |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
coerce 'Cfn::Resource::UpdatePolicy::AutoScalingScheduledAction', |
42
|
|
|
|
|
|
|
from 'HashRef', |
43
|
|
|
|
|
|
|
via { Cfn::Resource::UpdatePolicy::AutoScalingScheduledAction->new( %$_ ) }; |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
subtype 'Cfn::Resource::UpdatePolicy::AutoScalingRollingUpdate::SuspendProcesses', |
46
|
|
|
|
|
|
|
as 'Cfn::Value::Array', |
47
|
|
|
|
|
|
|
where { |
48
|
|
|
|
|
|
|
my $array = $_->Value; |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
my $valid = { Launch => 1, Terminate => 1, HealthCheck => 1, ReplaceUnhealthy => 1, |
51
|
|
|
|
|
|
|
AZRebalance => 1, AlarmNotification =>1, ScheduledActions => 1, |
52
|
|
|
|
|
|
|
AddToLoadBalancer => 1 }; |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
my @val = grep { $valid->{ $_->Value } } @$array; |
55
|
|
|
|
|
|
|
# The array is valid if all of it's values are found in $valid |
56
|
|
|
|
|
|
|
return @val == @$array; |
57
|
|
|
|
|
|
|
}, |
58
|
|
|
|
|
|
|
message { 'This type only supports the following values in the array: "Launch, Terminate, HealthCheck, ReplaceUnhealthy, AZRebalance, AlarmNotification, ScheduledActions, AddToLoadBalancer"' }; |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
coerce 'Cfn::Resource::UpdatePolicy::AutoScalingRollingUpdate::SuspendProcesses', |
61
|
|
|
|
|
|
|
from 'HashRef', via (\&coerce_hash), |
62
|
|
|
|
|
|
|
from 'ArrayRef', via (\&coerce_array); |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
subtype 'Cfn::Resource::DeletionPolicy', |
65
|
|
|
|
|
|
|
as 'Str', |
66
|
|
|
|
|
|
|
where { $_ eq 'Delete' or $_ eq 'Retain' or $_ eq 'Snapshot' }, |
67
|
|
|
|
|
|
|
message { "$_ is an invalid DeletionPolicy" }; |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
subtype 'Cfn::Resource::UpdateReplacePolicy', |
70
|
|
|
|
|
|
|
as 'Str', |
71
|
|
|
|
|
|
|
where { $_ eq 'Delete' or $_ eq 'Retain' or $_ eq 'Snapshot' }, |
72
|
|
|
|
|
|
|
message { "$_ is an invalid UpdateReplacePolicy" }; |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
subtype 'Cfn::Value::ArrayOfPrimitives', |
75
|
|
|
|
|
|
|
as 'Cfn::Value::Array', |
76
|
|
|
|
|
|
|
where { @{ $_[0]->Value } == grep { $_->isa('Cfn::Value::Primitive') } @{ $_[0]->Value } }, |
77
|
|
|
|
|
|
|
message { 'This type only supports Primitives' }; |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub coerce_array { |
80
|
|
|
|
|
|
|
Cfn::Value::Array->new(Value => [ |
81
|
2710
|
|
|
2710
|
|
1898350
|
map { Moose::Util::TypeConstraints::find_type_constraint('Cfn::Value')->coerce($_) } @$_ |
|
7164
|
|
|
|
|
1894957
|
|
82
|
|
|
|
|
|
|
]) |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
sub coerce_hash { |
86
|
3683
|
|
|
3683
|
|
1698800
|
my $arg = $_; |
87
|
3683
|
|
|
|
|
9732
|
my $function = try_function($arg); |
88
|
3683
|
100
|
|
|
|
2842410
|
return $function if (defined $function); |
89
|
1228
|
|
|
|
|
3045
|
my @keys = keys %$arg; |
90
|
|
|
|
|
|
|
return Cfn::Value::Hash->new(Value => { |
91
|
1228
|
|
|
|
|
2689
|
map { $_ => Moose::Util::TypeConstraints::find_type_constraint('Cfn::Value')->coerce($arg->{$_}) } @keys |
|
2769
|
|
|
|
|
1166057
|
|
92
|
|
|
|
|
|
|
}); |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub coerce_hashref_to_function { |
96
|
2486
|
|
|
2486
|
|
2411590
|
my $val = $_; |
97
|
2486
|
|
|
|
|
7839
|
my $function = try_function($val); |
98
|
2486
|
50
|
|
|
|
2617923
|
return $function if (defined $function); |
99
|
0
|
|
|
|
|
0
|
die "Is not a function"; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
coerce 'Cfn::Value', |
103
|
|
|
|
|
|
|
from 'Value', via { Cfn::Value::Primitive->new( Value => $_ ) }, |
104
|
|
|
|
|
|
|
from 'HashRef', via (\&coerce_hash), |
105
|
|
|
|
|
|
|
from 'ArrayRef', via (\&coerce_array); |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
subtype 'Cfn::Value::Boolean', as 'Cfn::Value'; |
108
|
|
|
|
|
|
|
subtype 'Cfn::Value::Integer', as 'Cfn::Value'; |
109
|
|
|
|
|
|
|
subtype 'Cfn::Value::Long', as 'Cfn::Value'; |
110
|
|
|
|
|
|
|
subtype 'Cfn::Value::String', as 'Cfn::Value'; |
111
|
|
|
|
|
|
|
subtype 'Cfn::Value::Double', as 'Cfn::Value'; |
112
|
|
|
|
|
|
|
subtype 'Cfn::Value::Timestamp', as 'Cfn::Value'; |
113
|
|
|
|
|
|
|
subtype 'Cfn::Value::Json', as 'Cfn::Value'; |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
coerce 'Cfn::Value::Boolean', |
116
|
|
|
|
|
|
|
from 'Int', via { |
117
|
|
|
|
|
|
|
my $val = $_; |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
if ($val == 1) { |
120
|
|
|
|
|
|
|
Cfn::Boolean->new( Value => 1, stringy => 0 ); |
121
|
|
|
|
|
|
|
} elsif($val == 0) { |
122
|
|
|
|
|
|
|
Cfn::Boolean->new( Value => 0, stringy => 0 ); |
123
|
|
|
|
|
|
|
} else { |
124
|
|
|
|
|
|
|
die "Cannot convert $val to an boolean value"; |
125
|
|
|
|
|
|
|
} |
126
|
|
|
|
|
|
|
}, |
127
|
|
|
|
|
|
|
from 'Str', via { |
128
|
|
|
|
|
|
|
my $val = $_; |
129
|
|
|
|
|
|
|
if (lc($val) eq 'false') { |
130
|
|
|
|
|
|
|
Cfn::Boolean->new( Value => 0, stringy => 1 ); |
131
|
|
|
|
|
|
|
} elsif (lc($val) eq 'true') { |
132
|
|
|
|
|
|
|
Cfn::Boolean->new( Value => 1, stringy => 1 ); |
133
|
|
|
|
|
|
|
} else { |
134
|
|
|
|
|
|
|
die "Cannot convert string $val to a boolean value"; |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
}, |
137
|
|
|
|
|
|
|
from 'Object', via { |
138
|
|
|
|
|
|
|
my $val = $_; |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
die "Cannot coerce a boolean from a non JSON::PP::Boolean" if (not $val->isa('JSON::PP::Boolean')); |
141
|
|
|
|
|
|
|
if ($val == 1) { |
142
|
|
|
|
|
|
|
Cfn::Boolean->new( Value => 1, stringy => 0 ); |
143
|
|
|
|
|
|
|
} elsif($val == 0) { |
144
|
|
|
|
|
|
|
Cfn::Boolean->new( Value => 0, stringy => 0 ); |
145
|
|
|
|
|
|
|
} else { |
146
|
|
|
|
|
|
|
die "Cannot convert $val to an boolean value"; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
}, |
149
|
|
|
|
|
|
|
from 'HashRef', via \&coerce_hashref_to_function; |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
coerce 'Cfn::Value::Integer', |
152
|
|
|
|
|
|
|
from 'Int', via { Cfn::Integer->new( Value => $_ ) }, |
153
|
|
|
|
|
|
|
from 'HashRef', via \&coerce_hashref_to_function; |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
coerce 'Cfn::Value::Long', |
156
|
|
|
|
|
|
|
from 'Num', via { Cfn::Long->new( Value => $_ ) }, |
157
|
|
|
|
|
|
|
from 'HashRef', via \&coerce_hashref_to_function; |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
coerce 'Cfn::Value::String', |
160
|
|
|
|
|
|
|
from 'Str', via { Cfn::String->new( Value => $_ ) }, |
161
|
|
|
|
|
|
|
from 'HashRef', via \&coerce_hashref_to_function; |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
coerce 'Cfn::Value::Double', |
164
|
|
|
|
|
|
|
from 'Num', via { Cfn::Double->new( Value => $_ ) }, |
165
|
|
|
|
|
|
|
from 'HashRef', via \&coerce_hashref_to_function; |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
coerce 'Cfn::Value::Timestamp', |
168
|
|
|
|
|
|
|
from 'Num', via { Cfn::Timestamp->new( Value => $_ ) }, |
169
|
|
|
|
|
|
|
from 'HashRef', via \&coerce_hashref_to_function; |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
subtype 'Cfn::Value::Json', |
172
|
|
|
|
|
|
|
as 'Cfn::Value::Hash'; |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
coerce 'Cfn::Value::Array', |
175
|
|
|
|
|
|
|
from 'HashRef', via (\&coerce_hash), |
176
|
|
|
|
|
|
|
from 'ArrayRef', via (\&coerce_array); |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
coerce 'Cfn::Value::ArrayOfPrimitives', |
179
|
|
|
|
|
|
|
from 'HashRef', via (\&coerce_hash), |
180
|
|
|
|
|
|
|
from 'ArrayRef', via (\&coerce_array); |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
coerce 'Cfn::Value::Hash', |
183
|
|
|
|
|
|
|
from 'HashRef', via (\&coerce_hash); |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
subtype 'Cfn::Transform', |
186
|
|
|
|
|
|
|
as 'ArrayRef[Str]'; |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
coerce 'Cfn::Transform', |
189
|
|
|
|
|
|
|
from 'ArrayRef', via { |
190
|
|
|
|
|
|
|
return $_; |
191
|
|
|
|
|
|
|
}; |
192
|
|
|
|
|
|
|
coerce 'Cfn::Transform', |
193
|
|
|
|
|
|
|
from 'Value', via { |
194
|
|
|
|
|
|
|
return [ $_ ]; |
195
|
|
|
|
|
|
|
}; |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
subtype 'Cfn::MappingHash', |
198
|
|
|
|
|
|
|
as 'HashRef[Cfn::Mapping]'; |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
my $cfn_mapping_constraint = Moose::Util::TypeConstraints::find_type_constraint('Cfn::Mapping'); |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
coerce 'Cfn::MappingHash', |
203
|
|
|
|
|
|
|
from 'HashRef', via { |
204
|
|
|
|
|
|
|
my $original = $_; |
205
|
|
|
|
|
|
|
return { map { ($_ => $cfn_mapping_constraint->coerce($original->{ $_ }) ) } keys %$original }; |
206
|
|
|
|
|
|
|
}; |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
coerce 'Cfn::Mapping', |
209
|
|
|
|
|
|
|
from 'HashRef', via { |
210
|
|
|
|
|
|
|
return Cfn::Mapping->new(Map => $_); |
211
|
|
|
|
|
|
|
}; |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
subtype 'Cfn::OutputHash', |
214
|
|
|
|
|
|
|
as 'HashRef[Cfn::Output]'; |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
my $cfn_output_constraint = Moose::Util::TypeConstraints::find_type_constraint('Cfn::Output'); |
217
|
|
|
|
|
|
|
coerce 'Cfn::OutputHash', |
218
|
|
|
|
|
|
|
from 'HashRef', via { |
219
|
|
|
|
|
|
|
my $original = $_; |
220
|
|
|
|
|
|
|
return { map { ($_ => $cfn_output_constraint->coerce($original->{ $_ }) ) } keys %$original }; |
221
|
|
|
|
|
|
|
}; |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
coerce 'Cfn::Output', |
224
|
|
|
|
|
|
|
from 'HashRef', via { |
225
|
|
|
|
|
|
|
return Cfn::Output->new(%$_); |
226
|
|
|
|
|
|
|
}; |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
subtype 'Cfn::ConditionHash', |
229
|
|
|
|
|
|
|
as 'HashRef[Cfn::Value]'; |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
my $cfn_value_constraint = Moose::Util::TypeConstraints::find_type_constraint('Cfn::Value'); |
232
|
|
|
|
|
|
|
coerce 'Cfn::ConditionHash', |
233
|
|
|
|
|
|
|
from 'HashRef', via { |
234
|
|
|
|
|
|
|
my $original = $_; |
235
|
|
|
|
|
|
|
return { map { ($_ => $cfn_value_constraint->coerce($original->{ $_ }) ) } keys %$original }; |
236
|
|
|
|
|
|
|
}; |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
subtype 'Cfn::ParameterHash', |
239
|
|
|
|
|
|
|
as 'HashRef[Cfn::Parameter]'; |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
my $cfn_parameter_constraint = Moose::Util::TypeConstraints::find_type_constraint('Cfn::Parameter'); |
242
|
|
|
|
|
|
|
coerce 'Cfn::ParameterHash', |
243
|
|
|
|
|
|
|
from 'HashRef', via { |
244
|
|
|
|
|
|
|
my $original = $_; |
245
|
|
|
|
|
|
|
return { map { ($_ => $cfn_parameter_constraint->coerce($original->{ $_ }) ) } keys %$original }; |
246
|
|
|
|
|
|
|
}; |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
coerce 'Cfn::Parameter', |
249
|
|
|
|
|
|
|
from 'HashRef', via { |
250
|
|
|
|
|
|
|
return Cfn::Parameter->new(%$_); |
251
|
|
|
|
|
|
|
}; |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
subtype 'Cfn::ResourceHash', |
254
|
|
|
|
|
|
|
as 'HashRef[Cfn::Resource]'; |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
my $cfn_resource_constraint = Moose::Util::TypeConstraints::find_type_constraint('Cfn::Resource'); |
257
|
|
|
|
|
|
|
coerce 'Cfn::ResourceHash', |
258
|
|
|
|
|
|
|
from 'HashRef', via { |
259
|
|
|
|
|
|
|
my $original = $_; |
260
|
|
|
|
|
|
|
return { map { ($_ => $cfn_resource_constraint->coerce($original->{ $_ }) ) } keys %$original }; |
261
|
|
|
|
|
|
|
}; |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
coerce 'Cfn::Resource', |
264
|
|
|
|
|
|
|
from 'HashRef', via { |
265
|
|
|
|
|
|
|
my $type = $_->{Type}; |
266
|
|
|
|
|
|
|
die "Can't coerce HashRef into a Cfn::Resource if it doesn't have a Type key" if (not defined $type); |
267
|
|
|
|
|
|
|
my $class_type = ($type =~ m/^Custom\:\:/) ? "AWS::CloudFormation::CustomResource" : $type; |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
Cfn->load_resource_module($class_type); |
270
|
|
|
|
|
|
|
return "Cfn::Resource::$class_type"->new( |
271
|
|
|
|
|
|
|
%$_ |
272
|
|
|
|
|
|
|
); |
273
|
|
|
|
|
|
|
}; |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
subtype 'Cfn::MetadataHash', |
276
|
|
|
|
|
|
|
as 'HashRef[Cfn::Value]'; |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
coerce 'Cfn::MetadataHash', |
279
|
|
|
|
|
|
|
from 'HashRef', via { |
280
|
|
|
|
|
|
|
my $original = $_; |
281
|
|
|
|
|
|
|
return { map { ($_ => $cfn_value_constraint->coerce($original->{ $_ }) ) } keys %$original }; |
282
|
|
|
|
|
|
|
}; |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
coerce 'Cfn::Value::Json', |
285
|
|
|
|
|
|
|
from 'HashRef', via (\&coerce_hash); |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
enum 'Cfn::Parameter::Type', [ |
288
|
|
|
|
|
|
|
'String', |
289
|
|
|
|
|
|
|
'Number', |
290
|
|
|
|
|
|
|
'List<Number>', |
291
|
|
|
|
|
|
|
'CommaDelimitedList', |
292
|
|
|
|
|
|
|
'AWS::EC2::AvailabilityZone::Name', |
293
|
|
|
|
|
|
|
'List<AWS::EC2::AvailabilityZone::Name>', |
294
|
|
|
|
|
|
|
'AWS::EC2::Instance::Id', |
295
|
|
|
|
|
|
|
'List<AWS::EC2::Instance::Id>', |
296
|
|
|
|
|
|
|
'AWS::EC2::Image::Id', |
297
|
|
|
|
|
|
|
'List<AWS::EC2::Image::Id>', |
298
|
|
|
|
|
|
|
'AWS::EC2::KeyPair::KeyName', |
299
|
|
|
|
|
|
|
'AWS::EC2::SecurityGroup::GroupName', |
300
|
|
|
|
|
|
|
'List<AWS::EC2::SecurityGroup::GroupName>', |
301
|
|
|
|
|
|
|
'AWS::EC2::SecurityGroup::Id', |
302
|
|
|
|
|
|
|
'List<AWS::EC2::SecurityGroup::Id>', |
303
|
|
|
|
|
|
|
'AWS::EC2::Subnet::Id', |
304
|
|
|
|
|
|
|
'List<AWS::EC2::Subnet::Id>', |
305
|
|
|
|
|
|
|
'AWS::EC2::Volume::Id', |
306
|
|
|
|
|
|
|
'List<AWS::EC2::Volume::Id>', |
307
|
|
|
|
|
|
|
'AWS::EC2::VPC::Id', |
308
|
|
|
|
|
|
|
'List<AWS::EC2::VPC::Id>', |
309
|
|
|
|
|
|
|
'AWS::Route53::HostedZone::Id', |
310
|
|
|
|
|
|
|
'List<AWS::Route53::HostedZone::Id>', |
311
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Name', |
312
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<String>', |
313
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<List<String>>', |
314
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<CommaDelimitedList>', |
315
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<AWS::EC2::AvailabilityZone::Name>', |
316
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>', |
317
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<AWS::EC2::Instance::Id>', |
318
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<AWS::EC2::SecurityGroup::GroupName>', |
319
|
|
|
|
|
|
|
'AWS::SSM:;Parameter::Value<AWS::EC2::SecurityGroup::Id>', |
320
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<AWS::EC2::Subnet::Id>', |
321
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<AWS::EC2::Volume::Id>', |
322
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<AWS::EC2::VPC::Id>', |
323
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<AWS::Route53::HostedZone::Id>', |
324
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<List<AWS::EC2::AvailabilityZone::Name>>', |
325
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<List<AWS::EC2::Image::Id>>', |
326
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<List<AWS::EC2::Instance::Id>>', |
327
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<List<AWS::EC2::SecurityGroup::GroupName>>', |
328
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<List<AWS::EC2::SecurityGroup::Id>>', |
329
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<List<AWS::EC2::Subnet::Id>>', |
330
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<List<AWS::EC2::Volume::Id>>', |
331
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<List<AWS::EC2::VPC::Id>>', |
332
|
|
|
|
|
|
|
'AWS::SSM::Parameter::Value<List<AWS::Route53::HostedZone::Id>>', |
333
|
|
|
|
|
|
|
]; |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
subtype 'ArrayOfCfn::Resource::Properties::TagType', |
336
|
|
|
|
|
|
|
as 'Cfn::Value', |
337
|
|
|
|
|
|
|
where { $_->isa('Cfn::Value::Array') or $_->isa('Cfn::Value::Function') }, |
338
|
|
|
|
|
|
|
message { "$_ is not a Cfn::Value or a Cfn::Value::Function" }; |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
coerce 'ArrayOfCfn::Resource::Properties::TagType', |
341
|
|
|
|
|
|
|
from 'HashRef', |
342
|
|
|
|
|
|
|
via { |
343
|
|
|
|
|
|
|
if (my $f = Cfn::TypeLibrary::try_function($_)) { |
344
|
|
|
|
|
|
|
return $f |
345
|
|
|
|
|
|
|
} else { |
346
|
|
|
|
|
|
|
die 'Only accepts functions'; |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
}, |
349
|
|
|
|
|
|
|
from 'ArrayRef', |
350
|
|
|
|
|
|
|
via { |
351
|
|
|
|
|
|
|
Cfn::Value::Array->new(Value => [ |
352
|
|
|
|
|
|
|
map { |
353
|
|
|
|
|
|
|
Moose::Util::TypeConstraints::find_type_constraint('Cfn::Resource::Properties::TagType')->coerce($_) |
354
|
|
|
|
|
|
|
} @$_ |
355
|
|
|
|
|
|
|
]); |
356
|
|
|
|
|
|
|
}; |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
subtype 'Cfn::Resource::Properties::TagType', |
359
|
|
|
|
|
|
|
as 'Cfn::Value'; |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
coerce 'Cfn::Resource::Properties::TagType', |
362
|
|
|
|
|
|
|
from 'HashRef', |
363
|
|
|
|
|
|
|
via { |
364
|
|
|
|
|
|
|
if (my $f = Cfn::TypeLibrary::try_function($_)) { |
365
|
|
|
|
|
|
|
return $f |
366
|
|
|
|
|
|
|
} else { |
367
|
|
|
|
|
|
|
return Cfn::Resource::Properties::Tag->new( %$_ ); |
368
|
|
|
|
|
|
|
} |
369
|
|
|
|
|
|
|
}; |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
enum 'Cfn::PseudoParameterValue', [ |
372
|
|
|
|
|
|
|
'AWS::AccountId', |
373
|
|
|
|
|
|
|
'AWS::NotificationARNs', |
374
|
|
|
|
|
|
|
'AWS::NoValue', |
375
|
|
|
|
|
|
|
'AWS::Partition', |
376
|
|
|
|
|
|
|
'AWS::Region', |
377
|
|
|
|
|
|
|
'AWS::StackId', |
378
|
|
|
|
|
|
|
'AWS::StackName', |
379
|
|
|
|
|
|
|
'AWS::URLSuffix', |
380
|
|
|
|
|
|
|
]; |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
coerce 'Cfn::Internal::Options', |
383
|
|
|
|
|
|
|
from 'HashRef', |
384
|
|
|
|
|
|
|
via { Cfn::Internal::Options->new(%$_) }; |
385
|
|
|
|
|
|
|
}; |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
package Cfn::Value { |
388
|
22
|
|
|
22
|
|
115246
|
use Moose; |
|
22
|
|
|
|
|
3803356
|
|
|
22
|
|
|
|
|
159
|
|
389
|
|
|
|
|
|
|
# just a base class for everything that can go into a cloudformation |
390
|
|
|
|
|
|
|
# object |
391
|
0
|
|
|
0
|
0
|
0
|
sub as_hashref { shift->Value->as_hashref(@_) } |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
package Cfn::DynamicValue { |
395
|
22
|
|
|
22
|
|
166058
|
use Moose; |
|
22
|
|
|
|
|
54
|
|
|
22
|
|
|
|
|
116
|
|
396
|
22
|
|
|
22
|
|
140271
|
use Scalar::Util qw/blessed/; |
|
22
|
|
|
|
|
117
|
|
|
22
|
|
|
|
|
10271
|
|
397
|
|
|
|
|
|
|
extends 'Cfn::Value'; |
398
|
|
|
|
|
|
|
has Value => (isa => 'CodeRef', is => 'rw', required => 1); |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
sub to_value { |
401
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
402
|
0
|
|
|
|
|
0
|
return Moose::Util::TypeConstraints::find_type_constraint('Cfn::Value')->coerce($self->resolve_value(@_)); |
403
|
|
|
|
|
|
|
} |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
sub _resolve_value { |
406
|
33
|
|
|
33
|
|
63
|
my ($v, $args) = @_; |
407
|
33
|
100
|
66
|
|
|
253
|
if (blessed($v) and $v->isa('Cfn::Value')) { |
|
|
100
|
66
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
408
|
5
|
|
|
|
|
22
|
return $v->as_hashref(@$args); |
409
|
|
|
|
|
|
|
} elsif (not blessed($v) and ref($v) eq 'HASH') { |
410
|
4
|
|
|
|
|
22
|
return { map { ($_ => _resolve_value($v->{ $_ })) } keys %$v } |
|
8
|
|
|
|
|
20
|
|
411
|
|
|
|
|
|
|
} elsif (not blessed($v) and ref($v) eq 'ARRAY') { |
412
|
4
|
|
|
|
|
8
|
return [ map { _resolve_value($_) } @$v ] |
|
5
|
|
|
|
|
10
|
|
413
|
|
|
|
|
|
|
} else { |
414
|
20
|
|
|
|
|
87
|
return $v |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
} |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
sub resolve_value { |
419
|
18
|
|
|
18
|
0
|
30
|
my $self = shift; |
420
|
18
|
|
|
|
|
37
|
my @args = reverse @_; |
421
|
18
|
|
|
|
|
438
|
my (@ret) = ($self->Value->(@args)); |
422
|
18
|
|
|
|
|
4552
|
@ret = map { _resolve_value($_, \@args) } @ret; |
|
20
|
|
|
|
|
53
|
|
423
|
18
|
|
|
|
|
615
|
return (@ret); |
424
|
|
|
|
|
|
|
} |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
override as_hashref => sub { |
427
|
|
|
|
|
|
|
my $self = shift; |
428
|
|
|
|
|
|
|
return $self->resolve_value(@_); |
429
|
|
|
|
|
|
|
}; |
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
package Cfn::Value::Function { |
433
|
22
|
|
|
22
|
|
185
|
use Moose; |
|
22
|
|
|
|
|
45
|
|
|
22
|
|
|
|
|
123
|
|
434
|
|
|
|
|
|
|
extends 'Cfn::Value'; |
435
|
|
|
|
|
|
|
has Function => (isa => 'Str', is => 'rw', required => 1); |
436
|
|
|
|
|
|
|
has Value => (isa => 'Cfn::Value', is => 'rw', required => 1, coerce => 1); |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
sub as_hashref { |
439
|
1089
|
|
|
1089
|
0
|
90190
|
my $self = shift; |
440
|
1089
|
|
|
|
|
26223
|
my $key = $self->Function; |
441
|
1089
|
|
|
|
|
25075
|
return { $key => $self->Value->as_hashref(@_) } |
442
|
|
|
|
|
|
|
} |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
sub path_to { |
445
|
4623
|
|
|
4623
|
0
|
9901
|
my ($self, $path) = @_; |
446
|
4623
|
|
|
|
|
8201
|
my ($part, $rest) = Cfn::path_split($path); |
447
|
|
|
|
|
|
|
|
448
|
4623
|
50
|
|
|
|
98054
|
die "Can't path $part into a $self" if ($part ne $self->Function); |
449
|
4623
|
100
|
|
|
|
64640
|
return $self->Value->path_to($rest) if (defined $rest); |
450
|
1672
|
|
|
|
|
36064
|
return $self->Value; |
451
|
|
|
|
|
|
|
} |
452
|
|
|
|
|
|
|
} |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
package Cfn::Value::TypedValue { |
455
|
22
|
|
|
22
|
|
145821
|
use Moose; |
|
22
|
|
|
|
|
48
|
|
|
22
|
|
|
|
|
127
|
|
456
|
|
|
|
|
|
|
extends 'Cfn::Value'; |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
sub as_hashref { |
459
|
698
|
|
|
698
|
0
|
1407
|
my $self = shift; |
460
|
1780
|
|
|
|
|
6248
|
my $hr = { map { ( $_->[0] => $_->[1]->as_hashref(@_) ) } |
461
|
3040
|
|
|
|
|
81523
|
grep { defined $_->[1] } |
462
|
698
|
|
|
|
|
2876
|
map { [ $_->name, $_->get_value($self) ] } |
|
3040
|
|
|
|
|
328818
|
|
463
|
|
|
|
|
|
|
$self->meta->get_all_attributes |
464
|
|
|
|
|
|
|
}; |
465
|
698
|
|
|
|
|
3633
|
return $hr; |
466
|
|
|
|
|
|
|
} |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
sub path_to { |
469
|
1985
|
|
|
1985
|
0
|
4148
|
my ($self, $path) = @_; |
470
|
1985
|
|
|
|
|
3667
|
my ($part, $rest) = Cfn::path_split($path); |
471
|
|
|
|
|
|
|
|
472
|
1985
|
50
|
|
|
|
7713
|
die "Can't go into $part on $self" if (not $self->can($part)); |
473
|
1985
|
100
|
|
|
|
27032
|
return $self->$part->path_to($rest) if (defined $rest); |
474
|
1250
|
|
|
|
|
41873
|
return $self->$part; |
475
|
|
|
|
|
|
|
} |
476
|
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
package Cfn::Value::Function::Condition { |
479
|
22
|
|
|
22
|
|
145533
|
use Moose; |
|
22
|
|
|
|
|
54
|
|
|
22
|
|
|
|
|
104
|
|
480
|
|
|
|
|
|
|
extends 'Cfn::Value::Function'; |
481
|
|
|
|
|
|
|
has Value => (isa => 'Cfn::Value', is => 'rw', required => 1, coerce => 1); |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
sub Condition { |
484
|
0
|
|
|
0
|
0
|
0
|
shift->Value->Value; |
485
|
|
|
|
|
|
|
} |
486
|
|
|
|
|
|
|
} |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
package Cfn::Value::Function::Ref { |
489
|
22
|
|
|
22
|
|
140908
|
use Moose; |
|
22
|
|
|
|
|
61
|
|
|
22
|
|
|
|
|
98
|
|
490
|
|
|
|
|
|
|
extends 'Cfn::Value::Function'; |
491
|
|
|
|
|
|
|
has Value => (isa => 'Cfn::Value', is => 'rw', required => 1, coerce => 1); |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
sub LogicalId { |
494
|
12
|
|
|
12
|
0
|
224
|
shift->Value->Value; |
495
|
|
|
|
|
|
|
} |
496
|
|
|
|
|
|
|
} |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
package Cfn::Value::Function::PseudoParameter { |
499
|
22
|
|
|
22
|
|
140703
|
use Moose; |
|
22
|
|
|
|
|
50
|
|
|
22
|
|
|
|
|
91
|
|
500
|
|
|
|
|
|
|
extends 'Cfn::Value::Function::Ref'; |
501
|
|
|
|
|
|
|
} |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
package Cfn::Value::Function::GetAtt { |
504
|
22
|
|
|
22
|
|
139188
|
use Moose; |
|
22
|
|
|
|
|
51
|
|
|
22
|
|
|
|
|
92
|
|
505
|
|
|
|
|
|
|
extends 'Cfn::Value::Function'; |
506
|
|
|
|
|
|
|
has Value => (isa => 'Cfn::Value::ArrayOfPrimitives', is => 'rw', required => 1, coerce => 1); |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
sub LogicalId { |
509
|
2
|
|
|
2
|
0
|
4
|
my $self = shift; |
510
|
2
|
|
|
|
|
41
|
$self->Value->Value->[0]->Value; |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
sub Property { |
514
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
515
|
0
|
|
|
|
|
0
|
$self->Value->Value->[1]->Value; |
516
|
|
|
|
|
|
|
} |
517
|
|
|
|
|
|
|
} |
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
package Cfn::Value::Array { |
521
|
22
|
|
|
22
|
|
142659
|
use Moose; |
|
22
|
|
|
|
|
50
|
|
|
22
|
|
|
|
|
126
|
|
522
|
|
|
|
|
|
|
extends 'Cfn::Value'; |
523
|
|
|
|
|
|
|
has Value => ( |
524
|
|
|
|
|
|
|
is => 'rw', |
525
|
|
|
|
|
|
|
required => 1, |
526
|
|
|
|
|
|
|
isa => 'ArrayRef[Cfn::Value|Cfn::Resource::Properties]', |
527
|
|
|
|
|
|
|
traits => ['Array'], |
528
|
|
|
|
|
|
|
handles => { |
529
|
|
|
|
|
|
|
'Count' => 'count', |
530
|
|
|
|
|
|
|
} |
531
|
|
|
|
|
|
|
); |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
sub as_hashref { |
534
|
912
|
|
|
912
|
0
|
1681
|
my $self = shift; |
535
|
912
|
|
|
|
|
1847
|
my @args = @_; |
536
|
912
|
|
|
|
|
1484
|
return [ map { $_->as_hashref(@args) } @{ $self->Value } ] |
|
1855
|
|
|
|
|
5879
|
|
|
912
|
|
|
|
|
19841
|
|
537
|
|
|
|
|
|
|
} |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
sub path_to { |
540
|
6232
|
|
|
6232
|
0
|
12635
|
my ($self, $path) = @_; |
541
|
6232
|
|
|
|
|
9530
|
my ($part, $rest) = Cfn::path_split($path); |
542
|
|
|
|
|
|
|
|
543
|
6232
|
50
|
|
|
|
126485
|
die "Can't go into $part on $self" if (not exists $self->Value->[ $part ]); |
544
|
6232
|
100
|
|
|
|
82252
|
return $self->Value->[ $part ]->path_to($rest) if (defined $rest); |
545
|
2298
|
|
|
|
|
43808
|
return $self->Value->[ $part ]; |
546
|
|
|
|
|
|
|
} |
547
|
|
|
|
|
|
|
} |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
package Cfn::Value::Hash { |
550
|
22
|
|
|
22
|
|
144479
|
use Moose; |
|
22
|
|
|
|
|
47
|
|
|
22
|
|
|
|
|
125
|
|
551
|
|
|
|
|
|
|
extends 'Cfn::Value'; |
552
|
|
|
|
|
|
|
has Value => ( |
553
|
|
|
|
|
|
|
is => 'rw', |
554
|
|
|
|
|
|
|
required => 1, |
555
|
|
|
|
|
|
|
isa => 'HashRef[Cfn::Value]', |
556
|
|
|
|
|
|
|
); |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
override as_hashref => sub { |
559
|
|
|
|
|
|
|
my $self = shift; |
560
|
|
|
|
|
|
|
my @args = @_; |
561
|
|
|
|
|
|
|
return { map { $_ => $self->Value->{$_}->as_hashref(@args) } keys %{ $self->Value } }; |
562
|
|
|
|
|
|
|
}; |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
sub path_to { |
565
|
1155
|
|
|
1155
|
0
|
2169
|
my ($self, $path) = @_; |
566
|
1155
|
|
|
|
|
1742
|
my ($part, $rest) = Cfn::path_split($path); |
567
|
|
|
|
|
|
|
|
568
|
1155
|
50
|
|
|
|
23097
|
die "Can't go into $part on $self" if (not exists $self->Value->{ $part }); |
569
|
1155
|
100
|
|
|
|
17210
|
return $self->Value->{ $part }->path_to($rest) if (defined $rest); |
570
|
305
|
|
|
|
|
5700
|
return $self->Value->{ $part }; |
571
|
|
|
|
|
|
|
} |
572
|
|
|
|
|
|
|
} |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
package Cfn::Value::Primitive { |
577
|
22
|
|
|
22
|
|
147835
|
use Moose; |
|
22
|
|
|
|
|
59
|
|
|
22
|
|
|
|
|
105
|
|
578
|
|
|
|
|
|
|
extends 'Cfn::Value'; |
579
|
|
|
|
|
|
|
has Value => (isa => 'Value', is => 'rw', required => 1); |
580
|
|
|
|
|
|
|
override as_hashref => sub { |
581
|
|
|
|
|
|
|
my $self = shift; |
582
|
|
|
|
|
|
|
return $self->Value; |
583
|
|
|
|
|
|
|
} |
584
|
|
|
|
|
|
|
} |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
package Cfn::Boolean { |
587
|
22
|
|
|
22
|
|
143714
|
use Moose; |
|
22
|
|
|
|
|
57
|
|
|
22
|
|
|
|
|
106
|
|
588
|
22
|
|
|
22
|
|
157967
|
use JSON; |
|
22
|
|
|
|
|
213466
|
|
|
22
|
|
|
|
|
220
|
|
589
|
|
|
|
|
|
|
extends 'Cfn::Value::Primitive'; |
590
|
|
|
|
|
|
|
has '+Value' => (isa => 'Bool'); |
591
|
|
|
|
|
|
|
has stringy => (is => 'ro', required => 1, isa => 'Bool'); |
592
|
|
|
|
|
|
|
override as_hashref => sub { |
593
|
|
|
|
|
|
|
my $self = shift; |
594
|
|
|
|
|
|
|
if ($self->stringy){ |
595
|
|
|
|
|
|
|
return ($self->Value)?'true':'false'; |
596
|
|
|
|
|
|
|
} else { |
597
|
|
|
|
|
|
|
return ($self->Value)?JSON->true:JSON->false; |
598
|
|
|
|
|
|
|
} |
599
|
|
|
|
|
|
|
} |
600
|
|
|
|
|
|
|
} |
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
package Cfn::Integer { |
603
|
22
|
|
|
22
|
|
5576
|
use Moose; |
|
22
|
|
|
|
|
50
|
|
|
22
|
|
|
|
|
160
|
|
604
|
|
|
|
|
|
|
extends 'Cfn::Value::Primitive'; |
605
|
|
|
|
|
|
|
has '+Value' => (isa => 'Int'); |
606
|
|
|
|
|
|
|
} |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
package Cfn::Long { |
609
|
22
|
|
|
22
|
|
145729
|
use Moose; |
|
22
|
|
|
|
|
52
|
|
|
22
|
|
|
|
|
98
|
|
610
|
|
|
|
|
|
|
extends 'Cfn::Value::Primitive'; |
611
|
|
|
|
|
|
|
has '+Value' => (isa => 'Num'); |
612
|
|
|
|
|
|
|
} |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
package Cfn::String { |
615
|
22
|
|
|
22
|
|
137509
|
use Moose; |
|
22
|
|
|
|
|
48
|
|
|
22
|
|
|
|
|
92
|
|
616
|
|
|
|
|
|
|
extends 'Cfn::Value::Primitive'; |
617
|
|
|
|
|
|
|
has '+Value' => (isa => 'Str'); |
618
|
|
|
|
|
|
|
} |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
package Cfn::Double { |
621
|
22
|
|
|
22
|
|
139535
|
use Moose; |
|
22
|
|
|
|
|
49
|
|
|
22
|
|
|
|
|
103
|
|
622
|
|
|
|
|
|
|
extends 'Cfn::Value::Primitive'; |
623
|
|
|
|
|
|
|
has '+Value' => (isa => 'Num'); |
624
|
|
|
|
|
|
|
} |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
package Cfn::Timestamp { |
627
|
22
|
|
|
22
|
|
138272
|
use Moose; |
|
22
|
|
|
|
|
52
|
|
|
22
|
|
|
|
|
89
|
|
628
|
|
|
|
|
|
|
extends 'Cfn::Value::Primitive'; |
629
|
|
|
|
|
|
|
has '+Value' => (isa => 'Str'); |
630
|
|
|
|
|
|
|
} |
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
package Cfn::Resource { |
633
|
22
|
|
|
22
|
|
138339
|
use Moose; |
|
22
|
|
|
|
|
56
|
|
|
22
|
|
|
|
|
94
|
|
634
|
|
|
|
|
|
|
# CCfnX::Dependencies is not production ready |
635
|
|
|
|
|
|
|
with 'Cfn::Dependencies'; |
636
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
sub BUILD { |
638
|
1723
|
|
|
1723
|
0
|
4613245
|
my $self = shift; |
639
|
|
|
|
|
|
|
|
640
|
1723
|
|
|
|
|
9218
|
my $class_name = $self->meta->name; |
641
|
1723
|
|
|
|
|
42624
|
$class_name =~ s/^Cfn::Resource:://; |
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
# If the user is forcing the Type we want to validate |
644
|
|
|
|
|
|
|
# that we ended up with a valid object |
645
|
1723
|
100
|
|
|
|
50327
|
if (defined $self->Type) { |
646
|
1718
|
100
|
100
|
|
|
35939
|
if ($class_name ne $self->Type and $class_name ne 'AWS::CloudFormation::CustomResource') { |
647
|
1
|
|
|
|
|
12
|
die "Invalid Cfn::Resource" |
648
|
|
|
|
|
|
|
} |
649
|
|
|
|
|
|
|
} else { |
650
|
5
|
|
|
|
|
116
|
$self->Type($class_name); |
651
|
|
|
|
|
|
|
} |
652
|
|
|
|
|
|
|
} |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
has Type => (isa => 'Str', is => 'rw'); |
655
|
|
|
|
|
|
|
has Properties => (isa => 'Cfn::Resource::Properties', is => 'rw'); |
656
|
|
|
|
|
|
|
has DeletionPolicy => (isa => 'Cfn::Resource::DeletionPolicy', is => 'rw'); |
657
|
|
|
|
|
|
|
has DependsOn => (isa => 'ArrayRef[Str]|Str', is => 'rw'); |
658
|
|
|
|
|
|
|
has Condition => (isa => 'Str', is => 'rw'); |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
sub Property { |
661
|
5680
|
|
|
5680
|
0
|
9707
|
my ($self, $property) = @_; |
662
|
5680
|
50
|
|
|
|
169299
|
return undef if (not defined $self->Properties); |
663
|
5680
|
|
|
|
|
156555
|
return $self->Properties->$property; |
664
|
|
|
|
|
|
|
} |
665
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
sub hasAttribute { |
667
|
3
|
|
|
3
|
0
|
11
|
my ($self, $attribute) = @_; |
668
|
3
|
|
|
|
|
5
|
my @matches = grep { $_ eq $attribute } @{ $self->AttributeList }; |
|
2
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
11
|
|
669
|
3
|
|
|
|
|
17
|
return @matches == 1; |
670
|
|
|
|
|
|
|
} |
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
sub DependsOnList { |
673
|
12
|
|
|
12
|
0
|
16
|
my $self = shift; |
674
|
12
|
100
|
|
|
|
237
|
return () if (not defined $self->DependsOn); |
675
|
4
|
100
|
|
|
|
67
|
return @{ $self->DependsOn } if (ref($self->DependsOn) eq 'ARRAY'); |
|
3
|
|
|
|
|
49
|
|
676
|
1
|
|
|
|
|
18
|
return $self->DependsOn; |
677
|
|
|
|
|
|
|
} |
678
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
has Metadata => (isa => 'Cfn::Value::Hash', is => 'rw', coerce => 1); |
680
|
|
|
|
|
|
|
has UpdatePolicy => (isa => 'Cfn::Resource::UpdatePolicy', is => 'rw', coerce => 1); |
681
|
|
|
|
|
|
|
has CreationPolicy => (isa => 'HashRef', is => 'rw'); |
682
|
|
|
|
|
|
|
has UpdateReplacePolicy => (isa => 'Cfn::Resource::UpdateReplacePolicy', is => 'rw'); |
683
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
sub as_hashref { |
685
|
468
|
|
|
468
|
0
|
1200
|
my $self = shift; |
686
|
468
|
|
|
|
|
1193
|
my @args = @_; |
687
|
|
|
|
|
|
|
return { |
688
|
468
|
|
|
|
|
14441
|
(map { $_ => $self->$_->as_hashref(@args) } |
689
|
1404
|
|
|
|
|
37730
|
grep { defined $self->$_ } qw/Properties Metadata UpdatePolicy/), |
690
|
473
|
|
|
|
|
9748
|
(map { $_ => $self->$_ } |
691
|
468
|
|
|
|
|
1322
|
grep { defined $self->$_ } qw/Type DeletionPolicy UpdateReplacePolicy DependsOn CreationPolicy Condition/), |
|
2808
|
|
|
|
|
66591
|
|
692
|
|
|
|
|
|
|
} |
693
|
|
|
|
|
|
|
} |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
sub path_to { |
696
|
6810
|
|
|
6810
|
0
|
12419
|
my ($self, $path) = @_; |
697
|
6810
|
|
|
|
|
10886
|
my ($part, $rest) = Cfn::path_split($path); |
698
|
|
|
|
|
|
|
|
699
|
6810
|
50
|
0
|
|
|
15944
|
if ($part eq 'Properties') { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
700
|
6810
|
50
|
|
|
|
11808
|
return $self->Properties if (not defined $rest); |
701
|
6810
|
|
|
|
|
206093
|
return $self->Properties->path_to($rest); |
702
|
|
|
|
|
|
|
} elsif ($part eq 'Metadata') { |
703
|
0
|
0
|
|
|
|
0
|
return $self->Metadata if (not defined $rest); |
704
|
0
|
|
|
|
|
0
|
return $self->Metadata->{ $rest }; |
705
|
|
|
|
|
|
|
} elsif ($part eq 'DependsOn') { |
706
|
0
|
0
|
|
|
|
0
|
return $self->DependsOn if (not defined $rest); |
707
|
0
|
|
|
|
|
0
|
die "Can't go into $path on resource"; |
708
|
|
|
|
|
|
|
} elsif ($part eq 'Type' or $path eq 'Condition') { |
709
|
0
|
0
|
|
|
|
0
|
return $self->$part if (not defined $rest); |
710
|
0
|
|
|
|
|
0
|
die "Can't go into $path on resource"; |
711
|
|
|
|
|
|
|
} else { |
712
|
0
|
|
|
|
|
0
|
die "Can't go into $path on resource"; |
713
|
|
|
|
|
|
|
} |
714
|
|
|
|
|
|
|
} |
715
|
|
|
|
|
|
|
} |
716
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
package Cfn::Resource::Properties { |
718
|
22
|
|
|
22
|
|
156428
|
use Moose; |
|
22
|
|
|
|
|
53
|
|
|
22
|
|
|
|
|
397
|
|
719
|
|
|
|
|
|
|
sub as_hashref { |
720
|
460
|
|
|
460
|
0
|
1255
|
my $self = shift; |
721
|
460
|
|
|
|
|
1174
|
my @args = @_; |
722
|
|
|
|
|
|
|
|
723
|
460
|
|
|
|
|
1235
|
my $ret = {}; |
724
|
460
|
|
|
|
|
2145
|
foreach my $att ($self->meta->get_all_attributes) { |
725
|
4175
|
|
|
|
|
46890
|
my $el = $att->name; |
726
|
4175
|
100
|
|
|
|
146620
|
if (defined $self->$el) { |
727
|
1619
|
|
|
|
|
52131
|
my @ret = $self->$el->as_hashref(@args); |
728
|
1619
|
50
|
|
|
|
4215
|
if (@ret == 1) { |
729
|
1619
|
|
|
|
|
4890
|
$ret->{ $el } = $ret[0]; |
730
|
|
|
|
|
|
|
} else { |
731
|
0
|
|
|
|
|
0
|
die "A property returned an odd number of values"; |
732
|
|
|
|
|
|
|
} |
733
|
|
|
|
|
|
|
} |
734
|
|
|
|
|
|
|
} |
735
|
460
|
|
|
|
|
2826
|
return $ret; |
736
|
|
|
|
|
|
|
} |
737
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
sub path_to { |
739
|
6810
|
|
|
6810
|
0
|
15931
|
my ($self, $path) = @_; |
740
|
6810
|
|
|
|
|
12543
|
my ($part, $rest) = Cfn::path_split($path); |
741
|
|
|
|
|
|
|
|
742
|
6810
|
50
|
|
|
|
28032
|
die "Can't go into $part on $self" if (not $self->can($part)); |
743
|
6810
|
100
|
|
|
|
162333
|
return $self->$part->path_to($rest) if (defined $rest); |
744
|
1915
|
|
|
|
|
64417
|
return $self->$part; |
745
|
|
|
|
|
|
|
} |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
sub resolve_references_to_logicalid_with { |
748
|
0
|
|
|
0
|
0
|
0
|
my ($self, $logical_id, $object) = @_; |
749
|
0
|
|
|
|
|
0
|
foreach my $att ($self->meta->get_attribute_list) { |
750
|
0
|
0
|
|
|
|
0
|
next if (not defined $self->$att); |
751
|
|
|
|
|
|
|
|
752
|
0
|
0
|
0
|
|
|
0
|
if ($self->$att->isa('Cfn::Value::Function::Ref') and $self->$att->LogicalId eq $logical_id) { |
|
|
0
|
0
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
753
|
0
|
|
|
|
|
0
|
my $func = $self->$att; |
754
|
|
|
|
|
|
|
#$self->$att('TBD'); #$object->$objects_ref_prop |
755
|
|
|
|
|
|
|
#warn "Resolved TBD $logical_id"; |
756
|
0
|
|
|
|
|
0
|
my @attrs = $object->meta->get_all_attributes; |
757
|
0
|
|
|
|
|
0
|
my @ref = grep { $_->does('CCfnX::Meta::Attribute::Trait::RefValue') } @attrs; |
|
0
|
|
|
|
|
0
|
|
758
|
0
|
0
|
|
|
|
0
|
if (not @ref) { die $object . " has no RefValue trait. Cannot resolve Ref" } |
|
0
|
|
|
|
|
0
|
|
759
|
|
|
|
|
|
|
else { |
760
|
0
|
|
|
|
|
0
|
my $property = $ref[0]->name; |
761
|
0
|
|
|
|
|
0
|
my $value = $object->$property; |
762
|
0
|
|
|
|
|
0
|
$self->$att($value); |
763
|
|
|
|
|
|
|
} |
764
|
|
|
|
|
|
|
} elsif ($self->$att->isa('Cfn::Value::Function::GetAtt') and $self->$att->LogicalId eq $logical_id) { |
765
|
0
|
|
|
|
|
0
|
my $func = $self->$att; |
766
|
0
|
|
|
|
|
0
|
my $property = $func->Property; |
767
|
0
|
|
|
|
|
0
|
$self->$att($object->$property); |
768
|
0
|
|
|
|
|
0
|
warn "Resolved $logical_id $property"; |
769
|
|
|
|
|
|
|
} elsif ($self->$att->isa('Cfn::Value::Array')) { |
770
|
0
|
|
|
|
|
0
|
map { resolve_references_to_logicalid_with($_, $logical_id, $object) } @{ $self->$att->Value }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
771
|
|
|
|
|
|
|
} elsif ($self->$att->isa('Cfn::Value::Function')) { |
772
|
0
|
|
|
|
|
0
|
resolve_references_to_logicalid_with($self->$att, $logical_id, $object); |
773
|
|
|
|
|
|
|
} elsif ($self->$att->isa('Cfn::Value::Primitive')) { |
774
|
|
|
|
|
|
|
# End case. Primitives do nothing |
775
|
|
|
|
|
|
|
# This case is important to be here, as it filters out any Primitives for |
776
|
|
|
|
|
|
|
# the next if |
777
|
|
|
|
|
|
|
} elsif ($self->$att->isa('Cfn::Value')) { |
778
|
0
|
|
|
|
|
0
|
resolve_references_to_logicalid_with($self->$att, $logical_id, $object); |
779
|
|
|
|
|
|
|
} else { |
780
|
0
|
|
|
|
|
0
|
die "Don't know how to resolve $att on " . $self->$att; |
781
|
|
|
|
|
|
|
} |
782
|
|
|
|
|
|
|
} |
783
|
|
|
|
|
|
|
} |
784
|
|
|
|
|
|
|
} |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
package Cfn::Resource::UpdatePolicy { |
787
|
22
|
|
|
22
|
|
153956
|
use Moose; |
|
22
|
|
|
|
|
74
|
|
|
22
|
|
|
|
|
114
|
|
788
|
|
|
|
|
|
|
extends 'Cfn::Value::TypedValue'; |
789
|
|
|
|
|
|
|
has AutoScalingReplacingUpdate => (isa => 'Cfn::Resource::UpdatePolicy::AutoScalingReplacingUpdate', is => 'rw', coerce => 1); |
790
|
|
|
|
|
|
|
has AutoScalingRollingUpdate => (isa => 'Cfn::Resource::UpdatePolicy::AutoScalingRollingUpdate', is => 'rw', coerce => 1); |
791
|
|
|
|
|
|
|
has AutoScalingAutoScalingScheduledAction => (isa => 'Cfn::Resource::UpdatePolicy::AutoScalingScheduledAction', is => 'rw', coerce => 1); |
792
|
|
|
|
|
|
|
has UseOnlineResharding => (isa => 'Cfn::Value::Boolean', is => 'rw', coerce => 1); |
793
|
|
|
|
|
|
|
} |
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
package Cfn::Resource::UpdatePolicy::AutoScalingReplacingUpdate { |
796
|
22
|
|
|
22
|
|
141579
|
use Moose; |
|
22
|
|
|
|
|
52
|
|
|
22
|
|
|
|
|
98
|
|
797
|
|
|
|
|
|
|
extends 'Cfn::Value::TypedValue'; |
798
|
|
|
|
|
|
|
has WillReplace => (isa => 'Cfn::Value::Boolean', is => 'rw', required => 1, coerce => 1); |
799
|
|
|
|
|
|
|
} |
800
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
package Cfn::Resource::UpdatePolicy::AutoScalingRollingUpdate { |
802
|
22
|
|
|
22
|
|
139888
|
use Moose; |
|
22
|
|
|
|
|
48
|
|
|
22
|
|
|
|
|
92
|
|
803
|
|
|
|
|
|
|
extends 'Cfn::Value::TypedValue'; |
804
|
|
|
|
|
|
|
has MaxBatchSize => (isa => 'Cfn::Value::Integer', is => 'rw', coerce => 1); |
805
|
|
|
|
|
|
|
has MinInstancesInService => (isa => 'Cfn::Value::Integer', is => 'rw', coerce => 1); |
806
|
|
|
|
|
|
|
has MinSuccessfulInstancesPercent => (isa => 'Cfn::Value::Integer', is => 'rw', coerce => 1); |
807
|
|
|
|
|
|
|
has PauseTime => (isa => 'Cfn::Value::String', is => 'rw', coerce => 1); |
808
|
|
|
|
|
|
|
# TODO: better validate SuspendProcesses |
809
|
|
|
|
|
|
|
has SuspendProcesses => (isa => 'Cfn::Resource::UpdatePolicy::AutoScalingRollingUpdate::SuspendProcesses', is => 'rw', coerce => 1); |
810
|
|
|
|
|
|
|
has WaitOnResourceSignals => (isa => 'Cfn::Value::Boolean', is => 'rw', coerce => 1); |
811
|
|
|
|
|
|
|
} |
812
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
package Cfn::Resource::UpdatePolicy::AutoScalingScheduledAction { |
814
|
22
|
|
|
22
|
|
141970
|
use Moose; |
|
22
|
|
|
|
|
54
|
|
|
22
|
|
|
|
|
105
|
|
815
|
|
|
|
|
|
|
extends 'Cfn::Value::TypedValue'; |
816
|
|
|
|
|
|
|
has IgnoreUnmodifiedGroupSizeProperties => (isa => 'Cfn::Value::Boolean', is => 'rw', required => 1, coerce => 1); |
817
|
|
|
|
|
|
|
} |
818
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
package Cfn::Output { |
820
|
22
|
|
|
22
|
|
139411
|
use Moose; |
|
22
|
|
|
|
|
48
|
|
|
22
|
|
|
|
|
93
|
|
821
|
|
|
|
|
|
|
has Value => (isa => 'Cfn::Value', is => 'rw', required => 1, coerce => 1); |
822
|
|
|
|
|
|
|
has Description => (isa => 'Str', is => 'rw'); |
823
|
|
|
|
|
|
|
has Condition => (isa => 'Str', is => 'rw'); |
824
|
|
|
|
|
|
|
has Export => (isa => 'Cfn::Value::Hash', is => 'rw', coerce => 1); |
825
|
|
|
|
|
|
|
sub as_hashref { |
826
|
4
|
|
|
4
|
0
|
10
|
my $self = shift; |
827
|
4
|
|
|
|
|
10
|
my @args = @_; |
828
|
|
|
|
|
|
|
return { |
829
|
4
|
100
|
|
|
|
105
|
Value => $self->Value->as_hashref(@args), |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
830
|
|
|
|
|
|
|
(defined $self->Condition) ? (Condition => $self->Condition) : (), |
831
|
|
|
|
|
|
|
(defined $self->Description) ? (Description => $self->Description) : (), |
832
|
|
|
|
|
|
|
(defined $self->Export) ? (Export => $self->Export->as_hashref) : (), |
833
|
|
|
|
|
|
|
} |
834
|
|
|
|
|
|
|
} |
835
|
|
|
|
|
|
|
sub path_to { |
836
|
765
|
|
|
765
|
0
|
1834
|
my ($self, $path) = @_; |
837
|
765
|
|
|
|
|
1278
|
my ($part, $rest) = Cfn::path_split($path); |
838
|
|
|
|
|
|
|
|
839
|
765
|
0
|
33
|
|
|
2115
|
die "Can't path into $part on $self" if ($part ne 'Value' and |
|
|
|
33
|
|
|
|
|
|
|
|
0
|
|
|
|
|
840
|
|
|
|
|
|
|
$part ne 'Description' and |
841
|
|
|
|
|
|
|
$part ne 'Condition' and |
842
|
|
|
|
|
|
|
$part ne 'Export' |
843
|
|
|
|
|
|
|
); |
844
|
765
|
50
|
0
|
|
|
1666
|
if ($part eq 'Value') { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
845
|
765
|
100
|
|
|
|
4175
|
return $self->Value if (not defined $rest); |
846
|
630
|
|
|
|
|
13256
|
return $self->Value->path_to($rest); |
847
|
|
|
|
|
|
|
} elsif ($part eq 'Description' or $part eq 'Condition') { |
848
|
0
|
0
|
|
|
|
0
|
die "Can't path into $part on $self" if (defined $rest); |
849
|
0
|
|
|
|
|
0
|
return $self->$part; |
850
|
|
|
|
|
|
|
} elsif ($part eq 'Export') { |
851
|
0
|
0
|
|
|
|
0
|
return $self->Export if (not defined $rest); |
852
|
0
|
|
|
|
|
0
|
return $self->Value->path_to($rest); |
853
|
|
|
|
|
|
|
} |
854
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
} |
856
|
|
|
|
|
|
|
} |
857
|
|
|
|
|
|
|
|
858
|
|
|
|
|
|
|
package Cfn::Parameter { |
859
|
22
|
|
|
22
|
|
150656
|
use Moose; |
|
22
|
|
|
|
|
51
|
|
|
22
|
|
|
|
|
115
|
|
860
|
|
|
|
|
|
|
has Type => (isa => 'Cfn::Parameter::Type', is => 'ro', required => 1); |
861
|
|
|
|
|
|
|
has Default => (isa => 'Str', is => 'rw'); |
862
|
|
|
|
|
|
|
has NoEcho => (isa => 'Str', is => 'rw'); |
863
|
|
|
|
|
|
|
has AllowedValues => ( isa => 'ArrayRef[Str]', is => 'rw'); |
864
|
|
|
|
|
|
|
has AllowedPattern => ( isa => 'Str', is => 'rw'); |
865
|
|
|
|
|
|
|
has MaxLength => ( isa => 'Str', is => 'rw'); |
866
|
|
|
|
|
|
|
has MinLength => ( isa => 'Str', is => 'rw'); |
867
|
|
|
|
|
|
|
has MaxValue => ( isa => 'Str', is => 'rw'); |
868
|
|
|
|
|
|
|
has MinValue => ( isa => 'Str', is => 'rw'); |
869
|
|
|
|
|
|
|
has Description => ( isa => 'Str', is => 'rw'); |
870
|
|
|
|
|
|
|
has ConstraintDescription => ( isa => 'Str', is => 'rw'); |
871
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
sub as_hashref { |
873
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
874
|
|
|
|
|
|
|
return { |
875
|
0
|
0
|
|
|
|
0
|
map { (defined $self->$_) ? ($_ => $self->$_) : () } |
|
0
|
|
|
|
|
0
|
|
876
|
|
|
|
|
|
|
qw/Type Default NoEcho AllowedValues AllowedPattern MaxLength |
877
|
|
|
|
|
|
|
MinLength MaxValue MinValue Description ConstraintDescription/, |
878
|
|
|
|
|
|
|
} |
879
|
|
|
|
|
|
|
} |
880
|
|
|
|
|
|
|
} |
881
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
package Cfn::Mapping { |
883
|
22
|
|
|
22
|
|
142734
|
use Moose; |
|
22
|
|
|
|
|
48
|
|
|
22
|
|
|
|
|
119
|
|
884
|
|
|
|
|
|
|
has Map => (isa => 'HashRef', is => 'ro'); |
885
|
|
|
|
|
|
|
|
886
|
|
|
|
|
|
|
sub as_hashref { |
887
|
2
|
|
|
2
|
0
|
3
|
my $self = shift; |
888
|
2
|
|
|
|
|
42
|
return $self->Map; |
889
|
|
|
|
|
|
|
} |
890
|
|
|
|
|
|
|
} |
891
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
package Cfn::Internal::Options { |
893
|
22
|
|
|
22
|
|
140724
|
use Moose; |
|
22
|
|
|
|
|
54
|
|
|
22
|
|
|
|
|
110
|
|
894
|
|
|
|
|
|
|
has custom_resource_rename => (is => 'rw', isa => 'Bool', default => 0); |
895
|
|
|
|
|
|
|
} |
896
|
|
|
|
|
|
|
|
897
|
|
|
|
|
|
|
package Cfn { |
898
|
22
|
|
|
22
|
|
139206
|
use Moose; |
|
22
|
|
|
|
|
70
|
|
|
22
|
|
|
|
|
96
|
|
899
|
22
|
|
|
22
|
|
138288
|
use Moose::Util; |
|
22
|
|
|
|
|
54
|
|
|
22
|
|
|
|
|
184
|
|
900
|
22
|
|
|
22
|
|
4223
|
use Scalar::Util; |
|
22
|
|
|
|
|
55
|
|
|
22
|
|
|
|
|
1325
|
|
901
|
22
|
|
|
22
|
|
14821
|
use Cfn::ResourceModules; |
|
22
|
|
|
|
|
57
|
|
|
22
|
|
|
|
|
51591
|
|
902
|
|
|
|
|
|
|
|
903
|
|
|
|
|
|
|
has AWSTemplateFormatVersion => (isa => 'Str', is => 'rw'); |
904
|
|
|
|
|
|
|
has Description => (isa => 'Str', is => 'rw'); |
905
|
|
|
|
|
|
|
has Transform => (isa => 'Cfn::Transform', is => 'rw', coerce => 1); |
906
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
our $VERSION = '0.11'; |
908
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
has Parameters => ( |
910
|
|
|
|
|
|
|
is => 'rw', |
911
|
|
|
|
|
|
|
isa => 'Cfn::ParameterHash', |
912
|
|
|
|
|
|
|
coerce => 1, |
913
|
|
|
|
|
|
|
traits => [ 'Hash' ], |
914
|
|
|
|
|
|
|
handles => { |
915
|
|
|
|
|
|
|
Parameter => 'accessor', |
916
|
|
|
|
|
|
|
ParameterList => 'keys', |
917
|
|
|
|
|
|
|
ParameterCount => 'count', |
918
|
|
|
|
|
|
|
ParameterList => 'keys', |
919
|
|
|
|
|
|
|
}, |
920
|
|
|
|
|
|
|
); |
921
|
|
|
|
|
|
|
has Mappings => ( |
922
|
|
|
|
|
|
|
is => 'rw', |
923
|
|
|
|
|
|
|
isa => 'Cfn::MappingHash', |
924
|
|
|
|
|
|
|
coerce => 1, |
925
|
|
|
|
|
|
|
traits => [ 'Hash' ], |
926
|
|
|
|
|
|
|
handles => { |
927
|
|
|
|
|
|
|
Mapping => 'accessor', |
928
|
|
|
|
|
|
|
MappingCount => 'count', |
929
|
|
|
|
|
|
|
MappingList => 'keys', |
930
|
|
|
|
|
|
|
}, |
931
|
|
|
|
|
|
|
); |
932
|
|
|
|
|
|
|
has Conditions => ( |
933
|
|
|
|
|
|
|
is => 'rw', |
934
|
|
|
|
|
|
|
isa => 'Cfn::ConditionHash', |
935
|
|
|
|
|
|
|
traits => [ 'Hash' ], |
936
|
|
|
|
|
|
|
coerce => 1, |
937
|
|
|
|
|
|
|
handles => { |
938
|
|
|
|
|
|
|
Condition => 'accessor', |
939
|
|
|
|
|
|
|
ConditionList => 'keys', |
940
|
|
|
|
|
|
|
ConditionCount => 'count', |
941
|
|
|
|
|
|
|
}, |
942
|
|
|
|
|
|
|
); |
943
|
|
|
|
|
|
|
has Resources => ( |
944
|
|
|
|
|
|
|
is => 'rw', |
945
|
|
|
|
|
|
|
isa => 'Cfn::ResourceHash', |
946
|
|
|
|
|
|
|
coerce => 1, |
947
|
|
|
|
|
|
|
traits => [ 'Hash' ], |
948
|
|
|
|
|
|
|
handles => { |
949
|
|
|
|
|
|
|
Resource => 'accessor', |
950
|
|
|
|
|
|
|
ResourceList => 'keys', |
951
|
|
|
|
|
|
|
ResourceCount => 'count', |
952
|
|
|
|
|
|
|
}, |
953
|
|
|
|
|
|
|
); |
954
|
|
|
|
|
|
|
has Outputs => ( |
955
|
|
|
|
|
|
|
is => 'rw', |
956
|
|
|
|
|
|
|
isa => 'Cfn::OutputHash', |
957
|
|
|
|
|
|
|
coerce => 1, |
958
|
|
|
|
|
|
|
traits => [ 'Hash' ], |
959
|
|
|
|
|
|
|
handles => { |
960
|
|
|
|
|
|
|
Output => 'accessor', |
961
|
|
|
|
|
|
|
OutputList => 'keys', |
962
|
|
|
|
|
|
|
OutputCount => 'count', |
963
|
|
|
|
|
|
|
}, |
964
|
|
|
|
|
|
|
); |
965
|
|
|
|
|
|
|
has Metadata => ( |
966
|
|
|
|
|
|
|
is => 'rw', |
967
|
|
|
|
|
|
|
isa => 'Cfn::MetadataHash', |
968
|
|
|
|
|
|
|
coerce => 1, |
969
|
|
|
|
|
|
|
traits => [ 'Hash' ], |
970
|
|
|
|
|
|
|
handles => { |
971
|
|
|
|
|
|
|
MetadataItem => 'accessor', |
972
|
|
|
|
|
|
|
MetadataList => 'keys', |
973
|
|
|
|
|
|
|
MetadataCount => 'count', |
974
|
|
|
|
|
|
|
}, |
975
|
|
|
|
|
|
|
); |
976
|
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
has cfn_options => ( |
978
|
|
|
|
|
|
|
is => 'ro', |
979
|
|
|
|
|
|
|
isa => 'Cfn::Internal::Options', |
980
|
|
|
|
|
|
|
coerce => 1, |
981
|
|
|
|
|
|
|
default => sub { Cfn::Internal::Options->new }, |
982
|
|
|
|
|
|
|
); |
983
|
|
|
|
|
|
|
|
984
|
|
|
|
|
|
|
sub list_resource_modules { |
985
|
0
|
|
|
0
|
0
|
0
|
return Cfn::ResourceModules::list(); |
986
|
|
|
|
|
|
|
} |
987
|
|
|
|
|
|
|
|
988
|
|
|
|
|
|
|
sub load_resource_module { |
989
|
1720
|
|
|
1720
|
0
|
5594
|
my (undef, $type) = @_; |
990
|
1720
|
|
|
|
|
7235
|
return Cfn::ResourceModules::load($type); |
991
|
|
|
|
|
|
|
} |
992
|
|
|
|
|
|
|
|
993
|
|
|
|
|
|
|
sub ResourcesOfType { |
994
|
0
|
|
|
0
|
1
|
0
|
my ($self, $type) = @_; |
995
|
0
|
|
|
|
|
0
|
return grep { $_->Type eq $type } values %{ $self->Resources }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
996
|
|
|
|
|
|
|
} |
997
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
sub addParameter { |
999
|
0
|
|
|
0
|
1
|
0
|
my ($self, $name, $type, %rest) = @_; |
1000
|
0
|
0
|
|
|
|
0
|
Moose->throw_error("A parameter named $name already exists") if (defined $self->Parameter($name)); |
1001
|
0
|
0
|
|
|
|
0
|
if (ref $type) { |
1002
|
0
|
|
|
|
|
0
|
return $self->Parameter($name, $type); |
1003
|
|
|
|
|
|
|
} else { |
1004
|
0
|
|
|
|
|
0
|
return $self->Parameter($name, Cfn::Parameter->new(Type => $type, %rest)); |
1005
|
|
|
|
|
|
|
} |
1006
|
|
|
|
|
|
|
} |
1007
|
|
|
|
|
|
|
|
1008
|
|
|
|
|
|
|
sub addMapping { |
1009
|
3
|
|
|
3
|
1
|
3118
|
my ($self, $name, $mapping) = @_; |
1010
|
3
|
100
|
|
|
|
99
|
Moose->throw_error("A mapping named $name already exists") if (defined $self->Mapping($name)); |
1011
|
2
|
50
|
|
|
|
6
|
if (ref $mapping eq 'HASH') { |
1012
|
2
|
|
|
|
|
15
|
return $self->Mapping($name, Cfn::Mapping->new(Map => $mapping)); |
1013
|
|
|
|
|
|
|
} else { |
1014
|
0
|
|
|
|
|
0
|
return $self->Mapping($name, $mapping); |
1015
|
|
|
|
|
|
|
} |
1016
|
|
|
|
|
|
|
} |
1017
|
|
|
|
|
|
|
|
1018
|
|
|
|
|
|
|
sub addOutput { |
1019
|
4
|
|
|
4
|
1
|
2326
|
my ($self, $name, $output, @rest) = @_; |
1020
|
4
|
50
|
|
|
|
133
|
Moose->throw_error("An output named $name already exists") if (defined $self->Output($name)); |
1021
|
4
|
50
|
|
|
|
17
|
if (my $class = blessed $output) { |
1022
|
0
|
0
|
|
|
|
0
|
die "Can't call addOutput with a $class" if ($class ne 'Cfn::Output'); |
1023
|
0
|
|
|
|
|
0
|
return $self->Output($name, $output); |
1024
|
|
|
|
|
|
|
} else { |
1025
|
4
|
|
|
|
|
69
|
return $self->Output($name, Cfn::Output->new( Value => $output, @rest )); |
1026
|
|
|
|
|
|
|
} |
1027
|
|
|
|
|
|
|
} |
1028
|
|
|
|
|
|
|
|
1029
|
|
|
|
|
|
|
sub addCondition { |
1030
|
1
|
|
|
1
|
1
|
5
|
my ($self, $name, $value) = @_; |
1031
|
1
|
50
|
|
|
|
35
|
Moose->throw_error("A condition named $name already exists") if (defined $self->Condition($name)); |
1032
|
1
|
|
|
|
|
5
|
return $self->Condition($name, Moose::Util::TypeConstraints::find_type_constraint('Cfn::Value')->coerce($value)); |
1033
|
|
|
|
|
|
|
} |
1034
|
|
|
|
|
|
|
|
1035
|
|
|
|
|
|
|
sub addResource { |
1036
|
492
|
|
|
492
|
1
|
541274
|
my ($self, $name, $second_param, $third_param, @rest) = @_; |
1037
|
492
|
50
|
|
|
|
15552
|
Moose->throw_error("A resource named $name already exists") if (defined $self->Resource($name)); |
1038
|
|
|
|
|
|
|
|
1039
|
492
|
100
|
|
|
|
1826
|
if (not ref $second_param){ |
1040
|
267
|
|
|
|
|
705
|
my $type = $second_param; |
1041
|
267
|
|
|
|
|
656
|
my (@properties, @extra_props); |
1042
|
|
|
|
|
|
|
|
1043
|
267
|
100
|
|
|
|
915
|
if (ref($third_param) eq 'HASH') { |
1044
|
33
|
|
|
|
|
131
|
@properties = %$third_param; |
1045
|
33
|
100
|
33
|
|
|
126
|
if (not defined $rest[0]){ |
|
|
50
|
|
|
|
|
|
1046
|
26
|
|
|
|
|
52
|
@extra_props = (); |
1047
|
|
|
|
|
|
|
} elsif (defined $rest[0] and ref($rest[0]) eq 'HASH') { |
1048
|
7
|
|
|
|
|
12
|
@extra_props = %{ $rest[0] } |
|
7
|
|
|
|
|
21
|
|
1049
|
|
|
|
|
|
|
} else { |
1050
|
0
|
|
|
|
|
0
|
die "Don't know what to do with the fourth parameter to addResource"; |
1051
|
|
|
|
|
|
|
} |
1052
|
|
|
|
|
|
|
} else { |
1053
|
234
|
|
66
|
|
|
1370
|
@properties = ( $third_param // () , @rest); |
1054
|
234
|
|
|
|
|
755
|
@extra_props = (); |
1055
|
|
|
|
|
|
|
} |
1056
|
|
|
|
|
|
|
|
1057
|
267
|
|
|
|
|
1264
|
return $self->Resources->{ $name } = Moose::Util::TypeConstraints::find_type_constraint('Cfn::Resource')->coerce({ |
1058
|
|
|
|
|
|
|
Type => $type, |
1059
|
|
|
|
|
|
|
Properties => { @properties }, |
1060
|
|
|
|
|
|
|
@extra_props, |
1061
|
|
|
|
|
|
|
}) |
1062
|
|
|
|
|
|
|
} else { |
1063
|
225
|
|
|
|
|
655
|
my $object = $second_param; |
1064
|
225
|
|
|
|
|
6662
|
return $self->Resource($name, $object); |
1065
|
|
|
|
|
|
|
} |
1066
|
|
|
|
|
|
|
} |
1067
|
|
|
|
|
|
|
|
1068
|
|
|
|
|
|
|
sub addMetadata { |
1069
|
5
|
|
|
5
|
0
|
10014
|
my ($self, $name, $metadata) = @_; |
1070
|
|
|
|
|
|
|
|
1071
|
5
|
50
|
|
|
|
17
|
if (ref($name) eq 'HASH') { |
1072
|
5
|
50
|
|
|
|
111
|
Moose->throw_error("The stack already has metadata") if (defined $self->Metadata); |
1073
|
5
|
|
|
|
|
97
|
$self->Metadata($name); |
1074
|
|
|
|
|
|
|
} else { |
1075
|
0
|
0
|
|
|
|
0
|
Moose->throw_error("A metadata item named $name already exists") if (defined $self->MetadataItem($name)); |
1076
|
0
|
|
|
|
|
0
|
return $self->MetadataItem($name, Moose::Util::TypeConstraints::find_type_constraint('Cfn::Value')->coerce($metadata)); |
1077
|
|
|
|
|
|
|
} |
1078
|
|
|
|
|
|
|
} |
1079
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
sub addResourceMetadata { |
1081
|
0
|
|
|
0
|
1
|
0
|
my ($self, $name, %args) = @_; |
1082
|
0
|
0
|
|
|
|
0
|
Moose->throw_error("A resource named $name must already exist") if (not defined $self->Resources->{ $name }); |
1083
|
0
|
|
|
|
|
0
|
$self->Resources->{ $name }->Metadata({ %args }); |
1084
|
|
|
|
|
|
|
} |
1085
|
|
|
|
|
|
|
sub addDependsOn { |
1086
|
0
|
|
|
0
|
1
|
0
|
my ($self, $name, @args) = @_; |
1087
|
0
|
0
|
|
|
|
0
|
Moose->throw_error("A resource named $name must already exist") if (not defined $self->Resources->{ $name }); |
1088
|
0
|
|
|
|
|
0
|
$self->Resources->{ $name }->DependsOn( [ @args ] ); |
1089
|
|
|
|
|
|
|
} |
1090
|
|
|
|
|
|
|
sub addDeletionPolicy { |
1091
|
0
|
|
|
0
|
1
|
0
|
my ($self, $name, $policy) = @_; |
1092
|
0
|
0
|
|
|
|
0
|
Moose->throw_error("A resource named $name must already exist") if (not defined $self->Resources->{ $name }); |
1093
|
0
|
|
|
|
|
0
|
$self->Resources->{ $name }->DeletionPolicy( $policy ); |
1094
|
|
|
|
|
|
|
} |
1095
|
|
|
|
|
|
|
sub addUpdatePolicy { |
1096
|
0
|
|
|
0
|
1
|
0
|
my ($self, $name, $policy) = @_; |
1097
|
0
|
0
|
|
|
|
0
|
Moose->throw_error("A resource named $name must already exist") if (not defined $self->Resources->{ $name }); |
1098
|
0
|
|
|
|
|
0
|
$self->Resources->{ $name }->UpdatePolicy( Moose::Util::TypeConstraints::find_type_constraint('Cfn::Resource:UpdatePolicy')->coerce($policy) ); |
1099
|
|
|
|
|
|
|
} |
1100
|
|
|
|
|
|
|
|
1101
|
|
|
|
|
|
|
sub addTransform { |
1102
|
0
|
|
|
0
|
0
|
0
|
my ($self, $name, $transform) = @_; |
1103
|
0
|
0
|
|
|
|
0
|
if ( not defined $self->Transform) { $self->Transform([]) }; |
|
0
|
|
|
|
|
0
|
|
1104
|
0
|
|
|
|
|
0
|
push @{$self->Transform}, @{$transform}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
1105
|
|
|
|
|
|
|
} |
1106
|
|
|
|
|
|
|
|
1107
|
|
|
|
|
|
|
sub from_hashref { |
1108
|
208
|
|
|
208
|
1
|
79502
|
my ($class, $hashref) = @_; |
1109
|
208
|
|
|
|
|
1688
|
return $class->new(%$hashref); |
1110
|
|
|
|
|
|
|
} |
1111
|
|
|
|
|
|
|
|
1112
|
|
|
|
|
|
|
sub resolve_dynamicvalues { |
1113
|
3
|
|
|
3
|
1
|
8
|
my $self = shift; |
1114
|
3
|
|
|
|
|
14
|
return Cfn->from_hashref($self->as_hashref); |
1115
|
|
|
|
|
|
|
} |
1116
|
|
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
sub as_hashref { |
1118
|
470
|
|
|
470
|
1
|
5568
|
my $self = shift; |
1119
|
|
|
|
|
|
|
return { |
1120
|
|
|
|
|
|
|
(defined $self->AWSTemplateFormatVersion)?(AWSTemplateFormatVersion => $self->AWSTemplateFormatVersion):(), |
1121
|
|
|
|
|
|
|
(defined $self->Description)?(Description => $self->Description):(), |
1122
|
|
|
|
|
|
|
(defined $self->Transform) ? (Transform => $self->Transform) : (), |
1123
|
2
|
|
|
|
|
40
|
(defined $self->Mappings)?(Mappings => { map { ($_ => $self->Mappings->{ $_ }->as_hashref) } keys %{ $self->Mappings } }):(), |
|
1
|
|
|
|
|
20
|
|
1124
|
0
|
|
|
|
|
0
|
(defined $self->Parameters)?(Parameters => { map { ($_ => $self->Parameters->{ $_ }->as_hashref) } keys %{ $self->Parameters } }):(), |
|
0
|
|
|
|
|
0
|
|
1125
|
4
|
|
|
|
|
84
|
(defined $self->Outputs)?(Outputs => { map { ($_ => $self->Outputs->{ $_ }->as_hashref($self)) } keys %{ $self->Outputs } }):(), |
|
2
|
|
|
|
|
42
|
|
1126
|
1
|
|
|
|
|
31
|
(defined $self->Conditions)?(Conditions => { map { ($_ => $self->Condition($_)->as_hashref($self)) } $self->ConditionList }):(), |
1127
|
8
|
|
|
|
|
155
|
(defined $self->Metadata)?(Metadata => { map { ($_ => $self->Metadata->{ $_ }->as_hashref($self)) } $self->MetadataList }):(), |
1128
|
470
|
50
|
|
|
|
13406
|
Resources => { map { ($_ => $self->Resource($_)->as_hashref($self)) } $self->ResourceList }, |
|
467
|
50
|
|
|
|
13617
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
1129
|
|
|
|
|
|
|
} |
1130
|
|
|
|
|
|
|
} |
1131
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
sub path_split { |
1133
|
45770
|
|
|
45770
|
0
|
62708
|
my $path = shift; |
1134
|
45770
|
50
|
|
|
|
78344
|
die "No path specified" if (not defined $path); |
1135
|
45770
|
|
|
|
|
92747
|
my @parts = split/\./, $path, 2; |
1136
|
45770
|
|
|
|
|
107109
|
return ($parts[0], $parts[1]); |
1137
|
|
|
|
|
|
|
} |
1138
|
|
|
|
|
|
|
|
1139
|
|
|
|
|
|
|
sub path_to { |
1140
|
8695
|
|
|
8695
|
1
|
39828
|
my ($self, $path) = @_; |
1141
|
8695
|
|
|
|
|
18205
|
my ($part, $rest) = Cfn::path_split($path); |
1142
|
|
|
|
|
|
|
|
1143
|
8695
|
50
|
100
|
|
|
28165
|
die "Can't path into $part" if ($part ne 'Resources' and |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
1144
|
|
|
|
|
|
|
$part ne 'Mappings' and |
1145
|
|
|
|
|
|
|
$part ne 'Parameters' and |
1146
|
|
|
|
|
|
|
$part ne 'Outputs' and |
1147
|
|
|
|
|
|
|
$part ne 'Conditions' and |
1148
|
|
|
|
|
|
|
$part ne 'Metadata'); |
1149
|
|
|
|
|
|
|
|
1150
|
8695
|
|
|
|
|
182556
|
my $current_element = $self->$part; |
1151
|
8695
|
50
|
|
|
|
17247
|
return $current_element if (not defined $rest); |
1152
|
|
|
|
|
|
|
|
1153
|
8695
|
|
|
|
|
13274
|
($part, $rest) = Cfn::path_split($rest); |
1154
|
|
|
|
|
|
|
|
1155
|
8695
|
50
|
|
|
|
18340
|
die "Must specify a resource to traverse into" if (not defined $part); |
1156
|
|
|
|
|
|
|
|
1157
|
8695
|
50
|
|
|
|
17584
|
die "No element $part found" if (not defined $current_element->{ $part }); |
1158
|
8695
|
100
|
|
|
|
32003
|
return $current_element->{ $part }->path_to($rest) if (defined $rest); |
1159
|
1120
|
|
|
|
|
24539
|
return $current_element->{ $part }; |
1160
|
|
|
|
|
|
|
} |
1161
|
|
|
|
|
|
|
|
1162
|
|
|
|
|
|
|
has json => (is => 'ro', lazy => 1, default => sub { |
1163
|
|
|
|
|
|
|
require JSON; |
1164
|
|
|
|
|
|
|
return JSON->new->canonical |
1165
|
|
|
|
|
|
|
}); |
1166
|
|
|
|
|
|
|
|
1167
|
|
|
|
|
|
|
sub as_json { |
1168
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1169
|
0
|
|
|
|
|
0
|
my $href = $self->as_hashref; |
1170
|
0
|
|
|
|
|
0
|
return $self->json->encode($href); |
1171
|
|
|
|
|
|
|
} |
1172
|
|
|
|
|
|
|
|
1173
|
|
|
|
|
|
|
sub from_json { |
1174
|
188
|
|
|
188
|
1
|
2958881
|
my ($class, $json) = @_; |
1175
|
|
|
|
|
|
|
|
1176
|
188
|
|
|
|
|
1754
|
require JSON; |
1177
|
188
|
|
|
|
|
1165
|
return $class->from_hashref(JSON::from_json($json)); |
1178
|
|
|
|
|
|
|
} |
1179
|
|
|
|
|
|
|
|
1180
|
|
|
|
|
|
|
sub _get_yaml_pp { |
1181
|
13
|
|
|
13
|
|
99
|
require YAML::PP; |
1182
|
13
|
|
|
|
|
95
|
YAML::PP->new( |
1183
|
|
|
|
|
|
|
schema => [ ':Cfn::YAML::Schema' ], |
1184
|
|
|
|
|
|
|
); |
1185
|
|
|
|
|
|
|
} |
1186
|
|
|
|
|
|
|
|
1187
|
|
|
|
|
|
|
has yaml => (is => 'ro', lazy => 1, default => \&_get_yaml_pp); |
1188
|
|
|
|
|
|
|
|
1189
|
|
|
|
|
|
|
sub as_yaml { |
1190
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1191
|
0
|
|
|
|
|
0
|
return $self->yaml->dump_string($self); |
1192
|
|
|
|
|
|
|
} |
1193
|
|
|
|
|
|
|
|
1194
|
|
|
|
|
|
|
sub from_yaml { |
1195
|
12
|
|
|
12
|
1
|
57004
|
my ($class, $yaml) = @_; |
1196
|
12
|
|
|
|
|
47
|
my $parser = _get_yaml_pp; |
1197
|
12
|
|
|
|
|
2468
|
return $class->from_hashref($parser->load_string($yaml)); |
1198
|
|
|
|
|
|
|
} |
1199
|
|
|
|
|
|
|
} |
1200
|
|
|
|
|
|
|
|
1201
|
|
|
|
|
|
|
package Cfn::MutabilityTrait { |
1202
|
22
|
|
|
22
|
|
11175
|
use Moose::Role; |
|
22
|
|
|
|
|
109828
|
|
|
22
|
|
|
|
|
87
|
|
1203
|
22
|
|
|
22
|
|
120371
|
use Moose::Util; |
|
22
|
|
|
|
|
57
|
|
|
22
|
|
|
|
|
105
|
|
1204
|
|
|
|
|
|
|
Moose::Util::meta_attribute_alias('CfnMutability'); |
1205
|
|
|
|
|
|
|
has mutability => (is => 'ro', isa => 'Str', required => 1); |
1206
|
|
|
|
|
|
|
} |
1207
|
|
|
|
|
|
|
|
1208
|
|
|
|
|
|
|
package Cfn::Resource::Properties::Tag { |
1209
|
22
|
|
|
22
|
|
5150
|
use Moose; |
|
22
|
|
|
|
|
48
|
|
|
22
|
|
|
|
|
157
|
|
1210
|
|
|
|
|
|
|
extends 'Cfn::Value::TypedValue'; |
1211
|
|
|
|
|
|
|
has Key => (isa => 'Cfn::Value::String', is => 'rw', coerce => 1, required => 1, traits => [ 'CfnMutability' ], mutability => 'Immutable'); |
1212
|
|
|
|
|
|
|
has Value => (isa => 'Cfn::Value::String', is => 'rw', coerce => 1, traits => [ 'CfnMutability' ], mutability => 'Mutable'); |
1213
|
|
|
|
|
|
|
} |
1214
|
|
|
|
|
|
|
|
1215
|
|
|
|
|
|
|
1; |
1216
|
|
|
|
|
|
|
### main pod documentation begin ### |
1217
|
|
|
|
|
|
|
|
1218
|
|
|
|
|
|
|
=encoding UTF-8 |
1219
|
|
|
|
|
|
|
|
1220
|
|
|
|
|
|
|
=head1 NAME |
1221
|
|
|
|
|
|
|
|
1222
|
|
|
|
|
|
|
Cfn - An object model for CloudFormation documents |
1223
|
|
|
|
|
|
|
|
1224
|
|
|
|
|
|
|
=head1 DESCRIPTION |
1225
|
|
|
|
|
|
|
|
1226
|
|
|
|
|
|
|
This module helps parse, manipulate, validate and generate CloudFormation documents in JSON |
1227
|
|
|
|
|
|
|
and YAML formats (see stability section for more information on YAML). It creates an object |
1228
|
|
|
|
|
|
|
model of a CloudFormation template so you can work with the document as a set of objects. |
1229
|
|
|
|
|
|
|
See L<https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html> for |
1230
|
|
|
|
|
|
|
more information. |
1231
|
|
|
|
|
|
|
|
1232
|
|
|
|
|
|
|
It provides full blown objects for all know CloudFormation resources. See |
1233
|
|
|
|
|
|
|
L<https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html> for a list |
1234
|
|
|
|
|
|
|
of all resource types. These objects live in the C<Cfn::Resource> namespace. |
1235
|
|
|
|
|
|
|
|
1236
|
|
|
|
|
|
|
The module provides a set of objects representing each piece of CloudFormation. Following is a list of all |
1237
|
|
|
|
|
|
|
object types in the distribution: |
1238
|
|
|
|
|
|
|
|
1239
|
|
|
|
|
|
|
=head1 Cfn object |
1240
|
|
|
|
|
|
|
|
1241
|
|
|
|
|
|
|
The C<Cfn> class is the "root" of a CloudFormation document. It represents an entire CloudFormation document. |
1242
|
|
|
|
|
|
|
It has attributes and methods to access the parts of a CloudFormation document. |
1243
|
|
|
|
|
|
|
|
1244
|
|
|
|
|
|
|
use Cfn; |
1245
|
|
|
|
|
|
|
my $cfn = Cfn->new; |
1246
|
|
|
|
|
|
|
$cfn->addResource('MyRes' => ...); |
1247
|
|
|
|
|
|
|
my $res = $cfn->Resource('MyRes'); |
1248
|
|
|
|
|
|
|
|
1249
|
|
|
|
|
|
|
=head2 Constructors |
1250
|
|
|
|
|
|
|
|
1251
|
|
|
|
|
|
|
=head3 new(Resources => { ... }, Outputs => { }, ...) |
1252
|
|
|
|
|
|
|
|
1253
|
|
|
|
|
|
|
The default Moose constructor. You can initialize an empty document like this: |
1254
|
|
|
|
|
|
|
|
1255
|
|
|
|
|
|
|
my $cfn = Cfn->new; |
1256
|
|
|
|
|
|
|
print $cfn->as_json; |
1257
|
|
|
|
|
|
|
|
1258
|
|
|
|
|
|
|
=head3 from_hashref |
1259
|
|
|
|
|
|
|
|
1260
|
|
|
|
|
|
|
CloudFormation documents resemble Perl HashRefs (since they're just JSON datastructures). |
1261
|
|
|
|
|
|
|
This method converts a hashref that represents a CloudFormation document into a Cfn object. |
1262
|
|
|
|
|
|
|
|
1263
|
|
|
|
|
|
|
use Data::Dumper; |
1264
|
|
|
|
|
|
|
my $cfn = Cfn->from_hashref({ Resources => { R1 => { Type => '...', Properties => { ... } } } }); |
1265
|
|
|
|
|
|
|
print Dumper($cfn->Resource('R1'); |
1266
|
|
|
|
|
|
|
|
1267
|
|
|
|
|
|
|
=head3 from_json |
1268
|
|
|
|
|
|
|
|
1269
|
|
|
|
|
|
|
This method creates a Cfn object from a JSON string that contains a CloudFormation document in JSON format |
1270
|
|
|
|
|
|
|
|
1271
|
|
|
|
|
|
|
=head3 from_yaml |
1272
|
|
|
|
|
|
|
|
1273
|
|
|
|
|
|
|
This method creates a Cfn object from a YAML string that contains a CloudFormation document in YAML format |
1274
|
|
|
|
|
|
|
|
1275
|
|
|
|
|
|
|
=head2 Attributes |
1276
|
|
|
|
|
|
|
|
1277
|
|
|
|
|
|
|
=head3 json |
1278
|
|
|
|
|
|
|
|
1279
|
|
|
|
|
|
|
When serializing to JSON with C<as_json>, the encode method on this object is called passing the |
1280
|
|
|
|
|
|
|
documents hashref representation. By default the JSON generated is "ugly", that is, all in one line, |
1281
|
|
|
|
|
|
|
but in canonical form (so a given serialization always has attributes in the same order). |
1282
|
|
|
|
|
|
|
|
1283
|
|
|
|
|
|
|
You can specify your own JSON serializer to control how JSON is generated: |
1284
|
|
|
|
|
|
|
|
1285
|
|
|
|
|
|
|
my $cfn = Cfn->new(json => JSON->new->canonical->pretty); |
1286
|
|
|
|
|
|
|
... |
1287
|
|
|
|
|
|
|
print $cfn->as_json; |
1288
|
|
|
|
|
|
|
|
1289
|
|
|
|
|
|
|
=head3 yaml |
1290
|
|
|
|
|
|
|
|
1291
|
|
|
|
|
|
|
Holds a configured C<YAML::PP> parser for use when serializing and deserializing to and from YAML. |
1292
|
|
|
|
|
|
|
Methods C<load_string> and C<dump_string> are called when needed from convert the object model |
1293
|
|
|
|
|
|
|
to a YAML document, and to convert a YAML document to a datastructure that can later be coerced |
1294
|
|
|
|
|
|
|
into the object model. |
1295
|
|
|
|
|
|
|
|
1296
|
|
|
|
|
|
|
=head3 cfn_options |
1297
|
|
|
|
|
|
|
|
1298
|
|
|
|
|
|
|
A C<Cfn::Internal::Options> object instance that controls how the as_hashref method converts the Cfn object |
1299
|
|
|
|
|
|
|
to a datastructure suitable for CloudFormation (only HashRefs, ArrayRefs and Scalars). |
1300
|
|
|
|
|
|
|
|
1301
|
|
|
|
|
|
|
You can specify your own options as a hashref with the attributes to C<Cfn::Internal::Options> in the |
1302
|
|
|
|
|
|
|
constructor. |
1303
|
|
|
|
|
|
|
|
1304
|
|
|
|
|
|
|
my $cfn = Cfn->new(cfn_options => { custom_resource_rename => 1 }); |
1305
|
|
|
|
|
|
|
... |
1306
|
|
|
|
|
|
|
print Dumper($cfn->as_hashref); |
1307
|
|
|
|
|
|
|
|
1308
|
|
|
|
|
|
|
See the C<Cfn::Internal::Options> object for more details |
1309
|
|
|
|
|
|
|
|
1310
|
|
|
|
|
|
|
=head3 AWSTemplateFormatVersion |
1311
|
|
|
|
|
|
|
|
1312
|
|
|
|
|
|
|
A string with the value of the AWSTemplateFormatVersion field of the CloudFormation document. Can be undef. |
1313
|
|
|
|
|
|
|
|
1314
|
|
|
|
|
|
|
=head3 Description |
1315
|
|
|
|
|
|
|
|
1316
|
|
|
|
|
|
|
A string with the value of the Description field of the CloudFormation document. Can be undef. |
1317
|
|
|
|
|
|
|
|
1318
|
|
|
|
|
|
|
=head3 Transform |
1319
|
|
|
|
|
|
|
|
1320
|
|
|
|
|
|
|
An ArrayRef of Strings with the values of the Transform field of the CloudFormation document. Can be undef. |
1321
|
|
|
|
|
|
|
|
1322
|
|
|
|
|
|
|
=head3 Parameters |
1323
|
|
|
|
|
|
|
|
1324
|
|
|
|
|
|
|
A HashRef of C<Cfn::Parameter> objects. The keys are the name of the Parameters. |
1325
|
|
|
|
|
|
|
There are a set of convenience methods for accessing this attribute: |
1326
|
|
|
|
|
|
|
|
1327
|
|
|
|
|
|
|
$cfn->Parameter('ParamName') # returns a Cfn::Parameter or undef |
1328
|
|
|
|
|
|
|
$cfn->ParameterList # returns a list of the parameters in the document |
1329
|
|
|
|
|
|
|
$cfn->ParameterCount # returns the number of parameters in the document |
1330
|
|
|
|
|
|
|
|
1331
|
|
|
|
|
|
|
=head3 Mappings |
1332
|
|
|
|
|
|
|
|
1333
|
|
|
|
|
|
|
A HashRef of C<Cfn::Mapping> objects. The keys are the name of the Mappings. |
1334
|
|
|
|
|
|
|
There are a set of convenience methods for accessing this attribute: |
1335
|
|
|
|
|
|
|
|
1336
|
|
|
|
|
|
|
$cfn->Mapping('MappingName') # returns a Cfn::Parameter or undef |
1337
|
|
|
|
|
|
|
$cfn->MappingList # returns a list of the mappings in the document |
1338
|
|
|
|
|
|
|
$cfn->MappingCount # returns the number of mappings in the document |
1339
|
|
|
|
|
|
|
|
1340
|
|
|
|
|
|
|
=head3 Conditions |
1341
|
|
|
|
|
|
|
|
1342
|
|
|
|
|
|
|
A HashRef of C<Cfn::Condition> objects. The keys are the name of the Mappings. |
1343
|
|
|
|
|
|
|
There are a set of convenience methods for accessing this attribute: |
1344
|
|
|
|
|
|
|
|
1345
|
|
|
|
|
|
|
$cfn->Mapping('MappingName') # returns a Cfn::Mapping or undef |
1346
|
|
|
|
|
|
|
$cfn->MappingList # returns a list of the mappings in the document |
1347
|
|
|
|
|
|
|
$cfn->MappingCount # returns the number of mappings in the document |
1348
|
|
|
|
|
|
|
|
1349
|
|
|
|
|
|
|
=head3 Resources |
1350
|
|
|
|
|
|
|
|
1351
|
|
|
|
|
|
|
A HashRef of C<Cfn::Resource> objects. The keys are the name of the Resources. |
1352
|
|
|
|
|
|
|
There are a set of convenience methods for accessing this attribute: |
1353
|
|
|
|
|
|
|
|
1354
|
|
|
|
|
|
|
$cfn->Resource('ResourceName') # returns a Cfn::Resource or undef |
1355
|
|
|
|
|
|
|
$cfn->ResourceList # returns a list of the resources in the document |
1356
|
|
|
|
|
|
|
$cfn->ResourceCount # returns the number of resources in the document |
1357
|
|
|
|
|
|
|
|
1358
|
|
|
|
|
|
|
=head3 Outputs |
1359
|
|
|
|
|
|
|
|
1360
|
|
|
|
|
|
|
A HashRef of C<Cfn::Output> objects. The keys are the name of the Outputs. |
1361
|
|
|
|
|
|
|
There are a set of convenience methods for accessing this attribute: |
1362
|
|
|
|
|
|
|
|
1363
|
|
|
|
|
|
|
$cfn->Output('OutputName') # returns a Cfn::Output or undef |
1364
|
|
|
|
|
|
|
$cfn->OutputList # returns a list of the outputs in the document |
1365
|
|
|
|
|
|
|
$cfn->OutputCount # returns the number of outputs in the document |
1366
|
|
|
|
|
|
|
|
1367
|
|
|
|
|
|
|
=head3 Metadata |
1368
|
|
|
|
|
|
|
|
1369
|
|
|
|
|
|
|
A HashRef of C<Cfn::Value> or subclasses of C<Cfn::Value>. Represents the |
1370
|
|
|
|
|
|
|
Metadata key of the CloudFormation document. |
1371
|
|
|
|
|
|
|
|
1372
|
|
|
|
|
|
|
There are a set of convenience methods for accessing this attribute: |
1373
|
|
|
|
|
|
|
|
1374
|
|
|
|
|
|
|
$cfn->Metadata('MetadataName') # returns a Cfn::Metadata or undef |
1375
|
|
|
|
|
|
|
$cfn->MetadataList # returns a list of keys in the document Metadata |
1376
|
|
|
|
|
|
|
$cfn->MetadataCount # returns the number of keys in the document Metadata |
1377
|
|
|
|
|
|
|
|
1378
|
|
|
|
|
|
|
=head2 Methods |
1379
|
|
|
|
|
|
|
|
1380
|
|
|
|
|
|
|
=head3 as_hashref |
1381
|
|
|
|
|
|
|
|
1382
|
|
|
|
|
|
|
Returns a Perl HashRef representation of the CloudFormation document. This HashRef |
1383
|
|
|
|
|
|
|
has no objects in it. It is suitable for converting to JSON and passing to CloudFormation |
1384
|
|
|
|
|
|
|
|
1385
|
|
|
|
|
|
|
C<as_hashref> triggers the serialization process of the document, which scans the whole |
1386
|
|
|
|
|
|
|
object model asking it's components to serialize (calling their C<as_hashref>). Objects |
1387
|
|
|
|
|
|
|
can decide how they serialize to a hashref. |
1388
|
|
|
|
|
|
|
|
1389
|
|
|
|
|
|
|
When C<$cfn->as_hashref> is invoked, all the dynamic values in the Cfn object will be |
1390
|
|
|
|
|
|
|
called with the C<$cfn> instance as the first parameter to their subroutine |
1391
|
|
|
|
|
|
|
|
1392
|
|
|
|
|
|
|
$cfn->addResource('R1', 'AWS::IAM::User', Path => Cfn::DynamicValue->new(Value => sub { |
1393
|
|
|
|
|
|
|
my $cfn = shift; |
1394
|
|
|
|
|
|
|
return $cfn->ResourceCount + 41 |
1395
|
|
|
|
|
|
|
})); |
1396
|
|
|
|
|
|
|
$cfn->as_hashref->{ Resources }->{ R1 }->{ Properties }->{ Path } # == 42 |
1397
|
|
|
|
|
|
|
|
1398
|
|
|
|
|
|
|
=head3 as_json |
1399
|
|
|
|
|
|
|
|
1400
|
|
|
|
|
|
|
Returns a JSON representation of the current instance |
1401
|
|
|
|
|
|
|
|
1402
|
|
|
|
|
|
|
=head3 as_yaml |
1403
|
|
|
|
|
|
|
|
1404
|
|
|
|
|
|
|
Returns a YAML representation of the current instance |
1405
|
|
|
|
|
|
|
|
1406
|
|
|
|
|
|
|
=head3 path_to($path) |
1407
|
|
|
|
|
|
|
|
1408
|
|
|
|
|
|
|
Given a path in the format C<'Resources.R1.Properties.PropName'> it will return the value |
1409
|
|
|
|
|
|
|
stored in PropName of the resource R1. Use C<'Resource.R1.Properties.ArrayProp.0'> to access |
1410
|
|
|
|
|
|
|
Arrays. |
1411
|
|
|
|
|
|
|
|
1412
|
|
|
|
|
|
|
=head3 resolve_dynamicvalues |
1413
|
|
|
|
|
|
|
|
1414
|
|
|
|
|
|
|
Returns a new C<Cfn> object with all C<Cfn::DynamicValues> resolved. |
1415
|
|
|
|
|
|
|
|
1416
|
|
|
|
|
|
|
=head3 ResourcesOfType($type) |
1417
|
|
|
|
|
|
|
|
1418
|
|
|
|
|
|
|
Returns a list of all the Resources of a given type. |
1419
|
|
|
|
|
|
|
|
1420
|
|
|
|
|
|
|
foreach my $iam_user ($cfn->ResourcesOfType('AWS::IAM::User')) { |
1421
|
|
|
|
|
|
|
... |
1422
|
|
|
|
|
|
|
} |
1423
|
|
|
|
|
|
|
|
1424
|
|
|
|
|
|
|
=head3 addParameter($name, $object) |
1425
|
|
|
|
|
|
|
|
1426
|
|
|
|
|
|
|
Adds an already instanced C<Cfn::Parameter> object. Throws an exception if the parameter already exists. |
1427
|
|
|
|
|
|
|
|
1428
|
|
|
|
|
|
|
$cfn->addParameter('P1', Cfn::Parameter->new(Type => 'String', MaxLength => 5)); |
1429
|
|
|
|
|
|
|
|
1430
|
|
|
|
|
|
|
=head3 addParameter($name, $type, %properties) |
1431
|
|
|
|
|
|
|
|
1432
|
|
|
|
|
|
|
Adds a named parameter to the document with the specified type and properties. See C<Cfn::Parameter> for available |
1433
|
|
|
|
|
|
|
properties. Throws an exception if the parameter already exists. |
1434
|
|
|
|
|
|
|
|
1435
|
|
|
|
|
|
|
$cfn->addParameter('P1', 'String', MaxLength => 5); |
1436
|
|
|
|
|
|
|
|
1437
|
|
|
|
|
|
|
=head3 addMapping($name, $object_or_hashref); |
1438
|
|
|
|
|
|
|
|
1439
|
|
|
|
|
|
|
Adds a named mapping to the mappings of the document. The second parameter can be a C<Cfn::Mapping> object or |
1440
|
|
|
|
|
|
|
a HashRef that will be coerced to a C<Cfn::Mapping> object |
1441
|
|
|
|
|
|
|
|
1442
|
|
|
|
|
|
|
$cfn->addMapping('amis', { 'eu-west-1' => 'ami-12345678' }); |
1443
|
|
|
|
|
|
|
$cfn->addMapping('amis', Cfn::Mapping->new(Map => { 'eu-west-1' => 'ami-12345678' })); |
1444
|
|
|
|
|
|
|
# $cfn->Mapping('amis') is a Cfn::Mapping object |
1445
|
|
|
|
|
|
|
|
1446
|
|
|
|
|
|
|
=head3 addOutput($name, $object) |
1447
|
|
|
|
|
|
|
|
1448
|
|
|
|
|
|
|
Adds an already instanced C<Cfn::Output> object. Throws an exception if the output already exists. |
1449
|
|
|
|
|
|
|
|
1450
|
|
|
|
|
|
|
$cfn->addParameter('O1', Cfn::Output->new(Value => { Ref => 'R1' }); |
1451
|
|
|
|
|
|
|
|
1452
|
|
|
|
|
|
|
=head3 addOutput($name, $output[, %output_attributes]); |
1453
|
|
|
|
|
|
|
|
1454
|
|
|
|
|
|
|
Adds a named output to the document. See C<Cfn::Output> for available |
1455
|
|
|
|
|
|
|
output_attributes. Throws an exception if the output already exists. |
1456
|
|
|
|
|
|
|
|
1457
|
|
|
|
|
|
|
$cfn->addParameter('O1', { Ref => 'R1' }); |
1458
|
|
|
|
|
|
|
$cfn->addParameter('O1', { Ref => 'R1' }, Description => 'Bla bla'); |
1459
|
|
|
|
|
|
|
|
1460
|
|
|
|
|
|
|
|
1461
|
|
|
|
|
|
|
=head3 addCondition($name, $value) |
1462
|
|
|
|
|
|
|
|
1463
|
|
|
|
|
|
|
Adds a named condition to the document. The value parameter should be |
1464
|
|
|
|
|
|
|
a HashRef that expresses a CloudFormation condition. See L<https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html> |
1465
|
|
|
|
|
|
|
|
1466
|
|
|
|
|
|
|
=head3 addResource($name, $object) |
1467
|
|
|
|
|
|
|
|
1468
|
|
|
|
|
|
|
Adds a named resource to the document. $object has to be an instance of a |
1469
|
|
|
|
|
|
|
subclass of C<Cfn::Resource>. Throws an exception if a resource already |
1470
|
|
|
|
|
|
|
exists with that name. |
1471
|
|
|
|
|
|
|
|
1472
|
|
|
|
|
|
|
=head3 addResource($name, $type, %properties) |
1473
|
|
|
|
|
|
|
|
1474
|
|
|
|
|
|
|
Adds a named resource to the document, putting the specified properties in the |
1475
|
|
|
|
|
|
|
resources properties. See subclasses of C<Cfn::Resource> for more details. |
1476
|
|
|
|
|
|
|
|
1477
|
|
|
|
|
|
|
$cfn->addResource('R1', 'AWS::IAM::User'); |
1478
|
|
|
|
|
|
|
|
1479
|
|
|
|
|
|
|
$cfn->addResource('R2', 'AWS::IAM::User', Path => '/'); |
1480
|
|
|
|
|
|
|
# $cfn->Resource('R2')->Properties->Path is '/' |
1481
|
|
|
|
|
|
|
|
1482
|
|
|
|
|
|
|
Throws an exception if a resource already exists with that name. |
1483
|
|
|
|
|
|
|
|
1484
|
|
|
|
|
|
|
=head3 addResource($name, $name, $properties, $resource_attributes) |
1485
|
|
|
|
|
|
|
|
1486
|
|
|
|
|
|
|
Adds a named resource to the document. properties and resource_attributes |
1487
|
|
|
|
|
|
|
are hashrefs. |
1488
|
|
|
|
|
|
|
|
1489
|
|
|
|
|
|
|
$cfn->addResource('R3', 'AWS::IAM::User', { Path => '/' }); |
1490
|
|
|
|
|
|
|
# $cfn->Resource('R3')->Properties->Path is '/' |
1491
|
|
|
|
|
|
|
$cfn->addResource('R3', 'AWS::IAM::User', { Path => '/' }, { DependsOn => [ 'R2' ] }); |
1492
|
|
|
|
|
|
|
# $cfn->Resource('R3')->DependsOn->[0] is 'R2' |
1493
|
|
|
|
|
|
|
|
1494
|
|
|
|
|
|
|
Throws an exception if a resource already exists with that name. |
1495
|
|
|
|
|
|
|
|
1496
|
|
|
|
|
|
|
=head3 addResourceMetadata($name, %metadata); |
1497
|
|
|
|
|
|
|
|
1498
|
|
|
|
|
|
|
Adds metadata to the Metadata attribute of a Resource. |
1499
|
|
|
|
|
|
|
|
1500
|
|
|
|
|
|
|
$cfn->addResourceMetadata('R1', MyMetadataKey1 => 'Value'); |
1501
|
|
|
|
|
|
|
# $cfn->Resource('R1')->Metadata->{ MyMedataKey1 } is 'Value' |
1502
|
|
|
|
|
|
|
|
1503
|
|
|
|
|
|
|
=head3 addDependsOn($resource_name, $depends_on1, $depends_on2) |
1504
|
|
|
|
|
|
|
|
1505
|
|
|
|
|
|
|
$cfn->addDependsOn('R1', 'R2', 'R3'); |
1506
|
|
|
|
|
|
|
# $cfn->Resource('R1')->DependsOn is [ 'R2', 'R3' ] |
1507
|
|
|
|
|
|
|
|
1508
|
|
|
|
|
|
|
=head3 addDeletionPolicy($resource_name) |
1509
|
|
|
|
|
|
|
|
1510
|
|
|
|
|
|
|
Adds a DeletionPolicy to the resource. L<https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html> |
1511
|
|
|
|
|
|
|
|
1512
|
|
|
|
|
|
|
=head3 addUpdatePolicy($resource_name) |
1513
|
|
|
|
|
|
|
|
1514
|
|
|
|
|
|
|
Adds an UpdatePolicy to the resource. L<https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatepolicy.html> |
1515
|
|
|
|
|
|
|
|
1516
|
|
|
|
|
|
|
=head1 Cfn::Value |
1517
|
|
|
|
|
|
|
|
1518
|
|
|
|
|
|
|
Is a base class for the attributes of Cloudformation values. In Cloudformation you can find that in |
1519
|
|
|
|
|
|
|
a resources attributes you can place functions, references, etc. |
1520
|
|
|
|
|
|
|
|
1521
|
|
|
|
|
|
|
"Attribute": "hello" |
1522
|
|
|
|
|
|
|
"Attribute": { "Ref": "R1" } |
1523
|
|
|
|
|
|
|
"Attribute": { "Fn::GetAtt": [ "R1", "InstanceId" ] } |
1524
|
|
|
|
|
|
|
|
1525
|
|
|
|
|
|
|
All value objects in the Cfn toolkit subclass C<Cfn::Value> as a common ancestor. Once the object model is built, |
1526
|
|
|
|
|
|
|
you can find that a |
1527
|
|
|
|
|
|
|
|
1528
|
|
|
|
|
|
|
$cfn->addResource('R1', 'AWS::IAM::User', Path => '/'); |
1529
|
|
|
|
|
|
|
# $cfn->Resource('R1')->Properties->Path is a Cfn::Value::Primitive |
1530
|
|
|
|
|
|
|
|
1531
|
|
|
|
|
|
|
$cfn->addResource('R1', 'AWS::IAM::User', Path => { 'Fn::Join' => [ '/', { Ref => 'Param1' }, '/' ] }); |
1532
|
|
|
|
|
|
|
# $cfn->Resource('R1')->Properties->Path is a Cfn::Value::Function::Join |
1533
|
|
|
|
|
|
|
|
1534
|
|
|
|
|
|
|
All C<Cfn::Value> subclasses have to implement an C<as_hashref> method that returns a HashRef suitable for |
1535
|
|
|
|
|
|
|
conversion to JSON for CloudFormation. A attributes of objects that hold C<Cfn::Value> subclasses should |
1536
|
|
|
|
|
|
|
enable coercion of the attribute so that plain hashrefs can be coerced into the appropiate Cfn::Value objects |
1537
|
|
|
|
|
|
|
|
1538
|
|
|
|
|
|
|
Here is a Hierarchy of the different Cfn::Value descendant object: |
1539
|
|
|
|
|
|
|
|
1540
|
|
|
|
|
|
|
Cfn::Value |
1541
|
|
|
|
|
|
|
|--Cfn::DynamicValue |
1542
|
|
|
|
|
|
|
|--Cfn::Value::Function |
1543
|
|
|
|
|
|
|
| |--Cfn::Value::Function::Condition |
1544
|
|
|
|
|
|
|
| |--Cfn::Value::Function::Ref |
1545
|
|
|
|
|
|
|
| |--Cfn::Value::Function::PseudoParameter |
1546
|
|
|
|
|
|
|
| |--Cfn::Value::Function::GetAtt |
1547
|
|
|
|
|
|
|
|--Cfn::Value::Array |
1548
|
|
|
|
|
|
|
|--Cfn::Value::Hash |
1549
|
|
|
|
|
|
|
|--Cfn::Value::Primitive |
1550
|
|
|
|
|
|
|
| |--Cfn::Boolean |
1551
|
|
|
|
|
|
|
| |--Cfn::Integer |
1552
|
|
|
|
|
|
|
| |--Cfn::Long |
1553
|
|
|
|
|
|
|
| |--Cfn::String |
1554
|
|
|
|
|
|
|
| |--Cfn::Double |
1555
|
|
|
|
|
|
|
| |--Cfn::Timestamp |
1556
|
|
|
|
|
|
|
|--Cfn::Value::TypedValue |
1557
|
|
|
|
|
|
|
|
1558
|
|
|
|
|
|
|
|
1559
|
|
|
|
|
|
|
=head2 Cfn::DynamicValue |
1560
|
|
|
|
|
|
|
|
1561
|
|
|
|
|
|
|
The C<Value> attribute of this object is a CodeRef that get's called |
1562
|
|
|
|
|
|
|
when as_hashref is called. |
1563
|
|
|
|
|
|
|
|
1564
|
|
|
|
|
|
|
$cfn->addResource('R1', 'AWS::IAM::User', Path => Cfn::DynamicValue->new(Value => sub { return 'Hello' }); |
1565
|
|
|
|
|
|
|
$cfn->path_to('Resources.R1.Properties.Path') # isa Cfn::DynamicValue |
1566
|
|
|
|
|
|
|
$cfn->path_to('Resources.R1.Properties.Path')->as_hashref # eq 'Hello' |
1567
|
|
|
|
|
|
|
|
1568
|
|
|
|
|
|
|
When C<$cfn->as_hashref> is invoked, all the dynamic values in the Cfn object will be |
1569
|
|
|
|
|
|
|
called with the C<$cfn> instance as the first parameter to their subroutine |
1570
|
|
|
|
|
|
|
|
1571
|
|
|
|
|
|
|
$cfn->addResource('R1', 'AWS::IAM::User', Path => Cfn::DynamicValue->new(Value => sub { |
1572
|
|
|
|
|
|
|
my $cfn = shift; |
1573
|
|
|
|
|
|
|
return $cfn->ResourceCount + 41 |
1574
|
|
|
|
|
|
|
})); |
1575
|
|
|
|
|
|
|
$cfn->as_hashref->{ Resources }->{ R1 }->{ Properties }->{ Path } # == 42 |
1576
|
|
|
|
|
|
|
|
1577
|
|
|
|
|
|
|
=head2 Cfn::Value::Function |
1578
|
|
|
|
|
|
|
|
1579
|
|
|
|
|
|
|
All function statements derive from Cfn::Value::Function. |
1580
|
|
|
|
|
|
|
The name of the function can be found in the C<Function> attribute |
1581
|
|
|
|
|
|
|
It's value can be found in the C<Value> attribute |
1582
|
|
|
|
|
|
|
|
1583
|
|
|
|
|
|
|
=head2 Cfn::Value::Function::Ref |
1584
|
|
|
|
|
|
|
|
1585
|
|
|
|
|
|
|
Object of this class represent a CloudFormation Ref. You can find the value |
1586
|
|
|
|
|
|
|
of the reference in the C<Value> attribute. Note that the Value attribute contains |
1587
|
|
|
|
|
|
|
another C<Cfn::Value>. It derives from C<Cfn::Value::Function> |
1588
|
|
|
|
|
|
|
|
1589
|
|
|
|
|
|
|
$cfn->addResource('R1', 'AWS::IAM::User', Path => { Ref => 'AWS::Region' }); |
1590
|
|
|
|
|
|
|
$cfn->path_to('Resources.R1.Properties.Path') # isa Cfn::Value::Function::PseudoParameter |
1591
|
|
|
|
|
|
|
|
1592
|
|
|
|
|
|
|
=head2 Cfn::Value::Function::PseudoParameter |
1593
|
|
|
|
|
|
|
|
1594
|
|
|
|
|
|
|
This is a subclass of C<Cfn::Value::Function::Ref> used to hold what CloudFormation |
1595
|
|
|
|
|
|
|
calls PseudoParameters. |
1596
|
|
|
|
|
|
|
|
1597
|
|
|
|
|
|
|
$cfn->addResource('R1', 'AWS::IAM::User', Path => { Ref => 'AWS::Region' }); |
1598
|
|
|
|
|
|
|
$cfn->path_to('Resources.R1.Properties.Path') # isa Cfn::Value::Function::PseudoParam |
1599
|
|
|
|
|
|
|
|
1600
|
|
|
|
|
|
|
=head2 Cfn::Value::Function::GetAtt |
1601
|
|
|
|
|
|
|
|
1602
|
|
|
|
|
|
|
This class represents 'Fn::GetAtt' nodes in the object model. It's a subclass of C<Cfn::Value::Function>. |
1603
|
|
|
|
|
|
|
|
1604
|
|
|
|
|
|
|
$cfn->addResource('R1', 'AWS::IAM::User', Path => { 'Fn::GetAtt' => [ 'R1', 'InstanceId' ] }); |
1605
|
|
|
|
|
|
|
$cfn->path_to('Resources.R1.Properties.Path') # isa Cfn::Value::Function::GetAtt |
1606
|
|
|
|
|
|
|
$cfn->path_to('Resources.R1.Properties.Path')->LogicalId # eq 'R1' |
1607
|
|
|
|
|
|
|
$cfn->path_to('Resources.R1.Properties.Path')->Property # eq 'InstanceId' |
1608
|
|
|
|
|
|
|
|
1609
|
|
|
|
|
|
|
=head2 Cfn::Value::Array |
1610
|
|
|
|
|
|
|
|
1611
|
|
|
|
|
|
|
This class represents Arrays in the object model. It's C<Value> property is an ArrayRef |
1612
|
|
|
|
|
|
|
of C<Cfn::Values> or C<Cfn::Resource::Properties>. |
1613
|
|
|
|
|
|
|
|
1614
|
|
|
|
|
|
|
There is also a subtype called C<Cfn::Value::ArrayOfPrimitives> that restricts the values |
1615
|
|
|
|
|
|
|
in the array to C<Cfn::Value::Primitive> types. |
1616
|
|
|
|
|
|
|
|
1617
|
|
|
|
|
|
|
=head2 Cfn::Value::Hash |
1618
|
|
|
|
|
|
|
|
1619
|
|
|
|
|
|
|
This class represents JSON objects whose keys are not defined beforehand (arbitrary keys). |
1620
|
|
|
|
|
|
|
It's C<Value> property is a HashRef of C<Cfn::Value>s. |
1621
|
|
|
|
|
|
|
|
1622
|
|
|
|
|
|
|
=head2 Cfn::Value::Primitive |
1623
|
|
|
|
|
|
|
|
1624
|
|
|
|
|
|
|
This is a base class for any "simple" value (what the CloudFormation spec calls C<PrimitiveType>). |
1625
|
|
|
|
|
|
|
This classes C<Value> attribute has no type constraint, so it actually accepts anything. This class |
1626
|
|
|
|
|
|
|
is supposed to only be inherited from, specializing the C<Value> attribute to a specific type. |
1627
|
|
|
|
|
|
|
|
1628
|
|
|
|
|
|
|
=head2 Cfn::Boolean |
1629
|
|
|
|
|
|
|
|
1630
|
|
|
|
|
|
|
Used to store and validate CloudFormation C<Boolean> values. Has a C<stringy> attribute that controls if C<as_hashref> |
1631
|
|
|
|
|
|
|
returns a string boolean C<"true"> or C<"false"> or a literal C<true> or C<false>, since these two |
1632
|
|
|
|
|
|
|
boolean forms are accepted in CloudFormation. |
1633
|
|
|
|
|
|
|
|
1634
|
|
|
|
|
|
|
|
1635
|
|
|
|
|
|
|
=head2 Cfn::Integer |
1636
|
|
|
|
|
|
|
|
1637
|
|
|
|
|
|
|
Used to store and validate CloudFormation C<Integer> values. |
1638
|
|
|
|
|
|
|
|
1639
|
|
|
|
|
|
|
=head2 Cfn::Long |
1640
|
|
|
|
|
|
|
|
1641
|
|
|
|
|
|
|
Used to store and validate CloudFormation C<Long> values. |
1642
|
|
|
|
|
|
|
|
1643
|
|
|
|
|
|
|
=head2 Cfn::String |
1644
|
|
|
|
|
|
|
|
1645
|
|
|
|
|
|
|
Used to store and validate CloudFormation C<String> values. |
1646
|
|
|
|
|
|
|
|
1647
|
|
|
|
|
|
|
=head2 Cfn::Double |
1648
|
|
|
|
|
|
|
|
1649
|
|
|
|
|
|
|
Used to store and validate CloudFormation C<Double> values. |
1650
|
|
|
|
|
|
|
|
1651
|
|
|
|
|
|
|
=head2 Cfn::Timestamp |
1652
|
|
|
|
|
|
|
|
1653
|
|
|
|
|
|
|
Used to store CloudFormation C<Timestamp> values. Only validates that it's a string. |
1654
|
|
|
|
|
|
|
|
1655
|
|
|
|
|
|
|
=head2 Cfn::Value::TypedValue |
1656
|
|
|
|
|
|
|
|
1657
|
|
|
|
|
|
|
Used as a base class for structured properties of CloudFormation resources. The subclasses |
1658
|
|
|
|
|
|
|
of TypedValue declare Moose attributes that are used to represent and validate that the |
1659
|
|
|
|
|
|
|
properties of a CloudFormation resource are well formed. |
1660
|
|
|
|
|
|
|
|
1661
|
|
|
|
|
|
|
=head1 Cfn::Resource |
1662
|
|
|
|
|
|
|
|
1663
|
|
|
|
|
|
|
Represents a CloudFormation Resource. All C<Cfn::Resource::*> objects (like L<Cfn::Resource::AWS::IAM::User>) |
1664
|
|
|
|
|
|
|
use C<Cfn::Resource> as a base class. |
1665
|
|
|
|
|
|
|
|
1666
|
|
|
|
|
|
|
=head2 Attributes for Cfn::Resource objects |
1667
|
|
|
|
|
|
|
|
1668
|
|
|
|
|
|
|
The attributes for Cfn::Resource objects map to the attributes of CloudFormation Resources. |
1669
|
|
|
|
|
|
|
|
1670
|
|
|
|
|
|
|
{ |
1671
|
|
|
|
|
|
|
"Type": "AWS::IAM::User", |
1672
|
|
|
|
|
|
|
"Properties": { ... }, |
1673
|
|
|
|
|
|
|
"DependsOn": "R2" |
1674
|
|
|
|
|
|
|
... |
1675
|
|
|
|
|
|
|
} |
1676
|
|
|
|
|
|
|
|
1677
|
|
|
|
|
|
|
=head3 Type |
1678
|
|
|
|
|
|
|
|
1679
|
|
|
|
|
|
|
Holds a string with the type of the resource. |
1680
|
|
|
|
|
|
|
|
1681
|
|
|
|
|
|
|
=head3 Properties |
1682
|
|
|
|
|
|
|
|
1683
|
|
|
|
|
|
|
Holds a C<Cfn::Value::Properties> subclass with the properties of the resource. |
1684
|
|
|
|
|
|
|
|
1685
|
|
|
|
|
|
|
=head3 DeletionPolicy |
1686
|
|
|
|
|
|
|
|
1687
|
|
|
|
|
|
|
Holds the DeletionPolicy. Validates that the DeletionPolicy is valid |
1688
|
|
|
|
|
|
|
|
1689
|
|
|
|
|
|
|
=head3 DependsOn |
1690
|
|
|
|
|
|
|
|
1691
|
|
|
|
|
|
|
Can hold either a single string or an arrayref of strings. This is because CloudFormation |
1692
|
|
|
|
|
|
|
supports C<DependsOn> in these two forms. Method C<DependsOnList> provides a uniform way |
1693
|
|
|
|
|
|
|
of accessing the DependsOn attribute. |
1694
|
|
|
|
|
|
|
|
1695
|
|
|
|
|
|
|
=head3 Condition |
1696
|
|
|
|
|
|
|
|
1697
|
|
|
|
|
|
|
Can hold a String identifying the Condition property of a resource |
1698
|
|
|
|
|
|
|
|
1699
|
|
|
|
|
|
|
=head3 Metadata |
1700
|
|
|
|
|
|
|
|
1701
|
|
|
|
|
|
|
Is a C<Cfn::Value::Hash> for the resources metadata |
1702
|
|
|
|
|
|
|
|
1703
|
|
|
|
|
|
|
=head3 UpdatePolicy |
1704
|
|
|
|
|
|
|
|
1705
|
|
|
|
|
|
|
Holds the UpdatePolicy. Validates that the UpdatePolicy is valid |
1706
|
|
|
|
|
|
|
|
1707
|
|
|
|
|
|
|
=head3 CreationPolicy |
1708
|
|
|
|
|
|
|
|
1709
|
|
|
|
|
|
|
HashRef with the CreationPolicy. Doesn't validate CreationPolicies. |
1710
|
|
|
|
|
|
|
|
1711
|
|
|
|
|
|
|
=head2 Methods for Cfn::Resource objects |
1712
|
|
|
|
|
|
|
|
1713
|
|
|
|
|
|
|
=head3 AttributeList |
1714
|
|
|
|
|
|
|
|
1715
|
|
|
|
|
|
|
Returns an ArrayRef of attributes that can be recalled in CloudFormation via C<Fn::GetAtt>. |
1716
|
|
|
|
|
|
|
|
1717
|
|
|
|
|
|
|
Can also be retrieved as a class method C<Cfn::Resource::...->AttributeList> |
1718
|
|
|
|
|
|
|
|
1719
|
|
|
|
|
|
|
=head3 supported_regions |
1720
|
|
|
|
|
|
|
|
1721
|
|
|
|
|
|
|
Returns an ArrayRef of the AWS regions where the resource can be provisioned. |
1722
|
|
|
|
|
|
|
|
1723
|
|
|
|
|
|
|
Can also be retrieved as a class method C<Cfn::Resource::...->supported_regions> |
1724
|
|
|
|
|
|
|
|
1725
|
|
|
|
|
|
|
=head3 DependsOnList |
1726
|
|
|
|
|
|
|
|
1727
|
|
|
|
|
|
|
Returns a list of dependencies from the DependsOn attribute (it doesn't matter |
1728
|
|
|
|
|
|
|
if the DependsOn attribute is a String or an ArrayRef of Strings. |
1729
|
|
|
|
|
|
|
|
1730
|
|
|
|
|
|
|
my @deps = $cfn->Resource('R1')->DependsOnList; |
1731
|
|
|
|
|
|
|
|
1732
|
|
|
|
|
|
|
=head3 hasAttribute($attribute) |
1733
|
|
|
|
|
|
|
|
1734
|
|
|
|
|
|
|
Returns true if the specified attribute is in the C<AttributeList>. Note that some resources |
1735
|
|
|
|
|
|
|
(AWS::CloudFormation::CustomResource) can return true for values that are not in AttributeList |
1736
|
|
|
|
|
|
|
|
1737
|
|
|
|
|
|
|
=head3 as_hashref |
1738
|
|
|
|
|
|
|
|
1739
|
|
|
|
|
|
|
Like C<Cfn::Values>, as_hashref returns a HashRef representation of the object ready |
1740
|
|
|
|
|
|
|
for transforming to JSON. |
1741
|
|
|
|
|
|
|
|
1742
|
|
|
|
|
|
|
=head1 Cfn::Resource::Properties |
1743
|
|
|
|
|
|
|
|
1744
|
|
|
|
|
|
|
A base class for the objects that the C<Properties> attribute of C<Cfn::Resource>s hold. |
1745
|
|
|
|
|
|
|
Subclasses of C<Cfn::Resource::Properties> are used to validate and represent the properties |
1746
|
|
|
|
|
|
|
of resources inside the object model. See L<Cfn::Resource::Properties::AWS::IAM::User> for |
1747
|
|
|
|
|
|
|
an example. |
1748
|
|
|
|
|
|
|
|
1749
|
|
|
|
|
|
|
Each subclass of C<Cfn::Resource::Properties> has to have attributes to hold the values of |
1750
|
|
|
|
|
|
|
the properties of the resource it represents. |
1751
|
|
|
|
|
|
|
|
1752
|
|
|
|
|
|
|
=head1 Cfn::Parameter |
1753
|
|
|
|
|
|
|
|
1754
|
|
|
|
|
|
|
Represents a Parameter in a CloudFormation document |
1755
|
|
|
|
|
|
|
|
1756
|
|
|
|
|
|
|
my $cfn = Cfn->new; |
1757
|
|
|
|
|
|
|
$cfn->addParameter('P1', 'String', Default => 5); |
1758
|
|
|
|
|
|
|
$cfn->Parameter('P1')->Default # 5 |
1759
|
|
|
|
|
|
|
$cfn->Parameter('P1')->NoEcho # undef |
1760
|
|
|
|
|
|
|
|
1761
|
|
|
|
|
|
|
=head2 Cfn::Parameter Attributes |
1762
|
|
|
|
|
|
|
|
1763
|
|
|
|
|
|
|
=head3 Type |
1764
|
|
|
|
|
|
|
|
1765
|
|
|
|
|
|
|
A string with the type of parameter. Validates that it's a CloudFormation supported parameter type. |
1766
|
|
|
|
|
|
|
|
1767
|
|
|
|
|
|
|
=head3 Default |
1768
|
|
|
|
|
|
|
|
1769
|
|
|
|
|
|
|
Holds the default value for the parameter |
1770
|
|
|
|
|
|
|
|
1771
|
|
|
|
|
|
|
=head3 NoEcho |
1772
|
|
|
|
|
|
|
|
1773
|
|
|
|
|
|
|
Holds the NoEcho property of the parameter |
1774
|
|
|
|
|
|
|
|
1775
|
|
|
|
|
|
|
=head3 AllowedValues |
1776
|
|
|
|
|
|
|
|
1777
|
|
|
|
|
|
|
An ArrayRef of the allowed values of the parameter |
1778
|
|
|
|
|
|
|
|
1779
|
|
|
|
|
|
|
=head3 AllowedPattern |
1780
|
|
|
|
|
|
|
|
1781
|
|
|
|
|
|
|
A String holding the pattern that the value of this parameter can take |
1782
|
|
|
|
|
|
|
|
1783
|
|
|
|
|
|
|
=head3 MaxLength, MinLength, MaxValue, MinValue |
1784
|
|
|
|
|
|
|
|
1785
|
|
|
|
|
|
|
Values holding the MaxLength, MinLength, MaxValue, MinValue of the parameter |
1786
|
|
|
|
|
|
|
|
1787
|
|
|
|
|
|
|
=head3 Description |
1788
|
|
|
|
|
|
|
|
1789
|
|
|
|
|
|
|
A string description of the parameter |
1790
|
|
|
|
|
|
|
|
1791
|
|
|
|
|
|
|
=head3 ConstraintDescription |
1792
|
|
|
|
|
|
|
|
1793
|
|
|
|
|
|
|
A string description of the constraint of the parameter |
1794
|
|
|
|
|
|
|
|
1795
|
|
|
|
|
|
|
=head1 Cfn::Mapping |
1796
|
|
|
|
|
|
|
|
1797
|
|
|
|
|
|
|
This object represents the value of the C<Mappings> key in a CloudFormation |
1798
|
|
|
|
|
|
|
document. It has a C<Map> attribute to hold the Mappings in the CloudFormation |
1799
|
|
|
|
|
|
|
document. |
1800
|
|
|
|
|
|
|
|
1801
|
|
|
|
|
|
|
=head1 Cfn::Output |
1802
|
|
|
|
|
|
|
|
1803
|
|
|
|
|
|
|
Represents an output object in a CloudFormation document |
1804
|
|
|
|
|
|
|
|
1805
|
|
|
|
|
|
|
=head2 Attributes for Cfn::Output objects |
1806
|
|
|
|
|
|
|
|
1807
|
|
|
|
|
|
|
"Outputs": { |
1808
|
|
|
|
|
|
|
"Output1": { |
1809
|
|
|
|
|
|
|
"Value": { "Ref": "Instance" } |
1810
|
|
|
|
|
|
|
} |
1811
|
|
|
|
|
|
|
} |
1812
|
|
|
|
|
|
|
|
1813
|
|
|
|
|
|
|
=head3 Value |
1814
|
|
|
|
|
|
|
|
1815
|
|
|
|
|
|
|
Holds the Value key of an output. Is a C<Cfn::Value> |
1816
|
|
|
|
|
|
|
|
1817
|
|
|
|
|
|
|
=head3 Description |
1818
|
|
|
|
|
|
|
|
1819
|
|
|
|
|
|
|
Holds a String with the descrption of the output |
1820
|
|
|
|
|
|
|
|
1821
|
|
|
|
|
|
|
=head3 Condition |
1822
|
|
|
|
|
|
|
|
1823
|
|
|
|
|
|
|
Holds a String with the condition of the output |
1824
|
|
|
|
|
|
|
|
1825
|
|
|
|
|
|
|
=head3 Export |
1826
|
|
|
|
|
|
|
|
1827
|
|
|
|
|
|
|
Holds a HashRef with the export definition of the object |
1828
|
|
|
|
|
|
|
|
1829
|
|
|
|
|
|
|
=head2 Methods for Cfn::Output objects |
1830
|
|
|
|
|
|
|
|
1831
|
|
|
|
|
|
|
=head3 as_hashref |
1832
|
|
|
|
|
|
|
|
1833
|
|
|
|
|
|
|
Returns a HashRef representation of the output that is convertible to JSON |
1834
|
|
|
|
|
|
|
|
1835
|
|
|
|
|
|
|
=head1 STABILITY |
1836
|
|
|
|
|
|
|
|
1837
|
|
|
|
|
|
|
YAML support is recent, and due to the still evolving YAML::PP module, may break |
1838
|
|
|
|
|
|
|
(altough the tests are there to detect that). This distribution will try to keep up |
1839
|
|
|
|
|
|
|
as hard as it can with latest YAML::PP developments. |
1840
|
|
|
|
|
|
|
|
1841
|
|
|
|
|
|
|
=head1 SEE ALSO |
1842
|
|
|
|
|
|
|
|
1843
|
|
|
|
|
|
|
L<https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html> |
1844
|
|
|
|
|
|
|
|
1845
|
|
|
|
|
|
|
This module kind of resembles troposphere (python): L<https://github.com/cloudtools/troposphere>. |
1846
|
|
|
|
|
|
|
|
1847
|
|
|
|
|
|
|
=head1 CLI utils |
1848
|
|
|
|
|
|
|
|
1849
|
|
|
|
|
|
|
This distribution includes a series of CLI utilities to help you with CloudFormation: |
1850
|
|
|
|
|
|
|
|
1851
|
|
|
|
|
|
|
=head2 cfn_list_resources [STRING] |
1852
|
|
|
|
|
|
|
|
1853
|
|
|
|
|
|
|
Lists all the resources supported by Cfn. If a string is specified, will filter the ones matching |
1854
|
|
|
|
|
|
|
the STRING. |
1855
|
|
|
|
|
|
|
|
1856
|
|
|
|
|
|
|
=head2 cfn_region_matrix |
1857
|
|
|
|
|
|
|
|
1858
|
|
|
|
|
|
|
Displays a table of what resource types are supported in each region |
1859
|
|
|
|
|
|
|
|
1860
|
|
|
|
|
|
|
=head2 cfn_region_compatibility FILE |
1861
|
|
|
|
|
|
|
|
1862
|
|
|
|
|
|
|
Takes a cloudformation template and calculates in what regions it will be deployable |
1863
|
|
|
|
|
|
|
|
1864
|
|
|
|
|
|
|
=head2 cfn_resource_properties RESOURCE |
1865
|
|
|
|
|
|
|
|
1866
|
|
|
|
|
|
|
Outputs information about a resource type: properties accessible via Fn::GetAtt, region availability |
1867
|
|
|
|
|
|
|
and it's whole property structure. |
1868
|
|
|
|
|
|
|
|
1869
|
|
|
|
|
|
|
=head1 AUTHOR |
1870
|
|
|
|
|
|
|
|
1871
|
|
|
|
|
|
|
Jose Luis Martinez |
1872
|
|
|
|
|
|
|
CAPSiDE |
1873
|
|
|
|
|
|
|
jlmartinez@capside.com |
1874
|
|
|
|
|
|
|
|
1875
|
|
|
|
|
|
|
=head1 Contributions |
1876
|
|
|
|
|
|
|
|
1877
|
|
|
|
|
|
|
Thanks to Sergi Pruneda, Miquel Ruiz, Luis Alberto Gimenez, Eleatzar Colomer, Oriol Soriano, |
1878
|
|
|
|
|
|
|
Roi Vazquez for years of work on this module. |
1879
|
|
|
|
|
|
|
|
1880
|
|
|
|
|
|
|
TINITA for helping make the YAML support possible. First for the YAML::PP module, which is the only |
1881
|
|
|
|
|
|
|
Perl module to support sufficiently modern YAML features, and also for helping me in the use of |
1882
|
|
|
|
|
|
|
YAML::PP. |
1883
|
|
|
|
|
|
|
|
1884
|
|
|
|
|
|
|
=head1 BUGS and SOURCE |
1885
|
|
|
|
|
|
|
|
1886
|
|
|
|
|
|
|
The source code is located here: L<https://github.com/pplu/cfn-perl> |
1887
|
|
|
|
|
|
|
|
1888
|
|
|
|
|
|
|
Please report bugs to: L<https://github.com/pplu/cfn-perl/issues> |
1889
|
|
|
|
|
|
|
|
1890
|
|
|
|
|
|
|
=head1 COPYRIGHT and LICENSE |
1891
|
|
|
|
|
|
|
|
1892
|
|
|
|
|
|
|
Copyright (c) 2013 by CAPSiDE |
1893
|
|
|
|
|
|
|
This code is distributed under the Apache 2 License. The full text of the |
1894
|
|
|
|
|
|
|
license can be found in the LICENSE file included with this module. |
1895
|
|
|
|
|
|
|
|
1896
|
|
|
|
|
|
|
=cut |