cloud-mu 3.1.5 → 3.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (185) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +5 -1
  3. data/ansible/roles/mu-windows/files/LaunchConfig.json +9 -0
  4. data/ansible/roles/mu-windows/files/config.xml +76 -0
  5. data/ansible/roles/mu-windows/tasks/main.yml +16 -0
  6. data/bin/mu-adopt +16 -12
  7. data/bin/mu-azure-tests +57 -0
  8. data/bin/mu-cleanup +2 -4
  9. data/bin/mu-configure +52 -0
  10. data/bin/mu-deploy +3 -3
  11. data/bin/mu-findstray-tests +25 -0
  12. data/bin/mu-gen-docs +2 -4
  13. data/bin/mu-load-config.rb +2 -1
  14. data/bin/mu-node-manage +15 -16
  15. data/bin/mu-run-tests +37 -12
  16. data/cloud-mu.gemspec +3 -3
  17. data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
  18. data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
  19. data/cookbooks/mu-tools/libraries/helper.rb +1 -1
  20. data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
  21. data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
  22. data/cookbooks/mu-tools/recipes/eks.rb +2 -2
  23. data/cookbooks/mu-tools/recipes/windows-client.rb +25 -22
  24. data/extras/clean-stock-amis +25 -19
  25. data/extras/generate-stock-images +1 -0
  26. data/extras/image-generators/AWS/win2k12.yaml +2 -0
  27. data/extras/image-generators/AWS/win2k16.yaml +2 -0
  28. data/extras/image-generators/AWS/win2k19.yaml +2 -0
  29. data/modules/mommacat.ru +1 -1
  30. data/modules/mu.rb +86 -98
  31. data/modules/mu/adoption.rb +373 -58
  32. data/modules/mu/cleanup.rb +214 -303
  33. data/modules/mu/cloud.rb +128 -1733
  34. data/modules/mu/cloud/database.rb +49 -0
  35. data/modules/mu/cloud/dnszone.rb +44 -0
  36. data/modules/mu/cloud/machine_images.rb +212 -0
  37. data/modules/mu/cloud/providers.rb +81 -0
  38. data/modules/mu/cloud/resource_base.rb +929 -0
  39. data/modules/mu/cloud/server.rb +40 -0
  40. data/modules/mu/cloud/server_pool.rb +1 -0
  41. data/modules/mu/cloud/ssh_sessions.rb +228 -0
  42. data/modules/mu/cloud/winrm_sessions.rb +237 -0
  43. data/modules/mu/cloud/wrappers.rb +169 -0
  44. data/modules/mu/config.rb +123 -81
  45. data/modules/mu/config/alarm.rb +2 -6
  46. data/modules/mu/config/bucket.rb +32 -3
  47. data/modules/mu/config/cache_cluster.rb +2 -2
  48. data/modules/mu/config/cdn.rb +100 -0
  49. data/modules/mu/config/collection.rb +1 -1
  50. data/modules/mu/config/container_cluster.rb +7 -2
  51. data/modules/mu/config/database.rb +84 -105
  52. data/modules/mu/config/database.yml +1 -2
  53. data/modules/mu/config/dnszone.rb +5 -4
  54. data/modules/mu/config/doc_helpers.rb +5 -6
  55. data/modules/mu/config/endpoint.rb +2 -1
  56. data/modules/mu/config/firewall_rule.rb +3 -19
  57. data/modules/mu/config/folder.rb +1 -1
  58. data/modules/mu/config/function.rb +17 -8
  59. data/modules/mu/config/group.rb +1 -1
  60. data/modules/mu/config/habitat.rb +1 -1
  61. data/modules/mu/config/job.rb +89 -0
  62. data/modules/mu/config/loadbalancer.rb +57 -11
  63. data/modules/mu/config/log.rb +1 -1
  64. data/modules/mu/config/msg_queue.rb +1 -1
  65. data/modules/mu/config/nosqldb.rb +1 -1
  66. data/modules/mu/config/notifier.rb +8 -19
  67. data/modules/mu/config/ref.rb +92 -14
  68. data/modules/mu/config/role.rb +1 -1
  69. data/modules/mu/config/schema_helpers.rb +38 -37
  70. data/modules/mu/config/search_domain.rb +1 -1
  71. data/modules/mu/config/server.rb +12 -13
  72. data/modules/mu/config/server_pool.rb +3 -7
  73. data/modules/mu/config/storage_pool.rb +1 -1
  74. data/modules/mu/config/tail.rb +11 -0
  75. data/modules/mu/config/user.rb +1 -1
  76. data/modules/mu/config/vpc.rb +27 -23
  77. data/modules/mu/config/vpc.yml +0 -1
  78. data/modules/mu/defaults/AWS.yaml +90 -90
  79. data/modules/mu/defaults/Azure.yaml +1 -0
  80. data/modules/mu/defaults/Google.yaml +1 -0
  81. data/modules/mu/deploy.rb +34 -20
  82. data/modules/mu/groomer.rb +16 -1
  83. data/modules/mu/groomers/ansible.rb +69 -4
  84. data/modules/mu/groomers/chef.rb +51 -4
  85. data/modules/mu/logger.rb +120 -144
  86. data/modules/mu/master.rb +97 -4
  87. data/modules/mu/mommacat.rb +160 -874
  88. data/modules/mu/mommacat/daemon.rb +23 -14
  89. data/modules/mu/mommacat/naming.rb +110 -3
  90. data/modules/mu/mommacat/search.rb +497 -0
  91. data/modules/mu/mommacat/storage.rb +252 -194
  92. data/modules/mu/{clouds → providers}/README.md +1 -1
  93. data/modules/mu/{clouds → providers}/aws.rb +258 -57
  94. data/modules/mu/{clouds → providers}/aws/alarm.rb +3 -3
  95. data/modules/mu/{clouds → providers}/aws/bucket.rb +275 -41
  96. data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +14 -50
  97. data/modules/mu/providers/aws/cdn.rb +782 -0
  98. data/modules/mu/{clouds → providers}/aws/collection.rb +5 -5
  99. data/modules/mu/{clouds → providers}/aws/container_cluster.rb +95 -84
  100. data/modules/mu/providers/aws/database.rb +1744 -0
  101. data/modules/mu/{clouds → providers}/aws/dnszone.rb +26 -12
  102. data/modules/mu/providers/aws/endpoint.rb +1072 -0
  103. data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +39 -32
  104. data/modules/mu/{clouds → providers}/aws/folder.rb +1 -1
  105. data/modules/mu/{clouds → providers}/aws/function.rb +289 -134
  106. data/modules/mu/{clouds → providers}/aws/group.rb +18 -20
  107. data/modules/mu/{clouds → providers}/aws/habitat.rb +3 -3
  108. data/modules/mu/providers/aws/job.rb +466 -0
  109. data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +77 -47
  110. data/modules/mu/{clouds → providers}/aws/log.rb +5 -5
  111. data/modules/mu/{clouds → providers}/aws/msg_queue.rb +14 -11
  112. data/modules/mu/{clouds → providers}/aws/nosqldb.rb +96 -5
  113. data/modules/mu/{clouds → providers}/aws/notifier.rb +135 -63
  114. data/modules/mu/{clouds → providers}/aws/role.rb +76 -48
  115. data/modules/mu/{clouds → providers}/aws/search_domain.rb +172 -41
  116. data/modules/mu/{clouds → providers}/aws/server.rb +66 -98
  117. data/modules/mu/{clouds → providers}/aws/server_pool.rb +42 -60
  118. data/modules/mu/{clouds → providers}/aws/storage_pool.rb +21 -38
  119. data/modules/mu/{clouds → providers}/aws/user.rb +12 -16
  120. data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
  121. data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +5 -4
  122. data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +0 -0
  123. data/modules/mu/{clouds → providers}/aws/vpc.rb +143 -74
  124. data/modules/mu/{clouds → providers}/aws/vpc_subnet.rb +0 -0
  125. data/modules/mu/{clouds → providers}/azure.rb +13 -0
  126. data/modules/mu/{clouds → providers}/azure/container_cluster.rb +1 -5
  127. data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +8 -1
  128. data/modules/mu/{clouds → providers}/azure/habitat.rb +0 -0
  129. data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +0 -0
  130. data/modules/mu/{clouds → providers}/azure/role.rb +0 -0
  131. data/modules/mu/{clouds → providers}/azure/server.rb +32 -24
  132. data/modules/mu/{clouds → providers}/azure/user.rb +1 -1
  133. data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
  134. data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
  135. data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
  136. data/modules/mu/{clouds → providers}/azure/vpc.rb +4 -6
  137. data/modules/mu/{clouds → providers}/cloudformation.rb +10 -0
  138. data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
  139. data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
  140. data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
  141. data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
  142. data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
  143. data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
  144. data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
  145. data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
  146. data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
  147. data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
  148. data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +3 -3
  149. data/modules/mu/{clouds → providers}/docker.rb +0 -0
  150. data/modules/mu/{clouds → providers}/google.rb +29 -6
  151. data/modules/mu/{clouds → providers}/google/bucket.rb +4 -4
  152. data/modules/mu/{clouds → providers}/google/container_cluster.rb +38 -20
  153. data/modules/mu/{clouds → providers}/google/database.rb +5 -12
  154. data/modules/mu/{clouds → providers}/google/firewall_rule.rb +5 -5
  155. data/modules/mu/{clouds → providers}/google/folder.rb +5 -9
  156. data/modules/mu/{clouds → providers}/google/function.rb +6 -6
  157. data/modules/mu/{clouds → providers}/google/group.rb +9 -17
  158. data/modules/mu/{clouds → providers}/google/habitat.rb +4 -8
  159. data/modules/mu/{clouds → providers}/google/loadbalancer.rb +5 -5
  160. data/modules/mu/{clouds → providers}/google/role.rb +50 -31
  161. data/modules/mu/{clouds → providers}/google/server.rb +41 -24
  162. data/modules/mu/{clouds → providers}/google/server_pool.rb +14 -14
  163. data/modules/mu/{clouds → providers}/google/user.rb +34 -24
  164. data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
  165. data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
  166. data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
  167. data/modules/mu/{clouds → providers}/google/vpc.rb +45 -14
  168. data/modules/tests/aws-jobs-functions.yaml +46 -0
  169. data/modules/tests/centos6.yaml +15 -0
  170. data/modules/tests/centos7.yaml +15 -0
  171. data/modules/tests/centos8.yaml +12 -0
  172. data/modules/tests/ecs.yaml +2 -2
  173. data/modules/tests/eks.yaml +1 -1
  174. data/modules/tests/functions/node-function/lambda_function.js +10 -0
  175. data/modules/tests/functions/python-function/lambda_function.py +12 -0
  176. data/modules/tests/microservice_app.yaml +288 -0
  177. data/modules/tests/rds.yaml +108 -0
  178. data/modules/tests/regrooms/rds.yaml +123 -0
  179. data/modules/tests/server-with-scrub-muisms.yaml +1 -1
  180. data/modules/tests/super_complex_bok.yml +2 -2
  181. data/modules/tests/super_simple_bok.yml +3 -5
  182. data/spec/mu/clouds/azure_spec.rb +2 -2
  183. metadata +122 -92
  184. data/modules/mu/clouds/aws/database.rb +0 -1974
  185. data/modules/mu/clouds/aws/endpoint.rb +0 -596
@@ -1,596 +0,0 @@
1
- module MU
2
- class Cloud
3
- class AWS
4
- # An API as configured in {MU::Config::BasketofKittens::endpoints}
5
- class Endpoint < MU::Cloud::Endpoint
6
-
7
- # Initialize this cloud resource object. Calling +super+ will invoke the initializer defined under {MU::Cloud}, which should set the attribtues listed in {MU::Cloud::PUBLIC_ATTRS} as well as applicable dependency shortcuts, like +@vpc+, for us.
8
- # @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
9
- def initialize(**args)
10
- super
11
- @mu_name ||= @deploy.getResourceName(@config["name"])
12
- end
13
-
14
- # Called automatically by {MU::Deploy#createResources}
15
- def create
16
- resp = MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).create_rest_api(
17
- name: @mu_name,
18
- description: @deploy.deploy_id,
19
- endpoint_configuration: {
20
- types: ["REGIONAL"] # XXX expose in BoK ["REGIONAL", "EDGE", "PRIVATE"]
21
- }
22
- )
23
- @cloud_id = resp.id
24
- generate_methods
25
-
26
-
27
- end
28
-
29
- # Create/update all of the methods declared for this endpoint
30
- def generate_methods
31
- resp = MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).get_resources(
32
- rest_api_id: @cloud_id,
33
- )
34
- root_resource = resp.items.first.id
35
-
36
- # TODO guard this crap so we don't touch it if there are no changes
37
- @config['methods'].each { |m|
38
- m["auth"] ||= m["iam_role"] ? "AWS_IAM" : "NONE"
39
-
40
- method_arn = "arn:#{MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws"}:execute-api:#{@config["region"]}:#{MU::Cloud::AWS.credToAcct(@config['credentials'])}:#{@cloud_id}/*/#{m['type']}/#{m['path']}"
41
-
42
- resp = MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).get_resources(
43
- rest_api_id: @cloud_id
44
- )
45
- ext_resource = nil
46
- resp.items.each { |resource|
47
- if resource.path_part == m['path']
48
- ext_resource = resource.id
49
- end
50
- }
51
-
52
- resp = if ext_resource
53
- MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).get_resource(
54
- rest_api_id: @cloud_id,
55
- resource_id: ext_resource,
56
- )
57
- # MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).update_resource(
58
- # rest_api_id: @cloud_id,
59
- # resource_id: ext_resource,
60
- # patch_operations: [
61
- # {
62
- # op: "replace",
63
- # path: "XXX ??",
64
- # value: m["path"]
65
- # }
66
- # ]
67
- # )
68
- else
69
- MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).create_resource(
70
- rest_api_id: @cloud_id,
71
- parent_id: root_resource,
72
- path_part: m['path']
73
- )
74
- end
75
- parent_id = resp.id
76
-
77
- resp = begin
78
- MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).get_method(
79
- rest_api_id: @cloud_id,
80
- resource_id: parent_id,
81
- http_method: m['type']
82
- )
83
- rescue Aws::APIGateway::Errors::NotFoundException
84
- resp = MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).put_method(
85
- rest_api_id: @cloud_id,
86
- resource_id: parent_id,
87
- authorization_type: m['auth'],
88
- http_method: m['type']
89
- )
90
- end
91
-
92
- # XXX effectively a placeholder default
93
- begin
94
- m['responses'].each { |r|
95
- params = {
96
- :rest_api_id => @cloud_id,
97
- :resource_id => parent_id,
98
- :http_method => m['type'],
99
- :status_code => r['code'].to_s
100
- }
101
- if r['headers']
102
- params[:response_parameters] = r['headers'].map { |h|
103
- ["method.response.header."+h['header'], h['required']]
104
- }.to_h
105
- end
106
-
107
- if r['body']
108
- # XXX I'm guessing we can also have arbirary user-defined models somehow, so is_error is probably inadequate to the demand of the times
109
- params[:response_models] = r['body'].map { |b| [b['content_type'], b['is_error'] ? "Error" : "Empty"] }.to_h
110
- end
111
-
112
- MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).put_method_response(params)
113
- }
114
- rescue Aws::APIGateway::Errors::ConflictException
115
- # fine to ignore
116
- end
117
-
118
- if m['integrate_with']
119
- # role_arn = if m['iam_role']
120
- # if m['iam_role'].match(/^arn:/)
121
- # m['iam_role']
122
- # else
123
- # sib_role = @deploy.findLitterMate(name: m['iam_role'], type: "roles")
124
- # sib_role.cloudobj.arn
125
- # XXX make this more like get_role_arn in Function, or just use Role.find?
126
- # end
127
- # end
128
-
129
- function_obj = nil
130
-
131
- uri, type = if m['integrate_with']['type'] == "aws_generic"
132
- svc, action = m['integrate_with']['aws_generic_action'].split(/:/)
133
- ["arn:aws:apigateway:"+@config['region']+":#{svc}:action/#{action}", "AWS"]
134
- elsif m['integrate_with']['type'] == "function"
135
- function_obj = @deploy.findLitterMate(name: m['integrate_with']['name'], type: "functions").cloudobj
136
- ["arn:aws:apigateway:"+@config['region']+":lambda:path/2015-03-31/functions/"+function_obj.arn+"/invocations", "AWS"]
137
- elsif m['integrate_with']['type'] == "mock"
138
- [nil, "MOCK"]
139
- end
140
-
141
- params = {
142
- :rest_api_id => @cloud_id,
143
- :resource_id => parent_id,
144
- :type => type, # XXX Lambda and Firehose can do AWS_PROXY
145
- :content_handling => "CONVERT_TO_TEXT", # XXX expose in BoK
146
- :http_method => m['type']
147
- # credentials: role_arn
148
- }
149
- params[:uri] = uri if uri
150
-
151
- if m['integrate_with']['type'] != "mock"
152
- params[:integration_http_method] = m['integrate_with']['backend_http_method']
153
- else
154
- params[:integration_http_method] = nil
155
- end
156
-
157
- if m['integrate_with']['passthrough_behavior']
158
- params[:passthrough_behavior] = m['integrate_with']['passthrough_behavior']
159
- end
160
- if m['integrate_with']['request_templates']
161
- params[:request_templates] = {}
162
- m['integrate_with']['request_templates'].each { |rt|
163
- params[:request_templates][rt['content_type']] = rt['template']
164
- }
165
- end
166
-
167
- resp = MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).put_integration(params)
168
-
169
- if m['integrate_with']['type'] == "function"
170
- function_obj.addTrigger(method_arn, "apigateway", @config['name'])
171
- end
172
-
173
- m['responses'].each { |r|
174
- params = {
175
- :rest_api_id => @cloud_id,
176
- :resource_id => parent_id,
177
- :http_method => m['type'],
178
- :status_code => r['code'].to_s,
179
- :selection_pattern => ""
180
- }
181
- if r['headers']
182
- params[:response_parameters] = r['headers'].map { |h|
183
- ["method.response.header."+h['header'], "'"+h['value']+"'"]
184
- }.to_h
185
- end
186
-
187
- MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).put_integration_response(params)
188
-
189
- }
190
-
191
- end
192
-
193
- }
194
- end
195
-
196
- # Called automatically by {MU::Deploy#createResources}
197
- def groom
198
- generate_methods
199
-
200
- MU.log "Deploying API Gateway #{@config['name']} to #{@config['deploy_to']}"
201
- MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).create_deployment(
202
- rest_api_id: @cloud_id,
203
- stage_name: @config['deploy_to']
204
- # cache_cluster_enabled: false,
205
- # cache_cluster_size: 0.5,
206
- )
207
- # this automatically creates a stage with the same name, so we don't
208
- # have to deal with that
209
-
210
- my_url = "https://"+@cloud_id+".execute-api."+@config['region']+".amazonaws.com/"+@config['deploy_to']
211
- MU.log "API Endpoint #{@config['name']}: "+my_url, MU::SUMMARY
212
-
213
- # resp = MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).create_authorizer(
214
- # rest_api_id: @cloud_id,
215
- # )
216
-
217
- # resp = MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).create_vpc_link(
218
- # )
219
-
220
- end
221
-
222
- @cloud_desc_cache = nil
223
- # @return [Struct]
224
- def cloud_desc(use_cache: true)
225
- return @cloud_desc_cache if @cloud_desc_cache and use_cache
226
- @cloud_desc_cache = MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).get_rest_api(
227
- rest_api_id: @cloud_id
228
- )
229
- @cloud_desc_cache
230
- end
231
-
232
- # Return the metadata for this API
233
- # @return [Hash]
234
- def notify
235
- deploy_struct = MU.structToHash(cloud_desc)
236
- # XXX stages and whatnot
237
- return deploy_struct
238
- end
239
-
240
- # Remove all APIs associated with the currently loaded deployment.
241
- # @param noop [Boolean]: If true, will only print what would be done
242
- # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
243
- # @param region [String]: The cloud provider region
244
- # @return [void]
245
- def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
246
- MU.log "AWS::Endpoint.cleanup: need to support flags['known']", MU::DEBUG, details: flags
247
- MU.log "Placeholder: AWS Endpoint artifacts do not support tags, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: ignoremaster
248
-
249
- resp = MU::Cloud::AWS.apig(region: region, credentials: credentials).get_rest_apis
250
- if resp and resp.items
251
- resp.items.each { |api|
252
- # The stupid things don't have tags
253
- if api.description == MU.deploy_id
254
- MU.log "Deleting API Gateway #{api.name} (#{api.id})"
255
- if !noop
256
- MU::Cloud::AWS.apig(region: region, credentials: credentials).delete_rest_api(
257
- rest_api_id: api.id
258
- )
259
- end
260
- end
261
- }
262
- end
263
- end
264
-
265
- # Locate an existing API.
266
- # @return [Hash<String,OpenStruct>]: The cloud provider's complete descriptions of matching APIs.
267
- def self.find(**args)
268
- found = {}
269
-
270
- if args[:cloud_id]
271
- found[args[:cloud_id]] = MU::Cloud::AWS.apig(region: args[:region], credentials: args[:credentials]).get_rest_api(
272
- rest_api_id: args[:cloud_id]
273
- )
274
- else
275
- resp = MU::Cloud::AWS.apig(region: args[:region], credentials: args[:credentials]).get_rest_apis
276
- if resp and resp.items
277
- resp.items.each { |api|
278
- found[api.id] = api
279
- }
280
- end
281
- end
282
-
283
- found
284
- end
285
-
286
- # Cloud-specific configuration properties.
287
- # @param _config [MU::Config]: The calling MU::Config object
288
- # @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
289
- def self.schema(_config)
290
- toplevel_required = []
291
- schema = {
292
- "deploy_to" => {
293
- "type" => "string",
294
- "description" => "The name of an environment under which to deploy our API. If not specified, will deploy to the name of the global Mu environment for this deployment."
295
- },
296
- "methods" => {
297
- "items" => {
298
- "type" => "object",
299
- "description" => "Other cloud resources to integrate as a back end to this API Gateway",
300
- "required" => ["integrate_with"],
301
- "properties" => {
302
- "integrate_with" => {
303
- "type" => "object",
304
- "description" => "Specify what application backend to invoke under this path/method combination",
305
- "properties" => {
306
- "proxy" => {
307
- "type" => "boolean",
308
- "default" => false,
309
- "description" => "For HTTP or AWS integrations, specify whether the target is a proxy (((docs unclear, is that actually what this means?)))" # XXX is that actually what this means?
310
- },
311
- "backend_http_method" => {
312
- "type" => "string",
313
- "description" => "The HTTP method to use when contacting our integrated backend. If not specified, this will be set to match our front end.",
314
- "enum" => ["GET", "POST", "PUT", "HEAD", "DELETE", "CONNECT", "OPTIONS", "TRACE"],
315
- },
316
- "url" => {
317
- "type" => "string",
318
- "description" => "For HTTP or HTTP_PROXY integrations, this should be a fully-qualified URL"
319
- },
320
- "responses"=> {
321
- "type" => "array",
322
- "items" => {
323
- "type" => "object",
324
- "description" => "Customize the response to the client for this method, by adding headers or transforming through a template. If not specified, we will default to returning an un-transformed HTTP 200 for this method.",
325
- "properties" => {
326
- "code" => {
327
- "type" => "integer",
328
- "description" => "The HTTP status code to return",
329
- "default" => 200
330
- },
331
- "headers" => {
332
- "type" => "array",
333
- "items" => {
334
- "description" => "One or more headers, used by the API Gateway integration response and filtered through the method response before returning to the client",
335
- "type" => "object",
336
- "properties" => {
337
- "header" => {
338
- "type" => "string",
339
- "description" => "The name of a header to return, such as +Access-Control-Allow-Methods+"
340
- },
341
- "value" => {
342
- "type" => "string",
343
- "description" => "The string to map to this header (ex +GET,OPTIONS+)"
344
- },
345
- "required" => {
346
- "type" => "boolean",
347
- "description" => "Indicate whether this header is required in order to return a response",
348
- "default" => true
349
- }
350
- }
351
- }
352
- },
353
- "body" => {
354
- "type" => "array",
355
- "items" => {
356
- "type" => "object",
357
- "description" => "Model for the body of our backend integration's response",
358
- "properties" => {
359
- "content_type" => {
360
- "type" => "string",
361
- "description" => "An HTTP content type to match to a response, such as +application/json+."
362
- },
363
- "is_error" => {
364
- "type" => "boolean",
365
- "description" => "Whether this response should be considered an error",
366
- "default" => false
367
- }
368
- }
369
- }
370
- }
371
- }
372
- }
373
- },
374
- "arn" => {
375
- "type" => "string",
376
- "description" => "For AWS or AWS_PROXY integrations with a compatible Amazon resource outside of Mu, a full-qualified ARN such as `arn:aws:apigateway:us-west-2:s3:action/GetObject&Bucket=`bucket&Key=key`"
377
- },
378
- "name" => {
379
- "type" => "string",
380
- "description" => "A Mu resource name, for integrations with a sibling resource (e.g. a Function)"
381
- },
382
- "cors" => {
383
- "type" => "boolean",
384
- "description" => "When enabled, this will create an +OPTIONS+ method under this path with request and response header mappings that implement Cross-Origin Resource Sharing",
385
- "default" => true
386
- },
387
- "type" => {
388
- "type" => "string",
389
- "description" => "A Mu resource type, for integrations with a sibling resource (e.g. a function), or the string +aws_generic+, which we can use in combination with +aws_generic_action+ to integrate with arbitrary AWS services.",
390
- "enum" => ["aws_generic"].concat(MU::Cloud.resource_types.values.map { |t| t[:cfg_name] }.sort)
391
- },
392
- "aws_generic_action" => {
393
- "type" => "string",
394
- "description" => "For use when +type+ is set to +aws_generic+, this should specify the action to be performed in the style of an IAM policy action, e.g. +acm:ListCertificates+ for this integration to return a list of Certificate Manager SSL certificates."
395
- },
396
- "deploy_id" => {
397
- "type" => "string",
398
- "description" => "A Mu deploy id (e.g. DEMO-DEV-2014111400-NG), for integrations with a sibling resource (e.g. a Function)"
399
- },
400
- "iam_role" => {
401
- "type" => "string",
402
- "description" => "The name of an IAM role used to grant usage of other AWS artifacts for this integration. If not specified, we will automatically generate an appropriate role."
403
- },
404
- "passthrough_behavior" => {
405
- "type" => "string",
406
- "description" => "Specifies the pass-through behavior for incoming requests based on the +Content-Type+ header in the request, and the available mapping templates specified in +request_templates+. +WHEN_NO_MATCH+ passes the request body for unmapped content types through to the integration back end without transformation. +WHEN_NO_TEMPLATES+ allows pass-through when the integration has NO content types mapped to templates. +NEVER+ rejects unmapped content types with an HTTP +415+.",
407
- "enum" => ["WHEN_NO_MATCH", "WHEN_NO_TEMPLATES", "NEVER"],
408
- "default" => "WHEN_NO_MATCH"
409
- },
410
- "request_templates" => {
411
- "type" => "array",
412
- "description" => "A JSON-encoded string which represents a map of Velocity templates that are applied on the request payload based on the value of the +Content-Type+ header sent by the client. The content type value is the key in this map, and the template (as a String) is the value.",
413
- "items" => {
414
- "type" => "object",
415
- "description" => "A JSON-encoded string which represents a map of Velocity templates that are applied on the request payload based on the value of the +Content-Type+ header sent by the client. The content type value is the key in this map, and the template (as a String) is the value.",
416
- "require" => ["content_type", "template"],
417
- "properties" => {
418
- "content_type" => {
419
- "type" => "string",
420
- "description" => "An HTTP content type to match with a template, such as +application/json+."
421
- },
422
- "template" => {
423
- "type" => "string",
424
- "description" => "A Velocity template to apply to our reques payload, encoded as a one-line string, like: "+'<tt>"#set($allParams = $input.params())\\n{\\n\\"url_data_json_encoded\\":\\"$input.params(\'url\')\\"\\n}"</tt>'
425
- }
426
- }
427
- }
428
- }
429
- }
430
- },
431
- "auth" => {
432
- "type" => "string",
433
- "enum" => ["NONE", "CUSTOM", "AWS_IAM", "COGNITO_USER_POOLS"],
434
- "default" => "NONE"
435
- }
436
- }
437
- }
438
- }
439
- }
440
- [toplevel_required, schema]
441
- end
442
-
443
- # Does this resource type exist as a global (cloud-wide) artifact, or
444
- # is it localized to a region/zone?
445
- # @return [Boolean]
446
- def self.isGlobal?
447
- false
448
- end
449
-
450
- # Denote whether this resource implementation is experiment, ready for
451
- # testing, or ready for production use.
452
- def self.quality
453
- MU::Cloud::BETA
454
- end
455
-
456
- # Canonical Amazon Resource Number for this resource
457
- # @return [String]
458
- def arn
459
- "arn:#{MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws"}:execute-api:#{@config["region"]}:#{MU::Cloud::AWS.credToAcct(@config['credentials'])}:#{@cloud_id}"
460
- end
461
-
462
-
463
- # Cloud-specific pre-processing of {MU::Config::BasketofKittens::endpoints}, bare and unvalidated.
464
- # @param endpoint [Hash]: The resource to process and validate
465
- # @param configurator [MU::Config]: The overall deployment configurator of which this resource is a member
466
- # @return [Boolean]: True if validation succeeded, False otherwise
467
- def self.validateConfig(endpoint, configurator)
468
- ok = true
469
-
470
- append = []
471
- endpoint['deploy_to'] ||= MU.environment || $environment || "dev"
472
- endpoint['methods'].each { |m|
473
- if m['integrate_with'] and m['integrate_with']['name']
474
- if m['integrate_with']['type'] != "aws_generic"
475
- endpoint['dependencies'] ||= []
476
- endpoint['dependencies'] << {
477
- "type" => m['integrate_with']['type'],
478
- "name" => m['integrate_with']['name']
479
- }
480
- end
481
-
482
- m['integrate_with']['backend_http_method'] ||= m['type']
483
-
484
- m['responses'] ||= [
485
- "code" => 200
486
- ]
487
-
488
- if m['cors']
489
- m['responses'].each { |r|
490
- r['headers'] ||= []
491
- r['headers'] << {
492
- "header" => "Access-Control-Allow-Origin",
493
- "value" => "*",
494
- "required" => true
495
- }
496
- r['headers'].uniq!
497
- }
498
-
499
- append << cors_option_integrations(m['path'])
500
- end
501
-
502
- if !m['iam_role']
503
- m['uri'] ||= "*" if m['integrate_with']['type'] == "aws_generic"
504
-
505
- roledesc = {
506
- "name" => endpoint['name']+"-"+m['integrate_with']['name'],
507
- "credentials" => endpoint['credentials'],
508
- "can_assume" => [
509
- {
510
- "entity_id" => "apigateway.amazonaws.com",
511
- "entity_type" => "service"
512
- }
513
- ],
514
- }
515
- if m['integrate_with']['type'] == "aws_generic"
516
- roledesc["policies"] = [
517
- {
518
- "name" => m['integrate_with']['aws_generic_action'].gsub(/[^a-z]/i, ""),
519
- "permissions" => [m['integrate_with']['aws_generic_action']],
520
- "targets" => [{ "identifier" => m['uri'] }]
521
- }
522
- ]
523
- elsif m['integrate_with']['type'] == "function"
524
- roledesc["import"] = ["AWSLambdaBasicExecutionRole"]
525
- end
526
- configurator.insertKitten(roledesc, "roles")
527
-
528
- endpoint['dependencies'] ||= []
529
- m['iam_role'] = endpoint['name']+"-"+m['integrate_with']['name']
530
-
531
- endpoint['dependencies'] << {
532
- "type" => "role",
533
- "name" => endpoint['name']+"-"+m['integrate_with']['name']
534
- }
535
- end
536
- end
537
- }
538
- endpoint['methods'].concat(append.uniq) if endpoint['methods']
539
- # if something_bad
540
- # ok = false
541
- # end
542
-
543
- ok
544
- end
545
-
546
- def self.cors_option_integrations(path)
547
- {
548
- "type" => "OPTIONS",
549
- "path" => path,
550
- "auth" => "NONE",
551
- "responses" => [
552
- {
553
- "code" => 200,
554
- "headers" => [
555
- {
556
- "header" => "Access-Control-Allow-Headers",
557
- "value" => "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token",
558
- "required" => true
559
- },
560
- {
561
- "header" => "Access-Control-Allow-Methods",
562
- "value" => "GET,OPTIONS",
563
- "required" => true
564
- },
565
- {
566
- "header" => "Access-Control-Allow-Origin",
567
- "value" => "*",
568
- "required" => true
569
- }
570
- ],
571
- "body" => [
572
- {
573
- "content_type" => "application/json"
574
- }
575
- ]
576
- }
577
- ],
578
- "integrate_with" => {
579
- "type" => "mock",
580
- "passthrough_behavior" => "WHEN_NO_MATCH",
581
- "backend_http_method" => "OPTIONS",
582
- "request_templates" => [
583
- {
584
- "content_type" => "application/json",
585
- "template" => '{"statusCode": 200}'
586
- }
587
- ]
588
- }
589
- }
590
- end
591
- private_class_method :cors_option_integrations
592
-
593
- end
594
- end
595
- end
596
- end