cloud-mu 3.1.5 → 3.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Dockerfile +5 -1
- data/ansible/roles/mu-windows/files/LaunchConfig.json +9 -0
- data/ansible/roles/mu-windows/files/config.xml +76 -0
- data/ansible/roles/mu-windows/tasks/main.yml +16 -0
- data/bin/mu-adopt +16 -12
- data/bin/mu-azure-tests +57 -0
- data/bin/mu-cleanup +2 -4
- data/bin/mu-configure +52 -0
- data/bin/mu-deploy +3 -3
- data/bin/mu-findstray-tests +25 -0
- data/bin/mu-gen-docs +2 -4
- data/bin/mu-load-config.rb +2 -1
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +37 -12
- data/cloud-mu.gemspec +3 -3
- data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
- data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
- data/cookbooks/mu-tools/libraries/helper.rb +1 -1
- data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
- data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
- data/cookbooks/mu-tools/recipes/eks.rb +2 -2
- data/cookbooks/mu-tools/recipes/windows-client.rb +25 -22
- data/extras/clean-stock-amis +25 -19
- data/extras/generate-stock-images +1 -0
- data/extras/image-generators/AWS/win2k12.yaml +2 -0
- data/extras/image-generators/AWS/win2k16.yaml +2 -0
- data/extras/image-generators/AWS/win2k19.yaml +2 -0
- data/modules/mommacat.ru +1 -1
- data/modules/mu.rb +86 -98
- data/modules/mu/adoption.rb +373 -58
- data/modules/mu/cleanup.rb +214 -303
- data/modules/mu/cloud.rb +128 -1733
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +44 -0
- data/modules/mu/cloud/machine_images.rb +212 -0
- data/modules/mu/cloud/providers.rb +81 -0
- data/modules/mu/cloud/resource_base.rb +929 -0
- data/modules/mu/cloud/server.rb +40 -0
- data/modules/mu/cloud/server_pool.rb +1 -0
- data/modules/mu/cloud/ssh_sessions.rb +228 -0
- data/modules/mu/cloud/winrm_sessions.rb +237 -0
- data/modules/mu/cloud/wrappers.rb +169 -0
- data/modules/mu/config.rb +123 -81
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +32 -3
- data/modules/mu/config/cache_cluster.rb +2 -2
- data/modules/mu/config/cdn.rb +100 -0
- data/modules/mu/config/collection.rb +1 -1
- data/modules/mu/config/container_cluster.rb +7 -2
- data/modules/mu/config/database.rb +84 -105
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +5 -4
- data/modules/mu/config/doc_helpers.rb +5 -6
- data/modules/mu/config/endpoint.rb +2 -1
- data/modules/mu/config/firewall_rule.rb +3 -19
- data/modules/mu/config/folder.rb +1 -1
- data/modules/mu/config/function.rb +17 -8
- data/modules/mu/config/group.rb +1 -1
- data/modules/mu/config/habitat.rb +1 -1
- data/modules/mu/config/job.rb +89 -0
- data/modules/mu/config/loadbalancer.rb +57 -11
- data/modules/mu/config/log.rb +1 -1
- data/modules/mu/config/msg_queue.rb +1 -1
- data/modules/mu/config/nosqldb.rb +1 -1
- data/modules/mu/config/notifier.rb +8 -19
- data/modules/mu/config/ref.rb +92 -14
- data/modules/mu/config/role.rb +1 -1
- data/modules/mu/config/schema_helpers.rb +38 -37
- data/modules/mu/config/search_domain.rb +1 -1
- data/modules/mu/config/server.rb +12 -13
- data/modules/mu/config/server_pool.rb +3 -7
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +11 -0
- data/modules/mu/config/user.rb +1 -1
- data/modules/mu/config/vpc.rb +27 -23
- data/modules/mu/config/vpc.yml +0 -1
- data/modules/mu/defaults/AWS.yaml +90 -90
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +1 -0
- data/modules/mu/deploy.rb +34 -20
- data/modules/mu/groomer.rb +16 -1
- data/modules/mu/groomers/ansible.rb +69 -4
- data/modules/mu/groomers/chef.rb +51 -4
- data/modules/mu/logger.rb +120 -144
- data/modules/mu/master.rb +97 -4
- data/modules/mu/mommacat.rb +160 -874
- data/modules/mu/mommacat/daemon.rb +23 -14
- data/modules/mu/mommacat/naming.rb +110 -3
- data/modules/mu/mommacat/search.rb +497 -0
- data/modules/mu/mommacat/storage.rb +252 -194
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +258 -57
- data/modules/mu/{clouds → providers}/aws/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/aws/bucket.rb +275 -41
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +14 -50
- data/modules/mu/providers/aws/cdn.rb +782 -0
- data/modules/mu/{clouds → providers}/aws/collection.rb +5 -5
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +95 -84
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +26 -12
- data/modules/mu/providers/aws/endpoint.rb +1072 -0
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +39 -32
- data/modules/mu/{clouds → providers}/aws/folder.rb +1 -1
- data/modules/mu/{clouds → providers}/aws/function.rb +289 -134
- data/modules/mu/{clouds → providers}/aws/group.rb +18 -20
- data/modules/mu/{clouds → providers}/aws/habitat.rb +3 -3
- data/modules/mu/providers/aws/job.rb +466 -0
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +77 -47
- data/modules/mu/{clouds → providers}/aws/log.rb +5 -5
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +14 -11
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +96 -5
- data/modules/mu/{clouds → providers}/aws/notifier.rb +135 -63
- data/modules/mu/{clouds → providers}/aws/role.rb +76 -48
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +172 -41
- data/modules/mu/{clouds → providers}/aws/server.rb +66 -98
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +42 -60
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +21 -38
- data/modules/mu/{clouds → providers}/aws/user.rb +12 -16
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +5 -4
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/aws/vpc.rb +143 -74
- data/modules/mu/{clouds → providers}/aws/vpc_subnet.rb +0 -0
- data/modules/mu/{clouds → providers}/azure.rb +13 -0
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +1 -5
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +8 -1
- data/modules/mu/{clouds → providers}/azure/habitat.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/role.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/server.rb +32 -24
- data/modules/mu/{clouds → providers}/azure/user.rb +1 -1
- data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/vpc.rb +4 -6
- data/modules/mu/{clouds → providers}/cloudformation.rb +10 -0
- data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
- data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
- data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
- data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +3 -3
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +29 -6
- data/modules/mu/{clouds → providers}/google/bucket.rb +4 -4
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +38 -20
- data/modules/mu/{clouds → providers}/google/database.rb +5 -12
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +5 -5
- data/modules/mu/{clouds → providers}/google/folder.rb +5 -9
- data/modules/mu/{clouds → providers}/google/function.rb +6 -6
- data/modules/mu/{clouds → providers}/google/group.rb +9 -17
- data/modules/mu/{clouds → providers}/google/habitat.rb +4 -8
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +5 -5
- data/modules/mu/{clouds → providers}/google/role.rb +50 -31
- data/modules/mu/{clouds → providers}/google/server.rb +41 -24
- data/modules/mu/{clouds → providers}/google/server_pool.rb +14 -14
- data/modules/mu/{clouds → providers}/google/user.rb +34 -24
- data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/google/vpc.rb +45 -14
- data/modules/tests/aws-jobs-functions.yaml +46 -0
- data/modules/tests/centos6.yaml +15 -0
- data/modules/tests/centos7.yaml +15 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +2 -2
- data/modules/tests/eks.yaml +1 -1
- data/modules/tests/functions/node-function/lambda_function.js +10 -0
- data/modules/tests/functions/python-function/lambda_function.py +12 -0
- data/modules/tests/microservice_app.yaml +288 -0
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +1 -1
- data/modules/tests/super_complex_bok.yml +2 -2
- data/modules/tests/super_simple_bok.yml +3 -5
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +122 -92
- data/modules/mu/clouds/aws/database.rb +0 -1974
- 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
|