cloud-mu 3.0.0 → 3.0.1

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +25 -0
  3. data/README.md +2 -2
  4. data/bin/mu-node-manage +1 -1
  5. data/chefignore +1 -0
  6. data/cloud-mu.gemspec +2 -2
  7. data/extras/clean-stock-amis +0 -0
  8. data/extras/generate-stock-images +0 -0
  9. data/extras/list-stock-amis +0 -0
  10. data/extras/vault_tools/export_vaults.sh +0 -0
  11. data/extras/vault_tools/recreate_vaults.sh +0 -0
  12. data/extras/vault_tools/test_vaults.sh +0 -0
  13. data/kitchen.yml +97 -0
  14. data/modules/mu.rb +14 -2
  15. data/modules/mu/cloud.rb +26 -0
  16. data/modules/mu/clouds/aws.rb +1 -2
  17. data/modules/mu/clouds/aws/container_cluster.rb +2 -1
  18. data/modules/mu/clouds/aws/database.rb +2 -2
  19. data/modules/mu/clouds/aws/loadbalancer.rb +1 -1
  20. data/modules/mu/clouds/aws/search_domain.rb +1 -1
  21. data/modules/mu/clouds/aws/server.rb +9 -1
  22. data/modules/mu/clouds/aws/vpc.rb +1 -2
  23. data/modules/mu/config.rb +83 -3
  24. data/modules/mu/config/bucket.yml +1 -1
  25. data/modules/mu/config/cache_cluster.yml +1 -9
  26. data/modules/mu/config/container_cluster.yml +1 -1
  27. data/modules/mu/config/database.yml +3 -3
  28. data/modules/mu/config/log.yml +8 -3
  29. data/modules/mu/config/msg_queue.yml +1 -1
  30. data/modules/mu/config/nosqldb.yml +1 -1
  31. data/modules/mu/config/notifier.yml +1 -1
  32. data/modules/mu/config/search_domain.yml +2 -2
  33. data/modules/mu/config/server.yml +23 -3
  34. data/modules/mu/config/server_pool.yml +5 -2
  35. data/modules/mu/config/storage_pool.yml +1 -1
  36. data/modules/mu/config/vpc.rb +6 -6
  37. data/modules/mu/config/vpc.yml +54 -3
  38. data/modules/mu/groomers/chef.rb +27 -0
  39. data/modules/mu/mommacat.rb +113 -18
  40. metadata +18 -22
  41. data/Berksfile.lock +0 -179
  42. data/bin/mu-azure-tests +0 -43
  43. data/cookbooks/mu-tools/files/default/Mu_CA.pem +0 -33
  44. data/modules/mu/kittens.rb +0 -20651
  45. data/modules/mu/mu.yaml.rb +0 -276
  46. data/modules/scratchpad.erb +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ec38717ba0e001faf5500c971fad6d2ce978302e11c9b7dfc587b4d7f1e7c7a3
4
- data.tar.gz: 57a212554afb4c30752e471211b515252524dc5a4e4cddabafe29f66bd6a377f
3
+ metadata.gz: c0ab46aed6ed1aaf58e3d8de76de9ea27adc49cbd754b51cc4ef7e6354a78a26
4
+ data.tar.gz: 5b341646d7533692813097af86fb37c46f1ba23fb0faf6acfe09688a3456e13c
5
5
  SHA512:
6
- metadata.gz: 5fa39a5ac28414a186e1a1b620e2f097d3d662989dfd0501e02f01ad8f406f289e397a9b506c79c3511c3a659a316a1920d8ca1b8ecc5995bfe8e5f076e98f6c
7
- data.tar.gz: 663202c112b0cf2c816a578da15c1d82724ddd577077b7d15075d0e1c6c683b8048dbf216f044a6a623cf82d3ba2ce370ff87a66627c052e9fd996a3b372244e
6
+ metadata.gz: e9c62154b428aa93f247fbf61589372744a167814f0403a339640e1e96042c8ece774b57617127860e7cfa46dc95c0c666022c3872beac77987f496cea65ad00
7
+ data.tar.gz: 12a4ced1bb6cbfe64ef666699a34bafe1aaf0228d080d6f8ee3584bcaec967084eca3d3a4167a405e05d1f8bc0d171093f7bab46e5648d1ff3339750a36c60e8
@@ -0,0 +1,25 @@
1
+ FROM ruby:2.5-slim
2
+
3
+ RUN mkdir -p /opt/mu/etc/ /home/mu /usr/local/ruby-current/lib/ruby/gems/2.5.0/gems/var/
4
+
5
+ WORKDIR /home/mu
6
+
7
+ RUN apt-get update
8
+
9
+ RUN apt-get install -y ruby2.5-dev dnsutils ansible build-essential
10
+
11
+ RUN apt-get upgrade -y
12
+
13
+ COPY ./cloud-mu-*.gem /home/mu
14
+
15
+ RUN gem install ./cloud-mu-*.gem thin -N
16
+
17
+ RUN rm cloud-mu-*.gem
18
+
19
+ RUN apt-get remove -y build-essential ruby2.5-dev
20
+
21
+ RUN apt-get autoremove -y
22
+
23
+ EXPOSE 2260
24
+
25
+ CMD /usr/sbin/init
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  mu -- Cloudamatic Automation Tooling
2
2
  ===
3
3
  [![pipeline status](https://gitlab.com/cloudamatic/mu/badges/master/pipeline.svg)](https://gitlab.com/cloudamatic/mu/commits/master)
4
- [![Gem Version](https://badge.fury.io/rb/cloud-mu.svg)](https://badge.fury.io/rb/cloud-mu)
5
4
  [![Maintainability](https://api.codeclimate.com/v1/badges/dd4e5d867890336accd1/maintainability)](https://codeclimate.com/github/cloudamatic/mu/maintainability)
6
- [![Inline docs](http://inch-ci.org/github/cloudamatic/mu.svg?branch=master)](http://inch-ci.org/github/cloudamatic/mu)
5
+ [![Gem Version](https://badge.fury.io/rb/cloud-mu.svg)](https://badge.fury.io/rb/cloud-mu)
6
+ [![Docker Version](https://images.microbadger.com/badges/version/egtlabs/mu.svg)](https://microbadger.com/images/egtlabs/mu)
7
7
 
8
8
  # About mu
9
9
  **Mu** is the deployer and developer toolset for the Cloudamatic suite of services, designed to provision, orchestrate and manage complex platforms and applications. At [eGT Labs](https://www.eglobaltech.com/egt-labs/), we use mu for rapid prototyping of cloud migration efforts for federal customers, for managing cloud applications throughout their lifecycles, and as a tools library for cloud maintenance tasks.
@@ -599,7 +599,7 @@ def updateAWSMetaData(deploys = MU::MommaCat.listDeploys, nodes = [])
599
599
 
600
600
  MU.log "Updating #{nodename} userdata (#{server["conf"]["platform"]})"
601
601
  begin
602
- MU::Cloud::AWS.ec2(server['region']).modify_instance_attribute(
602
+ MU::Cloud::AWS.ec2(region: server['region']).modify_instance_attribute(
603
603
  instance_id: id,
604
604
  attribute: "userData",
605
605
  value: Base64.encode64(userdata)
@@ -0,0 +1 @@
1
+ .kitchen
@@ -17,8 +17,8 @@ end
17
17
 
18
18
  Gem::Specification.new do |s|
19
19
  s.name = 'cloud-mu'
20
- s.version = '3.0.0'
21
- s.date = '2019-11-11'
20
+ s.version = '3.0.1'
21
+ s.date = '2019-11-22'
22
22
  s.require_paths = ['modules']
23
23
  s.required_ruby_version = '>= 2.4'
24
24
  s.summary = "The eGTLabs Mu toolkit for unified cloud deployments"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,97 @@
1
+ driver:
2
+ name: ec2
3
+ region: us-east-1
4
+ subnet_id: subnet-00f6ebfde53bbdccd
5
+ instance_type: t2.medium
6
+ iam_profile_name: mu-master-role
7
+ associate_public_ip: true
8
+ interface: dns
9
+ shared_credentials_profile: test_kitchen
10
+ instance_initiated_shutdown_behavior: terminate
11
+ tags:
12
+ Name: kitchen-mu-node
13
+ created-by: mu-pipeline
14
+ sudo: true
15
+
16
+ provisioner:
17
+ name: chef_zero
18
+ roles_path: roles
19
+ chef_license: accept
20
+
21
+ verifier:
22
+ name: shell
23
+
24
+ platforms:
25
+ - name: centos-7
26
+ vm_tags:
27
+ osdistro: centos7
28
+
29
+ - name: amazon2
30
+ vm_tags:
31
+ osdistro: amazon2
32
+
33
+ - name: centos-7-az
34
+ driver:
35
+ name: azurerm
36
+ subscription_id: '3d20ddd8-4652-4074-adda-0d127ef1f0e0'
37
+ location: 'East US'
38
+ #image_urn: 'tunnelbiz:centos70-min:centos7-min:0.1.1'
39
+ machine_size: 'Standard_B2s'
40
+ vm_name: mu-install
41
+ vm_tags:
42
+ osdistro: centos7
43
+
44
+ suites:
45
+ - name: mu-install-aws
46
+ provisioner:
47
+ name: shell
48
+ script:
49
+ - "./kitchen_vars"
50
+ - "./install/installer"
51
+ - "./install/mu-master.yaml"
52
+ command:
53
+ - sudo yum install -y bind-utils
54
+ - sudo chown root:root /tmp/installer
55
+ - sudo chmod u+x /tmp/installer
56
+ - sudo chown root:root /tmp/mu-master.yaml
57
+ - source /tmp/kitchen_vars
58
+ - env
59
+ - myip="$(dig +short myip.opendns.com @resolver1.opendns.com)"
60
+ - sudo /tmp/installer -p $myip -m zach@zach.systems -o 2260 -h "$(echo $HOSTNAME | sed s/\\./-/g)" -n
61
+ root_path: '/tmp/'
62
+ includes:
63
+ - centos-7
64
+ - amazon2
65
+
66
+ - name: mu-install-azure
67
+ provisioner:
68
+ name: shell
69
+ script:
70
+ - "./install/installer"
71
+ - "./install/mu-master.yaml"
72
+ command:
73
+ - myip="$(dig +short myip.opendns.com @resolver1.opendns.com)"
74
+ - sudo ll /tmp/ && sudo MU_BRANCH=development /tmp/installer -p $myip -m zach@zach.systems -o 2260 -h "$(echo $HOSTNAME | sed s/\\./-/g)" -n
75
+ - sudo mu-deploy /tmp/mu-master.yaml -p name=stange-mu -p cloud=Azure
76
+ root_path: '/tmp/'
77
+ includes:
78
+ - centos-7-az
79
+
80
+ #- name: mu-node
81
+ # run_list:
82
+ # - recipe[mu-tools::newclient]
83
+ # - recipe[mu-tools::gcloud]
84
+ # - role[mu-node]
85
+ # includes:
86
+ # - ubuntu
87
+ # - centos-7
88
+ # - centos-6
89
+ # - rhel-7
90
+ # - rhel-6
91
+ # - amazon
92
+ # - amazon2
93
+ # - windows
94
+
95
+ # - name: mu-master
96
+ # run_list:
97
+ # - role[mu-master]
@@ -343,6 +343,17 @@ module MU
343
343
  ((Gem.paths and Gem.paths.home and File.realpath(File.expand_path(File.dirname(__FILE__))).match(/^#{Gem.paths.home}/)) or !Dir.exist?("/opt/mu"))
344
344
  end
345
345
 
346
+ # Are we operating in a gem?
347
+ def self.inGem?
348
+ return @in_gem if defined? @in_gem
349
+
350
+ if Gem.paths and Gem.paths.home and File.dirname(__FILE__).match(/^#{Gem.paths.home}/)
351
+ @in_gem = true
352
+ else
353
+ @in_gem = false
354
+ end
355
+ end
356
+
346
357
  # The main (root) Mu user's data directory.
347
358
  @@mainDataDir = File.expand_path(@@myRoot+"/../var")
348
359
  # The main (root) Mu user's data directory.
@@ -631,8 +642,9 @@ module MU
631
642
  !$MU_CFG['public_address'].empty? and @@my_public_ip != $MU_CFG['public_address']
632
643
  @@mu_public_addr = $MU_CFG['public_address']
633
644
  if !@@mu_public_addr.match(/^\d+\.\d+\.\d+\.\d+$/)
634
- resolver = Resolv::DNS.new
635
- @@mu_public_ip = resolver.getaddress(@@mu_public_addr).to_s
645
+ hostname = IO.readlines("/etc/hostname")[0].gsub /\n/, ''
646
+
647
+ @@mu_public_ip = File.open('/etc/hosts').grep(/.*#{hostname}.*/).first.match(/^\d+\.\d+\.\d+\.\d+/)[0]
636
648
  else
637
649
  @@mu_public_ip = @@mu_public_addr
638
650
  end
@@ -1142,6 +1142,30 @@ module MU
1142
1142
 
1143
1143
  # Remove all metadata and cloud resources associated with this object
1144
1144
  def destroy
1145
+ if self.class.cfg_name == "server"
1146
+ begin
1147
+ ip = canonicalIP
1148
+ MU::MommaCat.removeIPFromSSHKnownHosts(ip) if ip
1149
+ if @deploy and @deploy.deployment and
1150
+ @deploy.deployment['servers'] and @config['name'] and
1151
+ me = @deploy.deployment['servers'][@config['name']][@mu_name]
1152
+ if me
1153
+ ["private_ip_address", "public_ip_address"].each { |field|
1154
+ if me[field]
1155
+ MU::MommaCat.removeIPFromSSHKnownHosts(me[field])
1156
+ end
1157
+ }
1158
+ if me["private_ip_list"]
1159
+ me["private_ip_list"].each { |ip|
1160
+ MU::MommaCat.removeIPFromSSHKnownHosts(ip)
1161
+ }
1162
+ end
1163
+ end
1164
+ end
1165
+ rescue MU::MuError => e
1166
+ MU.log e.message, MU::WARN
1167
+ end
1168
+ end
1145
1169
  if !@cloudobj.nil? and !@cloudobj.groomer.nil?
1146
1170
  @cloudobj.groomer.cleanup
1147
1171
  elsif !@groomer.nil?
@@ -1952,6 +1976,7 @@ puts "CHOOSING #{@vpc.to_s} 'cause it has #{@config['vpc']['subnet_name']}"
1952
1976
  :keys => [ssh_keydir+"/"+nat_ssh_key, ssh_keydir+"/"+@deploy.ssh_key_name],
1953
1977
  :verify_host_key => false,
1954
1978
  # :verbose => :info,
1979
+ :host_key => "ssh-rsa",
1955
1980
  :port => 22,
1956
1981
  :auth_methods => ['publickey'],
1957
1982
  :proxy => proxy
@@ -1967,6 +1992,7 @@ puts "CHOOSING #{@vpc.to_s} 'cause it has #{@config['vpc']['subnet_name']}"
1967
1992
  :keys => [ssh_keydir+"/"+@deploy.ssh_key_name],
1968
1993
  :verify_host_key => false,
1969
1994
  # :verbose => :info,
1995
+ :host_key => "ssh-rsa",
1970
1996
  :port => 22,
1971
1997
  :auth_methods => ['publickey']
1972
1998
  )
@@ -164,7 +164,6 @@ module MU
164
164
  # @param r [String]
165
165
  # @return [String]
166
166
  def self.validate_region(r, credentials: nil)
167
- require "aws-sdk-core"
168
167
  begin
169
168
  MU::Cloud::AWS.ec2(region: r, credentials: credentials).describe_availability_zones.availability_zones.first.region_name
170
169
  rescue ::Aws::EC2::Errors::UnauthorizedOperation => e
@@ -1339,8 +1338,8 @@ module MU
1339
1338
  # @param region [String]: Amazon region so we know what endpoint to use
1340
1339
  # @param api [String]: Which API are we wrapping?
1341
1340
  def initialize(region: MU.curRegion, api: "EC2", credentials: nil)
1342
- @credentials = MU::Cloud::AWS.credConfig(credentials, name_only: true)
1343
1341
  @cred_obj = MU::Cloud::AWS.loadCredentials(credentials)
1342
+ @credentials = MU::Cloud::AWS.credConfig(credentials, name_only: true)
1344
1343
 
1345
1344
  if !@cred_obj
1346
1345
  raise MuError, "Unable to locate valid AWS credentials for #{api} API. #{credentials ? "Credentials requested were '#{credentials}'": ""}"
@@ -66,6 +66,7 @@ module MU
66
66
  ]
67
67
  }
68
68
  end
69
+ params.delete(:version) if params[:version] == "latest"
69
70
 
70
71
  MU.log "Creating EKS cluster #{@mu_name}", details: params
71
72
  resp = MU::Cloud::AWS.eks(region: @config['region'], credentials: @config['credentials']).create_cluster(params)
@@ -91,7 +92,7 @@ module MU
91
92
  sleep 5
92
93
  retry
93
94
  else
94
- MU.log e.message, MU::WARN, details: role_arn
95
+ MU.log e.message, MU::WARN, details: params
95
96
  sleep 5
96
97
  retry
97
98
  end
@@ -928,7 +928,7 @@ module MU
928
928
  basename[0..29].gsub(/[^a-z0-9]/i, "")
929
929
  elsif config["engine"].match(/^sqlserver/)
930
930
  basename[0..127].gsub(/[^a-z0-9]/i, "")
931
- elsif config["engine"].match(/^mysql/)
931
+ elsif config["engine"].match(/^(mysql|maria)/)
932
932
  basename[0..15].gsub(/[^a-z0-9]/i, "")
933
933
  elsif config["engine"].match(/^aurora/)
934
934
  basename[0..15].gsub(/[^a-z0-9]/i, "")
@@ -1603,7 +1603,7 @@ module MU
1603
1603
  db["license_model"] ||=
1604
1604
  if ["postgres", "postgresql", "aurora-postgresql"].include?(db["engine"])
1605
1605
  "postgresql-license"
1606
- elsif db["engine"] == "mysql"
1606
+ elsif ["mysql", "mariadb"].include?(db["engine"])
1607
1607
  "general-public-license"
1608
1608
  else
1609
1609
  "license-included"
@@ -188,7 +188,7 @@ module MU
188
188
  if @config['targetgroups']
189
189
  MU.log "Configuring target groups and health checks check for ELB #{@mu_name}", details: @config['healthcheck']
190
190
  @config['targetgroups'].each { |tg|
191
- tg_name = @deploy.getResourceName(tg["name"], max_length: 32)
191
+ tg_name = @deploy.getResourceName(tg["name"], max_length: 32, allowed_chars: /[A-Za-z0-9-]/)
192
192
  tg_descriptor = {
193
193
  :name => tg_name,
194
194
  :protocol => tg['proto'],
@@ -67,7 +67,7 @@ module MU
67
67
  domain_name: @deploydata['domain_name']
68
68
  ).domain_status
69
69
  else
70
- raise MU::MuError "#{@mu_name} can't find its official Elasticsearch domain name!"
70
+ raise MuError "#{@mu_name} can't find its official Elasticsearch domain name!"
71
71
  end
72
72
  end
73
73
 
@@ -120,8 +120,10 @@ module MU
120
120
  @config['mu_name'] = @mu_name
121
121
 
122
122
  end
123
+
123
124
  @config['instance_secret'] ||= Password.random(50)
124
125
 
126
+ @groomer = MU::Groomer.new(self) unless MU.inGem?
125
127
  end
126
128
 
127
129
  @@userdata_semaphore = Mutex.new
@@ -938,11 +940,17 @@ module MU
938
940
 
939
941
  # See if this node already exists in our config management. If it does,
940
942
  # we're done.
941
- if @groomer.haveBootstrapped?
943
+ if MU.inGem?
944
+ MU.log "Deploying from a gem, not grooming"
945
+
946
+ return true
947
+ elsif @groomer.haveBootstrapped?
942
948
  MU.log "Node #{node} has already been bootstrapped, skipping groomer setup.", MU::NOTICE
949
+
943
950
  if @config['groom'].nil? or @config['groom']
944
951
  @groomer.saveDeployData
945
952
  end
953
+
946
954
  MU::MommaCat.unlock(instance.instance_id+"-orchestrate")
947
955
  MU::MommaCat.unlock(instance.instance_id+"-groom")
948
956
  return true
@@ -1161,7 +1161,6 @@ MU.log "wtf", MU::ERR, details: peer if peer_obj.nil? or peer_obj.first.nil?
1161
1161
  # @param region [String]: The cloud provider region
1162
1162
  # @return [void]
1163
1163
  def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
1164
-
1165
1164
  tagfilters = [
1166
1165
  {name: "tag:MU-ID", values: [MU.deploy_id]}
1167
1166
  ]
@@ -1172,7 +1171,7 @@ MU.log "wtf", MU::ERR, details: peer if peer_obj.nil? or peer_obj.first.nil?
1172
1171
  vpcs = []
1173
1172
  retries = 0
1174
1173
  begin
1175
- resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_vpcs(filters: tagfilters).vpcs
1174
+ resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_vpcs(filters: tagfilters, max_results: 1000).vpcs
1176
1175
  vpcs = resp if !resp.empty?
1177
1176
  rescue Aws::EC2::Errors::InvalidVpcIDNotFound => e
1178
1177
  if retries < 5
@@ -317,6 +317,13 @@ module MU
317
317
  }
318
318
  end
319
319
 
320
+ # A way of dynamically defining +attr_reader+ without leaking memory
321
+ def self.define_reader(name)
322
+ define_method(name) {
323
+ instance_variable_get("@#{name.to_s}")
324
+ }
325
+ end
326
+
320
327
  # @param cfg [Hash]: A Basket of Kittens configuration hash containing
321
328
  # lookup information for a cloud object
322
329
  def initialize(cfg)
@@ -327,7 +334,7 @@ module MU
327
334
  elsif !cfg[field.to_sym].nil?
328
335
  self.instance_variable_set("@#{field.to_s}".to_sym, cfg[field.to_sym])
329
336
  end
330
- self.singleton_class.instance_eval { attr_reader field.to_sym }
337
+ MU::Config::Ref.define_reader(field)
331
338
  }
332
339
  if cfg['tag'] and cfg['tag']['key'] and
333
340
  !cfg['tag']['key'].empty? and cfg['tag']['value']
@@ -985,6 +992,15 @@ return
985
992
 
986
993
  @config['credentials'] ||= @default_credentials
987
994
 
995
+ if @config['cloud'] and !MU::Cloud.availableClouds.include?(@config['cloud'])
996
+ if MU::Cloud.supportedClouds.include?(@config['cloud'])
997
+ MU.log "Cloud provider #{@config['cloud']} declared, but no #{@config['cloud']} credentials available", MU::ERR
998
+ else
999
+ MU.log "Cloud provider #{@config['cloud']} is not supported", MU::ERR, details: MU::Cloud.supportedClouds
1000
+ end
1001
+ exit 1
1002
+ end
1003
+
988
1004
  types = MU::Cloud.resource_types.values.map { |v| v[:cfg_plural] }
989
1005
 
990
1006
  MU::Cloud.resource_types.values.map { |v| v[:cfg_plural] }.each { |type|
@@ -1274,6 +1290,16 @@ $CONFIGURABLES
1274
1290
  }
1275
1291
  ok = true
1276
1292
 
1293
+ if descriptor['cloud'] and
1294
+ !MU::Cloud.availableClouds.include?(descriptor['cloud'])
1295
+ if MU::Cloud.supportedClouds.include?(descriptor['cloud'])
1296
+ MU.log "#{cfg_name} #{descriptor['name']} is configured with cloud #{descriptor['cloud']}, but no #{descriptor['cloud']} credentials available", MU::ERR
1297
+ else
1298
+ MU.log "#{cfg_name} #{descriptor['name']}: Cloud provider #{descriptor['cloud']} is not supported", MU::ERR, details: MU::Cloud.supportedClouds
1299
+ end
1300
+ return false
1301
+ end
1302
+
1277
1303
  descriptor["#MU_CLOUDCLASS"] = classname
1278
1304
 
1279
1305
  applyInheritedDefaults(descriptor, cfg_plural)
@@ -1975,7 +2001,7 @@ $CONFIGURABLES
1975
2001
  conf_chunk.map! { |item|
1976
2002
  # If we're working on a resource type, go get implementation-specific
1977
2003
  # schema information so that we set those defaults correctly.
1978
- realschema = if type and schema_chunk["items"] and schema_chunk["items"]["properties"] and item["cloud"]
2004
+ realschema = if type and schema_chunk["items"] and schema_chunk["items"]["properties"] and item["cloud"] and MU::Cloud.supportedClouds.include?(item['cloud'])
1979
2005
 
1980
2006
  cloudclass = Object.const_get("MU").const_get("Cloud").const_get(item["cloud"]).const_get(type)
1981
2007
  toplevel_required, cloudschema = cloudclass.schema(self)
@@ -2126,6 +2152,10 @@ $CONFIGURABLES
2126
2152
  kitten['cloud'] ||= @config['cloud']
2127
2153
  kitten['cloud'] ||= MU::Config.defaultCloud
2128
2154
 
2155
+ if !MU::Cloud.supportedClouds.include?(kitten['cloud'])
2156
+ return
2157
+ end
2158
+
2129
2159
  cloudclass = Object.const_get("MU").const_get("Cloud").const_get(kitten['cloud'])
2130
2160
  shortclass, cfg_name, cfg_plural, classname = MU::Cloud.getResourceNames(type)
2131
2161
  resclass = Object.const_get("MU").const_get("Cloud").const_get(kitten['cloud']).const_get(shortclass)
@@ -2198,6 +2228,7 @@ $CONFIGURABLES
2198
2228
  count = count + @kittens[type].size
2199
2229
  }
2200
2230
 
2231
+
2201
2232
  if count == 0
2202
2233
  MU.log "You must declare at least one resource to create", MU::ERR
2203
2234
  ok = false
@@ -2437,8 +2468,10 @@ $CONFIGURABLES
2437
2468
  # and turn into documentation.
2438
2469
  def self.printSchema(kitten_rb, class_hierarchy, schema, in_array = false, required = false, prefix: nil)
2439
2470
  return if schema.nil?
2471
+
2440
2472
  if schema["type"] == "object"
2441
- printme = Array.new
2473
+ printme = []
2474
+
2442
2475
  if !schema["properties"].nil?
2443
2476
  # order sub-elements by whether they're required, so we can use YARD's
2444
2477
  # grouping tags on them
@@ -2453,6 +2486,53 @@ $CONFIGURABLES
2453
2486
  printme << "# @!group Optional parameters" if schema["required"].nil? or schema["required"].size == 0
2454
2487
  prop_list.each { |name|
2455
2488
  prop = schema["properties"][name]
2489
+
2490
+ if class_hierarchy.size == 1
2491
+
2492
+ _shortclass, cfg_name, cfg_plural, _classname = MU::Cloud.getResourceNames(name)
2493
+ if cfg_name
2494
+ example_path = MU.myRoot+"/modules/mu/config/"+cfg_name+".yml"
2495
+ if File.exist?(example_path)
2496
+ example = "#\n# Examples:\n#\n"
2497
+ # XXX these variables are all parameters from the BoKs in
2498
+ # modules/tests. A really clever implementation would read
2499
+ # and parse them to get default values, perhaps, instead of
2500
+ # hard-coding them here.
2501
+ instance_type = "t2.medium"
2502
+ db_size = "db.t2.medium"
2503
+ vpc_name = "some_vpc"
2504
+ logs_name = "some_loggroup"
2505
+ queues_name = "some_queue"
2506
+ server_pools_name = "some_server_pool"
2507
+ ["simple", "complex"].each { |complexity|
2508
+ erb = ERB.new(File.read(example_path), nil, "<>")
2509
+ example += "# !!!yaml\n"
2510
+ example += "# ---\n"
2511
+ example += "# appname: #{complexity}\n"
2512
+ example += "# #{cfg_plural}:\n"
2513
+ firstline = true
2514
+ erb.result(binding).split(/\n/).each { |l|
2515
+ l.sub!(/#.*/, "")
2516
+ next if l.empty? or l.match(/^\s+$/)
2517
+ if firstline
2518
+ l = "- "+l
2519
+ firstline = false
2520
+ else
2521
+ l = " "+l
2522
+ end
2523
+ example += "# "+l+" "+"\n"
2524
+ }
2525
+ example += "# &nbsp;\n#\n" if complexity == "simple"
2526
+ }
2527
+ schema["properties"][name]["items"]["description"] ||= ""
2528
+ if !schema["properties"][name]["items"]["description"].empty?
2529
+ schema["properties"][name]["items"]["description"] += "\n"
2530
+ end
2531
+ schema["properties"][name]["items"]["description"] += example
2532
+ end
2533
+ end
2534
+ end
2535
+
2456
2536
  if !schema["required"].nil? and schema["required"].include?(name)
2457
2537
  printme << "# @!group Required parameters" if !req
2458
2538
  req = true