cloud-mu 3.1.3 → 3.3.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 +21 -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 +4 -4
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +147 -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 +158 -111
- data/modules/mu/adoption.rb +404 -71
- data/modules/mu/cleanup.rb +221 -306
- data/modules/mu/cloud.rb +129 -1633
- 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 +926 -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 +171 -1767
- 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 +4 -4
- data/modules/mu/config/container_cluster.rb +9 -4
- data/modules/mu/config/database.rb +84 -105
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +10 -9
- data/modules/mu/config/doc_helpers.rb +516 -0
- data/modules/mu/config/endpoint.rb +5 -4
- data/modules/mu/config/firewall_rule.rb +103 -4
- data/modules/mu/config/folder.rb +4 -4
- data/modules/mu/config/function.rb +19 -10
- data/modules/mu/config/group.rb +4 -4
- data/modules/mu/config/habitat.rb +4 -4
- data/modules/mu/config/job.rb +89 -0
- 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 +10 -21
- data/modules/mu/config/ref.rb +411 -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 +98 -71
- 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 +71 -27
- data/modules/mu/config/vpc.yml +0 -1
- data/modules/mu/defaults/AWS.yaml +91 -68
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +3 -2
- data/modules/mu/deploy.rb +43 -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 +410 -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 +218 -2612
- data/modules/mu/mommacat/daemon.rb +403 -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 +380 -122
- data/modules/mu/{clouds → providers}/aws/alarm.rb +7 -5
- data/modules/mu/{clouds → providers}/aws/bucket.rb +297 -59
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +37 -71
- data/modules/mu/providers/aws/cdn.rb +782 -0
- data/modules/mu/{clouds → providers}/aws/collection.rb +26 -25
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +724 -744
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +88 -70
- data/modules/mu/providers/aws/endpoint.rb +1072 -0
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +220 -247
- data/modules/mu/{clouds → providers}/aws/folder.rb +8 -8
- data/modules/mu/{clouds → providers}/aws/function.rb +300 -142
- data/modules/mu/{clouds → providers}/aws/group.rb +31 -29
- data/modules/mu/{clouds → providers}/aws/habitat.rb +18 -15
- data/modules/mu/providers/aws/job.rb +466 -0
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +66 -56
- data/modules/mu/{clouds → providers}/aws/log.rb +17 -14
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +29 -19
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +114 -16
- data/modules/mu/{clouds → providers}/aws/notifier.rb +142 -65
- data/modules/mu/{clouds → providers}/aws/role.rb +158 -118
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +201 -59
- data/modules/mu/{clouds → providers}/aws/server.rb +844 -1139
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +74 -65
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +26 -44
- data/modules/mu/{clouds → providers}/aws/user.rb +24 -25
- 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 +2 -1
- data/modules/mu/{clouds → providers}/aws/vpc.rb +525 -931
- 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 +97 -49
- 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 +68 -30
- data/modules/mu/{clouds → providers}/google/bucket.rb +13 -15
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +85 -78
- data/modules/mu/{clouds → providers}/google/database.rb +11 -21
- 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 +140 -168
- 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 +19 -21
- data/modules/mu/{clouds → providers}/google/role.rb +94 -58
- data/modules/mu/{clouds → providers}/google/server.rb +243 -156
- data/modules/mu/{clouds → providers}/google/server_pool.rb +26 -45
- 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/aws-jobs-functions.yaml +46 -0
- data/modules/tests/bucket.yml +4 -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 +23 -0
- 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/includes-and-params.yaml +2 -1
- data/modules/tests/microservice_app.yaml +288 -0
- 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 +2 -1
- data/modules/tests/super_complex_bok.yml +2 -2
- data/modules/tests/super_simple_bok.yml +3 -5
- 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 +240 -154
- data/extras/image-generators/AWS/windows.yaml +0 -18
- data/modules/mu/clouds/aws/database.rb +0 -1985
- data/modules/mu/clouds/aws/endpoint.rb +0 -592
|
@@ -59,8 +59,10 @@ module MU
|
|
|
59
59
|
def groom
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
@cached_cloud_desc = nil
|
|
62
63
|
# Return the cloud descriptor for the Habitat
|
|
63
|
-
def cloud_desc
|
|
64
|
+
def cloud_desc(use_cache: true)
|
|
65
|
+
return @cached_cloud_desc if @cached_cloud_desc and use_cache
|
|
64
66
|
@cached_cloud_desc ||= MU::Cloud::Azure::Habitat.find(cloud_id: @cloud_id).values.first
|
|
65
67
|
# @habitat_id ||= @cached_cloud_desc.parent.id if @cached_cloud_desc
|
|
66
68
|
@cached_cloud_desc
|
|
@@ -131,7 +133,7 @@ module MU
|
|
|
131
133
|
# Reverse-map our cloud description into a runnable config hash.
|
|
132
134
|
# We assume that any values we have in +@config+ are placeholders, and
|
|
133
135
|
# calculate our own accordingly based on what's live in the cloud.
|
|
134
|
-
def toKitten(
|
|
136
|
+
def toKitten(**args)
|
|
135
137
|
bok = {
|
|
136
138
|
"cloud" => "Azure",
|
|
137
139
|
"credentials" => @config['credentials']
|
|
@@ -141,9 +143,9 @@ module MU
|
|
|
141
143
|
end
|
|
142
144
|
|
|
143
145
|
# Cloud-specific configuration properties.
|
|
144
|
-
# @param
|
|
146
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
145
147
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
146
|
-
def self.schema(
|
|
148
|
+
def self.schema(_config)
|
|
147
149
|
toplevel_required = []
|
|
148
150
|
schema = {
|
|
149
151
|
}
|
|
@@ -152,9 +154,9 @@ module MU
|
|
|
152
154
|
|
|
153
155
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::habitats}, bare and unvalidated.
|
|
154
156
|
# @param habitat [Hash]: The resource to process and validate
|
|
155
|
-
# @param
|
|
157
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
156
158
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
157
|
-
def self.validateConfig(habitat,
|
|
159
|
+
def self.validateConfig(habitat, _configurator)
|
|
158
160
|
ok = true
|
|
159
161
|
habitat['region'] ||= MU::Cloud::Azure.myRegion(habitat['credentials'])
|
|
160
162
|
|
|
@@ -74,9 +74,9 @@ module MU
|
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
# Cloud-specific configuration properties.
|
|
77
|
-
# @param
|
|
77
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
78
78
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
79
|
-
def self.schema(
|
|
79
|
+
def self.schema(_config)
|
|
80
80
|
toplevel_required = []
|
|
81
81
|
schema = {
|
|
82
82
|
# "named_ports" => {
|
|
@@ -102,9 +102,9 @@ module MU
|
|
|
102
102
|
|
|
103
103
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::loadbalancers}, bare and unvalidated.
|
|
104
104
|
# @param lb [Hash]: The resource to process and validate
|
|
105
|
-
# @param
|
|
105
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
106
106
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
107
|
-
def self.validateConfig(lb,
|
|
107
|
+
def self.validateConfig(lb, _configurator)
|
|
108
108
|
ok = true
|
|
109
109
|
lb['region'] ||= MU::Cloud::Azure.myRegion(lb['credentials'])
|
|
110
110
|
|
|
@@ -144,7 +144,7 @@ module MU
|
|
|
144
144
|
found[Id.new(lb.id)] = lb
|
|
145
145
|
}
|
|
146
146
|
else
|
|
147
|
-
MU::Cloud::Azure.network(credentials: args[:credentials]).load_balancers.list_all.each { |
|
|
147
|
+
MU::Cloud::Azure.network(credentials: args[:credentials]).load_balancers.list_all.each { |lb|
|
|
148
148
|
found[Id.new(lb.id)] = lb
|
|
149
149
|
}
|
|
150
150
|
end
|
|
@@ -65,8 +65,8 @@ module MU
|
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
# Assign this role object to a given principal (create a RoleAssignment)
|
|
68
|
-
# @param
|
|
69
|
-
def assignTo(
|
|
68
|
+
# @param principal_id [MU::Cloud::Azure::Id]
|
|
69
|
+
def assignTo(principal_id)
|
|
70
70
|
MU::Cloud::Azure::Role.assignTo(principal_id, role_id: @cloud_id)
|
|
71
71
|
end
|
|
72
72
|
|
|
@@ -145,7 +145,7 @@ module MU
|
|
|
145
145
|
begin
|
|
146
146
|
resp = MU::Cloud::Azure.authorization(credentials: args[:credentials]).role_definitions.get(scope, id_str)
|
|
147
147
|
found[Id.new(resp.id)] = resp
|
|
148
|
-
rescue MsRestAzure::AzureOperationError
|
|
148
|
+
rescue MsRestAzure::AzureOperationError
|
|
149
149
|
# this is fine, we're doing a blind search after all
|
|
150
150
|
end
|
|
151
151
|
else
|
|
@@ -155,7 +155,7 @@ module MU
|
|
|
155
155
|
end
|
|
156
156
|
}
|
|
157
157
|
if args[:role_name]
|
|
158
|
-
@@role_list_cache[scope].
|
|
158
|
+
@@role_list_cache[scope].values.each { |role|
|
|
159
159
|
begin
|
|
160
160
|
if role.role_name == args[:role_name]
|
|
161
161
|
found[Id.new(role.id)] = role
|
|
@@ -183,9 +183,9 @@ module MU
|
|
|
183
183
|
end
|
|
184
184
|
|
|
185
185
|
# Cloud-specific configuration properties.
|
|
186
|
-
# @param
|
|
186
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
187
187
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
188
|
-
def self.schema(
|
|
188
|
+
def self.schema(_config)
|
|
189
189
|
toplevel_required = []
|
|
190
190
|
schema = {
|
|
191
191
|
}
|
|
@@ -194,17 +194,15 @@ module MU
|
|
|
194
194
|
|
|
195
195
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::roles}, bare and unvalidated.
|
|
196
196
|
# @param role [Hash]: The resource to process and validate
|
|
197
|
-
# @param
|
|
197
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
198
198
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
199
|
-
def self.validateConfig(role,
|
|
199
|
+
def self.validateConfig(role, _configurator)
|
|
200
200
|
ok = true
|
|
201
201
|
role['region'] ||= MU::Cloud::Azure.myRegion(role['credentials'])
|
|
202
202
|
|
|
203
203
|
ok
|
|
204
204
|
end
|
|
205
205
|
|
|
206
|
-
private
|
|
207
|
-
|
|
208
206
|
end
|
|
209
207
|
end
|
|
210
208
|
end
|
|
@@ -139,21 +139,21 @@ module MU
|
|
|
139
139
|
# Figure out what's needed to SSH into this server.
|
|
140
140
|
# @return [Array<String>]: nat_ssh_key, nat_ssh_user, nat_ssh_host, canonical_ip, ssh_user, ssh_key_name, alternate_names
|
|
141
141
|
def getSSHConfig
|
|
142
|
-
|
|
142
|
+
describe(cloud_id: @cloud_id)
|
|
143
143
|
# XXX add some awesome alternate names from metadata and make sure they end
|
|
144
144
|
# up in MU::MommaCat's ssh config wangling
|
|
145
145
|
ssh_keydir = Etc.getpwuid(Process.uid).dir+"/.ssh"
|
|
146
146
|
return nil if @config.nil? or @deploy.nil?
|
|
147
147
|
|
|
148
148
|
nat_ssh_key = nat_ssh_user = nat_ssh_host = nil
|
|
149
|
-
if !@config["vpc"].nil? and !MU::Cloud
|
|
149
|
+
if !@config["vpc"].nil? and !MU::Cloud.resourceClass("Azure", "VPC").haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @config['credentials'])
|
|
150
150
|
|
|
151
151
|
if !@nat.nil? and @nat.mu_name != @mu_name
|
|
152
152
|
if @nat.cloud_desc.nil?
|
|
153
153
|
MU.log "NAT was missing cloud descriptor when called in #{@mu_name}'s getSSHConfig", MU::ERR
|
|
154
154
|
return nil
|
|
155
155
|
end
|
|
156
|
-
|
|
156
|
+
_foo, _bar, _baz, nat_ssh_host, nat_ssh_user, nat_ssh_key = @nat.getSSHConfig
|
|
157
157
|
if nat_ssh_user.nil? and !nat_ssh_host.nil?
|
|
158
158
|
MU.log "#{@config["name"]} (#{MU.deploy_id}) is configured to use #{@config['vpc']} NAT #{nat_ssh_host}, but username isn't specified. Guessing root.", MU::ERR, details: caller
|
|
159
159
|
nat_ssh_user = "root"
|
|
@@ -163,7 +163,7 @@ module MU
|
|
|
163
163
|
|
|
164
164
|
if @config['ssh_user'].nil?
|
|
165
165
|
if windows?
|
|
166
|
-
@config['ssh_user'] = "
|
|
166
|
+
@config['ssh_user'] = "muadmin"
|
|
167
167
|
else
|
|
168
168
|
@config['ssh_user'] = "root"
|
|
169
169
|
end
|
|
@@ -188,8 +188,8 @@ module MU
|
|
|
188
188
|
@named = true
|
|
189
189
|
end
|
|
190
190
|
|
|
191
|
-
|
|
192
|
-
if !nat_ssh_host and !MU::Cloud
|
|
191
|
+
_nat_ssh_key, _nat_ssh_user, nat_ssh_host, _canonical_ip, _ssh_user, _ssh_key_name = getSSHConfig
|
|
192
|
+
if !nat_ssh_host and !MU::Cloud.resourceClass("Azure", "VPC").haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @config['credentials'])
|
|
193
193
|
# XXX check if canonical_ip is in the private ranges
|
|
194
194
|
# raise MuError, "#{node} has no NAT host configured, and I have no other route to it"
|
|
195
195
|
end
|
|
@@ -236,7 +236,7 @@ module MU
|
|
|
236
236
|
resp = MU::Cloud::Azure.compute(credentials: args[:credentials]).virtual_machines.get(rg, id_str)
|
|
237
237
|
next if resp.nil?
|
|
238
238
|
found[Id.new(resp.id)] = resp
|
|
239
|
-
rescue MU::Cloud::Azure::APIError
|
|
239
|
+
rescue MU::Cloud::Azure::APIError
|
|
240
240
|
# this is fine, we're doing a blind search after all
|
|
241
241
|
end
|
|
242
242
|
}
|
|
@@ -267,7 +267,7 @@ module MU
|
|
|
267
267
|
|
|
268
268
|
MU::MommaCat.lock(@cloud_id.to_s+"-groom")
|
|
269
269
|
|
|
270
|
-
node,
|
|
270
|
+
node, _config, deploydata = describe(cloud_id: @cloud_id)
|
|
271
271
|
|
|
272
272
|
if node.nil? or node.empty?
|
|
273
273
|
raise MuError, "MU::Cloud::Azure::Server.groom was called without a mu_name"
|
|
@@ -357,7 +357,7 @@ module MU
|
|
|
357
357
|
# bastion hosts that may be in the path, see getSSHConfig if that's what
|
|
358
358
|
# you need.
|
|
359
359
|
def canonicalIP
|
|
360
|
-
|
|
360
|
+
describe(cloud_id: @cloud_id)
|
|
361
361
|
|
|
362
362
|
if !cloud_desc
|
|
363
363
|
raise MuError, "Couldn't retrieve cloud descriptor for server #{self}"
|
|
@@ -384,7 +384,7 @@ module MU
|
|
|
384
384
|
# Our deploydata gets corrupted often with server pools, this will cause us to use the wrong IP to identify a node
|
|
385
385
|
# which will cause us to create certificates, DNS records and other artifacts with incorrect information which will cause our deploy to fail.
|
|
386
386
|
# The cloud_id is always correct so lets use 'cloud_desc' to get the correct IPs
|
|
387
|
-
if MU::Cloud
|
|
387
|
+
if MU::Cloud.resourceClass("Azure", "VPC").haveRouteToInstance?(cloud_desc, credentials: @config['credentials']) or public_ips.size == 0
|
|
388
388
|
@config['canonical_ip'] = private_ips.first
|
|
389
389
|
return private_ips.first
|
|
390
390
|
else
|
|
@@ -393,6 +393,28 @@ module MU
|
|
|
393
393
|
end
|
|
394
394
|
end
|
|
395
395
|
|
|
396
|
+
# Return all of the IP addresses, public and private, from all of our
|
|
397
|
+
# network interfaces.
|
|
398
|
+
# @return [Array<String>]
|
|
399
|
+
def listIPs
|
|
400
|
+
ips = []
|
|
401
|
+
cloud_desc.network_profile.network_interfaces.each { |iface|
|
|
402
|
+
iface_id = Id.new(iface.is_a?(Hash) ? iface['id'] : iface.id)
|
|
403
|
+
iface_desc = MU::Cloud::Azure.network(credentials: @credentials).network_interfaces.get(@resource_group, iface_id.to_s)
|
|
404
|
+
iface_desc.ip_configurations.each { |ipcfg|
|
|
405
|
+
ips << ipcfg.private_ipaddress
|
|
406
|
+
if ipcfg.respond_to?(:public_ipaddress) and ipcfg.public_ipaddress
|
|
407
|
+
ip_id = Id.new(ipcfg.public_ipaddress.id)
|
|
408
|
+
ip_desc = MU::Cloud::Azure.network(credentials: @credentials).public_ipaddresses.get(@resource_group, ip_id.to_s)
|
|
409
|
+
if ip_desc
|
|
410
|
+
ips << ip_desc.ip_address
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
ips
|
|
416
|
+
end
|
|
417
|
+
|
|
396
418
|
# return [String]: A password string.
|
|
397
419
|
def getWindowsAdminPassword
|
|
398
420
|
end
|
|
@@ -430,7 +452,7 @@ module MU
|
|
|
430
452
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
|
431
453
|
# @param region [String]: The cloud provider region
|
|
432
454
|
# @return [void]
|
|
433
|
-
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
455
|
+
def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
434
456
|
end
|
|
435
457
|
|
|
436
458
|
# Cloud-specific configuration properties.
|
|
@@ -441,7 +463,7 @@ module MU
|
|
|
441
463
|
hosts_schema = MU::Config::CIDR_PRIMITIVE
|
|
442
464
|
hosts_schema["pattern"] = "^(\\d+\\.\\d+\\.\\d+\\.\\d+\/[0-9]{1,2}|\\*)$"
|
|
443
465
|
schema = {
|
|
444
|
-
"roles" => MU::Cloud
|
|
466
|
+
"roles" => MU::Cloud.resourceClass("Azure", "User").schema(config)[1]["roles"],
|
|
445
467
|
"ingress_rules" => {
|
|
446
468
|
"items" => {
|
|
447
469
|
"properties" => {
|
|
@@ -451,6 +473,34 @@ module MU
|
|
|
451
473
|
}
|
|
452
474
|
}
|
|
453
475
|
}
|
|
476
|
+
},
|
|
477
|
+
"windows_admin_username" => {
|
|
478
|
+
"type" => "string",
|
|
479
|
+
"default" => "muadmin",
|
|
480
|
+
},
|
|
481
|
+
"ssh_user" => {
|
|
482
|
+
"default_if" => [
|
|
483
|
+
{
|
|
484
|
+
"key_is" => "platform",
|
|
485
|
+
"value_is" => "windows",
|
|
486
|
+
"set" => "muadmin"
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
"key_is" => "platform",
|
|
490
|
+
"value_is" => "win2k12",
|
|
491
|
+
"set" => "muadmin"
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
"key_is" => "platform",
|
|
495
|
+
"value_is" => "win2k12r2",
|
|
496
|
+
"set" => "muadmin"
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
"key_is" => "platform",
|
|
500
|
+
"value_is" => "win2k16",
|
|
501
|
+
"set" => "muadmin"
|
|
502
|
+
}
|
|
503
|
+
]
|
|
454
504
|
}
|
|
455
505
|
}
|
|
456
506
|
[toplevel_required, schema]
|
|
@@ -469,8 +519,7 @@ module MU
|
|
|
469
519
|
foundmatch = false
|
|
470
520
|
MU::Cloud.availableClouds.each { |cloud|
|
|
471
521
|
next if cloud == "Azure"
|
|
472
|
-
|
|
473
|
-
foreign_types = (cloudbase.listInstanceTypes).values.first
|
|
522
|
+
foreign_types = (MU::Cloud.cloudClass(cloud).listInstanceTypes).values.first
|
|
474
523
|
if foreign_types.size == 1
|
|
475
524
|
foreign_types = foreign_types.values.first
|
|
476
525
|
end
|
|
@@ -479,6 +528,7 @@ module MU
|
|
|
479
528
|
mem = foreign_types[size]["memory"]
|
|
480
529
|
ecu = foreign_types[size]["ecu"]
|
|
481
530
|
types.keys.sort.reverse.each { |type|
|
|
531
|
+
next if type.match(/_Promo$/i)
|
|
482
532
|
features = types[type]
|
|
483
533
|
next if ecu == "Variable" and ecu != features["ecu"]
|
|
484
534
|
next if features["vcpu"] != vcpu
|
|
@@ -495,7 +545,6 @@ module MU
|
|
|
495
545
|
|
|
496
546
|
if !foundmatch
|
|
497
547
|
MU.log "Invalid size '#{size}' for Azure Compute instance in #{region}. Supported types:", MU::ERR, details: types.keys.sort.join(", ")
|
|
498
|
-
exit
|
|
499
548
|
return nil
|
|
500
549
|
end
|
|
501
550
|
end
|
|
@@ -512,6 +561,10 @@ exit
|
|
|
512
561
|
|
|
513
562
|
server['region'] ||= MU::Cloud::Azure.myRegion(server['credentials'])
|
|
514
563
|
server['ssh_user'] ||= "muadmin"
|
|
564
|
+
if server['windows_admin_username'] == "Administrator"
|
|
565
|
+
MU.log "Azure does not permit admin user to be 'Administrator'", MU::ERR
|
|
566
|
+
ok = false
|
|
567
|
+
end
|
|
515
568
|
|
|
516
569
|
server['size'] = validateInstanceType(server["size"], server["region"])
|
|
517
570
|
ok = false if server['size'].nil?
|
|
@@ -527,17 +580,17 @@ exit
|
|
|
527
580
|
end
|
|
528
581
|
|
|
529
582
|
image_desc = MU::Cloud::Azure::Server.fetchImage(server['image_id'].to_s, credentials: server['credentials'], region: server['region'])
|
|
530
|
-
if image_desc.plan
|
|
531
|
-
terms = MU::Cloud::Azure.marketplace(credentials: @credentials).marketplace_agreements.get(image_desc.plan.publisher, image_desc.plan.product, image_desc.plan.name)
|
|
532
|
-
if !terms.accepted
|
|
533
|
-
MU.log "Deploying #{server['name']} will automatically agree to the licensing terms for #{terms.product}", MU::NOTICE, details: terms.license_text_link
|
|
534
|
-
end
|
|
535
|
-
end
|
|
536
583
|
|
|
537
584
|
if !image_desc
|
|
538
585
|
MU.log "Failed to locate an Azure VM image for #{server['name']} from #{server['image_id']} in #{server['region']}", MU::ERR
|
|
539
586
|
ok = false
|
|
540
587
|
else
|
|
588
|
+
if image_desc.plan
|
|
589
|
+
terms = MU::Cloud::Azure.marketplace(credentials: @credentials).marketplace_agreements.get(image_desc.plan.publisher, image_desc.plan.product, image_desc.plan.name)
|
|
590
|
+
if !terms.accepted
|
|
591
|
+
MU.log "Deploying #{server['name']} will automatically agree to the licensing terms for #{terms.product}", MU::NOTICE, details: terms.license_text_link
|
|
592
|
+
end
|
|
593
|
+
end
|
|
541
594
|
server['image_id'] = image_desc.id
|
|
542
595
|
end
|
|
543
596
|
|
|
@@ -558,18 +611,8 @@ exit
|
|
|
558
611
|
if !configurator.insertKitten(vpc, "vpcs", true)
|
|
559
612
|
ok = false
|
|
560
613
|
end
|
|
561
|
-
server['
|
|
562
|
-
|
|
563
|
-
server['dependencies'] << {
|
|
564
|
-
"type" => "vpc",
|
|
565
|
-
"name" => server['name']+"vpc"
|
|
566
|
-
}
|
|
567
|
-
# XXX what happens if there's no natstion here?
|
|
568
|
-
server['dependencies'] << {
|
|
569
|
-
"type" => "server",
|
|
570
|
-
"name" => server['name']+"vpc-natstion",
|
|
571
|
-
"phase" => "groom"
|
|
572
|
-
}
|
|
614
|
+
MU::Config.addDependency(server, server['name']+"vpc", "vpc")
|
|
615
|
+
MU::Config.addDependency(server, server['name']+"vpc-natstion", "server", phase: "groom")
|
|
573
616
|
server['vpc'] = {
|
|
574
617
|
"name" => server['name']+"vpc",
|
|
575
618
|
"subnet_pref" => "private"
|
|
@@ -586,17 +629,14 @@ exit
|
|
|
586
629
|
"credentials" => server["credentials"],
|
|
587
630
|
"roles" => server["roles"]
|
|
588
631
|
}
|
|
589
|
-
server['
|
|
590
|
-
server['dependencies'] << {
|
|
591
|
-
"type" => "user",
|
|
592
|
-
"name" => server["name"]+"user"
|
|
593
|
-
}
|
|
632
|
+
MU::Config.addDependency(server, server['name']+"user", "user")
|
|
594
633
|
|
|
595
634
|
ok = false if !configurator.insertKitten(svcacct_desc, "users")
|
|
596
635
|
|
|
597
636
|
ok
|
|
598
637
|
end
|
|
599
638
|
|
|
639
|
+
# stub
|
|
600
640
|
def self.diskConfig(config, create = true, disk_as_url = true, credentials: nil)
|
|
601
641
|
end
|
|
602
642
|
|
|
@@ -624,17 +664,22 @@ exit
|
|
|
624
664
|
skus = MU::Cloud::Azure.compute(credentials: credentials).virtual_machine_images.list_skus(region, publisher, offer).map { |s| s.name }
|
|
625
665
|
|
|
626
666
|
if !skus.include?(sku)
|
|
627
|
-
skus.
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
break
|
|
631
|
-
end
|
|
632
|
-
}
|
|
667
|
+
skus.reject! { |s| !s.match(/^#{Regexp.quote(sku)}/) }
|
|
668
|
+
skus.sort! { |a, b| MU.version_sort(a, b) }.reverse!
|
|
669
|
+
sku = skus.first
|
|
633
670
|
end
|
|
634
671
|
|
|
635
|
-
|
|
672
|
+
version = nil
|
|
673
|
+
begin
|
|
674
|
+
versions = MU::Cloud::Azure.compute(credentials: credentials).virtual_machine_images.list(region, publisher, offer, sku).map { |v| v.name }
|
|
675
|
+
if versions.nil? or versions.empty?
|
|
676
|
+
skus.delete(sku)
|
|
677
|
+
sku = skus.first
|
|
678
|
+
end
|
|
679
|
+
end while skus.size > 0 and (versions.nil? or versions.empty?)
|
|
680
|
+
|
|
636
681
|
if versions.nil? or versions.empty?
|
|
637
|
-
MU.log "Azure API returned empty machine image version list for publisher #{publisher} offer #{offer} sku #{sku}", MU::ERR
|
|
682
|
+
MU.log "Azure API returned empty machine image version list for publisher #{publisher} offer #{offer} sku #{sku}", MU::ERR, details: skus
|
|
638
683
|
return nil
|
|
639
684
|
end
|
|
640
685
|
|
|
@@ -724,12 +769,15 @@ exit
|
|
|
724
769
|
hw_obj.vm_size = @config['size']
|
|
725
770
|
|
|
726
771
|
os_obj = MU::Cloud::Azure.compute(:OSProfile).new
|
|
727
|
-
os_obj.admin_username = @config['ssh_user']
|
|
728
|
-
os_obj.computer_name = @mu_name
|
|
729
772
|
if windows?
|
|
730
773
|
win_obj = MU::Cloud::Azure.compute(:WindowsConfiguration).new
|
|
731
774
|
os_obj.windows_configuration = win_obj
|
|
775
|
+
os_obj.admin_username = @config['windows_admin_username']
|
|
776
|
+
os_obj.admin_password = MU.generateWindowsPassword
|
|
777
|
+
os_obj.computer_name = @deploy.getResourceName(@config["name"], max_length: 15, disallowed_chars: /[~!@#$%^&*()=+_\[\]{}\\\|;:\.'",<>\/\?]/)
|
|
732
778
|
else
|
|
779
|
+
os_obj.admin_username = @config['ssh_user']
|
|
780
|
+
os_obj.computer_name = @mu_name
|
|
733
781
|
key_obj = MU::Cloud::Azure.compute(:SshPublicKey).new
|
|
734
782
|
key_obj.key_data = @deploy.ssh_public_key
|
|
735
783
|
key_obj.path = "/home/#{@config['ssh_user']}/.ssh/authorized_keys"
|
|
@@ -772,7 +820,7 @@ exit
|
|
|
772
820
|
begin
|
|
773
821
|
# XXX this doesn't actually work as documented
|
|
774
822
|
MU::Cloud::Azure.marketplace(credentials: @credentials).marketplace_agreements.sign(image_desc.plan.publisher, image_desc.plan.product, image_desc.plan.name)
|
|
775
|
-
rescue
|
|
823
|
+
rescue StandardError => e
|
|
776
824
|
MU.log e.message, MU::ERR
|
|
777
825
|
vm_obj.plan = nil
|
|
778
826
|
end
|
|
@@ -86,7 +86,6 @@ module MU
|
|
|
86
86
|
|
|
87
87
|
client = ::MsRest::ServiceClient.new(cred_obj)
|
|
88
88
|
cloud_desc.client_secret_url.match(/^(http.*?\.azure\.net)(\/.*)/)
|
|
89
|
-
base = Regexp.last_match[1]
|
|
90
89
|
path = Regexp.last_match[2]
|
|
91
90
|
#MU.log "Calling into #{base} #{path}"
|
|
92
91
|
promise = client.make_request_async(
|
|
@@ -97,7 +96,7 @@ module MU
|
|
|
97
96
|
|
|
98
97
|
# XXX this is async, need to stop and wait somehow
|
|
99
98
|
promise.then do | result|
|
|
100
|
-
|
|
99
|
+
result.response
|
|
101
100
|
# MU.log "RESPONSE", MU::WARN, details: resp
|
|
102
101
|
end
|
|
103
102
|
end
|
|
@@ -106,10 +105,9 @@ module MU
|
|
|
106
105
|
|
|
107
106
|
# Called automatically by {MU::Deploy#createResources}
|
|
108
107
|
def groom
|
|
109
|
-
rgroup_name = @deploy.deploy_id+"-"+@config['region'].upcase
|
|
110
108
|
if @config['roles']
|
|
111
109
|
@config['roles'].each { |role|
|
|
112
|
-
MU::Cloud
|
|
110
|
+
MU::Cloud.resourceClass("Azure", "Role").assignTo(cloud_desc.principal_id, role_name: role, credentials: @config['credentials'])
|
|
113
111
|
}
|
|
114
112
|
end
|
|
115
113
|
end
|
|
@@ -191,9 +189,9 @@ module MU
|
|
|
191
189
|
end
|
|
192
190
|
|
|
193
191
|
# Cloud-specific configuration properties.
|
|
194
|
-
# @param
|
|
192
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
195
193
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
196
|
-
def self.schema(
|
|
194
|
+
def self.schema(_config)
|
|
197
195
|
toplevel_required = []
|
|
198
196
|
schema = {
|
|
199
197
|
"region" => MU::Config.region_primitive,
|
|
@@ -221,9 +219,9 @@ module MU
|
|
|
221
219
|
|
|
222
220
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::users}, bare and unvalidated.
|
|
223
221
|
# @param user [Hash]: The resource to process and validate
|
|
224
|
-
# @param
|
|
222
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
225
223
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
226
|
-
def self.validateConfig(user,
|
|
224
|
+
def self.validateConfig(user, _configurator)
|
|
227
225
|
ok = true
|
|
228
226
|
user['region'] ||= MU::Cloud::Azure.myRegion(user['credentials'])
|
|
229
227
|
|