cloud-mu 3.1.2 → 3.2.0
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 +15 -3
- data/ansible/roles/mu-windows/README.md +33 -0
- data/ansible/roles/mu-windows/defaults/main.yml +2 -0
- 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/handlers/main.yml +2 -0
- data/ansible/roles/mu-windows/meta/main.yml +53 -0
- data/ansible/roles/mu-windows/tasks/main.yml +36 -0
- data/ansible/roles/mu-windows/tests/inventory +2 -0
- data/ansible/roles/mu-windows/tests/test.yml +5 -0
- data/ansible/roles/mu-windows/vars/main.yml +2 -0
- data/bin/mu-adopt +10 -13
- 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 -3
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +135 -37
- data/cloud-mu.gemspec +22 -20
- 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 +3 -2
- data/cookbooks/mu-tools/libraries/monkey.rb +35 -0
- 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/google_api.rb +2 -2
- data/cookbooks/mu-tools/recipes/selinux.rb +2 -1
- data/cookbooks/mu-tools/recipes/windows-client.rb +163 -164
- data/cookbooks/mu-tools/resources/disk.rb +1 -1
- data/cookbooks/mu-tools/resources/windows_users.rb +44 -43
- data/extras/clean-stock-amis +25 -19
- data/extras/generate-stock-images +1 -0
- data/extras/image-generators/AWS/win2k12.yaml +18 -13
- data/extras/image-generators/AWS/win2k16.yaml +18 -13
- data/extras/image-generators/AWS/win2k19.yaml +21 -0
- data/extras/image-generators/Google/centos6.yaml +1 -0
- data/extras/image-generators/Google/centos7.yaml +1 -1
- data/modules/mommacat.ru +6 -16
- data/modules/mu.rb +165 -111
- data/modules/mu/adoption.rb +401 -68
- data/modules/mu/cleanup.rb +199 -306
- data/modules/mu/cloud.rb +100 -1632
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +46 -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 +920 -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 +165 -0
- data/modules/mu/config.rb +171 -1767
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +4 -4
- data/modules/mu/config/cache_cluster.rb +1 -1
- data/modules/mu/config/collection.rb +4 -4
- data/modules/mu/config/container_cluster.rb +9 -4
- data/modules/mu/config/database.rb +83 -104
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +6 -6
- data/modules/mu/config/doc_helpers.rb +516 -0
- data/modules/mu/config/endpoint.rb +4 -4
- data/modules/mu/config/firewall_rule.rb +103 -4
- data/modules/mu/config/folder.rb +4 -4
- data/modules/mu/config/function.rb +3 -3
- data/modules/mu/config/group.rb +4 -4
- data/modules/mu/config/habitat.rb +4 -4
- data/modules/mu/config/loadbalancer.rb +60 -14
- data/modules/mu/config/log.rb +4 -4
- data/modules/mu/config/msg_queue.rb +4 -4
- data/modules/mu/config/nosqldb.rb +4 -4
- data/modules/mu/config/notifier.rb +3 -3
- data/modules/mu/config/ref.rb +365 -0
- data/modules/mu/config/role.rb +4 -4
- data/modules/mu/config/schema_helpers.rb +509 -0
- data/modules/mu/config/search_domain.rb +4 -4
- data/modules/mu/config/server.rb +97 -70
- data/modules/mu/config/server.yml +1 -0
- data/modules/mu/config/server_pool.rb +5 -9
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +200 -0
- data/modules/mu/config/user.rb +4 -4
- data/modules/mu/config/vpc.rb +70 -27
- data/modules/mu/config/vpc.yml +0 -1
- data/modules/mu/defaults/AWS.yaml +83 -60
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +3 -2
- data/modules/mu/deploy.rb +30 -26
- data/modules/mu/groomer.rb +17 -2
- data/modules/mu/groomers/ansible.rb +188 -41
- data/modules/mu/groomers/chef.rb +116 -55
- data/modules/mu/logger.rb +127 -148
- data/modules/mu/master.rb +389 -2
- data/modules/mu/master/chef.rb +3 -4
- data/modules/mu/master/ldap.rb +3 -3
- data/modules/mu/master/ssl.rb +12 -3
- data/modules/mu/mommacat.rb +217 -2612
- data/modules/mu/mommacat/daemon.rb +397 -0
- data/modules/mu/mommacat/naming.rb +473 -0
- data/modules/mu/mommacat/search.rb +495 -0
- data/modules/mu/mommacat/storage.rb +722 -0
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +271 -112
- data/modules/mu/{clouds → providers}/aws/alarm.rb +5 -3
- data/modules/mu/{clouds → providers}/aws/bucket.rb +26 -22
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +33 -67
- data/modules/mu/{clouds → providers}/aws/collection.rb +24 -23
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +681 -721
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +64 -63
- data/modules/mu/{clouds → providers}/aws/endpoint.rb +22 -27
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +214 -244
- data/modules/mu/{clouds → providers}/aws/folder.rb +7 -7
- data/modules/mu/{clouds → providers}/aws/function.rb +17 -22
- data/modules/mu/{clouds → providers}/aws/group.rb +23 -23
- data/modules/mu/{clouds → providers}/aws/habitat.rb +17 -14
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +57 -48
- data/modules/mu/{clouds → providers}/aws/log.rb +15 -12
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +17 -16
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +18 -11
- data/modules/mu/{clouds → providers}/aws/notifier.rb +11 -6
- data/modules/mu/{clouds → providers}/aws/role.rb +112 -86
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +39 -33
- data/modules/mu/{clouds → providers}/aws/server.rb +835 -1133
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +56 -60
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +24 -42
- data/modules/mu/{clouds → providers}/aws/user.rb +21 -22
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +2 -1
- data/modules/mu/{clouds → providers}/aws/vpc.rb +523 -929
- data/modules/mu/providers/aws/vpc_subnet.rb +286 -0
- data/modules/mu/{clouds → providers}/azure.rb +29 -9
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +3 -8
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +18 -11
- data/modules/mu/{clouds → providers}/azure/habitat.rb +8 -6
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +5 -5
- data/modules/mu/{clouds → providers}/azure/role.rb +8 -10
- data/modules/mu/{clouds → providers}/azure/server.rb +95 -48
- data/modules/mu/{clouds → providers}/azure/user.rb +6 -8
- 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 +16 -21
- data/modules/mu/{clouds → providers}/cloudformation.rb +18 -7
- 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 +5 -7
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +67 -30
- data/modules/mu/{clouds → providers}/google/bucket.rb +13 -15
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +84 -77
- data/modules/mu/{clouds → providers}/google/database.rb +10 -20
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +15 -14
- data/modules/mu/{clouds → providers}/google/folder.rb +20 -17
- data/modules/mu/{clouds → providers}/google/function.rb +139 -167
- data/modules/mu/{clouds → providers}/google/group.rb +29 -34
- data/modules/mu/{clouds → providers}/google/habitat.rb +21 -22
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +18 -20
- data/modules/mu/{clouds → providers}/google/role.rb +92 -58
- data/modules/mu/{clouds → providers}/google/server.rb +242 -155
- data/modules/mu/{clouds → providers}/google/server_pool.rb +25 -44
- data/modules/mu/{clouds → providers}/google/user.rb +95 -31
- 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 +103 -79
- data/modules/tests/bucket.yml +4 -0
- data/modules/tests/centos6.yaml +11 -0
- data/modules/tests/centos7.yaml +11 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +23 -0
- data/modules/tests/includes-and-params.yaml +2 -1
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/aws-iam.yaml +201 -0
- data/modules/tests/regrooms/bucket.yml +19 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +1 -0
- data/modules/tests/super_simple_bok.yml +1 -3
- data/modules/tests/win2k12.yaml +17 -5
- data/modules/tests/win2k16.yaml +25 -0
- data/modules/tests/win2k19.yaml +25 -0
- data/requirements.txt +1 -0
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +232 -154
- data/extras/image-generators/AWS/windows.yaml +0 -18
- data/modules/mu/clouds/aws/database.rb +0 -1985
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# Copyright:: Copyright (c) 2020 eGlobalTech, Inc., all rights reserved
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the BSD-3 license (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License in the root of the project or at
|
|
6
|
+
#
|
|
7
|
+
# http://egt-labs.com/mu/LICENSE.html
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
module MU
|
|
16
|
+
class Cloud
|
|
17
|
+
class AWS
|
|
18
|
+
|
|
19
|
+
# Creation of Virtual Private Clouds and associated artifacts (routes, subnets, etc).
|
|
20
|
+
class VPC < MU::Cloud::VPC
|
|
21
|
+
|
|
22
|
+
# Subnets are almost a first-class resource. So let's kinda sorta treat
|
|
23
|
+
# them like one. This should only be invoked on objects that already
|
|
24
|
+
# exists in the cloud layer.
|
|
25
|
+
class Subnet < MU::Cloud::AWS::VPC
|
|
26
|
+
|
|
27
|
+
attr_reader :cloud_id
|
|
28
|
+
attr_reader :ip_block
|
|
29
|
+
attr_reader :mu_name
|
|
30
|
+
attr_reader :name
|
|
31
|
+
attr_reader :az
|
|
32
|
+
attr_reader :cloud_desc
|
|
33
|
+
|
|
34
|
+
# @param parent [MU::Cloud::AWS::VPC]: The parent VPC of this subnet.
|
|
35
|
+
# @param config [Hash<String>]:
|
|
36
|
+
def initialize(parent, config)
|
|
37
|
+
@parent = parent
|
|
38
|
+
@config = MU::Config.manxify(config)
|
|
39
|
+
@cloud_id = config['cloud_id']
|
|
40
|
+
@mu_name = config['mu_name']
|
|
41
|
+
@name = config['name']
|
|
42
|
+
@deploydata = config # This is a dummy for the sake of describe()
|
|
43
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_subnets(subnet_ids: [@cloud_id]).subnets.first
|
|
44
|
+
@az = resp.availability_zone
|
|
45
|
+
@ip_block = resp.cidr_block
|
|
46
|
+
@cloud_desc = resp # XXX this really isn't the cloud implementation's business
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Return the cloud identifier for the default route of this subnet.
|
|
51
|
+
# @return [String,nil]
|
|
52
|
+
def defaultRoute
|
|
53
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_route_tables(
|
|
54
|
+
filters: [{name: "association.subnet-id", values: [@cloud_id]}]
|
|
55
|
+
)
|
|
56
|
+
if resp.route_tables.size == 0 # use default route table for the VPC
|
|
57
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_route_tables(
|
|
58
|
+
filters: [{name: "vpc-id", values: [@parent.cloud_id]}]
|
|
59
|
+
)
|
|
60
|
+
end
|
|
61
|
+
resp.route_tables.each { |route_table|
|
|
62
|
+
route_table.routes.each { |route|
|
|
63
|
+
if route.destination_cidr_block =="0.0.0.0/0" and route.state != "blackhole"
|
|
64
|
+
return route.instance_id if !route.instance_id.nil?
|
|
65
|
+
return route.gateway_id if !route.gateway_id.nil?
|
|
66
|
+
return route.vpc_peering_connection_id if !route.vpc_peering_connection_id.nil?
|
|
67
|
+
return route.network_interface_id if !route.network_interface_id.nil?
|
|
68
|
+
end
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return nil
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Is this subnet privately-routable only, or public?
|
|
75
|
+
# @return [Boolean]
|
|
76
|
+
def private?
|
|
77
|
+
return false if @cloud_id.nil?
|
|
78
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_route_tables(
|
|
79
|
+
filters: [{name: "association.subnet-id", values: [@cloud_id]}]
|
|
80
|
+
)
|
|
81
|
+
if resp.route_tables.size == 0 # use default route table for the VPC
|
|
82
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_route_tables(
|
|
83
|
+
filters: [{name: "vpc-id", values: [@parent.cloud_id]}]
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
resp.route_tables.each { |route_table|
|
|
87
|
+
route_table.routes.each { |route|
|
|
88
|
+
return false if !route.gateway_id.nil? and route.gateway_id != "local" # you can have an IgW and route it to a subset of IPs instead of 0.0.0.0/0
|
|
89
|
+
if route.destination_cidr_block == "0.0.0.0/0"
|
|
90
|
+
return true if !route.instance_id.nil?
|
|
91
|
+
return true if route.nat_gateway_id
|
|
92
|
+
end
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return true
|
|
96
|
+
end
|
|
97
|
+
end # VPC::Subnet class
|
|
98
|
+
|
|
99
|
+
private
|
|
100
|
+
|
|
101
|
+
def create_subnets
|
|
102
|
+
return [] if @config['subnets'].nil? or @config['subnets'].empty?
|
|
103
|
+
nat_gateways = []
|
|
104
|
+
|
|
105
|
+
@eip_allocation_ids ||= []
|
|
106
|
+
|
|
107
|
+
subnetthreads = Array.new
|
|
108
|
+
|
|
109
|
+
azs = MU::Cloud::AWS.listAZs(region: @config['region'], credentials: @config['credentials'])
|
|
110
|
+
@config['subnets'].each { |subnet|
|
|
111
|
+
subnet_name = @config['name']+"-"+subnet['name']
|
|
112
|
+
az = subnet['availability_zone'] ? subnet['availability_zone'] : azs.op
|
|
113
|
+
MU.log "Creating Subnet #{subnet_name} (#{subnet['ip_block']}) in #{az}", details: subnet
|
|
114
|
+
|
|
115
|
+
subnetthreads << Thread.new {
|
|
116
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_subnet(
|
|
117
|
+
vpc_id: @cloud_id,
|
|
118
|
+
cidr_block: subnet['ip_block'],
|
|
119
|
+
availability_zone: az
|
|
120
|
+
).subnet
|
|
121
|
+
subnet_id = subnet['subnet_id'] = resp.subnet_id
|
|
122
|
+
|
|
123
|
+
tag_me(subnet_id, @mu_name+"-"+subnet['name'])
|
|
124
|
+
|
|
125
|
+
loop_if = Proc.new {
|
|
126
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_subnets(subnet_ids: [subnet_id]).subnets.first
|
|
127
|
+
(!resp or resp.state != "available")
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
MU.retrier([Aws::EC2::Errors::InvalidSubnetIDNotFound, NoMethodError], wait: 5, loop_if: loop_if) { |retries, _wait|
|
|
131
|
+
MU.log "Waiting for Subnet #{subnet_name} (#{subnet_id}) to become available", MU::NOTICE if retries > 0 and (retries % 3) == 0
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if !subnet['route_table'].nil?
|
|
135
|
+
routes = {}
|
|
136
|
+
@config['route_tables'].each { |tbl|
|
|
137
|
+
routes[tbl['name']] = tbl
|
|
138
|
+
}
|
|
139
|
+
if routes[subnet['route_table']].nil?
|
|
140
|
+
raise "Subnet #{subnet_name} references nonexistent route #{subnet['route_table']}"
|
|
141
|
+
end
|
|
142
|
+
MU.log "Associating Route Table '#{subnet['route_table']}' (#{routes[subnet['route_table']]['route_table_id']}) with #{subnet_name}"
|
|
143
|
+
MU.retrier([Aws::EC2::Errors::InvalidRouteTableIDNotFound], wait: 10, max: 10) {
|
|
144
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).associate_route_table(
|
|
145
|
+
route_table_id: routes[subnet['route_table']]['route_table_id'],
|
|
146
|
+
subnet_id: subnet_id
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
if subnet.has_key?("map_public_ips")
|
|
152
|
+
MU.retrier([Aws::EC2::Errors::InvalidSubnetIDNotFound], wait: 10, max: 10) {
|
|
153
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).modify_subnet_attribute(
|
|
154
|
+
subnet_id: subnet_id,
|
|
155
|
+
map_public_ip_on_launch: {
|
|
156
|
+
value: subnet['map_public_ips'],
|
|
157
|
+
}
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
if subnet['is_public'] and subnet['create_nat_gateway']
|
|
163
|
+
nat_gateways << create_nat_gateway(subnet)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
if subnet["enable_traffic_logging"]
|
|
167
|
+
loggroup = @deploy.findLitterMate(name: @config['name']+"loggroup", type: "logs")
|
|
168
|
+
logrole = @deploy.findLitterMate(name: @config['name']+"logrole", type: "roles")
|
|
169
|
+
MU.log "Enabling traffic logging on Subnet #{subnet_name} in VPC #{@mu_name} to log group #{loggroup.mu_name}"
|
|
170
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_flow_logs(
|
|
171
|
+
resource_ids: [subnet_id],
|
|
172
|
+
resource_type: "Subnet",
|
|
173
|
+
traffic_type: subnet["traffic_type_to_log"],
|
|
174
|
+
log_group_name: loggroup.mu_name,
|
|
175
|
+
deliver_logs_permission_arn: logrole.cloudobj.arn
|
|
176
|
+
)
|
|
177
|
+
end
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
subnetthreads.each { |t|
|
|
182
|
+
t.join
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
nat_gateways
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def allocate_eip_for_nat
|
|
189
|
+
MU::MommaCat.lock("nat-gateway-eipalloc")
|
|
190
|
+
|
|
191
|
+
eips = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_addresses(
|
|
192
|
+
filters: [
|
|
193
|
+
{
|
|
194
|
+
name: "domain",
|
|
195
|
+
values: ["vpc"]
|
|
196
|
+
}
|
|
197
|
+
]
|
|
198
|
+
).addresses
|
|
199
|
+
|
|
200
|
+
allocation_id = nil
|
|
201
|
+
eips.each { |eip|
|
|
202
|
+
next if !eip.association_id.nil? and !eip.association_id.empty?
|
|
203
|
+
if (eip.private_ip_address.nil? || eip.private_ip_address.empty?) and MU::MommaCat.lock(eip.allocation_id, true, true)
|
|
204
|
+
if !@eip_allocation_ids.include?(eip.allocation_id)
|
|
205
|
+
allocation_id = eip.allocation_id
|
|
206
|
+
break
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if allocation_id.nil?
|
|
212
|
+
allocation_id = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).allocate_address(domain: "vpc").allocation_id
|
|
213
|
+
MU::MommaCat.lock(allocation_id, false, true)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
@eip_allocation_ids << allocation_id
|
|
217
|
+
|
|
218
|
+
MU::MommaCat.unlock("nat-gateway-eipalloc")
|
|
219
|
+
|
|
220
|
+
allocation_id
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def create_nat_gateway(subnet)
|
|
224
|
+
allocation_id = allocate_eip_for_nat
|
|
225
|
+
|
|
226
|
+
nat_gateway_id = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_nat_gateway(
|
|
227
|
+
subnet_id: subnet['subnet_id'],
|
|
228
|
+
allocation_id: allocation_id,
|
|
229
|
+
).nat_gateway.nat_gateway_id
|
|
230
|
+
|
|
231
|
+
ensure_unlock = Proc.new { MU::MommaCat.unlock(allocation_id, true) }
|
|
232
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_nat_gateways(nat_gateway_ids: [nat_gateway_id]).nat_gateways.first
|
|
233
|
+
loop_if = Proc.new {
|
|
234
|
+
resp = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_nat_gateways(nat_gateway_ids: [nat_gateway_id]).nat_gateways.first
|
|
235
|
+
resp.class != Aws::EC2::Types::NatGateway or resp.state == "pending"
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
MU.retrier([Aws::EmptyStructure, NoMethodError], wait: 5, max: 30, always: ensure_unlock, loop_if: loop_if) { |retries, _wait|
|
|
239
|
+
MU.log "Waiting for nat gateway #{nat_gateway_id} to become available (EIP allocation: #{allocation_id})" if retries % 5 == 0
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
raise MuError, "NAT Gateway failed #{nat_gateway_id}: #{resp}" if resp.state == "failed"
|
|
243
|
+
|
|
244
|
+
tag_me(nat_gateway_id)
|
|
245
|
+
|
|
246
|
+
{'id' => nat_gateway_id, 'availability_zone' => subnet['availability_zone']}
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# Remove all subnets associated with the currently loaded deployment.
|
|
250
|
+
# @param noop [Boolean]: If true, will only print what would be done
|
|
251
|
+
# @param tagfilters [Array<Hash>]: EC2 tags to filter against when search for resources to purge
|
|
252
|
+
# @param region [String]: The cloud provider region
|
|
253
|
+
# @return [void]
|
|
254
|
+
def self.purge_subnets(noop = false, tagfilters = [{name: "tag:MU-ID", values: [MU.deploy_id]}], region: MU.curRegion, credentials: nil)
|
|
255
|
+
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_subnets(
|
|
256
|
+
filters: tagfilters
|
|
257
|
+
)
|
|
258
|
+
subnets = resp.data.subnets
|
|
259
|
+
|
|
260
|
+
return if subnets.nil? or subnets.size == 0
|
|
261
|
+
|
|
262
|
+
subnets.each { |subnet|
|
|
263
|
+
on_retry = Proc.new {
|
|
264
|
+
MU::Cloud::AWS::VPC.purge_interfaces(noop, [{name: "subnet-id", values: [subnet.subnet_id]}], region: region, credentials: credentials)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
MU.log "Deleting Subnet #{subnet.subnet_id}"
|
|
268
|
+
MU.retrier([Aws::EC2::Errors::DependencyViolation], ignoreme: [Aws::EC2::Errors::InvalidSubnetIDNotFound], max: 20, on_retry: on_retry) { |_retries, wait|
|
|
269
|
+
begin
|
|
270
|
+
if subnet.state != "available"
|
|
271
|
+
MU.log "Waiting for #{subnet.subnet_id} to be in a removable state...", MU::NOTICE
|
|
272
|
+
sleep wait
|
|
273
|
+
else
|
|
274
|
+
MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_subnet(subnet_id: subnet.subnet_id) if !noop
|
|
275
|
+
end
|
|
276
|
+
end while subnet.state != "available"
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
end
|
|
280
|
+
private_class_method :purge_subnets
|
|
281
|
+
|
|
282
|
+
end # VPC class
|
|
283
|
+
|
|
284
|
+
end #class
|
|
285
|
+
end
|
|
286
|
+
end #module
|
|
@@ -47,6 +47,11 @@ module MU
|
|
|
47
47
|
guid_chunks.join("-")
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
# List all Azure subscriptions available to our credentials
|
|
51
|
+
def self.listHabitats(credentials = nil, use_cache: true)
|
|
52
|
+
[]
|
|
53
|
+
end
|
|
54
|
+
|
|
50
55
|
# A hook that is always called just before any of the instance method of
|
|
51
56
|
# our resource implementations gets invoked, so that we can ensure that
|
|
52
57
|
# repetitive setup tasks (like resolving +:resource_group+ for Azure
|
|
@@ -77,6 +82,11 @@ module MU
|
|
|
77
82
|
[:resource_group]
|
|
78
83
|
end
|
|
79
84
|
|
|
85
|
+
# Is this a "real" cloud provider, or a stub like CloudFormation?
|
|
86
|
+
def self.virtual?
|
|
87
|
+
false
|
|
88
|
+
end
|
|
89
|
+
|
|
80
90
|
# Stub class to represent Azure's resource identifiers, which look like:
|
|
81
91
|
# /subscriptions/3d20ddd8-4652-4074-adda-0d127ef1f0e0/resourceGroups/mu/providers/Microsoft.Network/virtualNetworks/mu-vnet
|
|
82
92
|
# Various API calls need chunks of this in different contexts, and this
|
|
@@ -101,11 +111,11 @@ module MU
|
|
|
101
111
|
def initialize(*args)
|
|
102
112
|
if args.first.is_a?(String)
|
|
103
113
|
@raw = args.first
|
|
104
|
-
|
|
114
|
+
_junk, _junk2, @subscription, _junk3, @resource_group, _junk4, @provider, @resource_type, @name = @raw.split(/\//)
|
|
105
115
|
if @subscription.nil? or @resource_group.nil? or @provider.nil? or @resource_type.nil? or @name.nil?
|
|
106
116
|
# Not everything has a resource group
|
|
107
117
|
if @raw.match(/^\/subscriptions\/#{Regexp.quote(@subscription)}\/providers/)
|
|
108
|
-
|
|
118
|
+
_junk, _junk2, @subscription, _junk3, @provider, @resource_type, @name = @raw.split(/\//)
|
|
109
119
|
if @subscription.nil? or @provider.nil? or @resource_type.nil? or @name.nil?
|
|
110
120
|
raise MuError, "Failed to parse Azure resource id string #{@raw} (got subscription: #{@subscription}, provider: #{@provider}, resource_type: #{@resource_type}, name: #{@name}"
|
|
111
121
|
end
|
|
@@ -266,7 +276,7 @@ module MU
|
|
|
266
276
|
|
|
267
277
|
begin
|
|
268
278
|
sdk_response = MU::Cloud::Azure.subs(credentials: credentials).subscriptions().list_locations(subscription)
|
|
269
|
-
rescue
|
|
279
|
+
rescue StandardError => e
|
|
270
280
|
MU.log e.inspect, MU::ERR, details: e.backtrace
|
|
271
281
|
#pp "Error Getting the list of regions from Azure" #TODO: SWITCH THIS TO MU LOG
|
|
272
282
|
if @@regions and @@regions.size > 0
|
|
@@ -274,6 +284,9 @@ module MU
|
|
|
274
284
|
end
|
|
275
285
|
raise e
|
|
276
286
|
end
|
|
287
|
+
if !sdk_response
|
|
288
|
+
raise MuError, "Nil response from Azure API attempting list_locations(#{subscription})"
|
|
289
|
+
end
|
|
277
290
|
|
|
278
291
|
sdk_response.value.each do | region |
|
|
279
292
|
@@regions.push(region.name)
|
|
@@ -378,7 +391,7 @@ module MU
|
|
|
378
391
|
rg_obj = MU::Cloud::Azure.resources(:ResourceGroup).new
|
|
379
392
|
rg_obj.location = region
|
|
380
393
|
rg_obj.tags = MU::MommaCat.listStandardTags
|
|
381
|
-
rg_obj.tags.reject! { |
|
|
394
|
+
rg_obj.tags.reject! { |_k, v| v.nil? }
|
|
382
395
|
|
|
383
396
|
MU::Cloud::Azure.resources(credentials: credentials).resource_groups.list.each { |rg|
|
|
384
397
|
if rg.name == name and rg.location == region and rg.tags == rg_obj.tags
|
|
@@ -519,7 +532,7 @@ module MU
|
|
|
519
532
|
end
|
|
520
533
|
return @@metadata
|
|
521
534
|
|
|
522
|
-
rescue Timeout::Error
|
|
535
|
+
rescue Timeout::Error
|
|
523
536
|
# MU.log "Timeout querying Azure Metadata"
|
|
524
537
|
return nil
|
|
525
538
|
rescue
|
|
@@ -906,7 +919,6 @@ module MU
|
|
|
906
919
|
# END SDK STUBS
|
|
907
920
|
|
|
908
921
|
# BEGIN SDK CLIENT
|
|
909
|
-
private
|
|
910
922
|
|
|
911
923
|
@@authorization_api = {}
|
|
912
924
|
@@subscriptions_api = {}
|
|
@@ -967,7 +979,7 @@ module MU
|
|
|
967
979
|
begin
|
|
968
980
|
modelpath = "::Azure::#{api}::Mgmt::#{profile}::#{@subclass}"
|
|
969
981
|
@api = Object.const_get(modelpath).new(@cred_obj)
|
|
970
|
-
rescue NameError
|
|
982
|
+
rescue NameError
|
|
971
983
|
raise MuError, "Unable to locate a profile #{profile} of Azure API #{api}. I tried:\n#{stdpath}\n#{modelpath}"
|
|
972
984
|
end
|
|
973
985
|
end
|
|
@@ -1017,6 +1029,7 @@ module MU
|
|
|
1017
1029
|
# @param arguments [Array]
|
|
1018
1030
|
def method_missing(method_sym, *arguments)
|
|
1019
1031
|
MU.log "Calling #{@parentname}.#{@myname}.#{method_sym.to_s}", MU::DEBUG, details: arguments
|
|
1032
|
+
retries = 0
|
|
1020
1033
|
begin
|
|
1021
1034
|
if !arguments.nil? and arguments.size == 1
|
|
1022
1035
|
retval = @myobject.method(method_sym).call(arguments[0])
|
|
@@ -1025,9 +1038,16 @@ module MU
|
|
|
1025
1038
|
else
|
|
1026
1039
|
retval = @myobject.method(method_sym).call
|
|
1027
1040
|
end
|
|
1028
|
-
rescue ::Net::ReadTimeout, ::Faraday::TimeoutError => e
|
|
1041
|
+
rescue ::Net::ReadTimeout, ::Faraday::TimeoutError, ::Faraday::ConnectionFailed => e
|
|
1029
1042
|
sleep 5
|
|
1030
|
-
|
|
1043
|
+
if retries < 12
|
|
1044
|
+
MU.log e.message+" calling #{@parentname}.#{@myname}.#{method_sym.to_s}(#{arguments.map { |a| a.to_s }.join(", ")})", MU::DEBUG, details: caller
|
|
1045
|
+
retries += 1
|
|
1046
|
+
retry
|
|
1047
|
+
else
|
|
1048
|
+
MU.log e.message+" calling #{@parentname}.#{@myname}.#{method_sym.to_s}(#{arguments.map { |a| a.to_s }.join(", ")})", MU::ERR, details: caller
|
|
1049
|
+
raise e
|
|
1050
|
+
end
|
|
1031
1051
|
rescue ::MsRestAzure::AzureOperationError, ::MsRest::HttpOperationError => e
|
|
1032
1052
|
MU.log "Error calling #{@parent.api.class.name}.#{@myname}.#{method_sym.to_s}", MU::DEBUG, details: arguments
|
|
1033
1053
|
begin
|
|
@@ -119,7 +119,6 @@ module MU
|
|
|
119
119
|
|
|
120
120
|
# Register a description of this cluster instance with this deployment's metadata.
|
|
121
121
|
def notify
|
|
122
|
-
base = {}
|
|
123
122
|
base = MU.structToHash(cloud_desc)
|
|
124
123
|
base["cloud_id"] = @cloud_id.name
|
|
125
124
|
base.merge!(@config.to_h)
|
|
@@ -146,9 +145,9 @@ module MU
|
|
|
146
145
|
end
|
|
147
146
|
|
|
148
147
|
# Cloud-specific configuration properties.
|
|
149
|
-
# @param
|
|
148
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
150
149
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
151
|
-
def self.schema(
|
|
150
|
+
def self.schema(_config)
|
|
152
151
|
toplevel_required = []
|
|
153
152
|
schema = {
|
|
154
153
|
"flavor" => {
|
|
@@ -219,11 +218,7 @@ module MU
|
|
|
219
218
|
"Azure Kubernetes Service Cluster Admin Role"
|
|
220
219
|
]
|
|
221
220
|
}
|
|
222
|
-
cluster['
|
|
223
|
-
cluster['dependencies'] << {
|
|
224
|
-
"type" => "user",
|
|
225
|
-
"name" => cluster["name"]+"user"
|
|
226
|
-
}
|
|
221
|
+
MU::Config.addDependency(cluster, cluster['name']+"user", "user")
|
|
227
222
|
|
|
228
223
|
ok = false if !configurator.insertKitten(svcacct_desc, "users")
|
|
229
224
|
|
|
@@ -53,7 +53,7 @@ module MU
|
|
|
53
53
|
oldrules[rule.name] = rule
|
|
54
54
|
end
|
|
55
55
|
}
|
|
56
|
-
used_priorities = oldrules.values.map { |r| r.priority }
|
|
56
|
+
# used_priorities = oldrules.values.map { |r| r.priority }
|
|
57
57
|
|
|
58
58
|
newrules_semaphore = Mutex.new
|
|
59
59
|
num_rules = 0
|
|
@@ -136,12 +136,12 @@ module MU
|
|
|
136
136
|
}
|
|
137
137
|
end
|
|
138
138
|
|
|
139
|
-
resolved_lbs = []
|
|
140
|
-
if lbs
|
|
141
|
-
lbs.each { |lb|
|
|
139
|
+
# resolved_lbs = []
|
|
140
|
+
# if lbs
|
|
141
|
+
# lbs.each { |lb|
|
|
142
142
|
# TODO awaiting LoadBalancer implementation
|
|
143
|
-
}
|
|
144
|
-
end
|
|
143
|
+
# }
|
|
144
|
+
# end
|
|
145
145
|
|
|
146
146
|
if egress
|
|
147
147
|
rule_obj.direction = MU::Cloud::Azure.network(:SecurityRuleDirection)::Outbound
|
|
@@ -295,7 +295,7 @@ module MU
|
|
|
295
295
|
resp = MU::Cloud::Azure.network(credentials: args[:credentials]).network_security_groups.get(rg, id_str)
|
|
296
296
|
next if resp.nil?
|
|
297
297
|
found[Id.new(resp.id)] = resp
|
|
298
|
-
rescue MU::Cloud::Azure::APIError
|
|
298
|
+
rescue MU::Cloud::Azure::APIError
|
|
299
299
|
# this is fine, we're doing a blind search after all
|
|
300
300
|
end
|
|
301
301
|
}
|
|
@@ -336,16 +336,23 @@ module MU
|
|
|
336
336
|
# Reverse-map our cloud description into a runnable config hash.
|
|
337
337
|
# We assume that any values we have in +@config+ are placeholders, and
|
|
338
338
|
# calculate our own accordingly based on what's live in the cloud.
|
|
339
|
-
def toKitten(
|
|
340
|
-
|
|
339
|
+
def toKitten(**args)
|
|
340
|
+
|
|
341
|
+
bok = {
|
|
342
|
+
"cloud" => "Azure",
|
|
343
|
+
"name" => cloud_desc.name,
|
|
344
|
+
"project" => @config['project'],
|
|
345
|
+
"credentials" => @config['credentials'],
|
|
346
|
+
"cloud_id" => @cloud_id.to_s
|
|
347
|
+
}
|
|
341
348
|
|
|
342
349
|
bok
|
|
343
350
|
end
|
|
344
351
|
|
|
345
352
|
# Cloud-specific configuration properties.
|
|
346
|
-
# @param
|
|
353
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
347
354
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
348
|
-
def self.schema(
|
|
355
|
+
def self.schema(_config = nil)
|
|
349
356
|
toplevel_required = []
|
|
350
357
|
hosts_schema = MU::Config::CIDR_PRIMITIVE
|
|
351
358
|
hosts_schema["pattern"] = "^(\\d+\\.\\d+\\.\\d+\\.\\d+\/[0-9]{1,2}|\\*)$"
|