cloud-mu 3.2.0 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/ansible/roles/mu-nat/tasks/main.yml +3 -0
- data/bin/mu-adopt +12 -1
- data/bin/mu-aws-setup +41 -7
- data/bin/mu-azure-setup +34 -0
- data/bin/mu-configure +214 -119
- data/bin/mu-gcp-setup +37 -2
- data/bin/mu-load-config.rb +2 -1
- data/bin/mu-node-manage +3 -0
- data/bin/mu-refresh-ssl +67 -0
- data/bin/mu-run-tests +28 -6
- data/bin/mu-self-update +30 -10
- data/bin/mu-upload-chef-artifacts +30 -26
- data/cloud-mu.gemspec +10 -8
- data/cookbooks/mu-master/attributes/default.rb +5 -1
- data/cookbooks/mu-master/metadata.rb +2 -2
- data/cookbooks/mu-master/recipes/default.rb +81 -26
- data/cookbooks/mu-master/recipes/init.rb +197 -62
- data/cookbooks/mu-master/recipes/update_nagios_only.rb +1 -1
- data/cookbooks/mu-master/recipes/vault.rb +78 -77
- data/cookbooks/mu-master/templates/default/mods/rewrite.conf.erb +1 -0
- data/cookbooks/mu-master/templates/default/nagios.conf.erb +103 -0
- data/cookbooks/mu-master/templates/default/web_app.conf.erb +14 -30
- data/cookbooks/mu-tools/attributes/default.rb +12 -0
- data/cookbooks/mu-tools/files/centos-6/CentOS-Base.repo +47 -0
- data/cookbooks/mu-tools/libraries/helper.rb +98 -4
- data/cookbooks/mu-tools/libraries/monkey.rb +1 -1
- data/cookbooks/mu-tools/recipes/apply_security.rb +31 -9
- data/cookbooks/mu-tools/recipes/aws_api.rb +8 -2
- data/cookbooks/mu-tools/recipes/base_repositories.rb +1 -1
- data/cookbooks/mu-tools/recipes/gcloud.rb +2 -9
- data/cookbooks/mu-tools/recipes/google_api.rb +7 -0
- data/cookbooks/mu-tools/recipes/rsyslog.rb +8 -1
- data/cookbooks/mu-tools/resources/disk.rb +113 -42
- data/cookbooks/mu-tools/resources/mommacat_request.rb +1 -2
- data/cookbooks/mu-tools/templates/centos-8/sshd_config.erb +215 -0
- data/extras/Gemfile.lock.bootstrap +394 -0
- data/extras/bucketstubs/error.html +0 -0
- data/extras/bucketstubs/index.html +0 -0
- data/extras/clean-stock-amis +11 -3
- data/extras/generate-stock-images +6 -3
- data/extras/git_rpm/build.sh +20 -0
- data/extras/git_rpm/mugit.spec +53 -0
- data/extras/image-generators/AWS/centos7.yaml +19 -16
- data/extras/image-generators/AWS/{rhel7.yaml → rhel71.yaml} +0 -0
- data/extras/image-generators/AWS/{win2k12.yaml → win2k12r2.yaml} +0 -0
- data/extras/image-generators/VMWare/centos8.yaml +15 -0
- data/extras/openssl_rpm/build.sh +19 -0
- data/extras/openssl_rpm/mussl.spec +46 -0
- data/extras/python_rpm/muthon.spec +14 -4
- data/extras/ruby_rpm/muby.spec +9 -5
- data/extras/sqlite_rpm/build.sh +19 -0
- data/extras/sqlite_rpm/muqlite.spec +47 -0
- data/install/installer +7 -5
- data/modules/mommacat.ru +2 -2
- data/modules/mu.rb +14 -7
- data/modules/mu/adoption.rb +5 -5
- data/modules/mu/cleanup.rb +47 -25
- data/modules/mu/cloud.rb +29 -1
- data/modules/mu/cloud/dnszone.rb +0 -2
- data/modules/mu/cloud/machine_images.rb +1 -1
- data/modules/mu/cloud/providers.rb +6 -1
- data/modules/mu/cloud/resource_base.rb +16 -7
- data/modules/mu/cloud/ssh_sessions.rb +5 -1
- data/modules/mu/cloud/wrappers.rb +20 -7
- data/modules/mu/config.rb +28 -12
- data/modules/mu/config/bucket.rb +31 -2
- data/modules/mu/config/cache_cluster.rb +1 -1
- data/modules/mu/config/cdn.rb +100 -0
- data/modules/mu/config/container_cluster.rb +1 -1
- data/modules/mu/config/database.rb +3 -3
- data/modules/mu/config/dnszone.rb +4 -3
- data/modules/mu/config/endpoint.rb +1 -0
- data/modules/mu/config/firewall_rule.rb +1 -1
- data/modules/mu/config/function.rb +16 -7
- data/modules/mu/config/job.rb +89 -0
- data/modules/mu/config/notifier.rb +7 -18
- data/modules/mu/config/ref.rb +55 -9
- data/modules/mu/config/schema_helpers.rb +12 -3
- data/modules/mu/config/server.rb +11 -5
- data/modules/mu/config/server_pool.rb +2 -2
- data/modules/mu/config/vpc.rb +11 -10
- data/modules/mu/defaults/AWS.yaml +106 -106
- data/modules/mu/deploy.rb +40 -14
- data/modules/mu/groomers/chef.rb +2 -2
- data/modules/mu/master.rb +70 -3
- data/modules/mu/mommacat.rb +28 -9
- data/modules/mu/mommacat/daemon.rb +13 -7
- data/modules/mu/mommacat/naming.rb +2 -2
- data/modules/mu/mommacat/search.rb +16 -5
- data/modules/mu/mommacat/storage.rb +67 -32
- data/modules/mu/providers/aws.rb +298 -85
- data/modules/mu/providers/aws/alarm.rb +5 -5
- data/modules/mu/providers/aws/bucket.rb +284 -50
- data/modules/mu/providers/aws/cache_cluster.rb +26 -26
- data/modules/mu/providers/aws/cdn.rb +782 -0
- data/modules/mu/providers/aws/collection.rb +16 -16
- data/modules/mu/providers/aws/container_cluster.rb +84 -64
- data/modules/mu/providers/aws/database.rb +59 -55
- data/modules/mu/providers/aws/dnszone.rb +29 -12
- data/modules/mu/providers/aws/endpoint.rb +535 -50
- data/modules/mu/providers/aws/firewall_rule.rb +32 -26
- data/modules/mu/providers/aws/folder.rb +1 -1
- data/modules/mu/providers/aws/function.rb +300 -134
- data/modules/mu/providers/aws/group.rb +16 -14
- data/modules/mu/providers/aws/habitat.rb +4 -4
- data/modules/mu/providers/aws/job.rb +469 -0
- data/modules/mu/providers/aws/loadbalancer.rb +67 -45
- data/modules/mu/providers/aws/log.rb +17 -17
- data/modules/mu/providers/aws/msg_queue.rb +22 -13
- data/modules/mu/providers/aws/nosqldb.rb +99 -8
- data/modules/mu/providers/aws/notifier.rb +137 -65
- data/modules/mu/providers/aws/role.rb +119 -83
- data/modules/mu/providers/aws/search_domain.rb +166 -30
- data/modules/mu/providers/aws/server.rb +209 -118
- data/modules/mu/providers/aws/server_pool.rb +95 -130
- data/modules/mu/providers/aws/storage_pool.rb +19 -11
- data/modules/mu/providers/aws/user.rb +5 -5
- data/modules/mu/providers/aws/userdata/linux.erb +5 -4
- data/modules/mu/providers/aws/vpc.rb +109 -54
- data/modules/mu/providers/aws/vpc_subnet.rb +43 -39
- data/modules/mu/providers/azure.rb +78 -12
- data/modules/mu/providers/azure/server.rb +20 -4
- data/modules/mu/providers/cloudformation/server.rb +1 -1
- data/modules/mu/providers/google.rb +21 -5
- data/modules/mu/providers/google/bucket.rb +1 -1
- data/modules/mu/providers/google/container_cluster.rb +1 -1
- data/modules/mu/providers/google/database.rb +1 -1
- data/modules/mu/providers/google/firewall_rule.rb +1 -1
- data/modules/mu/providers/google/folder.rb +7 -3
- data/modules/mu/providers/google/function.rb +66 -31
- data/modules/mu/providers/google/group.rb +1 -1
- data/modules/mu/providers/google/habitat.rb +1 -1
- data/modules/mu/providers/google/loadbalancer.rb +1 -1
- data/modules/mu/providers/google/role.rb +6 -3
- data/modules/mu/providers/google/server.rb +1 -1
- data/modules/mu/providers/google/server_pool.rb +1 -1
- data/modules/mu/providers/google/user.rb +1 -1
- data/modules/mu/providers/google/vpc.rb +28 -3
- data/modules/tests/aws-jobs-functions.yaml +46 -0
- data/modules/tests/aws-servers-with-handrolled-iam.yaml +37 -0
- data/modules/tests/centos6.yaml +4 -0
- data/modules/tests/centos7.yaml +4 -0
- data/modules/tests/ecs.yaml +2 -2
- data/modules/tests/eks.yaml +1 -1
- data/modules/tests/functions/node-function/lambda_function.js +10 -0
- data/modules/tests/functions/python-function/lambda_function.py +12 -0
- data/modules/tests/k8s.yaml +1 -1
- data/modules/tests/microservice_app.yaml +288 -0
- data/modules/tests/rds.yaml +5 -5
- data/modules/tests/regrooms/rds.yaml +5 -5
- data/modules/tests/server-with-scrub-muisms.yaml +1 -1
- data/modules/tests/super_complex_bok.yml +2 -2
- data/modules/tests/super_simple_bok.yml +2 -2
- metadata +42 -17
data/modules/mu/groomers/chef.rb
CHANGED
@@ -70,8 +70,8 @@ module MU
|
|
70
70
|
# XXX kludge to get at knife-windows when it's installed from
|
71
71
|
# a git repo and bundler sticks it somewhere in a corner
|
72
72
|
$LOAD_PATH.each { |path|
|
73
|
-
if path.match(/\/gems\/
|
74
|
-
addpath = path.sub(/\/gems\/
|
73
|
+
if path.match(/\/gems\/chef\-\d+\.\d+\.\d+\/lib$/)
|
74
|
+
addpath = path.sub(/\/gems\/chef\-\d+\.\d+\.\d+\/lib$/, "")+"/bundler/gems"
|
75
75
|
Dir.glob(addpath+"/knife-windows-*").each { |version|
|
76
76
|
$LOAD_PATH << version+"/lib"
|
77
77
|
}
|
data/modules/mu/master.rb
CHANGED
@@ -195,9 +195,12 @@ module MU
|
|
195
195
|
temp_dev = "/dev/#{ramdisk}"
|
196
196
|
|
197
197
|
if !File.open("/etc/mtab").read.match(/ #{path} /)
|
198
|
-
realdevice =
|
199
|
-
|
200
|
-
|
198
|
+
realdevice = if MU::Cloud::Google.hosted?
|
199
|
+
"/dev/disk/by-id/google-"+device.gsub(/.*?\/([^\/]+)$/, '\1')
|
200
|
+
elsif MU::Cloud::AWS.hosted?
|
201
|
+
MU::Cloud::AWS.realDevicePath(device.dup)
|
202
|
+
else
|
203
|
+
device.dup
|
201
204
|
end
|
202
205
|
alias_device = cryptfile ? "/dev/mapper/"+path.gsub(/[^0-9a-z_\-]/i, "_") : realdevice
|
203
206
|
|
@@ -216,6 +219,9 @@ module MU
|
|
216
219
|
tag_name: "Name",
|
217
220
|
tag_value: "#{$MU_CFG['hostname']} #{path}"
|
218
221
|
)
|
222
|
+
# the device might be on some arbitrary NVMe slot
|
223
|
+
realdevice = MU::Cloud::AWS.realDevicePath(realdevice)
|
224
|
+
alias_device = cryptfile ? "/dev/mapper/"+path.gsub(/[^0-9a-z_\-]/i, "_") : realdevice
|
219
225
|
elsif MU::Cloud::Google.hosted?
|
220
226
|
dummy_svr = MU::Cloud::Google::Server.new(
|
221
227
|
mu_name: "MU-MASTER",
|
@@ -880,5 +886,66 @@ module MU
|
|
880
886
|
end
|
881
887
|
end
|
882
888
|
|
889
|
+
# Recursively zip a directory
|
890
|
+
# @param srcdir [String]
|
891
|
+
# @param outfile [String]
|
892
|
+
def self.zipDir(srcdir, outfile)
|
893
|
+
require 'zip'
|
894
|
+
::Zip::File.open(outfile, ::Zip::File::CREATE) { |zipfile|
|
895
|
+
addpath = Proc.new { |zip_path, parent_path|
|
896
|
+
Dir.entries(parent_path).reject{ |d| [".", ".."].include?(d) }.each { |entry|
|
897
|
+
src = File.join(parent_path, entry)
|
898
|
+
dst = File.join(zip_path, entry).sub(/^\//, '')
|
899
|
+
if File.directory?(src)
|
900
|
+
addpath.call(dst, src)
|
901
|
+
else
|
902
|
+
zipfile.add(dst, src)
|
903
|
+
end
|
904
|
+
}
|
905
|
+
}
|
906
|
+
addpath.call("", srcdir)
|
907
|
+
}
|
908
|
+
end
|
909
|
+
|
910
|
+
# Just list our block devices
|
911
|
+
# @return [Array<String>]
|
912
|
+
def self.listBlockDevices
|
913
|
+
if File.executable?("/bin/lsblk")
|
914
|
+
%x{/bin/lsblk -i -p -r -n | egrep ' disk( |$)'}.each_line.map { |l|
|
915
|
+
l.chomp.sub(/ .*/, '')
|
916
|
+
}
|
917
|
+
else
|
918
|
+
# XXX something dumber
|
919
|
+
nil
|
920
|
+
end
|
921
|
+
end
|
922
|
+
|
923
|
+
|
924
|
+
# Retrieve the UUID of a block device, if available
|
925
|
+
# @param dev [String]
|
926
|
+
def self.diskUUID(dev)
|
927
|
+
realdev = if MU::Cloud::Google.hosted?
|
928
|
+
"/dev/disk/by-id/google-"+dev.gsub(/.*?\/([^\/]+)$/, '\1')
|
929
|
+
elsif MU::Cloud::AWS.hosted?
|
930
|
+
MU::Cloud::AWS.realDevicePath(dev)
|
931
|
+
else
|
932
|
+
dev
|
933
|
+
end
|
934
|
+
%x{/sbin/blkid #{realdev} -o export | grep ^UUID=}.chomp
|
935
|
+
end
|
936
|
+
|
937
|
+
# Determine whether we're running in an NVMe-enabled environment
|
938
|
+
def self.nvme?
|
939
|
+
if File.executable?("/bin/lsblk")
|
940
|
+
%x{/bin/lsblk -i -p -r -n}.each_line { |l|
|
941
|
+
return true if l =~ /^\/dev\/nvme\d/
|
942
|
+
}
|
943
|
+
else
|
944
|
+
return true if File.exists?("/dev/nvme0n1")
|
945
|
+
end
|
946
|
+
false
|
947
|
+
end
|
948
|
+
|
949
|
+
|
883
950
|
end
|
884
951
|
end
|
data/modules/mu/mommacat.rb
CHANGED
@@ -173,6 +173,7 @@ module MU
|
|
173
173
|
@public_key = nil
|
174
174
|
@secrets = Hash.new
|
175
175
|
@secrets['instance_secret'] = Hash.new
|
176
|
+
@secrets['windows_admin_password'] = Hash.new
|
176
177
|
@ssh_key_name = ssh_key_name
|
177
178
|
@ssh_private_key = ssh_private_key
|
178
179
|
@ssh_public_key = ssh_public_key
|
@@ -512,6 +513,8 @@ module MU
|
|
512
513
|
@ssh_private_key = File.read("#{ssh_dir}/#{@ssh_key_name}")
|
513
514
|
@ssh_private_key.chomp!
|
514
515
|
|
516
|
+
# XXX the following mess belongs in cloud layers, probably in their initDeploy
|
517
|
+
# methods
|
515
518
|
if numKittens(clouds: ["AWS"], types: ["Server", "ServerPool", "ContainerCluster"]) > 0
|
516
519
|
creds_used = []
|
517
520
|
["servers", "server_pools", "container_clusters"].each { |type|
|
@@ -547,15 +550,26 @@ module MU
|
|
547
550
|
# @param remove [Boolean]: Remove this resource from the deploy structure, instead of adding it.
|
548
551
|
# @return [void]
|
549
552
|
def notify(type, key, data, mu_name: nil, remove: false, triggering_node: nil, delayed_save: false)
|
553
|
+
no_write = (@no_artifacts or !caller.grep(/\/mommacat\.rb:\d+:in `notify'/).empty?)
|
550
554
|
|
551
555
|
begin
|
552
|
-
|
556
|
+
if !no_write
|
557
|
+
if !MU::MommaCat.lock("deployment-notification", deploy_id: @deploy_id, retries: 300)
|
558
|
+
raise MuError, "Failed to get deployment-notifcation lock for #{@deploy_id}"
|
559
|
+
end
|
560
|
+
end
|
553
561
|
|
554
562
|
if !@need_deploy_flush or @deployment.nil? or @deployment.empty?
|
555
563
|
loadDeploy(true) # make sure we're saving the latest and greatest
|
556
564
|
end
|
557
565
|
|
558
|
-
|
566
|
+
@timestamp ||= @deployment['timestamp']
|
567
|
+
@seed ||= @deployment['seed']
|
568
|
+
@appname ||= @deployment['appname']
|
569
|
+
@handle ||= @deployment['handle']
|
570
|
+
|
571
|
+
_shortclass, _cfg_name, mu_type, _classname, attrs = MU::Cloud.getResourceNames(type, false)
|
572
|
+
type = mu_type if mu_type
|
559
573
|
has_multiples = attrs[:has_multiples] ? true : false
|
560
574
|
|
561
575
|
mu_name ||= if !data.nil? and !data["mu_name"].nil?
|
@@ -569,6 +583,7 @@ module MU
|
|
569
583
|
end
|
570
584
|
|
571
585
|
@need_deploy_flush = true
|
586
|
+
@last_modified = Time.now
|
572
587
|
|
573
588
|
if !remove
|
574
589
|
if data.nil?
|
@@ -588,7 +603,9 @@ module MU
|
|
588
603
|
@deployment[type][key] = data
|
589
604
|
MU.log "Adding to @deployment[#{type}][#{key}]", MU::DEBUG, details: data
|
590
605
|
end
|
591
|
-
|
606
|
+
if !delayed_save and !no_write
|
607
|
+
save!(key)
|
608
|
+
end
|
592
609
|
else
|
593
610
|
have_deploy = true
|
594
611
|
if @deployment[type].nil? or @deployment[type][key].nil?
|
@@ -613,10 +630,10 @@ module MU
|
|
613
630
|
end
|
614
631
|
}
|
615
632
|
end
|
616
|
-
save! if !delayed_save and
|
633
|
+
save! if !delayed_save and !no_write
|
617
634
|
end
|
618
635
|
ensure
|
619
|
-
MU::MommaCat.unlock("deployment-notification", deploy_id: @deploy_id) if
|
636
|
+
MU::MommaCat.unlock("deployment-notification", deploy_id: @deploy_id) if !no_write
|
620
637
|
end
|
621
638
|
end
|
622
639
|
|
@@ -811,6 +828,7 @@ MAIL_HEAD_END
|
|
811
828
|
|
812
829
|
threads = []
|
813
830
|
update_servers.each { |sibling|
|
831
|
+
next if sibling.config.has_key?("groom") and !sibling.config["groom"]
|
814
832
|
threads << Thread.new {
|
815
833
|
Thread.abort_on_exception = true
|
816
834
|
Thread.current.thread_variable_set("name", "sync-"+sibling.mu_name.downcase)
|
@@ -869,13 +887,13 @@ MAIL_HEAD_END
|
|
869
887
|
if resource and resource.config and resource.config['cloud']
|
870
888
|
cloudclass = MU::Cloud.cloudClass(resource.config['cloud'])
|
871
889
|
|
872
|
-
cloudclass.writeDeploySecret(
|
873
|
-
cloudclass.writeDeploySecret(
|
890
|
+
cloudclass.writeDeploySecret(self, cert.to_pem, cert_cn+".crt", credentials: resource.config['credentials'])
|
891
|
+
cloudclass.writeDeploySecret(self, key.to_pem, cert_cn+".key", credentials: resource.config['credentials'])
|
874
892
|
if pfx_cert
|
875
|
-
cloudclass.writeDeploySecret(
|
893
|
+
cloudclass.writeDeploySecret(self, pfx_cert.to_der, cert_cn+".pfx", credentials: resource.config['credentials'])
|
876
894
|
end
|
877
895
|
if winrm_cert
|
878
|
-
cloudclass.writeDeploySecret(
|
896
|
+
cloudclass.writeDeploySecret(self, winrm_cert.to_pem, cert_cn+"-winrm.crt", credentials: resource.config['credentials'])
|
879
897
|
end
|
880
898
|
end
|
881
899
|
|
@@ -895,6 +913,7 @@ MAIL_HEAD_END
|
|
895
913
|
###########################################################################
|
896
914
|
###########################################################################
|
897
915
|
def setThreadContextToMe
|
916
|
+
|
898
917
|
["appname", "environment", "timestamp", "seed", "handle"].each { |var|
|
899
918
|
@deployment[var] ||= instance_variable_get("@#{var}".to_sym)
|
900
919
|
if @deployment[var]
|
@@ -288,8 +288,8 @@ module MU
|
|
288
288
|
|
289
289
|
# Path to the PID file used by the Momma Cat daemon
|
290
290
|
# @return [String]
|
291
|
-
def self.daemonPidFile
|
292
|
-
base = (Process.uid == 0 and !MU.localOnly) ? "/var" : MU.dataDir
|
291
|
+
def self.daemonPidFile(root = false)
|
292
|
+
base = ((Process.uid == 0 or root) and !MU.localOnly) ? "/var" : MU.dataDir
|
293
293
|
"#{base}/run/mommacat.pid"
|
294
294
|
end
|
295
295
|
|
@@ -306,8 +306,14 @@ module MU
|
|
306
306
|
Dir.mkdir(dir)
|
307
307
|
end
|
308
308
|
}
|
309
|
-
|
309
|
+
if (Process.uid != 0 and
|
310
|
+
(!$MU_CFG['overridden_keys'] or !$MU_CFG['overridden_keys'].include?("mommacat_port")) and
|
311
|
+
status(true)
|
312
|
+
) or status
|
313
|
+
return 0
|
314
|
+
end
|
310
315
|
|
316
|
+
File.unlink(daemonPidFile) if File.exists?(daemonPidFile)
|
311
317
|
MU.log "Starting Momma Cat on port #{MU.mommaCatPort}, logging to #{daemonLogFile}, PID file #{daemonPidFile}"
|
312
318
|
origdir = Dir.getwd
|
313
319
|
Dir.chdir(MU.myRoot+"/modules")
|
@@ -346,12 +352,12 @@ module MU
|
|
346
352
|
|
347
353
|
# Return true if the Momma Cat daemon appears to be running
|
348
354
|
# @return [Boolean]
|
349
|
-
def self.status
|
355
|
+
def self.status(root = false)
|
350
356
|
if MU.inGem? and MU.muCfg['disable_mommacat']
|
351
357
|
return true
|
352
358
|
end
|
353
|
-
if File.exist?(daemonPidFile)
|
354
|
-
pid = File.read(daemonPidFile).chomp.to_i
|
359
|
+
if File.exist?(daemonPidFile(root))
|
360
|
+
pid = File.read(daemonPidFile(root)).chomp.to_i
|
355
361
|
begin
|
356
362
|
Process.getpgid(pid)
|
357
363
|
MU.log "Momma Cat running with pid #{pid.to_s}", (@@notified_on_pid[pid] ? MU::DEBUG : MU::INFO) # shush
|
@@ -360,7 +366,7 @@ module MU
|
|
360
366
|
rescue Errno::ESRCH
|
361
367
|
end
|
362
368
|
end
|
363
|
-
MU.log "Momma Cat daemon not running", MU::NOTICE, details: daemonPidFile
|
369
|
+
MU.log "Momma Cat daemon not running", MU::NOTICE, details: daemonPidFile(root)
|
364
370
|
false
|
365
371
|
end
|
366
372
|
|
@@ -164,7 +164,7 @@ module MU
|
|
164
164
|
# @param scrub_mu_isms [Boolean]: Don't bother with generating names specific to this deployment. Used to generate generic CloudFormation templates, amongst other purposes.
|
165
165
|
# @param disallowed_chars [Regexp]: A pattern of characters that are illegal for this resource name, such as +/[^a-zA-Z0-9-]/+
|
166
166
|
# @return [String]: A full name string for this resource
|
167
|
-
def getResourceName(name, max_length: 255, need_unique_string: false, use_unique_string: nil, reuse_unique_string: false, scrub_mu_isms: @original_config['scrub_mu_isms'], disallowed_chars: nil)
|
167
|
+
def getResourceName(name, max_length: 255, need_unique_string: false, use_unique_string: nil, reuse_unique_string: false, scrub_mu_isms: @original_config['scrub_mu_isms'], disallowed_chars: nil, never_gen_unique: false)
|
168
168
|
if name.nil?
|
169
169
|
raise MuError, "Got no argument to MU::MommaCat.getResourceName"
|
170
170
|
end
|
@@ -219,7 +219,7 @@ module MU
|
|
219
219
|
else
|
220
220
|
# If we have to strip anything, assume we've lost uniqueness and
|
221
221
|
# will have to compensate with #genUniquenessString.
|
222
|
-
need_unique_string = true
|
222
|
+
need_unique_string = true if !never_gen_unique
|
223
223
|
reserved = 4
|
224
224
|
basename.sub!(/-[^-]+-#{@seed.upcase}-#{Regexp.escape(name.upcase)}$/, "")
|
225
225
|
basename = basename + "-" + @seed.upcase + "-" + name.upcase
|
@@ -107,8 +107,17 @@ module MU
|
|
107
107
|
matches = []
|
108
108
|
|
109
109
|
credlist.each { |creds|
|
110
|
-
|
111
|
-
|
110
|
+
cur_habitats = []
|
111
|
+
|
112
|
+
if habitats and !habitats.empty? and habitats != [nil]
|
113
|
+
valid_habitats = cloudclass.listHabitats(creds)
|
114
|
+
cur_habitats = (habitats & valid_habitats)
|
115
|
+
next if cur_habitats.empty?
|
116
|
+
else
|
117
|
+
cur_habitats = cloudclass.listHabitats(creds)
|
118
|
+
end
|
119
|
+
|
120
|
+
cloud_descs = search_cloud_provider(type, cloud, cur_habitats, region, cloud_id: cloud_id, tag_key: tag_key, tag_value: tag_value, credentials: creds, flags: flags)
|
112
121
|
|
113
122
|
cloud_descs.each_pair.each { |p, regions|
|
114
123
|
regions.each_pair.each { |r, results|
|
@@ -138,7 +147,7 @@ module MU
|
|
138
147
|
# @param created_only [Boolean]: Only return the littermate if its cloud_id method returns a value
|
139
148
|
# @param return_all [Boolean]: Return a Hash of matching objects indexed by their mu_name, instead of a single match. Only valid for resource types where has_multiples is true.
|
140
149
|
# @return [MU::Cloud]
|
141
|
-
def findLitterMate(type: nil, name: nil, mu_name: nil, cloud_id: nil, created_only: false, return_all: false, credentials: nil, habitat: nil, debug: false, **flags)
|
150
|
+
def findLitterMate(type: nil, name: nil, mu_name: nil, cloud_id: nil, created_only: false, return_all: false, credentials: nil, habitat: nil, ignore_missing: false, debug: false, **flags)
|
142
151
|
_shortclass, _cfg_name, type, _classname, attrs = MU::Cloud.getResourceNames(type)
|
143
152
|
|
144
153
|
# If we specified a habitat, which we may also have done by its shorthand
|
@@ -173,8 +182,10 @@ module MU
|
|
173
182
|
end
|
174
183
|
end
|
175
184
|
if @object_load_fails or !@kittens[type]
|
176
|
-
|
177
|
-
|
185
|
+
if !ignore_missing
|
186
|
+
MU.log "#{@deploy_id}'s original config has #{@original_config[type].size == 1 ? "a" : @original_config[type].size.to_s} #{type}, but loadObjects could not populate anything from deployment metadata", MU::ERR if !@object_load_fails
|
187
|
+
@object_load_fails = true
|
188
|
+
end
|
178
189
|
return nil
|
179
190
|
end
|
180
191
|
end
|
@@ -123,11 +123,12 @@ module MU
|
|
123
123
|
MU::Cloud.resource_types.each_pair { |res_type, attrs|
|
124
124
|
next if !@deployment.has_key?(attrs[:cfg_plural])
|
125
125
|
deletia = []
|
126
|
+
# existing_deploys
|
126
127
|
@deployment[attrs[:cfg_plural]].each_pair { |res_name, data|
|
127
128
|
orig_cfg = findResourceConfig(attrs[:cfg_plural], res_name, (scrub_with || @original_config))
|
128
129
|
|
129
|
-
if orig_cfg.nil?
|
130
|
-
MU.log "#{res_type} #{res_name} no longer configured, will remove deployment metadata", MU::NOTICE
|
130
|
+
if orig_cfg.nil? and (!data['mu_name'] or data['mu_name'] =~ /^#{Regexp.quote(@deploy_id)}/)
|
131
|
+
MU.log "#{res_type} #{res_name} no longer configured, will remove deployment metadata", MU::NOTICE, details: data
|
131
132
|
deletia << res_name
|
132
133
|
end
|
133
134
|
}
|
@@ -176,7 +177,7 @@ module MU
|
|
176
177
|
# @param id [String]: The lock identifier to release.
|
177
178
|
# @param nonblock [Boolean]: Whether to block while waiting for the lock. In non-blocking mode, we simply return false if the lock is not available.
|
178
179
|
# return [false, nil]
|
179
|
-
def self.lock(id, nonblock = false, global = false, deploy_id: MU.deploy_id)
|
180
|
+
def self.lock(id, nonblock = false, global = false, retries: 0, deploy_id: MU.deploy_id)
|
180
181
|
raise MuError, "Can't pass a nil id to MU::MommaCat.lock" if id.nil?
|
181
182
|
|
182
183
|
if !global
|
@@ -189,6 +190,7 @@ module MU
|
|
189
190
|
MU.log "Creating #{lockdir}", MU::DEBUG
|
190
191
|
Dir.mkdir(lockdir, 0700)
|
191
192
|
end
|
193
|
+
nonblock = true if retries > 0
|
192
194
|
|
193
195
|
@lock_semaphore.synchronize {
|
194
196
|
if @locks[Thread.current.object_id].nil?
|
@@ -197,11 +199,39 @@ module MU
|
|
197
199
|
|
198
200
|
@locks[Thread.current.object_id][id] = File.open("#{lockdir}/#{id}.lock", File::CREAT|File::RDWR, 0600)
|
199
201
|
}
|
200
|
-
|
202
|
+
|
203
|
+
MU.log "Getting a lock on #{lockdir}/#{id}.lock (thread #{Thread.current.object_id})...", MU::DEBUG, details: caller
|
204
|
+
show_relevant = Proc.new {
|
205
|
+
@lock_semaphore.synchronize {
|
206
|
+
@locks.each_pair { |thread_id, lock|
|
207
|
+
lock.each_pair { |lockid, lockpath|
|
208
|
+
if lockid == id
|
209
|
+
thread = Thread.list.select { |t| t.object_id == thread_id }.first
|
210
|
+
if thread.object_id != Thread.current.object_id
|
211
|
+
MU.log "#{thread_id} sitting on #{id} (#{thread.thread_variables.map { |v| "#{v.to_s}: #{thread.thread_variable_get(v).to_s}" }.join(", ")})", MU::WARN, thread.backtrace
|
212
|
+
end
|
213
|
+
end
|
214
|
+
}
|
215
|
+
}
|
216
|
+
}
|
217
|
+
}
|
218
|
+
|
201
219
|
begin
|
202
220
|
if nonblock
|
203
221
|
if !@locks[Thread.current.object_id][id].flock(File::LOCK_EX|File::LOCK_NB)
|
204
|
-
|
222
|
+
if retries > 0
|
223
|
+
success = false
|
224
|
+
MU.retrier([], loop_if: Proc.new { !success }, loop_msg: "Waiting for lock on #{lockdir}/#{id}.lock...", max: retries, wait: 1, logmsg_interval: 0) { |cur_retries, _wait|
|
225
|
+
success = @locks[Thread.current.object_id][id].flock(File::LOCK_EX|File::LOCK_NB)
|
226
|
+
if !success and cur_retries > 0 and (cur_retries % 45) == 0
|
227
|
+
show_relevant.call
|
228
|
+
end
|
229
|
+
}
|
230
|
+
show_relevant.call if !success
|
231
|
+
return success
|
232
|
+
else
|
233
|
+
return false
|
234
|
+
end
|
205
235
|
end
|
206
236
|
else
|
207
237
|
@locks[Thread.current.object_id][id].flock(File::LOCK_EX)
|
@@ -390,6 +420,7 @@ module MU
|
|
390
420
|
deploy.flock(File::LOCK_UN)
|
391
421
|
deploy.close
|
392
422
|
@need_deploy_flush = false
|
423
|
+
@last_modified = nil
|
393
424
|
MU::MommaCat.updateLitter(@deploy_id, self)
|
394
425
|
end
|
395
426
|
|
@@ -512,6 +543,22 @@ module MU
|
|
512
543
|
return Dir.exist?(deploy_path)
|
513
544
|
end
|
514
545
|
|
546
|
+
# Write our shared deploy secret out to wherever the cloud provider layers
|
547
|
+
# like to stash it.
|
548
|
+
def writeDeploySecret
|
549
|
+
return if !@deploy_secret
|
550
|
+
credsets = credsUsed
|
551
|
+
return if !credsets
|
552
|
+
if !@original_config['scrub_mu_isms'] and !@no_artifacts
|
553
|
+
cloudsUsed.each { |cloud|
|
554
|
+
credsets.each { |credentials|
|
555
|
+
next if MU::Cloud.cloudClass(cloud).credConfig(credentials).nil? # XXX this is a dumb way to check this, should be able to get credsUsed by cloud
|
556
|
+
MU::Cloud.cloudClass(cloud).writeDeploySecret(self, @deploy_secret, credentials: credentials)
|
557
|
+
}
|
558
|
+
}
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
515
562
|
private
|
516
563
|
|
517
564
|
def writeFile(filename, contents)
|
@@ -522,30 +569,8 @@ module MU
|
|
522
569
|
|
523
570
|
# Helper for +initialize+
|
524
571
|
def setDeploySecret
|
525
|
-
credsets = {}
|
526
|
-
MU::Cloud.resource_types.values.each { |attrs|
|
527
|
-
if !@original_config[attrs[:cfg_plural]].nil? and @original_config[attrs[:cfg_plural]].size > 0
|
528
|
-
@original_config[attrs[:cfg_plural]].each { |resource|
|
529
|
-
|
530
|
-
credsets[resource['cloud']] ||= []
|
531
|
-
credsets[resource['cloud']] << resource['credentials']
|
532
|
-
@clouds[resource['cloud']] = 0 if !@clouds.has_key?(resource['cloud'])
|
533
|
-
@clouds[resource['cloud']] = @clouds[resource['cloud']] + 1
|
534
|
-
|
535
|
-
}
|
536
|
-
end
|
537
|
-
}
|
538
|
-
|
539
572
|
MU.log "Creating deploy secret for #{MU.deploy_id}"
|
540
573
|
@deploy_secret = Password.random(256)
|
541
|
-
if !@original_config['scrub_mu_isms'] and !@no_artifacts
|
542
|
-
credsets.each_pair { |cloud, creds|
|
543
|
-
creds.uniq!
|
544
|
-
creds.each { |credentials|
|
545
|
-
MU::Cloud.cloudClass(cloud).writeDeploySecret(@deploy_id, @deploy_secret, credentials: credentials)
|
546
|
-
}
|
547
|
-
}
|
548
|
-
end
|
549
574
|
end
|
550
575
|
|
551
576
|
def loadObjects(delay_descriptor_load)
|
@@ -618,6 +643,14 @@ module MU
|
|
618
643
|
def loadDeployFromCache(set_context_to_me = true)
|
619
644
|
return false if !File.size?(deploy_dir+"/deployment.json")
|
620
645
|
|
646
|
+
lastmod = File.mtime("#{deploy_dir}/deployment.json")
|
647
|
+
if @last_modified and lastmod < @last_modified
|
648
|
+
MU.log "#{deploy_dir}/deployment.json last written at #{lastmod}, live meta at #{@last_modified}, not loading", MU::WARN if @last_modified
|
649
|
+
# this is a weird place for this
|
650
|
+
setThreadContextToMe if set_context_to_me
|
651
|
+
return true
|
652
|
+
end
|
653
|
+
|
621
654
|
deploy = File.open("#{deploy_dir}/deployment.json", File::RDONLY)
|
622
655
|
MU.log "Getting lock to read #{deploy_dir}/deployment.json", MU::DEBUG
|
623
656
|
# deploy.flock(File::LOCK_EX)
|
@@ -629,6 +662,7 @@ module MU
|
|
629
662
|
|
630
663
|
begin
|
631
664
|
@deployment = JSON.parse(File.read("#{deploy_dir}/deployment.json"))
|
665
|
+
# XXX is it worthwhile to merge fuckery?
|
632
666
|
rescue JSON::ParserError => e
|
633
667
|
MU.log "JSON parse failed on #{deploy_dir}/deployment.json", MU::ERR, details: e.message
|
634
668
|
end
|
@@ -638,20 +672,21 @@ module MU
|
|
638
672
|
|
639
673
|
setThreadContextToMe if set_context_to_me
|
640
674
|
|
641
|
-
@timestamp = @deployment['timestamp']
|
642
|
-
@seed = @deployment['seed']
|
643
|
-
@appname = @deployment['appname']
|
644
|
-
@handle = @deployment['handle']
|
645
|
-
|
646
675
|
true
|
647
676
|
end
|
648
677
|
|
678
|
+
|
649
679
|
###########################################################################
|
650
680
|
###########################################################################
|
651
681
|
def loadDeploy(deployment_json_only = false, set_context_to_me: true)
|
652
682
|
MU::MommaCat.deploy_struct_semaphore.synchronize {
|
653
683
|
success = loadDeployFromCache(set_context_to_me)
|
654
684
|
|
685
|
+
@timestamp ||= @deployment['timestamp']
|
686
|
+
@seed ||= @deployment['seed']
|
687
|
+
@appname ||= @deployment['appname']
|
688
|
+
@handle ||= @deployment['handle']
|
689
|
+
|
655
690
|
return if deployment_json_only and success
|
656
691
|
|
657
692
|
if File.exist?(deploy_dir+"/private_key")
|