cloud-mu 3.1.6 → 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/bin/mu-adopt +4 -12
- data/bin/mu-azure-tests +57 -0
- data/bin/mu-cleanup +2 -4
- data/bin/mu-configure +37 -1
- data/bin/mu-deploy +3 -3
- data/bin/mu-findstray-tests +25 -0
- data/bin/mu-gen-docs +2 -4
- data/bin/mu-run-tests +23 -10
- data/cloud-mu.gemspec +2 -2
- data/cookbooks/mu-tools/libraries/helper.rb +1 -1
- data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
- data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
- data/extras/generate-stock-images +1 -0
- data/modules/mu.rb +82 -95
- data/modules/mu/adoption.rb +356 -56
- data/modules/mu/cleanup.rb +21 -20
- data/modules/mu/cloud.rb +79 -1753
- 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 +122 -80
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +1 -1
- data/modules/mu/config/cache_cluster.rb +1 -1
- data/modules/mu/config/collection.rb +1 -1
- data/modules/mu/config/container_cluster.rb +2 -2
- data/modules/mu/config/database.rb +83 -104
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +1 -1
- data/modules/mu/config/doc_helpers.rb +4 -5
- data/modules/mu/config/endpoint.rb +1 -1
- data/modules/mu/config/firewall_rule.rb +3 -19
- data/modules/mu/config/folder.rb +1 -1
- data/modules/mu/config/function.rb +1 -1
- data/modules/mu/config/group.rb +1 -1
- data/modules/mu/config/habitat.rb +1 -1
- data/modules/mu/config/loadbalancer.rb +57 -11
- data/modules/mu/config/log.rb +1 -1
- data/modules/mu/config/msg_queue.rb +1 -1
- data/modules/mu/config/nosqldb.rb +1 -1
- data/modules/mu/config/notifier.rb +1 -1
- data/modules/mu/config/ref.rb +30 -4
- data/modules/mu/config/role.rb +1 -1
- data/modules/mu/config/schema_helpers.rb +30 -34
- data/modules/mu/config/search_domain.rb +1 -1
- data/modules/mu/config/server.rb +4 -12
- data/modules/mu/config/server_pool.rb +3 -7
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +10 -0
- data/modules/mu/config/user.rb +1 -1
- data/modules/mu/config/vpc.rb +12 -17
- data/modules/mu/defaults/AWS.yaml +32 -32
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +1 -0
- data/modules/mu/deploy.rb +16 -15
- data/modules/mu/groomer.rb +15 -0
- data/modules/mu/groomers/chef.rb +3 -0
- data/modules/mu/logger.rb +120 -144
- data/modules/mu/master.rb +1 -1
- data/modules/mu/mommacat.rb +54 -25
- data/modules/mu/mommacat/daemon.rb +10 -7
- data/modules/mu/mommacat/naming.rb +82 -3
- data/modules/mu/mommacat/search.rb +47 -15
- data/modules/mu/mommacat/storage.rb +72 -41
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +114 -47
- data/modules/mu/{clouds → providers}/aws/alarm.rb +1 -1
- data/modules/mu/{clouds → providers}/aws/bucket.rb +2 -2
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +10 -46
- data/modules/mu/{clouds → providers}/aws/collection.rb +3 -3
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +15 -33
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +2 -5
- data/modules/mu/{clouds → providers}/aws/endpoint.rb +2 -11
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +33 -29
- data/modules/mu/{clouds → providers}/aws/folder.rb +0 -0
- data/modules/mu/{clouds → providers}/aws/function.rb +2 -10
- data/modules/mu/{clouds → providers}/aws/group.rb +9 -13
- data/modules/mu/{clouds → providers}/aws/habitat.rb +1 -1
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +41 -33
- data/modules/mu/{clouds → providers}/aws/log.rb +2 -2
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +2 -8
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +0 -0
- data/modules/mu/{clouds → providers}/aws/notifier.rb +0 -0
- data/modules/mu/{clouds → providers}/aws/role.rb +7 -7
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +8 -13
- data/modules/mu/{clouds → providers}/aws/server.rb +55 -90
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +10 -33
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +19 -36
- data/modules/mu/{clouds → providers}/aws/user.rb +8 -12
- 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 +0 -0
- data/modules/mu/{clouds → providers}/aws/vpc.rb +135 -70
- data/modules/mu/{clouds → providers}/aws/vpc_subnet.rb +0 -0
- data/modules/mu/{clouds → providers}/azure.rb +4 -1
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +1 -5
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +8 -1
- data/modules/mu/{clouds → providers}/azure/habitat.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/role.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/server.rb +30 -23
- data/modules/mu/{clouds → providers}/azure/user.rb +1 -1
- 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 +4 -6
- data/modules/mu/{clouds → providers}/cloudformation.rb +1 -1
- 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 +3 -3
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +14 -6
- data/modules/mu/{clouds → providers}/google/bucket.rb +1 -1
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +28 -13
- data/modules/mu/{clouds → providers}/google/database.rb +1 -8
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +2 -2
- data/modules/mu/{clouds → providers}/google/folder.rb +4 -8
- data/modules/mu/{clouds → providers}/google/function.rb +3 -3
- data/modules/mu/{clouds → providers}/google/group.rb +8 -16
- data/modules/mu/{clouds → providers}/google/habitat.rb +3 -7
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +1 -1
- data/modules/mu/{clouds → providers}/google/role.rb +42 -34
- data/modules/mu/{clouds → providers}/google/server.rb +25 -10
- data/modules/mu/{clouds → providers}/google/server_pool.rb +10 -10
- data/modules/mu/{clouds → providers}/google/user.rb +31 -21
- 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 +37 -2
- data/modules/tests/centos6.yaml +11 -0
- data/modules/tests/centos7.yaml +11 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +108 -89
- data/modules/mu/clouds/aws/database.rb +0 -1974
@@ -88,16 +88,28 @@ module MU
|
|
88
88
|
}
|
89
89
|
end
|
90
90
|
|
91
|
+
|
91
92
|
# Overwrite this deployment's configuration with a new version. Save the
|
92
93
|
# previous version as well.
|
93
94
|
# @param new_conf [Hash]: A new configuration, fully resolved by {MU::Config}
|
94
|
-
def updateBasketofKittens(new_conf)
|
95
|
+
def updateBasketofKittens(new_conf, skip_validation: false, new_metadata: nil, save_now: false)
|
95
96
|
loadDeploy
|
96
97
|
if new_conf == @original_config
|
97
|
-
MU.log "#{@deploy_id}", MU::WARN
|
98
98
|
return
|
99
99
|
end
|
100
100
|
|
101
|
+
scrub_with = nil
|
102
|
+
|
103
|
+
# Make sure the new config that we were just handed resolves and makes
|
104
|
+
# sense
|
105
|
+
if !skip_validation
|
106
|
+
f = Tempfile.new(@deploy_id)
|
107
|
+
f.write JSON.parse(JSON.generate(new_conf)).to_yaml
|
108
|
+
conf_engine = MU::Config.new(f.path) # will throw an exception if it's bad, adoption should catch this and cope reasonably
|
109
|
+
scrub_with = conf_engine.config
|
110
|
+
f.close
|
111
|
+
end
|
112
|
+
|
101
113
|
backup = "#{deploy_dir}/basket_of_kittens.json.#{Time.now.to_i.to_s}"
|
102
114
|
MU.log "Saving previous config of #{@deploy_id} to #{backup}"
|
103
115
|
config = File.new(backup, File::CREAT|File::TRUNC|File::RDWR, 0600)
|
@@ -106,9 +118,26 @@ module MU
|
|
106
118
|
config.flock(File::LOCK_UN)
|
107
119
|
config.close
|
108
120
|
|
109
|
-
@original_config = new_conf
|
110
|
-
|
111
|
-
MU.
|
121
|
+
@original_config = new_conf.clone
|
122
|
+
|
123
|
+
MU::Cloud.resource_types.each_pair { |res_type, attrs|
|
124
|
+
next if !@deployment.has_key?(attrs[:cfg_plural])
|
125
|
+
deletia = []
|
126
|
+
@deployment[attrs[:cfg_plural]].each_pair { |res_name, data|
|
127
|
+
orig_cfg = findResourceConfig(attrs[:cfg_plural], res_name, (scrub_with || @original_config))
|
128
|
+
|
129
|
+
if orig_cfg.nil?
|
130
|
+
MU.log "#{res_type} #{res_name} no longer configured, will remove deployment metadata", MU::NOTICE
|
131
|
+
deletia << res_name
|
132
|
+
end
|
133
|
+
}
|
134
|
+
@deployment[attrs[:cfg_plural]].reject! { |k, v| deletia.include?(k) }
|
135
|
+
}
|
136
|
+
|
137
|
+
if save_now
|
138
|
+
save!
|
139
|
+
MU.log "New config saved to #{deploy_dir}/basket_of_kittens.json"
|
140
|
+
end
|
112
141
|
end
|
113
142
|
|
114
143
|
@lock_semaphore = Mutex.new
|
@@ -147,11 +176,11 @@ module MU
|
|
147
176
|
# @param id [String]: The lock identifier to release.
|
148
177
|
# @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.
|
149
178
|
# return [false, nil]
|
150
|
-
def self.lock(id, nonblock = false, global = false)
|
179
|
+
def self.lock(id, nonblock = false, global = false, deploy_id: MU.deploy_id)
|
151
180
|
raise MuError, "Can't pass a nil id to MU::MommaCat.lock" if id.nil?
|
152
181
|
|
153
182
|
if !global
|
154
|
-
lockdir = "#{deploy_dir(
|
183
|
+
lockdir = "#{deploy_dir(deploy_id)}/locks"
|
155
184
|
else
|
156
185
|
lockdir = File.expand_path(MU.dataDir+"/locks")
|
157
186
|
end
|
@@ -186,11 +215,11 @@ module MU
|
|
186
215
|
|
187
216
|
# Release a flock() lock.
|
188
217
|
# @param id [String]: The lock identifier to release.
|
189
|
-
def self.unlock(id, global = false)
|
218
|
+
def self.unlock(id, global = false, deploy_id: MU.deploy_id)
|
190
219
|
raise MuError, "Can't pass a nil id to MU::MommaCat.unlock" if id.nil?
|
191
220
|
lockdir = nil
|
192
221
|
if !global
|
193
|
-
lockdir = "#{deploy_dir(
|
222
|
+
lockdir = "#{deploy_dir(deploy_id)}/locks"
|
194
223
|
else
|
195
224
|
lockdir = File.expand_path(MU.dataDir+"/locks")
|
196
225
|
end
|
@@ -512,48 +541,30 @@ module MU
|
|
512
541
|
if !@original_config['scrub_mu_isms'] and !@no_artifacts
|
513
542
|
credsets.each_pair { |cloud, creds|
|
514
543
|
creds.uniq!
|
515
|
-
cloudclass = Object.const_get("MU").const_get("Cloud").const_get(cloud)
|
516
544
|
creds.each { |credentials|
|
517
|
-
|
545
|
+
MU::Cloud.cloudClass(cloud).writeDeploySecret(@deploy_id, @deploy_secret, credentials: credentials)
|
518
546
|
}
|
519
547
|
}
|
520
548
|
end
|
521
549
|
end
|
522
550
|
|
523
551
|
def loadObjects(delay_descriptor_load)
|
552
|
+
# Load up MU::Cloud objects for all our kittens in this deploy
|
553
|
+
|
524
554
|
MU::Cloud.resource_types.each_pair { |res_type, attrs|
|
525
555
|
type = attrs[:cfg_plural]
|
526
556
|
next if !@deployment.has_key?(type)
|
527
557
|
|
558
|
+
deletia = {}
|
528
559
|
@deployment[type].each_pair { |res_name, data|
|
529
|
-
orig_cfg =
|
530
|
-
if @original_config.has_key?(type)
|
531
|
-
@original_config[type].each { |resource|
|
532
|
-
if resource["name"] == res_name
|
533
|
-
orig_cfg = resource
|
534
|
-
break
|
535
|
-
end
|
536
|
-
}
|
537
|
-
end
|
538
|
-
|
539
|
-
# Some Server objects originated from ServerPools, get their
|
540
|
-
# configs from there
|
541
|
-
if type == "servers" and orig_cfg.nil? and
|
542
|
-
@original_config.has_key?("server_pools")
|
543
|
-
@original_config["server_pools"].each { |resource|
|
544
|
-
if resource["name"] == res_name
|
545
|
-
orig_cfg = resource
|
546
|
-
break
|
547
|
-
end
|
548
|
-
}
|
549
|
-
end
|
560
|
+
orig_cfg = findResourceConfig(type, res_name)
|
550
561
|
|
551
562
|
if orig_cfg.nil?
|
552
563
|
MU.log "Failed to locate original config for #{attrs[:cfg_name]} #{res_name} in #{@deploy_id}", MU::WARN if !["firewall_rules", "databases", "storage_pools", "cache_clusters", "alarms"].include?(type) # XXX shaddap
|
553
564
|
next
|
554
565
|
end
|
555
566
|
|
556
|
-
if orig_cfg['vpc']
|
567
|
+
if orig_cfg['vpc']
|
557
568
|
ref = if orig_cfg['vpc']['id'] and orig_cfg['vpc']['id'].is_a?(Hash)
|
558
569
|
orig_cfg['vpc']['id']['mommacat'] = self
|
559
570
|
MU::Config::Ref.get(orig_cfg['vpc']['id'])
|
@@ -566,18 +577,12 @@ module MU
|
|
566
577
|
end
|
567
578
|
|
568
579
|
begin
|
569
|
-
# Load up MU::Cloud objects for all our kittens in this deploy
|
570
|
-
orig_cfg['environment'] = @environment # not always set in old deploys
|
571
580
|
if attrs[:has_multiples]
|
572
581
|
data.keys.each { |mu_name|
|
573
|
-
attrs[:interface].new(mommacat: self, kitten_cfg: orig_cfg, mu_name: mu_name, delay_descriptor_load: delay_descriptor_load)
|
582
|
+
addKitten(type, res_name, attrs[:interface].new(mommacat: self, kitten_cfg: orig_cfg, mu_name: mu_name, delay_descriptor_load: delay_descriptor_load))
|
574
583
|
}
|
575
584
|
else
|
576
|
-
|
577
|
-
if data['mu_name'].nil?
|
578
|
-
raise MuError, "Unable to find or guess a Mu name for #{res_type}: #{res_name} in #{@deploy_id}"
|
579
|
-
end
|
580
|
-
attrs[:interface].new(mommacat: self, kitten_cfg: orig_cfg, mu_name: data['mu_name'], cloud_id: data['cloud_id'])
|
585
|
+
addKitten(type, res_name, attrs[:interface].new(mommacat: self, kitten_cfg: orig_cfg, mu_name: data['mu_name'], cloud_id: data['cloud_id']))
|
581
586
|
end
|
582
587
|
rescue StandardError => e
|
583
588
|
if e.class != MU::Cloud::MuCloudResourceNotImplemented
|
@@ -585,6 +590,7 @@ module MU
|
|
585
590
|
end
|
586
591
|
end
|
587
592
|
}
|
593
|
+
|
588
594
|
}
|
589
595
|
end
|
590
596
|
|
@@ -687,5 +693,30 @@ module MU
|
|
687
693
|
}
|
688
694
|
end
|
689
695
|
|
696
|
+
def findResourceConfig(type, name, config = @original_config)
|
697
|
+
orig_cfg = nil
|
698
|
+
if config.has_key?(type)
|
699
|
+
config[type].each { |resource|
|
700
|
+
if resource["name"] == name
|
701
|
+
orig_cfg = resource
|
702
|
+
break
|
703
|
+
end
|
704
|
+
}
|
705
|
+
end
|
706
|
+
|
707
|
+
# Some Server objects originated from ServerPools, get their
|
708
|
+
# configs from there
|
709
|
+
if type == "servers" and orig_cfg.nil? and config.has_key?("server_pools")
|
710
|
+
config["server_pools"].each { |resource|
|
711
|
+
if resource["name"] == name
|
712
|
+
orig_cfg = resource
|
713
|
+
break
|
714
|
+
end
|
715
|
+
}
|
716
|
+
end
|
717
|
+
|
718
|
+
orig_cfg
|
719
|
+
end
|
720
|
+
|
690
721
|
end #class
|
691
722
|
end #module
|
@@ -89,7 +89,7 @@ Looking elsewhere in `cloud.rb` let's see what all we have to do:
|
|
89
89
|
generic_instance_methods = [:create, :notify, :mu_name, :cloud_id, :config]
|
90
90
|
```
|
91
91
|
|
92
|
-
Just the basics, for now. Here's what that will look like in the AWS layer, in the file `modules/mu/
|
92
|
+
Just the basics, for now. Here's what that will look like in the AWS layer, in the file `modules/mu/providers/aws/function.rb`:
|
93
93
|
|
94
94
|
```
|
95
95
|
module MU
|
@@ -39,7 +39,7 @@ module MU
|
|
39
39
|
end
|
40
40
|
|
41
41
|
# List all AWS projects available to our credentials
|
42
|
-
def self.listHabitats(credentials = nil)
|
42
|
+
def self.listHabitats(credentials = nil, use_cache: true)
|
43
43
|
cfg = credConfig(credentials)
|
44
44
|
return [] if !cfg or !cfg['account_number']
|
45
45
|
[cfg['account_number']]
|
@@ -805,46 +805,41 @@ end
|
|
805
805
|
|
806
806
|
@@instance_types ||= {}
|
807
807
|
@@instance_types[region] ||= {}
|
808
|
-
next_token = nil
|
809
808
|
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
type: "TERM_MATCH"
|
830
|
-
}
|
831
|
-
],
|
832
|
-
next_token: next_token
|
833
|
-
)
|
834
|
-
resp.price_list.each { |pricing|
|
835
|
-
data = JSON.parse(pricing)
|
836
|
-
type = data["product"]["attributes"]["instanceType"]
|
837
|
-
next if @@instance_types[region].has_key?(type)
|
838
|
-
@@instance_types[region][type] = {}
|
839
|
-
["ecu", "vcpu", "memory", "storage"].each { |a|
|
840
|
-
@@instance_types[region][type][a] = data["product"]["attributes"][a]
|
809
|
+
# Pricing API isn't widely available, so ask a region we know supports
|
810
|
+
# it
|
811
|
+
resp = MU::Cloud::AWS.pricing(region: "us-east-1").get_products(
|
812
|
+
service_code: "AmazonEC2",
|
813
|
+
filters: [
|
814
|
+
{
|
815
|
+
field: "productFamily",
|
816
|
+
value: "Compute Instance",
|
817
|
+
type: "TERM_MATCH"
|
818
|
+
},
|
819
|
+
{
|
820
|
+
field: "tenancy",
|
821
|
+
value: "Shared",
|
822
|
+
type: "TERM_MATCH"
|
823
|
+
},
|
824
|
+
{
|
825
|
+
field: "location",
|
826
|
+
value: human_region,
|
827
|
+
type: "TERM_MATCH"
|
841
828
|
}
|
842
|
-
|
843
|
-
|
844
|
-
|
829
|
+
]
|
830
|
+
)
|
831
|
+
resp.price_list.each { |pricing|
|
832
|
+
data = JSON.parse(pricing)
|
833
|
+
type = data["product"]["attributes"]["instanceType"]
|
834
|
+
next if @@instance_types[region].has_key?(type)
|
835
|
+
@@instance_types[region][type] = {}
|
836
|
+
["ecu", "vcpu", "memory", "storage"].each { |a|
|
837
|
+
@@instance_types[region][type][a] = data["product"]["attributes"][a]
|
845
838
|
}
|
846
|
-
|
847
|
-
|
839
|
+
@@instance_types[region][type]["memory"].sub!(/ GiB/, "")
|
840
|
+
@@instance_types[region][type]["memory"] = @@instance_types[region][type]["memory"].to_f
|
841
|
+
@@instance_types[region][type]["vcpu"] = @@instance_types[region][type]["vcpu"].to_f
|
842
|
+
}
|
848
843
|
|
849
844
|
@@instance_types
|
850
845
|
end
|
@@ -1251,7 +1246,7 @@ end
|
|
1251
1246
|
# Mu Master, if we're in AWS.
|
1252
1247
|
# @return [void]
|
1253
1248
|
def self.openFirewallForClients
|
1254
|
-
MU::Cloud.
|
1249
|
+
MU::Cloud.resourceClass("AWS", :FirewallRule)
|
1255
1250
|
begin
|
1256
1251
|
if File.exist?(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
|
1257
1252
|
::Chef::Config.from_file(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
|
@@ -1454,21 +1449,93 @@ end
|
|
1454
1449
|
# Catch-all for AWS client methods. Essentially a pass-through with some
|
1455
1450
|
# rescues for known silly endpoint behavior.
|
1456
1451
|
def method_missing(method_sym, *arguments)
|
1452
|
+
# make sure error symbols are loaded for our exception handling later
|
1457
1453
|
require "aws-sdk-core"
|
1454
|
+
require "aws-sdk-core/rds"
|
1455
|
+
require "aws-sdk-core/ec2"
|
1456
|
+
require "aws-sdk-core/route53"
|
1457
|
+
require "aws-sdk-core/iam"
|
1458
|
+
require "aws-sdk-core/efs"
|
1459
|
+
require "aws-sdk-core/pricing"
|
1460
|
+
require "aws-sdk-core/apigateway"
|
1461
|
+
require "aws-sdk-core/ecs"
|
1462
|
+
require "aws-sdk-core/eks"
|
1463
|
+
require "aws-sdk-core/cloudwatchlogs"
|
1464
|
+
require "aws-sdk-core/elasticloadbalancing"
|
1465
|
+
require "aws-sdk-core/elasticloadbalancingv2"
|
1466
|
+
require "aws-sdk-core/autoscaling"
|
1467
|
+
require "aws-sdk-core/client_waiters"
|
1468
|
+
require "aws-sdk-core/waiters/errors"
|
1458
1469
|
|
1459
1470
|
retries = 0
|
1460
1471
|
begin
|
1461
1472
|
MU.log "Calling #{method_sym} in #{@region}", MU::DEBUG, details: arguments
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1467
|
-
|
1468
|
-
|
1473
|
+
|
1474
|
+
retval = if !arguments.nil? and arguments.size == 1
|
1475
|
+
@api.method(method_sym).call(arguments[0])
|
1476
|
+
elsif !arguments.nil? and arguments.size > 0
|
1477
|
+
@api.method(method_sym).call(*arguments)
|
1478
|
+
else
|
1479
|
+
@api.method(method_sym).call
|
1480
|
+
end
|
1481
|
+
|
1482
|
+
if !retval.nil?
|
1483
|
+
begin
|
1484
|
+
page_markers = [:marker, :next_token]
|
1485
|
+
paginator = nil
|
1486
|
+
new_page = nil
|
1487
|
+
[:next_token, :marker].each { |m|
|
1488
|
+
if !retval.nil? and retval.respond_to?(m)
|
1489
|
+
paginator = m
|
1490
|
+
new_page = retval.send(paginator)
|
1491
|
+
break
|
1492
|
+
end
|
1493
|
+
}
|
1494
|
+
|
1495
|
+
if paginator and new_page and !new_page.empty?
|
1496
|
+
resp = retval.respond_to?(:__getobj__) ? retval.__getobj__ : retval
|
1497
|
+
concat_to = resp.class.instance_methods(false).reject { |m|
|
1498
|
+
m.to_s.match(/=$/) or m == paginator or resp.send(m).nil? or !resp.send(m).is_a?(Array)
|
1499
|
+
}
|
1500
|
+
if concat_to.size != 1
|
1501
|
+
MU.log "Tried to figure out where I might append paginated results for a #{resp.class.name}, but failed", MU::DEBUG, details: concat_to
|
1502
|
+
else
|
1503
|
+
concat_to = concat_to.first
|
1504
|
+
new_args = arguments ? arguments.dup : [{}]
|
1505
|
+
begin
|
1506
|
+
if new_args.is_a?(Array)
|
1507
|
+
new_args << {} if new_args.empty?
|
1508
|
+
if new_args.size == 1 and new_args.first.is_a?(Hash)
|
1509
|
+
new_args[0][paginator] = new_page
|
1510
|
+
else
|
1511
|
+
MU.log "I don't know how to insert a #{paginator} into these arguments for #{method_sym}", MU::WARN, details: new_args
|
1512
|
+
end
|
1513
|
+
elsif new_args.is_a?(Hash)
|
1514
|
+
new_args[paginator] = new_page
|
1515
|
+
end
|
1516
|
+
|
1517
|
+
MU.log "Attempting magic pagination for #{method_sym}", MU::DEBUG, details: new_args
|
1518
|
+
|
1519
|
+
# resp = if !arguments.nil? and arguments.size == 1
|
1520
|
+
# @api.method(method_sym).call(new_args[0])
|
1521
|
+
# elsif !arguments.nil? and arguments.size > 0
|
1522
|
+
resp = @api.method(method_sym).call(*new_args)
|
1523
|
+
# end
|
1524
|
+
break if resp.nil?
|
1525
|
+
resp = resp.__getobj__ if resp.respond_to?(:__getobj__)
|
1526
|
+
retval.send(concat_to).concat(resp.send(concat_to))
|
1527
|
+
new_page = resp.send(paginator) if !resp.nil?
|
1528
|
+
end while !resp.nil? and !new_page.nil? and !new_page.empty?
|
1529
|
+
end
|
1530
|
+
end
|
1531
|
+
rescue StandardError => e
|
1532
|
+
MU.log "Made a good-faith effort to auto-paginate API call to #{method_sym} and failed with #{e.message}", MU::DEBUG, details: arguments
|
1533
|
+
raise e
|
1534
|
+
end
|
1469
1535
|
end
|
1536
|
+
|
1470
1537
|
return retval
|
1471
|
-
rescue Aws::EC2::Errors::InternalError, Aws::EC2::Errors::RequestLimitExceeded, Aws::EC2::Errors::Unavailable, Aws::Route53::Errors::Throttling, Aws::ElasticLoadBalancing::Errors::HttpFailureException, Aws::EC2::Errors::Http503Error, Aws::AutoScaling::Errors::Http503Error, Aws::AutoScaling::Errors::InternalFailure, Aws::AutoScaling::Errors::ServiceUnavailable, Aws::Route53::Errors::ServiceUnavailable, Aws::ElasticLoadBalancing::Errors::Throttling, Aws::RDS::Errors::ClientUnavailable, Aws::Waiters::Errors::UnexpectedError, Aws::ElasticLoadBalancing::Errors::ServiceUnavailable, Aws::ElasticLoadBalancingV2::Errors::Throttling, Seahorse::Client::NetworkingError, Aws::IAM::Errors::Throttling, Aws::EFS::Errors::ThrottlingException, Aws::Pricing::Errors::ThrottlingException, Aws::APIGateway::Errors::TooManyRequestsException, Aws::ECS::Errors::ThrottlingException, Net::ReadTimeout, Faraday::TimeoutError, Aws::CloudWatchLogs::Errors::ThrottlingException => e
|
1538
|
+
rescue Aws::RDS::Errors::Throttling, Aws::EC2::Errors::InternalError, Aws::EC2::Errors::RequestLimitExceeded, Aws::EC2::Errors::Unavailable, Aws::Route53::Errors::Throttling, Aws::ElasticLoadBalancing::Errors::HttpFailureException, Aws::EC2::Errors::Http503Error, Aws::AutoScaling::Errors::Http503Error, Aws::AutoScaling::Errors::InternalFailure, Aws::AutoScaling::Errors::ServiceUnavailable, Aws::Route53::Errors::ServiceUnavailable, Aws::ElasticLoadBalancing::Errors::Throttling, Aws::RDS::Errors::ClientUnavailable, Aws::Waiters::Errors::UnexpectedError, Aws::ElasticLoadBalancing::Errors::ServiceUnavailable, Aws::ElasticLoadBalancingV2::Errors::Throttling, Seahorse::Client::NetworkingError, Aws::IAM::Errors::Throttling, Aws::EFS::Errors::ThrottlingException, Aws::Pricing::Errors::ThrottlingException, Aws::APIGateway::Errors::TooManyRequestsException, Aws::ECS::Errors::ThrottlingException, Net::ReadTimeout, Faraday::TimeoutError, Aws::CloudWatchLogs::Errors::ThrottlingException => e
|
1472
1539
|
if e.class.name == "Seahorse::Client::NetworkingError" and e.message.match(/Name or service not known/)
|
1473
1540
|
MU.log e.inspect, MU::ERR
|
1474
1541
|
raise e
|
@@ -321,7 +321,7 @@ module MU
|
|
321
321
|
if !depclass.nil?
|
322
322
|
dimension["depclass"] = depclass
|
323
323
|
if !dimension["name"].nil? and !dimension["name"].empty?
|
324
|
-
alarm
|
324
|
+
MU::Config.addDependency(alarm, dimension["name"], depclass)
|
325
325
|
end
|
326
326
|
end
|
327
327
|
}
|
@@ -97,7 +97,7 @@ module MU
|
|
97
97
|
]
|
98
98
|
}
|
99
99
|
|
100
|
-
policy_docs = MU::Cloud
|
100
|
+
policy_docs = MU::Cloud.resourceClass("AWS", "Role").genPolicyDocument(@config['policies'], deploy_obj: @deploy, bucket_style: true)
|
101
101
|
policy_docs.each { |doc|
|
102
102
|
MU.log "Applying S3 bucket policy #{doc.keys.first} to bucket #{@cloud_id}", MU::NOTICE, details: JSON.pretty_generate(doc.values.first)
|
103
103
|
MU::Cloud::AWS.s3(credentials: @config['credentials'], region: @config['region']).put_bucket_policy(
|
@@ -309,7 +309,7 @@ module MU
|
|
309
309
|
def self.schema(_config)
|
310
310
|
toplevel_required = []
|
311
311
|
schema = {
|
312
|
-
"policies" => MU::Cloud
|
312
|
+
"policies" => MU::Cloud.resourceClass("AWS", "Role").condition_schema,
|
313
313
|
"acl" => {
|
314
314
|
"type" => "string",
|
315
315
|
"enum" => ["private", "public-read", "public-read-write", "authenticated-read"],
|
@@ -199,7 +199,7 @@ module MU
|
|
199
199
|
addStandardTags(member, "cluster", region: @config['region'])
|
200
200
|
}
|
201
201
|
|
202
|
-
MU::Cloud
|
202
|
+
MU::Cloud.resourceClass("AWS", "DNSZone").genericMuDNSEntry(
|
203
203
|
name: resp.replication_group_id,
|
204
204
|
target: "#{resp.node_groups.first.primary_endpoint.address}.",
|
205
205
|
cloudclass: MU::Cloud::CacheCluster,
|
@@ -207,7 +207,7 @@ module MU
|
|
207
207
|
)
|
208
208
|
|
209
209
|
resp.node_groups.first.node_group_members.each { |member|
|
210
|
-
MU::Cloud
|
210
|
+
MU::Cloud.resourceClass("AWS", "DNSZone").genericMuDNSEntry(
|
211
211
|
name: member.cache_cluster_id,
|
212
212
|
target: "#{member.read_endpoint.address}.",
|
213
213
|
cloudclass: MU::Cloud::CacheCluster,
|
@@ -270,7 +270,7 @@ module MU
|
|
270
270
|
def createSubnetGroup
|
271
271
|
subnet_ids = []
|
272
272
|
if @config["vpc"] && !@config["vpc"].empty?
|
273
|
-
raise MuError
|
273
|
+
raise MuError.new "Didn't find the VPC specified for #{@mu_name}", details: @config["vpc"].to_h unless @vpc
|
274
274
|
|
275
275
|
vpc_id = @vpc.cloud_id
|
276
276
|
|
@@ -283,7 +283,7 @@ module MU
|
|
283
283
|
else
|
284
284
|
@config["vpc"]["subnets"].each { |subnet|
|
285
285
|
subnet_obj = @vpc.getSubnet(cloud_id: subnet["subnet_id"].to_s, name: subnet["subnet_name"].to_s)
|
286
|
-
raise MuError
|
286
|
+
raise MuError.new "Couldn't find a live subnet matching #{subnet} in #{@vpc}", details: @vpc.subnets if subnet_obj.nil?
|
287
287
|
subnet_ids << subnet_obj.cloud_id
|
288
288
|
}
|
289
289
|
end
|
@@ -333,24 +333,7 @@ module MU
|
|
333
333
|
subnet_ids: subnet_ids
|
334
334
|
)
|
335
335
|
|
336
|
-
|
337
|
-
# Adding just for consistency, but do we really need this for cache clusters? I guess Nagios and such..
|
338
|
-
if @config["vpc"]["nat_host_name"] || @config["vpc"]["nat_host_id"] || @config["vpc"]["nat_host_tag"] || @config["vpc"]["nat_host_ip"]
|
339
|
-
nat = @nat
|
340
|
-
if nat.is_a?(Struct) && nat.nat_gateway_id && nat.nat_gateway_id.start_with?("nat-")
|
341
|
-
MU.log "Using NAT Gateway, not modifying security groups"
|
342
|
-
else
|
343
|
-
_nat_name, _nat_conf, nat_deploydata = @nat.describe
|
344
|
-
@deploy.kittens['firewall_rules'].values.each { |acl|
|
345
|
-
# XXX if a user doesn't set up dependencies correctly, this can die horribly on a NAT that's still in mid-creation. Fix this... possibly in the config parser.
|
346
|
-
if acl.config["admin"]
|
347
|
-
acl.addRule([nat_deploydata["private_ip_address"]], proto: "tcp")
|
348
|
-
acl.addRule([nat_deploydata["private_ip_address"]], proto: "udp")
|
349
|
-
break
|
350
|
-
end
|
351
|
-
}
|
352
|
-
end
|
353
|
-
end
|
336
|
+
allowBastionAccess
|
354
337
|
|
355
338
|
if @dependencies.has_key?('firewall_rule')
|
356
339
|
@config["security_group_ids"] = []
|
@@ -430,7 +413,7 @@ module MU
|
|
430
413
|
}
|
431
414
|
end
|
432
415
|
# XXX this should be a call to @deploy.nameKitten
|
433
|
-
MU::Cloud
|
416
|
+
MU::Cloud.resourceClass("AWS", "DNSZone").createRecordsFromConfig(@config['dns_records'], target: repl_group.node_groups.first.primary_endpoint.address)
|
434
417
|
|
435
418
|
deploy_struct = {
|
436
419
|
"identifier" => repl_group.replication_group_id,
|
@@ -703,26 +686,7 @@ module MU
|
|
703
686
|
"type" => "boolean",
|
704
687
|
"description" => "Create a replication group; will be set automatically if +engine+ is +redis+ and +node_count+ is greated than one."
|
705
688
|
},
|
706
|
-
"ingress_rules" =>
|
707
|
-
"items" => {
|
708
|
-
"properties" => {
|
709
|
-
"sgs" => {
|
710
|
-
"type" => "array",
|
711
|
-
"items" => {
|
712
|
-
"description" => "Other AWS Security Groups; resources that are associated with this group will have this rule applied to their traffic",
|
713
|
-
"type" => "string"
|
714
|
-
}
|
715
|
-
},
|
716
|
-
"lbs" => {
|
717
|
-
"type" => "array",
|
718
|
-
"items" => {
|
719
|
-
"description" => "AWS Load Balancers which will have this rule applied to their traffic",
|
720
|
-
"type" => "string"
|
721
|
-
}
|
722
|
-
}
|
723
|
-
}
|
724
|
-
}
|
725
|
-
}
|
689
|
+
"ingress_rules" => MU::Cloud.resourceClass("AWS", "FirewallRule").ingressRuleAddtlSchema
|
726
690
|
}
|
727
691
|
[toplevel_required, schema]
|
728
692
|
end
|
@@ -823,7 +787,7 @@ module MU
|
|
823
787
|
end
|
824
788
|
|
825
789
|
# The API is broken, cluster.cache_nodes is returnning an empty array, and the only URL we can get is the config one with cluster.configuration_endpoint.address.
|
826
|
-
# MU::Cloud
|
790
|
+
# MU::Cloud.resourceClass("AWS", "DNSZone").genericMuDNSEntry(name: cluster_id, target: , cloudclass: MU::Cloud::CacheCluster, delete: true)
|
827
791
|
|
828
792
|
if %w{deleting deleted}.include?(cluster.cache_cluster_status)
|
829
793
|
MU.log "#{cluster_id} has already been terminated", MU::WARN
|
@@ -925,10 +889,10 @@ module MU
|
|
925
889
|
end
|
926
890
|
|
927
891
|
# What's the likelihood of having more than one node group? maybe iterate over node_groups instead of assuming there is only one?
|
928
|
-
MU::Cloud
|
892
|
+
MU::Cloud.resourceClass("AWS", "DNSZone").genericMuDNSEntry(name: repl_group_id, target: repl_group.node_groups.first.primary_endpoint.address, cloudclass: MU::Cloud::CacheCluster, delete: true)
|
929
893
|
# Assuming we also created DNS records for each of our cluster's read endpoint.
|
930
894
|
repl_group.node_groups.first.node_group_members.each { |member|
|
931
|
-
MU::Cloud
|
895
|
+
MU::Cloud.resourceClass("AWS", "DNSZone").genericMuDNSEntry(name: member.cache_cluster_id, target: member.read_endpoint.address, cloudclass: MU::Cloud::CacheCluster, delete: true)
|
932
896
|
}
|
933
897
|
|
934
898
|
if %w{deleting deleted}.include?(repl_group.status)
|