cloud-mu 3.1.2 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -195,48 +195,49 @@ action :config do
|
|
195
195
|
else
|
196
196
|
# We want to run ec2config as admin user so Windows userdata executes as admin, however the local admin account doesn't have Logon As a Service right. Domain privileges are set separately
|
197
197
|
|
198
|
-
cookbook_file "c:\\Windows\\SysWOW64\\ntrights.exe" do
|
199
|
-
source "ntrights"
|
200
|
-
end
|
201
|
-
[new_resource.ssh_user, new_resource.ec2config_user].each { |usr|
|
202
|
-
pass = if usr == new_resource.ec2config_user
|
203
|
-
new_resource.ec2config_password
|
204
|
-
elsif usr == new_resource.ssh_user
|
205
|
-
new_resource.ssh_password
|
206
|
-
end
|
207
|
-
|
208
|
-
user usr do
|
209
|
-
password pass
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
198
|
+
# cookbook_file "c:\\Windows\\SysWOW64\\ntrights.exe" do
|
199
|
+
# source "ntrights"
|
200
|
+
# end
|
201
|
+
# [new_resource.ssh_user, new_resource.ec2config_user].each { |usr|
|
202
|
+
# pass = if usr == new_resource.ec2config_user
|
203
|
+
# new_resource.ec2config_password
|
204
|
+
# elsif usr == new_resource.ssh_user
|
205
|
+
# new_resource.ssh_password
|
206
|
+
# end
|
207
|
+
#
|
208
|
+
# user usr do
|
209
|
+
# password pass
|
210
|
+
# action :modify
|
211
|
+
# end
|
212
|
+
#
|
213
|
+
# group "Administrators" do
|
214
|
+
# action :modify
|
215
|
+
# members usr
|
216
|
+
# append true
|
217
|
+
# end
|
218
|
+
#
|
219
|
+
# %w{SeDenyRemoteInteractiveLogonRight SeDenyInteractiveLogonRight SeServiceLogonRight}.each { |privilege|
|
220
|
+
# batch "Grant local user #{usr} logon as service right" do
|
221
|
+
# code "C:\\Windows\\SysWOW64\\ntrights +r #{privilege} -u #{usr}"
|
222
|
+
# end
|
223
|
+
# }
|
224
|
+
#
|
225
|
+
# # XXX user resource seems not to really be setting password, or is setting # in such a way that the user is being required to change it. Workaround.
|
226
|
+
# powershell_script "Adjust local account params for #{usr}" do
|
227
|
+
# code <<-EOH
|
228
|
+
# (([adsi]('WinNT://./#{usr}, user')).psbase.invoke('SetPassword', '#{pass}'))
|
229
|
+
# EOH
|
230
|
+
# end
|
231
|
+
#
|
232
|
+
# if usr == new_resource.ssh_user
|
233
|
+
#
|
234
|
+
# %w{SeCreateTokenPrivilege SeTcbPrivilege SeAssignPrimaryTokenPrivilege}.each { |privilege|
|
235
|
+
# batch "Grant local user #{usr} logon as service right" do
|
236
|
+
# code "C:\\Windows\\SysWOW64\\ntrights +r #{privilege} -u #{usr}"
|
237
|
+
# end
|
238
|
+
# }
|
239
|
+
#
|
240
|
+
# end
|
241
|
+
# }
|
241
242
|
end
|
242
243
|
end
|
data/extras/clean-stock-amis
CHANGED
@@ -18,37 +18,43 @@ require 'json'
|
|
18
18
|
require File.realpath(File.expand_path(File.dirname(__FILE__)+"/../bin/mu-load-config.rb"))
|
19
19
|
require 'mu'
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
$opts = Optimist::options do
|
22
|
+
banner <<-EOS
|
23
|
+
#{$0} [-c credentials] [-i imagename]
|
24
|
+
EOS
|
25
|
+
opt :credentials, "Use these AWS credentials from mu.yaml instead of the default set", :required => false, :type => :string
|
26
|
+
opt :image, "Purge a specific image, instead of just scrubing old ones", :required => false, :type => :string
|
25
27
|
end
|
26
28
|
|
27
29
|
filters = [
|
28
30
|
{
|
29
31
|
name: "owner-id",
|
30
|
-
values: [MU::Cloud::AWS.credToAcct(credentials)]
|
32
|
+
values: [MU::Cloud::AWS.credToAcct($opts[:credentials])]
|
31
33
|
}
|
32
34
|
]
|
33
35
|
|
34
36
|
|
35
37
|
MU::Cloud::AWS.listRegions.each { | r|
|
36
|
-
images = MU::Cloud::AWS.ec2(region: r, credentials: credentials).describe_images(
|
38
|
+
images = MU::Cloud::AWS.ec2(region: r, credentials: $opts[:credentials]).describe_images(
|
37
39
|
filters: filters + [{ "name" => "state", "values" => ["available"]}]
|
38
40
|
).images
|
39
41
|
images.each { |ami|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
42
|
+
if ($opts[:image] and ami.name == $opts[:image]) or
|
43
|
+
((DateTime.now.to_time - DateTime.parse(ami.creation_date).to_time) > 15552000 and ami.name.match(/^MU-(PROD|DEV)/))
|
44
|
+
snaps = []
|
45
|
+
ami.block_device_mappings.each { |dev|
|
46
|
+
if !dev.ebs.nil?
|
47
|
+
snaps << dev.ebs.snapshot_id
|
48
|
+
end
|
49
|
+
}
|
50
|
+
MU.log "Deregistering #{ami.name}, #{r} (#{ami.creation_date})", MU::WARN, details: snaps
|
51
|
+
begin
|
52
|
+
MU::Cloud::AWS.ec2(region: r, credentials: $opts[:credentials]).deregister_image(image_id: ami.image_id)
|
53
|
+
rescue Aws::EC2::Errors::InvalidAMIIDUnavailable
|
54
|
+
end
|
55
|
+
snaps.each { |snap_id|
|
56
|
+
MU::Cloud::AWS.ec2(region: r, credentials: $opts[:credentials]).delete_snapshot(snapshot_id: snap_id)
|
57
|
+
}
|
58
|
+
end
|
53
59
|
}
|
54
60
|
}
|
@@ -91,6 +91,7 @@ $opts[:clouds].each { |cloud|
|
|
91
91
|
end
|
92
92
|
next if !needed
|
93
93
|
end
|
94
|
+
MU.log "Loading "+bok_dir+"/"+cloud+"/"+platform+".yaml"
|
94
95
|
conf_engine = MU::Config.new(
|
95
96
|
bok_dir+"/"+cloud+"/"+platform+".yaml",
|
96
97
|
default_credentials: $opts[(cloud.downcase+"_creds").to_sym]
|
@@ -1,16 +1,21 @@
|
|
1
1
|
---
|
2
2
|
appname: mu
|
3
|
+
vpcs:
|
4
|
+
- name: windowsbuild
|
3
5
|
servers:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
6
|
+
- name: win2k12
|
7
|
+
platform: win2k12
|
8
|
+
vpc:
|
9
|
+
name: windowsbuild
|
10
|
+
size: m4.large
|
11
|
+
scrub_groomer: true
|
12
|
+
groomer: Ansible
|
13
|
+
run_list:
|
14
|
+
- mu-windows
|
15
|
+
ansible_vars:
|
16
|
+
mu_build_image: true
|
17
|
+
create_image:
|
18
|
+
image_then_destroy: true
|
19
|
+
public: true
|
20
|
+
copy_to_regions:
|
21
|
+
- "#ALL"
|
@@ -1,16 +1,21 @@
|
|
1
1
|
---
|
2
2
|
appname: mu
|
3
|
+
vpcs:
|
4
|
+
- name: windowsbuild
|
3
5
|
servers:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
6
|
+
- name: win2k16
|
7
|
+
platform: win2k16
|
8
|
+
vpc:
|
9
|
+
name: windowsbuild
|
10
|
+
size: m4.large
|
11
|
+
scrub_groomer: true
|
12
|
+
groomer: Ansible
|
13
|
+
run_list:
|
14
|
+
- mu-windows
|
15
|
+
ansible_vars:
|
16
|
+
mu_build_image: true
|
17
|
+
create_image:
|
18
|
+
image_then_destroy: true
|
19
|
+
public: true
|
20
|
+
copy_to_regions:
|
21
|
+
- "#ALL"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
---
|
2
|
+
appname: mu
|
3
|
+
vpcs:
|
4
|
+
- name: windowsbuild
|
5
|
+
servers:
|
6
|
+
- name: win2k19
|
7
|
+
platform: windows
|
8
|
+
vpc:
|
9
|
+
name: windowsbuild
|
10
|
+
size: m4.large
|
11
|
+
scrub_groomer: true
|
12
|
+
groomer: Ansible
|
13
|
+
run_list:
|
14
|
+
- mu-windows
|
15
|
+
ansible_vars:
|
16
|
+
mu_build_image: true
|
17
|
+
create_image:
|
18
|
+
image_then_destroy: true
|
19
|
+
public: true
|
20
|
+
copy_to_regions:
|
21
|
+
- "#ALL"
|
data/modules/mommacat.ru
CHANGED
@@ -16,7 +16,7 @@ require 'pp'
|
|
16
16
|
require 'base64'
|
17
17
|
require 'etc'
|
18
18
|
|
19
|
-
|
19
|
+
Etc.getpwuid(Process.uid).dir
|
20
20
|
|
21
21
|
if !ENV.include?('MU_INSTALLDIR')
|
22
22
|
ENV['MU_INSTALLDIR'] = "/opt/mu"
|
@@ -51,8 +51,8 @@ Signal.trap("URG") do
|
|
51
51
|
end
|
52
52
|
|
53
53
|
begin
|
54
|
-
MU::
|
55
|
-
rescue
|
54
|
+
MU::Master.syncMonitoringConfig(false)
|
55
|
+
rescue StandardError => e
|
56
56
|
MU.log e.inspect, MU::ERR, details: e.backtrace
|
57
57
|
# ...but don't die!
|
58
58
|
end
|
@@ -64,14 +64,12 @@ Thread.new {
|
|
64
64
|
MU::MommaCat.cleanTerminatedInstances
|
65
65
|
MU::Master.cleanExpiredScratchpads if $ENABLE_SCRATCHPAD
|
66
66
|
sleep 60
|
67
|
-
rescue
|
67
|
+
rescue StandardError => e
|
68
68
|
MU.log "Error in cleanTerminatedInstances thread: #{e.inspect}", MU::ERR, details: e.backtrace
|
69
69
|
retry
|
70
70
|
end while true
|
71
71
|
}
|
72
72
|
|
73
|
-
required_vars = ["mu_id", "mu_deploy_secret", "mu_resource_name", "mu_resource_type", "mu_instance_id"]
|
74
|
-
|
75
73
|
# Use a template to generate a pleasant-looking HTML page for simple messages
|
76
74
|
# and errors.
|
77
75
|
def genHTMLMessage(title: "", headline: "", msg: "", template: $MU_CFG['html_template'], extra_vars: {})
|
@@ -193,7 +191,6 @@ def releaseKitten(mu_id)
|
|
193
191
|
end
|
194
192
|
|
195
193
|
app = proc do |env|
|
196
|
-
ok = false
|
197
194
|
returnval = [
|
198
195
|
200,
|
199
196
|
{
|
@@ -318,7 +315,7 @@ app = proc do |env|
|
|
318
315
|
elsif !filter or !path
|
319
316
|
returnval = throw404 env['REQUEST_PATH']
|
320
317
|
else
|
321
|
-
MU::
|
318
|
+
MU::Master.addInstanceToEtcHosts(path, filter)
|
322
319
|
returnval = [
|
323
320
|
200,
|
324
321
|
{
|
@@ -356,7 +353,6 @@ app = proc do |env|
|
|
356
353
|
|
357
354
|
elsif !env["rack.input"].nil?
|
358
355
|
req = Rack::Utils.parse_nested_query(env["rack.input"].read)
|
359
|
-
ok = true
|
360
356
|
|
361
357
|
if req["mu_user"].nil?
|
362
358
|
req["mu_user"] = "mu"
|
@@ -373,7 +369,6 @@ app = proc do |env|
|
|
373
369
|
kittenpile = getKittenPile(req)
|
374
370
|
if kittenpile.nil? or kittenpile.original_config.nil? or kittenpile.original_config[req["mu_resource_type"]+"s"].nil?
|
375
371
|
returnval = throw500 "Couldn't find config data for #{req["mu_resource_type"]} in deploy_id #{req["mu_id"]}"
|
376
|
-
ok = false
|
377
372
|
next
|
378
373
|
end
|
379
374
|
server_cfg = nil
|
@@ -385,7 +380,6 @@ app = proc do |env|
|
|
385
380
|
}
|
386
381
|
if server_cfg.nil?
|
387
382
|
returnval = throw500 "Couldn't find config data for #{req["mu_resource_type"]} name: #{req["mu_resource_name"]} deploy_id: #{req["mu_id"]}"
|
388
|
-
ok = false
|
389
383
|
next
|
390
384
|
end
|
391
385
|
|
@@ -426,7 +420,6 @@ MU.log "ADDVOLUME REQUEST", MU::WARN, details: params
|
|
426
420
|
instance.addVolume(params["dev"], params["size"], delete_on_termination: params["delete_on_termination"])
|
427
421
|
else
|
428
422
|
returnval = throw500 "I don't know how to add a volume for #{instance}"
|
429
|
-
ok = false
|
430
423
|
end
|
431
424
|
elsif !instance.nil?
|
432
425
|
if !req["mu_bootstrap"].nil?
|
@@ -434,16 +427,13 @@ MU.log "ADDVOLUME REQUEST", MU::WARN, details: params
|
|
434
427
|
returnval[2] = ["Grooming asynchronously, check Momma Cat logs on the master for details."]
|
435
428
|
else
|
436
429
|
returnval = throw500 "Didn't get 'mu_bootstrap' parameter from instance id '#{req["mu_instance_id"]}'"
|
437
|
-
ok = false
|
438
430
|
end
|
439
431
|
else
|
440
432
|
returnval = throw500 "No such instance id '#{req["mu_instance_id"]}' nor was this an SSL signing request"
|
441
|
-
ok = false
|
442
433
|
end
|
443
434
|
end
|
444
|
-
rescue
|
435
|
+
rescue StandardError => e
|
445
436
|
returnval = throw500 "Invalid request: #{e.inspect} (#{req})", e.backtrace
|
446
|
-
ok = false
|
447
437
|
ensure
|
448
438
|
if !req.nil?
|
449
439
|
releaseKitten(req['mu_id'])
|
data/modules/mu.rb
CHANGED
@@ -79,38 +79,40 @@ class Hash
|
|
79
79
|
}
|
80
80
|
return 0 if self == other # that was easy!
|
81
81
|
# compare elements and decide who's "bigger" based on their totals?
|
82
|
-
|
82
|
+
|
83
|
+
# fine, try some brute force and just hope everything implements to_s
|
84
|
+
self.flatten.map { |e| e.to_s }.join() <=> other.flatten.map { |e| e.to_s }.join()
|
83
85
|
end
|
84
86
|
|
85
|
-
# Recursively compare two hashes
|
86
|
-
def diff(with, on = self, level: 0, parents: [])
|
87
|
+
# Recursively compare two Mu Basket of Kittens hashes and report the differences
|
88
|
+
def diff(with, on = self, level: 0, parents: [], report: {}, habitat: nil)
|
87
89
|
return if with.nil? and on.nil?
|
88
90
|
if with.nil? or on.nil? or with.class != on.class
|
89
91
|
return # XXX ...however we're flagging differences
|
90
92
|
end
|
91
93
|
return if on == with
|
92
94
|
|
93
|
-
tree = ""
|
94
|
-
indentsize = 0
|
95
|
-
parents.each { |p|
|
96
|
-
tree += (" " * indentsize) + p + " => \n"
|
97
|
-
indentsize += 2
|
98
|
-
}
|
99
|
-
indent = (" " * indentsize)
|
100
|
-
|
101
95
|
changes = []
|
96
|
+
report ||= {}
|
102
97
|
if on.is_a?(Hash)
|
103
98
|
on_unique = (on.keys - with.keys)
|
104
99
|
with_unique = (with.keys - on.keys)
|
105
100
|
shared = (with.keys & on.keys)
|
106
101
|
shared.each { |k|
|
107
|
-
|
102
|
+
|
103
|
+
report_data = diff(with[k], on[k], level: level+1, parents: parents + [k], report: report[k], habitat: habitat)
|
104
|
+
if report_data and !report_data.empty?
|
105
|
+
report ||= {}
|
106
|
+
report[k] = report_data
|
107
|
+
end
|
108
108
|
}
|
109
109
|
on_unique.each { |k|
|
110
|
-
|
110
|
+
report[k] = { :action => :removed, :parents => parents, :value => on[k].clone }
|
111
|
+
report[k][:habitat] = habitat if habitat
|
111
112
|
}
|
112
113
|
with_unique.each { |k|
|
113
|
-
|
114
|
+
report[k] = { :action => :added, :parents => parents, :value => with[k].clone }
|
115
|
+
report[k][:habitat] = habitat if habitat
|
114
116
|
}
|
115
117
|
elsif on.is_a?(Array)
|
116
118
|
return if with == on
|
@@ -121,34 +123,28 @@ class Hash
|
|
121
123
|
# custom objects which we might find in here so that we can get away with
|
122
124
|
# sorting arrays full of weird, non-primitive types.
|
123
125
|
done = []
|
124
|
-
# before_a = on.dup
|
125
|
-
# after_a = on.dup.sort
|
126
|
-
# before_b = with.dup
|
127
|
-
# after_b = with.dup.sort
|
128
126
|
on.sort.each { |elt|
|
129
|
-
if elt.is_a?(Hash) and elt
|
127
|
+
if elt.is_a?(Hash) and !MU::MommaCat.getChunkName(elt).first.nil?
|
128
|
+
elt_namestr, elt_location, elt_location_list = MU::MommaCat.getChunkName(elt)
|
129
|
+
|
130
130
|
with.sort.each { |other_elt|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
131
|
+
other_elt_namestr, other_elt_location, other_elt_location_list = MU::MommaCat.getChunkName(other_elt)
|
132
|
+
|
133
|
+
# Case 1: The array element exists in both version of this array
|
134
|
+
if elt_namestr and other_elt_namestr and
|
135
|
+
elt_namestr == other_elt_namestr and
|
136
|
+
(elt_location.nil? or other_elt_location.nil? or
|
137
|
+
elt_location == other_elt_location or
|
138
|
+
!(elt_location_list & other_elt_location_list).empty?
|
139
139
|
)
|
140
|
-
break if elt == other_elt
|
141
140
|
done << elt
|
142
141
|
done << other_elt
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
elt['entity']['id']
|
142
|
+
break if elt == other_elt # if they're identical, we're done
|
143
|
+
report_data = diff(other_elt, elt, level: level+1, parents: parents + [elt_namestr], habitat: (elt_location || habitat))
|
144
|
+
if report_data and !report_data.empty?
|
145
|
+
report ||= {}
|
146
|
+
report[elt_namestr] = report_data
|
149
147
|
end
|
150
|
-
|
151
|
-
diff(other_elt, elt, level: level+1, parents: parents + [namestr])
|
152
148
|
break
|
153
149
|
end
|
154
150
|
}
|
@@ -156,43 +152,34 @@ class Hash
|
|
156
152
|
}
|
157
153
|
on_unique = (on - with) - done
|
158
154
|
with_unique = (with - on) - done
|
159
|
-
|
160
|
-
#
|
161
|
-
# MU.log "A BEFORE", MU::NOTICE, details: before_a
|
162
|
-
# MU.log "A AFTER", MU::NOTICE, details: after_a
|
163
|
-
# end
|
164
|
-
# if before_b != after_b
|
165
|
-
# MU.log "B BEFORE", MU::NOTICE, details: before_b
|
166
|
-
# MU.log "B AFTER", MU::NOTICE, details: after_b
|
167
|
-
# end
|
168
|
-
# end
|
155
|
+
|
156
|
+
# Case 2: This array entry exists in the old version, but not the new one
|
169
157
|
on_unique.each { |e|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
158
|
+
namestr, loc = MU::MommaCat.getChunkName(e)
|
159
|
+
|
160
|
+
report ||= {}
|
161
|
+
report[namestr] = { :action => :removed, :parents => parents, :value => e.clone }
|
162
|
+
report[namestr][:habitat] = loc if loc
|
175
163
|
}
|
164
|
+
|
165
|
+
# Case 3: This array entry exists in the new version, but not the old one
|
176
166
|
with_unique.each { |e|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
167
|
+
namestr, loc = MU::MommaCat.getChunkName(e)
|
168
|
+
|
169
|
+
report ||= {}
|
170
|
+
report[namestr] = { :action => :added, :parents => parents, :value => e.clone }
|
171
|
+
report[namestr][:habitat] = loc if loc
|
182
172
|
}
|
173
|
+
|
174
|
+
# A plain old leaf node of data
|
183
175
|
else
|
184
176
|
if on != with
|
185
|
-
|
186
|
-
|
177
|
+
report = { :action => :changed, :parents => parents, :oldvalue => on, :value => with.clone }
|
178
|
+
report[:habitat] = habitat if habitat
|
187
179
|
end
|
188
180
|
end
|
189
181
|
|
190
|
-
|
191
|
-
puts tree
|
192
|
-
changes.each { |c|
|
193
|
-
puts indent+c
|
194
|
-
}
|
195
|
-
end
|
182
|
+
report.freeze
|
196
183
|
end
|
197
184
|
|
198
185
|
# Implement a merge! that just updates each hash leaf as needed, not
|
@@ -216,8 +203,29 @@ class Hash
|
|
216
203
|
end
|
217
204
|
|
218
205
|
ENV['HOME'] = Etc.getpwuid(Process.uid).dir
|
206
|
+
module MU
|
207
|
+
|
208
|
+
# For log entries that should only be logged when we're in verbose mode
|
209
|
+
DEBUG = 0.freeze
|
210
|
+
# For ordinary log entries
|
211
|
+
INFO = 1.freeze
|
212
|
+
# For more interesting log entries which are not errors
|
213
|
+
NOTICE = 2.freeze
|
214
|
+
# Log entries for non-fatal errors
|
215
|
+
WARN = 3.freeze
|
216
|
+
# Log entries for non-fatal errors
|
217
|
+
WARNING = 3.freeze
|
218
|
+
# Log entries for fatal errors
|
219
|
+
ERR = 4.freeze
|
220
|
+
# Log entries for fatal errors
|
221
|
+
ERROR = 4.freeze
|
222
|
+
# Log entries that will be held and displayed/emailed at the end of deploy,
|
223
|
+
# cleanup, etc.
|
224
|
+
SUMMARY = 5.freeze
|
225
|
+
end
|
219
226
|
|
220
227
|
require 'mu/logger'
|
228
|
+
|
221
229
|
module MU
|
222
230
|
|
223
231
|
# Subclass core thread so we can gracefully handle it when we hit system
|
@@ -267,6 +275,7 @@ module MU
|
|
267
275
|
end while newguy.nil?
|
268
276
|
|
269
277
|
@@mu_global_thread_semaphore.synchronize {
|
278
|
+
MU.dupGlobals(Thread.current.object_id, target_thread: newguy)
|
270
279
|
@@mu_global_threads << newguy
|
271
280
|
}
|
272
281
|
|
@@ -276,8 +285,9 @@ module MU
|
|
276
285
|
# Wrapper class for fatal Exceptions. Gives our internals something to
|
277
286
|
# inherit that will log an error message appropriately before bubbling up.
|
278
287
|
class MuError < StandardError
|
279
|
-
def initialize(message = nil)
|
280
|
-
|
288
|
+
def initialize(message = nil, silent: false, details: nil)
|
289
|
+
details ||= caller[2]
|
290
|
+
MU.log message, MU::ERR, details: details if !message.nil? and !silent
|
281
291
|
if MU.verbosity == MU::Logger::SILENT
|
282
292
|
super ""
|
283
293
|
else
|
@@ -289,8 +299,8 @@ module MU
|
|
289
299
|
# Wrapper class for temporary Exceptions. Gives our internals something to
|
290
300
|
# inherit that will log a notice message appropriately before bubbling up.
|
291
301
|
class MuNonFatal < StandardError
|
292
|
-
def initialize(message = nil)
|
293
|
-
MU.log message, MU::NOTICE if !message.nil?
|
302
|
+
def initialize(message = nil, silent: false)
|
303
|
+
MU.log message, MU::NOTICE if !message.nil? and !silent
|
294
304
|
if MU.verbosity == MU::Logger::SILENT
|
295
305
|
super ""
|
296
306
|
else
|
@@ -299,6 +309,68 @@ module MU
|
|
299
309
|
end
|
300
310
|
end
|
301
311
|
|
312
|
+
# Boilerplate retry block executor, for making cloud API calls which might
|
313
|
+
# fail transiently.
|
314
|
+
#
|
315
|
+
# @param catchme [Array<Exception>]: Exception classes which should be caught and retried
|
316
|
+
# @param wait [Integer]: Number of seconds to wait between retries
|
317
|
+
# @param max [Integer]: Maximum number of retries; if less than 1, will retry indefinitely
|
318
|
+
# @param ignoreme [Array<Exception>]: Exception classes which can be silently treated as success. This will override any +loop_if+ block and return automatically (after invoking +always+, if the latter was specified).
|
319
|
+
# @param on_retry [Proc]: Optional block of code to invoke during retries
|
320
|
+
# @param always [Proc]: Optional block of code to invoke before returning or failing, a bit like +ensure+
|
321
|
+
# @param loop_if [Proc]: Optional block of code to invoke which will cause our block to be rerun until true
|
322
|
+
# @param loop_msg [String]: Message to display every third attempt
|
323
|
+
def self.retrier(catchme = nil, wait: 30, max: 0, ignoreme: [], on_retry: nil, always: nil, loop_if: nil, loop_msg: nil)
|
324
|
+
|
325
|
+
loop_if ||= Proc.new { false }
|
326
|
+
|
327
|
+
retries = 0
|
328
|
+
begin
|
329
|
+
retries += 1
|
330
|
+
loglevel = ((retries % 3) == 0) ? MU::NOTICE : MU::DEBUG
|
331
|
+
log_attempts = retries.to_s
|
332
|
+
log_attempts += (max > 0 ? "/"+max.to_s : "")
|
333
|
+
yield(retries, wait) if block_given?
|
334
|
+
if loop_if.call
|
335
|
+
MU.log loop_msg, loglevel, details: log_attempts if loop_msg
|
336
|
+
sleep wait
|
337
|
+
end
|
338
|
+
rescue StandardError => e
|
339
|
+
if catchme and catchme.include?(e.class)
|
340
|
+
if max > 0 and retries >= max
|
341
|
+
always.call if always and always.is_a?(Proc)
|
342
|
+
if ignoreme.include?(e.class)
|
343
|
+
return
|
344
|
+
else
|
345
|
+
raise e
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
if on_retry and on_retry.is_a?(Proc)
|
350
|
+
on_retry.call(e)
|
351
|
+
end
|
352
|
+
|
353
|
+
if retries == max-1
|
354
|
+
MU.log e.message, MU::WARN, details: caller
|
355
|
+
sleep wait # wait extra on the final attempt
|
356
|
+
else
|
357
|
+
MU.log e.message, loglevel, details: log_attempts
|
358
|
+
end
|
359
|
+
|
360
|
+
sleep wait
|
361
|
+
retry
|
362
|
+
elsif ignoreme and ignoreme.include?(e.class)
|
363
|
+
always.call if always and always.is_a?(Proc)
|
364
|
+
return
|
365
|
+
else
|
366
|
+
always.call if always and always.is_a?(Proc)
|
367
|
+
raise e
|
368
|
+
end
|
369
|
+
end while loop_if.call and (max < 1 or retries < max)
|
370
|
+
|
371
|
+
always.call if always and always.is_a?(Proc)
|
372
|
+
end
|
373
|
+
|
302
374
|
if !ENV.has_key?("MU_LIBDIR") and ENV.has_key?("MU_INSTALLDIR")
|
303
375
|
ENV['MU_LIBDIR'] = ENV['MU_INSTALLDIR']+"/lib"
|
304
376
|
else
|
@@ -349,6 +421,13 @@ module MU
|
|
349
421
|
|
350
422
|
if Gem.paths and Gem.paths.home and File.dirname(__FILE__).match(/^#{Gem.paths.home}/)
|
351
423
|
@in_gem = true
|
424
|
+
elsif Gem.paths and Gem.paths.path and !Gem.paths.path.empty?
|
425
|
+
Gem.paths.path.each { |p|
|
426
|
+
if File.dirname(__FILE__).match(/^#{Regexp.quote(p)}/)
|
427
|
+
@in_gem = true
|
428
|
+
end
|
429
|
+
}
|
430
|
+
@in_gem = false if !defined? @in_gem
|
352
431
|
else
|
353
432
|
@in_gem = false
|
354
433
|
end
|
@@ -391,20 +470,20 @@ module MU
|
|
391
470
|
@@global_var_semaphore = Mutex.new
|
392
471
|
|
393
472
|
# Set one of our global per-thread variables.
|
394
|
-
def self.setVar(name, value)
|
473
|
+
def self.setVar(name, value, target_thread: Thread.current)
|
395
474
|
@@global_var_semaphore.synchronize {
|
396
|
-
@@globals[
|
397
|
-
@@globals[
|
398
|
-
@@globals[
|
475
|
+
@@globals[target_thread.object_id] ||= Hash.new
|
476
|
+
@@globals[target_thread.object_id][name] ||= Hash.new
|
477
|
+
@@globals[target_thread.object_id][name] = value
|
399
478
|
}
|
400
479
|
end
|
401
480
|
|
402
481
|
# Copy the set of global variables in use by another thread, typically our
|
403
482
|
# parent thread.
|
404
|
-
def self.dupGlobals(parent_thread_id)
|
483
|
+
def self.dupGlobals(parent_thread_id, target_thread: Thread.current)
|
405
484
|
@@globals[parent_thread_id] ||= {}
|
406
485
|
@@globals[parent_thread_id].each_pair { |name, value|
|
407
|
-
setVar(name, value)
|
486
|
+
setVar(name, value, target_thread: target_thread)
|
408
487
|
}
|
409
488
|
end
|
410
489
|
|
@@ -532,9 +611,10 @@ module MU
|
|
532
611
|
end
|
533
612
|
|
534
613
|
# Shortcut to invoke {MU::Logger#log}
|
535
|
-
def self.log(msg, level = MU::INFO, details: nil, html: false, verbosity: nil, color: true)
|
614
|
+
def self.log(msg, level = MU::INFO, shorthand_details = nil, details: nil, html: false, verbosity: nil, color: true)
|
536
615
|
return if (level == MU::DEBUG and verbosity and verbosity <= MU::Logger::LOUD)
|
537
616
|
return if verbosity and verbosity == MU::Logger::SILENT
|
617
|
+
details ||= shorthand_details
|
538
618
|
|
539
619
|
if (level == MU::ERR or
|
540
620
|
level == MU::WARN or
|
@@ -553,25 +633,6 @@ module MU
|
|
553
633
|
@@logger.log(msg, level, details: details, html: html, verbosity: verbosity, color: color)
|
554
634
|
end
|
555
635
|
|
556
|
-
# For log entries that should only be logged when we're in verbose mode
|
557
|
-
DEBUG = 0.freeze
|
558
|
-
# For ordinary log entries
|
559
|
-
INFO = 1.freeze
|
560
|
-
# For more interesting log entries which are not errors
|
561
|
-
NOTICE = 2.freeze
|
562
|
-
# Log entries for non-fatal errors
|
563
|
-
WARN = 3.freeze
|
564
|
-
# Log entries for non-fatal errors
|
565
|
-
WARNING = 3.freeze
|
566
|
-
# Log entries for fatal errors
|
567
|
-
ERR = 4.freeze
|
568
|
-
# Log entries for fatal errors
|
569
|
-
ERROR = 4.freeze
|
570
|
-
# Log entries that will be held and displayed/emailed at the end of deploy,
|
571
|
-
# cleanup, etc.
|
572
|
-
SUMMARY = 5.freeze
|
573
|
-
|
574
|
-
|
575
636
|
autoload :Cleanup, 'mu/cleanup'
|
576
637
|
autoload :Deploy, 'mu/deploy'
|
577
638
|
autoload :MommaCat, 'mu/mommacat'
|
@@ -585,7 +646,7 @@ module MU
|
|
585
646
|
new_cfg = $MU_CFG.dup
|
586
647
|
examples = {}
|
587
648
|
MU::Cloud.supportedClouds.each { |cloud|
|
588
|
-
cloudclass =
|
649
|
+
cloudclass = MU::Cloud.cloudClass(cloud)
|
589
650
|
begin
|
590
651
|
if cloudclass.hosted? and !$MU_CFG[cloud.downcase]
|
591
652
|
cfg_blob = cloudclass.hosted_config
|
@@ -642,7 +703,7 @@ module MU
|
|
642
703
|
!$MU_CFG['public_address'].empty? and @@my_public_ip != $MU_CFG['public_address']
|
643
704
|
@@mu_public_addr = $MU_CFG['public_address']
|
644
705
|
if !@@mu_public_addr.match(/^\d+\.\d+\.\d+\.\d+$/)
|
645
|
-
hostname = IO.readlines("/etc/hostname")[0].gsub
|
706
|
+
hostname = IO.readlines("/etc/hostname")[0].gsub(/\n/, '')
|
646
707
|
|
647
708
|
hostlines = File.open('/etc/hosts').grep(/.*#{hostname}.*/)
|
648
709
|
if hostlines and !hostlines.empty?
|
@@ -741,11 +802,7 @@ module MU
|
|
741
802
|
# @param groomer [String]: The grooming agent to load.
|
742
803
|
# @return [Class]: The class object implementing this groomer agent
|
743
804
|
def self.loadGroomer(groomer)
|
744
|
-
|
745
|
-
raise MuError, "Requested to use unsupported grooming agent #{groomer}"
|
746
|
-
end
|
747
|
-
require "mu/groomers/#{groomer.downcase}"
|
748
|
-
return Object.const_get("MU").const_get("Groomer").const_get(groomer)
|
805
|
+
MU::Groomer.loadGroomer(groomer)
|
749
806
|
end
|
750
807
|
|
751
808
|
@@myRegion_var = nil
|
@@ -899,8 +956,7 @@ module MU
|
|
899
956
|
|
900
957
|
@@myCloudDescriptor = nil
|
901
958
|
if MU.myCloud
|
902
|
-
|
903
|
-
found = svrclass.find(cloud_id: @@myInstanceId, region: MU.myRegion) # XXX need habitat arg for google et al
|
959
|
+
found = MU::Cloud.resourceClass(MU.myCloud, "Server").find(cloud_id: @@myInstanceId, region: MU.myRegion) # XXX need habitat arg for google et al
|
904
960
|
# found = MU::MommaCat.findStray(MU.myCloud, "server", cloud_id: @@myInstanceId, dummy_ok: true, region: MU.myRegion)
|
905
961
|
if !found.nil? and found.size == 1
|
906
962
|
@@myCloudDescriptor = found.values.first
|
@@ -913,8 +969,7 @@ module MU
|
|
913
969
|
def self.myVPCObj
|
914
970
|
return nil if MU.myCloud.nil?
|
915
971
|
return @@myVPCObj_var if @@myVPCObj_var
|
916
|
-
|
917
|
-
@@myVPCObj_var ||= cloudclass.myVPCObj
|
972
|
+
@@myVPCObj_var ||= MU::Cloud.cloudClass(MU.myCloud).myVPCObj
|
918
973
|
@@myVPCObj_var
|
919
974
|
end
|
920
975
|
|
@@ -1012,15 +1067,15 @@ module MU
|
|
1012
1067
|
|
1013
1068
|
# Generate a random password which will satisfy the complexity requirements of stock Amazon Windows AMIs.
|
1014
1069
|
# return [String]: A password string.
|
1015
|
-
def self.generateWindowsPassword(safe_pattern: '~!@#%^&*_-+=`|(){}[]:;<>,.?', retries:
|
1070
|
+
def self.generateWindowsPassword(safe_pattern: '~!@#%^&*_-+=`|(){}[]:;<>,.?', retries: 50)
|
1016
1071
|
# We have dopey complexity requirements, be stringent here.
|
1017
1072
|
# I'll be nice and not condense this into one elegant-but-unreadable regular expression
|
1018
1073
|
attempts = 0
|
1019
1074
|
safe_metachars = Regexp.escape(safe_pattern)
|
1020
1075
|
begin
|
1021
1076
|
if attempts > retries
|
1022
|
-
MU.log "Failed to generate an adequate Windows password after #{attempts}", MU::ERR
|
1023
|
-
raise MuError, "Failed to generate an adequate Windows password after #{attempts}"
|
1077
|
+
MU.log "Failed to generate an adequate Windows password after #{attempts} attempts", MU::ERR
|
1078
|
+
raise MuError, "Failed to generate an adequate Windows password after #{attempts} attempts"
|
1024
1079
|
end
|
1025
1080
|
winpass = Password.random(14..16)
|
1026
1081
|
attempts += 1
|
@@ -1039,10 +1094,9 @@ module MU
|
|
1039
1094
|
|
1040
1095
|
clouds = platform.nil? ? MU::Cloud.supportedClouds : [platform]
|
1041
1096
|
clouds.each { |cloud|
|
1042
|
-
|
1043
|
-
bucketname = cloudclass.adminBucketName(credentials)
|
1097
|
+
bucketname = MU::Cloud.cloudClass(cloud).adminBucketName(credentials)
|
1044
1098
|
begin
|
1045
|
-
if platform or (
|
1099
|
+
if platform or (MU::Cloud.cloudClass(cloud).hosted? and platform.nil?) or cloud == MU::Config.defaultCloud
|
1046
1100
|
return bucketname
|
1047
1101
|
end
|
1048
1102
|
end
|