cloud-mu 3.2.0 → 3.5.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 +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")
|