cloud-mu 2.1.0beta → 3.0.0beta

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 (291) hide show
  1. checksums.yaml +5 -5
  2. data/Berksfile +4 -5
  3. data/Berksfile.lock +179 -0
  4. data/README.md +1 -6
  5. data/ansible/roles/geerlingguy.firewall/templates/firewall.bash.j2 +0 -0
  6. data/ansible/roles/mu-installer/README.md +33 -0
  7. data/ansible/roles/mu-installer/defaults/main.yml +2 -0
  8. data/ansible/roles/mu-installer/handlers/main.yml +2 -0
  9. data/ansible/roles/mu-installer/meta/main.yml +60 -0
  10. data/ansible/roles/mu-installer/tasks/main.yml +13 -0
  11. data/ansible/roles/mu-installer/tests/inventory +2 -0
  12. data/ansible/roles/mu-installer/tests/test.yml +5 -0
  13. data/ansible/roles/mu-installer/vars/main.yml +2 -0
  14. data/bin/mu-adopt +125 -0
  15. data/bin/mu-aws-setup +4 -4
  16. data/bin/mu-azure-setup +265 -0
  17. data/bin/mu-azure-tests +43 -0
  18. data/bin/mu-cleanup +20 -8
  19. data/bin/mu-configure +224 -98
  20. data/bin/mu-deploy +8 -3
  21. data/bin/mu-gcp-setup +16 -8
  22. data/bin/mu-gen-docs +92 -8
  23. data/bin/mu-load-config.rb +52 -12
  24. data/bin/mu-momma-cat +36 -0
  25. data/bin/mu-node-manage +34 -27
  26. data/bin/mu-self-update +2 -2
  27. data/bin/mu-ssh +12 -8
  28. data/bin/mu-upload-chef-artifacts +11 -4
  29. data/bin/mu-user-manage +3 -0
  30. data/cloud-mu.gemspec +8 -11
  31. data/cookbooks/firewall/libraries/helpers_iptables.rb +2 -2
  32. data/cookbooks/firewall/metadata.json +1 -1
  33. data/cookbooks/firewall/recipes/default.rb +5 -9
  34. data/cookbooks/mu-firewall/attributes/default.rb +2 -0
  35. data/cookbooks/mu-firewall/metadata.rb +1 -1
  36. data/cookbooks/mu-glusterfs/templates/default/mu-gluster-client.erb +0 -0
  37. data/cookbooks/mu-master/Berksfile +2 -2
  38. data/cookbooks/mu-master/files/default/check_mem.pl +0 -0
  39. data/cookbooks/mu-master/files/default/cloudamatic.png +0 -0
  40. data/cookbooks/mu-master/metadata.rb +5 -4
  41. data/cookbooks/mu-master/recipes/389ds.rb +1 -1
  42. data/cookbooks/mu-master/recipes/basepackages.rb +30 -10
  43. data/cookbooks/mu-master/recipes/default.rb +59 -7
  44. data/cookbooks/mu-master/recipes/firewall-holes.rb +1 -1
  45. data/cookbooks/mu-master/recipes/init.rb +65 -47
  46. data/cookbooks/mu-master/recipes/{eks-kubectl.rb → kubectl.rb} +4 -10
  47. data/cookbooks/mu-master/recipes/sssd.rb +2 -1
  48. data/cookbooks/mu-master/recipes/update_nagios_only.rb +6 -6
  49. data/cookbooks/mu-master/templates/default/web_app.conf.erb +2 -2
  50. data/cookbooks/mu-master/templates/mods/ldap.conf.erb +4 -0
  51. data/cookbooks/mu-php54/Berksfile +1 -2
  52. data/cookbooks/mu-php54/metadata.rb +4 -5
  53. data/cookbooks/mu-php54/recipes/default.rb +1 -1
  54. data/cookbooks/mu-splunk/templates/default/splunk-init.erb +0 -0
  55. data/cookbooks/mu-tools/Berksfile +3 -2
  56. data/cookbooks/mu-tools/files/default/Mu_CA.pem +33 -0
  57. data/cookbooks/mu-tools/libraries/helper.rb +20 -8
  58. data/cookbooks/mu-tools/metadata.rb +5 -2
  59. data/cookbooks/mu-tools/recipes/apply_security.rb +2 -3
  60. data/cookbooks/mu-tools/recipes/eks.rb +1 -1
  61. data/cookbooks/mu-tools/recipes/gcloud.rb +5 -30
  62. data/cookbooks/mu-tools/recipes/nagios.rb +1 -1
  63. data/cookbooks/mu-tools/recipes/rsyslog.rb +1 -0
  64. data/cookbooks/mu-tools/recipes/selinux.rb +19 -0
  65. data/cookbooks/mu-tools/recipes/split_var_partitions.rb +0 -1
  66. data/cookbooks/mu-tools/recipes/windows-client.rb +256 -122
  67. data/cookbooks/mu-tools/resources/disk.rb +3 -1
  68. data/cookbooks/mu-tools/templates/amazon/sshd_config.erb +1 -1
  69. data/cookbooks/mu-tools/templates/default/etc_hosts.erb +1 -1
  70. data/cookbooks/mu-tools/templates/default/{kubeconfig.erb → kubeconfig-eks.erb} +0 -0
  71. data/cookbooks/mu-tools/templates/default/kubeconfig-gke.erb +27 -0
  72. data/cookbooks/mu-tools/templates/windows-10/sshd_config.erb +137 -0
  73. data/cookbooks/mu-utility/recipes/nat.rb +4 -0
  74. data/extras/alpha.png +0 -0
  75. data/extras/beta.png +0 -0
  76. data/extras/clean-stock-amis +2 -2
  77. data/extras/generate-stock-images +131 -0
  78. data/extras/git-fix-permissions-hook +0 -0
  79. data/extras/image-generators/AWS/centos6.yaml +17 -0
  80. data/extras/image-generators/{aws → AWS}/centos7-govcloud.yaml +0 -0
  81. data/extras/image-generators/{aws → AWS}/centos7.yaml +0 -0
  82. data/extras/image-generators/{aws → AWS}/rhel7.yaml +0 -0
  83. data/extras/image-generators/{aws → AWS}/win2k12.yaml +0 -0
  84. data/extras/image-generators/{aws → AWS}/win2k16.yaml +0 -0
  85. data/extras/image-generators/{aws → AWS}/windows.yaml +0 -0
  86. data/extras/image-generators/{gcp → Google}/centos6.yaml +1 -0
  87. data/extras/image-generators/Google/centos7.yaml +18 -0
  88. data/extras/python_rpm/build.sh +0 -0
  89. data/extras/release.png +0 -0
  90. data/extras/ruby_rpm/build.sh +0 -0
  91. data/extras/ruby_rpm/muby.spec +1 -1
  92. data/install/README.md +43 -5
  93. data/install/deprecated-bash-library.sh +0 -0
  94. data/install/installer +1 -1
  95. data/install/jenkinskeys.rb +0 -0
  96. data/install/mu-master.yaml +55 -0
  97. data/modules/mommacat.ru +41 -7
  98. data/modules/mu.rb +444 -149
  99. data/modules/mu/adoption.rb +500 -0
  100. data/modules/mu/cleanup.rb +235 -158
  101. data/modules/mu/cloud.rb +675 -138
  102. data/modules/mu/clouds/aws.rb +156 -24
  103. data/modules/mu/clouds/aws/alarm.rb +4 -14
  104. data/modules/mu/clouds/aws/bucket.rb +60 -18
  105. data/modules/mu/clouds/aws/cache_cluster.rb +8 -20
  106. data/modules/mu/clouds/aws/collection.rb +12 -22
  107. data/modules/mu/clouds/aws/container_cluster.rb +209 -118
  108. data/modules/mu/clouds/aws/database.rb +120 -45
  109. data/modules/mu/clouds/aws/dnszone.rb +7 -18
  110. data/modules/mu/clouds/aws/endpoint.rb +5 -15
  111. data/modules/mu/clouds/aws/firewall_rule.rb +144 -72
  112. data/modules/mu/clouds/aws/folder.rb +4 -11
  113. data/modules/mu/clouds/aws/function.rb +6 -16
  114. data/modules/mu/clouds/aws/group.rb +4 -12
  115. data/modules/mu/clouds/aws/habitat.rb +11 -13
  116. data/modules/mu/clouds/aws/loadbalancer.rb +40 -28
  117. data/modules/mu/clouds/aws/log.rb +5 -13
  118. data/modules/mu/clouds/aws/msg_queue.rb +9 -24
  119. data/modules/mu/clouds/aws/nosqldb.rb +4 -12
  120. data/modules/mu/clouds/aws/notifier.rb +6 -13
  121. data/modules/mu/clouds/aws/role.rb +69 -40
  122. data/modules/mu/clouds/aws/search_domain.rb +17 -20
  123. data/modules/mu/clouds/aws/server.rb +184 -94
  124. data/modules/mu/clouds/aws/server_pool.rb +33 -38
  125. data/modules/mu/clouds/aws/storage_pool.rb +5 -12
  126. data/modules/mu/clouds/aws/user.rb +59 -33
  127. data/modules/mu/clouds/aws/userdata/linux.erb +18 -30
  128. data/modules/mu/clouds/aws/userdata/windows.erb +9 -9
  129. data/modules/mu/clouds/aws/vpc.rb +214 -145
  130. data/modules/mu/clouds/azure.rb +978 -44
  131. data/modules/mu/clouds/azure/container_cluster.rb +413 -0
  132. data/modules/mu/clouds/azure/firewall_rule.rb +500 -0
  133. data/modules/mu/clouds/azure/habitat.rb +167 -0
  134. data/modules/mu/clouds/azure/loadbalancer.rb +205 -0
  135. data/modules/mu/clouds/azure/role.rb +211 -0
  136. data/modules/mu/clouds/azure/server.rb +810 -0
  137. data/modules/mu/clouds/azure/user.rb +257 -0
  138. data/modules/mu/clouds/azure/userdata/README.md +4 -0
  139. data/modules/mu/clouds/azure/userdata/linux.erb +137 -0
  140. data/modules/mu/clouds/azure/userdata/windows.erb +275 -0
  141. data/modules/mu/clouds/azure/vpc.rb +782 -0
  142. data/modules/mu/clouds/cloudformation.rb +12 -9
  143. data/modules/mu/clouds/cloudformation/firewall_rule.rb +5 -13
  144. data/modules/mu/clouds/cloudformation/server.rb +10 -1
  145. data/modules/mu/clouds/cloudformation/server_pool.rb +1 -0
  146. data/modules/mu/clouds/cloudformation/vpc.rb +0 -2
  147. data/modules/mu/clouds/google.rb +554 -117
  148. data/modules/mu/clouds/google/bucket.rb +173 -32
  149. data/modules/mu/clouds/google/container_cluster.rb +1112 -157
  150. data/modules/mu/clouds/google/database.rb +24 -47
  151. data/modules/mu/clouds/google/firewall_rule.rb +344 -89
  152. data/modules/mu/clouds/google/folder.rb +156 -79
  153. data/modules/mu/clouds/google/group.rb +272 -82
  154. data/modules/mu/clouds/google/habitat.rb +177 -52
  155. data/modules/mu/clouds/google/loadbalancer.rb +9 -34
  156. data/modules/mu/clouds/google/role.rb +1211 -0
  157. data/modules/mu/clouds/google/server.rb +491 -227
  158. data/modules/mu/clouds/google/server_pool.rb +233 -48
  159. data/modules/mu/clouds/google/user.rb +479 -125
  160. data/modules/mu/clouds/google/userdata/linux.erb +3 -3
  161. data/modules/mu/clouds/google/userdata/windows.erb +9 -9
  162. data/modules/mu/clouds/google/vpc.rb +381 -223
  163. data/modules/mu/config.rb +689 -214
  164. data/modules/mu/config/bucket.rb +1 -1
  165. data/modules/mu/config/cache_cluster.rb +1 -1
  166. data/modules/mu/config/cache_cluster.yml +0 -4
  167. data/modules/mu/config/container_cluster.rb +18 -9
  168. data/modules/mu/config/database.rb +6 -23
  169. data/modules/mu/config/firewall_rule.rb +9 -15
  170. data/modules/mu/config/folder.rb +22 -21
  171. data/modules/mu/config/habitat.rb +22 -21
  172. data/modules/mu/config/loadbalancer.rb +2 -2
  173. data/modules/mu/config/role.rb +9 -40
  174. data/modules/mu/config/server.rb +26 -5
  175. data/modules/mu/config/server_pool.rb +1 -1
  176. data/modules/mu/config/storage_pool.rb +2 -2
  177. data/modules/mu/config/user.rb +4 -0
  178. data/modules/mu/config/vpc.rb +350 -110
  179. data/modules/mu/defaults/{amazon_images.yaml → AWS.yaml} +37 -39
  180. data/modules/mu/defaults/Azure.yaml +17 -0
  181. data/modules/mu/defaults/Google.yaml +24 -0
  182. data/modules/mu/defaults/README.md +1 -1
  183. data/modules/mu/deploy.rb +168 -125
  184. data/modules/mu/groomer.rb +2 -1
  185. data/modules/mu/groomers/ansible.rb +104 -32
  186. data/modules/mu/groomers/chef.rb +96 -44
  187. data/modules/mu/kittens.rb +20602 -0
  188. data/modules/mu/logger.rb +38 -11
  189. data/modules/mu/master.rb +90 -8
  190. data/modules/mu/master/chef.rb +2 -3
  191. data/modules/mu/master/ldap.rb +0 -1
  192. data/modules/mu/master/ssl.rb +250 -0
  193. data/modules/mu/mommacat.rb +917 -513
  194. data/modules/scratchpad.erb +1 -1
  195. data/modules/tests/super_complex_bok.yml +0 -0
  196. data/modules/tests/super_simple_bok.yml +0 -0
  197. data/roles/mu-master.json +2 -1
  198. data/spec/azure_creds +5 -0
  199. data/spec/mu.yaml +56 -0
  200. data/spec/mu/clouds/azure_spec.rb +164 -27
  201. data/spec/spec_helper.rb +5 -0
  202. data/test/clean_up.py +0 -0
  203. data/test/exec_inspec.py +0 -0
  204. data/test/exec_mu_install.py +0 -0
  205. data/test/exec_retry.py +0 -0
  206. data/test/smoke_test.rb +0 -0
  207. metadata +90 -118
  208. data/cookbooks/mu-jenkins/Berksfile +0 -14
  209. data/cookbooks/mu-jenkins/CHANGELOG.md +0 -13
  210. data/cookbooks/mu-jenkins/LICENSE +0 -37
  211. data/cookbooks/mu-jenkins/README.md +0 -105
  212. data/cookbooks/mu-jenkins/attributes/default.rb +0 -42
  213. data/cookbooks/mu-jenkins/files/default/cleanup_deploy_config.xml +0 -73
  214. data/cookbooks/mu-jenkins/files/default/deploy_config.xml +0 -44
  215. data/cookbooks/mu-jenkins/metadata.rb +0 -21
  216. data/cookbooks/mu-jenkins/recipes/default.rb +0 -195
  217. data/cookbooks/mu-jenkins/recipes/node-ssh-config.rb +0 -54
  218. data/cookbooks/mu-jenkins/recipes/public_key.rb +0 -24
  219. data/cookbooks/mu-jenkins/templates/default/example_job.config.xml.erb +0 -24
  220. data/cookbooks/mu-jenkins/templates/default/org.jvnet.hudson.plugins.SSHBuildWrapper.xml.erb +0 -14
  221. data/cookbooks/mu-jenkins/templates/default/ssh_config.erb +0 -6
  222. data/cookbooks/nagios/Berksfile +0 -11
  223. data/cookbooks/nagios/CHANGELOG.md +0 -589
  224. data/cookbooks/nagios/CONTRIBUTING.md +0 -11
  225. data/cookbooks/nagios/LICENSE +0 -37
  226. data/cookbooks/nagios/README.md +0 -328
  227. data/cookbooks/nagios/TESTING.md +0 -2
  228. data/cookbooks/nagios/attributes/config.rb +0 -171
  229. data/cookbooks/nagios/attributes/default.rb +0 -228
  230. data/cookbooks/nagios/chefignore +0 -102
  231. data/cookbooks/nagios/definitions/command.rb +0 -33
  232. data/cookbooks/nagios/definitions/contact.rb +0 -33
  233. data/cookbooks/nagios/definitions/contactgroup.rb +0 -33
  234. data/cookbooks/nagios/definitions/host.rb +0 -33
  235. data/cookbooks/nagios/definitions/hostdependency.rb +0 -33
  236. data/cookbooks/nagios/definitions/hostescalation.rb +0 -34
  237. data/cookbooks/nagios/definitions/hostgroup.rb +0 -33
  238. data/cookbooks/nagios/definitions/nagios_conf.rb +0 -38
  239. data/cookbooks/nagios/definitions/resource.rb +0 -33
  240. data/cookbooks/nagios/definitions/service.rb +0 -33
  241. data/cookbooks/nagios/definitions/servicedependency.rb +0 -33
  242. data/cookbooks/nagios/definitions/serviceescalation.rb +0 -34
  243. data/cookbooks/nagios/definitions/servicegroup.rb +0 -33
  244. data/cookbooks/nagios/definitions/timeperiod.rb +0 -33
  245. data/cookbooks/nagios/libraries/base.rb +0 -314
  246. data/cookbooks/nagios/libraries/command.rb +0 -91
  247. data/cookbooks/nagios/libraries/contact.rb +0 -230
  248. data/cookbooks/nagios/libraries/contactgroup.rb +0 -112
  249. data/cookbooks/nagios/libraries/custom_option.rb +0 -36
  250. data/cookbooks/nagios/libraries/data_bag_helper.rb +0 -23
  251. data/cookbooks/nagios/libraries/default.rb +0 -90
  252. data/cookbooks/nagios/libraries/host.rb +0 -412
  253. data/cookbooks/nagios/libraries/hostdependency.rb +0 -181
  254. data/cookbooks/nagios/libraries/hostescalation.rb +0 -173
  255. data/cookbooks/nagios/libraries/hostgroup.rb +0 -119
  256. data/cookbooks/nagios/libraries/nagios.rb +0 -282
  257. data/cookbooks/nagios/libraries/resource.rb +0 -59
  258. data/cookbooks/nagios/libraries/service.rb +0 -455
  259. data/cookbooks/nagios/libraries/servicedependency.rb +0 -215
  260. data/cookbooks/nagios/libraries/serviceescalation.rb +0 -195
  261. data/cookbooks/nagios/libraries/servicegroup.rb +0 -144
  262. data/cookbooks/nagios/libraries/timeperiod.rb +0 -160
  263. data/cookbooks/nagios/libraries/users_helper.rb +0 -54
  264. data/cookbooks/nagios/metadata.rb +0 -25
  265. data/cookbooks/nagios/recipes/_load_databag_config.rb +0 -153
  266. data/cookbooks/nagios/recipes/_load_default_config.rb +0 -241
  267. data/cookbooks/nagios/recipes/apache.rb +0 -48
  268. data/cookbooks/nagios/recipes/default.rb +0 -204
  269. data/cookbooks/nagios/recipes/nginx.rb +0 -82
  270. data/cookbooks/nagios/recipes/pagerduty.rb +0 -143
  271. data/cookbooks/nagios/recipes/server_package.rb +0 -40
  272. data/cookbooks/nagios/recipes/server_source.rb +0 -164
  273. data/cookbooks/nagios/templates/default/apache2.conf.erb +0 -96
  274. data/cookbooks/nagios/templates/default/cgi.cfg.erb +0 -266
  275. data/cookbooks/nagios/templates/default/commands.cfg.erb +0 -13
  276. data/cookbooks/nagios/templates/default/contacts.cfg.erb +0 -37
  277. data/cookbooks/nagios/templates/default/hostgroups.cfg.erb +0 -25
  278. data/cookbooks/nagios/templates/default/hosts.cfg.erb +0 -15
  279. data/cookbooks/nagios/templates/default/htpasswd.users.erb +0 -6
  280. data/cookbooks/nagios/templates/default/nagios.cfg.erb +0 -22
  281. data/cookbooks/nagios/templates/default/nginx.conf.erb +0 -62
  282. data/cookbooks/nagios/templates/default/pagerduty.cgi.erb +0 -185
  283. data/cookbooks/nagios/templates/default/resource.cfg.erb +0 -27
  284. data/cookbooks/nagios/templates/default/servicedependencies.cfg.erb +0 -15
  285. data/cookbooks/nagios/templates/default/servicegroups.cfg.erb +0 -14
  286. data/cookbooks/nagios/templates/default/services.cfg.erb +0 -14
  287. data/cookbooks/nagios/templates/default/templates.cfg.erb +0 -31
  288. data/cookbooks/nagios/templates/default/timeperiods.cfg.erb +0 -13
  289. data/extras/image-generators/aws/centos6.yaml +0 -18
  290. data/modules/mu/defaults/google_images.yaml +0 -16
  291. data/roles/mu-master-jenkins.json +0 -24
@@ -0,0 +1,500 @@
1
+ # Copyright:: Copyright (c) 2019 eGlobalTech, Inc., all rights reserved
2
+ #
3
+ # Licensed under the BSD-3 license (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License in the root of the project or at
6
+ #
7
+ # http://egt-labs.com/mu/LICENSE.html
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module MU
16
+
17
+ # Scrape cloud providers for existing resources, and reverse-engineer them
18
+ # into runnable {MU::Config} descriptors and/or {MU::MommaCat} deploy objects.
19
+ class Adoption
20
+
21
+ attr_reader :found
22
+
23
+ # Error class for objects which fail to fully resolve (e.g. references to
24
+ # other objects which are not found)
25
+ class Incomplete < MU::MuNonFatal; end
26
+
27
+ # Presets methods we use to clump discovered resources into discrete deploys
28
+ GROUPMODES = {
29
+ :logical => "Group resources in logical layers (folders and habitats together, users/roles/groups together, network resources together, etc)",
30
+ :omnibus => "Jam everything into one monolothic configuration"
31
+ }
32
+
33
+ def initialize(clouds: MU::Cloud.supportedClouds, types: MU::Cloud.resource_types.keys, parent: nil, billing: nil, sources: nil, credentials: nil, group_by: :logical, savedeploys: true, diff: false, habitats: [])
34
+ @scraped = {}
35
+ @clouds = clouds
36
+ @types = types
37
+ @parent = parent
38
+ @boks = {}
39
+ @billing = billing
40
+ @reference_map = {}
41
+ @sources = sources
42
+ @target_creds = credentials
43
+ @group_by = group_by
44
+ @savedeploys = savedeploys
45
+ @diff = diff
46
+ @habitats = habitats
47
+ @habitats ||= []
48
+ end
49
+
50
+ # Walk cloud providers with available credentials to discover resources
51
+ def scrapeClouds()
52
+ @default_parent = nil
53
+
54
+ @clouds.each { |cloud|
55
+ cloudclass = Object.const_get("MU").const_get("Cloud").const_get(cloud)
56
+ next if cloudclass.listCredentials.nil?
57
+
58
+ if cloud == "Google" and !@parent and @target_creds
59
+ dest_org = MU::Cloud::Google.getOrg(@target_creds)
60
+ if dest_org
61
+ @default_parent = dest_org.name
62
+ end
63
+ end
64
+
65
+ cloudclass.listCredentials.each { |credset|
66
+ next if @sources and !@sources.include?(credset)
67
+
68
+ if @parent
69
+ # TODO handle different inputs (cloud_id, etc)
70
+ # TODO do something about vague matches
71
+ found = MU::MommaCat.findStray(
72
+ cloud,
73
+ "folders",
74
+ flags: { "display_name" => @parent },
75
+ credentials: credset,
76
+ allow_multi: false,
77
+ dummy_ok: true,
78
+ debug: false
79
+ )
80
+ if found and found.size == 1
81
+ @default_parent = found.first
82
+ end
83
+ end
84
+
85
+ @types.each { |type|
86
+ begin
87
+ resclass = Object.const_get("MU").const_get("Cloud").const_get(cloud).const_get(type)
88
+ rescue ::MU::Cloud::MuCloudResourceNotImplemented
89
+ next
90
+ end
91
+ if !resclass.instance_methods.include?(:toKitten)
92
+ MU.log "Skipping MU::Cloud::#{cloud}::#{type} (resource has not implemented #toKitten)", MU::WARN
93
+ next
94
+ end
95
+ MU.log "Scraping #{cloud}/#{credset} for #{resclass.cfg_plural}"
96
+
97
+ found = MU::MommaCat.findStray(
98
+ cloud,
99
+ type,
100
+ credentials: credset,
101
+ allow_multi: true,
102
+ habitats: @habitats.dup,
103
+ dummy_ok: true,
104
+ debug: false,
105
+ flags: { "skip_provider_owned" => true }
106
+ )
107
+
108
+
109
+ if found and found.size > 0
110
+ MU.log "Found #{found.size.to_s} raw #{resclass.cfg_plural} in #{cloud}"
111
+ @scraped[type] ||= {}
112
+ found.each { |obj|
113
+ # XXX apply any filters (e.g. MU-ID tags)
114
+ @scraped[type][obj.cloud_id] = obj
115
+ }
116
+ end
117
+
118
+ }
119
+ }
120
+ }
121
+
122
+ if @parent and !@default_parent
123
+ MU.log "Failed to locate a folder that resembles #{@parent}", MU::ERR
124
+ end
125
+ MU.log "Scraping complete"
126
+ end
127
+
128
+ # Generate a {MU::Config} (Basket of Kittens) hash using our discovered
129
+ # cloud objects.
130
+ # @return [Hash]
131
+ def generateBaskets(prefix: "")
132
+ groupings = {
133
+ "" => MU::Cloud.resource_types.values.map { |v| v[:cfg_plural] }
134
+ }
135
+
136
+ # XXX as soon as we come up with a method that isn't about what resource
137
+ # type you are, this code will stop making sense
138
+ if @group_by == :logical
139
+ groupings = {
140
+ "spaces" => ["folders", "habitats"],
141
+ "people" => ["users", "groups", "roles"],
142
+ "network" => ["vpcs", "firewall_rules", "dnszones"],
143
+ "storage" => ["storage_pools", "buckets"],
144
+ }
145
+ # "the movie star/and the rest"
146
+ groupings["services"] = MU::Cloud.resource_types.values.map { |v| v[:cfg_plural] } - groupings.values.flatten
147
+ elsif @group_by == :omnibus
148
+ prefix = "mu" if prefix.empty? # so that appnames aren't ever empty
149
+ end
150
+
151
+ groupings.each_pair { |appname, types|
152
+ bok = { "appname" => prefix+appname }
153
+ if @target_creds
154
+ bok["credentials"] = @target_creds
155
+ end
156
+
157
+ count = 0
158
+ allowed_types = @types.map { |t| MU::Cloud.resource_types[t][:cfg_plural] }
159
+ next if (types & allowed_types).size == 0
160
+ origin = {
161
+ "appname" => bok['appname'],
162
+ "types" => (types & allowed_types).sort,
163
+ "habitats" => @habitats.sort,
164
+ "group_by" => @group_by.to_s
165
+ }
166
+
167
+ deploy = MU::MommaCat.findMatchingDeploy(origin)
168
+ if @diff and !deploy
169
+ MU.log "--diff was set but I failed to find a deploy like me to compare to", MU::ERR, details: origin
170
+ exit 1
171
+ end
172
+
173
+ threads = []
174
+ @clouds.each { |cloud|
175
+ @scraped.each_pair { |type, resources|
176
+ res_class = begin
177
+ MU::Cloud.loadCloudType(cloud, type)
178
+ rescue MU::Cloud::MuCloudResourceNotImplemented => e
179
+ # XXX I don't think this can actually happen
180
+ next
181
+ end
182
+ next if !types.include?(res_class.cfg_plural)
183
+
184
+ bok[res_class.cfg_plural] ||= []
185
+
186
+ class_semaphore = Mutex.new
187
+
188
+ Thread.abort_on_exception = true
189
+ resources.each_pair { |cloud_id_thr, obj_thr|
190
+ threads << Thread.new(cloud_id_thr, obj_thr) { |cloud_id, obj|
191
+
192
+ kitten_cfg = obj.toKitten(rootparent: @default_parent, billing: @billing, habitats: @habitats)
193
+ if kitten_cfg
194
+ print "."
195
+ kitten_cfg.delete("credentials") if @target_creds
196
+ class_semaphore.synchronize {
197
+ bok[res_class.cfg_plural] << kitten_cfg
198
+ }
199
+ count += 1
200
+ end
201
+ }
202
+
203
+ }
204
+
205
+ threads.each { |t|
206
+ t.join
207
+ }
208
+ puts ""
209
+ bok[res_class.cfg_plural].sort! { |a, b|
210
+ strs = [a, b].map { |x|
211
+ if x['cloud_id']
212
+ x['cloud_id']
213
+ elsif x['parent'] and ['parent'].respond_to?(:id) and kitten_cfg['parent'].id
214
+ x['name']+x['parent'].id
215
+ elsif x['project']
216
+ x['name']+x['project']
217
+ else
218
+ x['name']
219
+ end
220
+ }
221
+ strs[0] <=> strs[1]
222
+ }
223
+
224
+ # If we've got duplicate names in here, try to deal with it
225
+ bok[res_class.cfg_plural].each { |kitten_cfg|
226
+ bok[res_class.cfg_plural].each { |sibling|
227
+ next if kitten_cfg == sibling
228
+ if sibling['name'] == kitten_cfg['name']
229
+ MU.log "#{res_class.cfg_name} name #{sibling['name']} unavailable, will attempt to rename duplicate object", MU::DEBUG, details: kitten_cfg
230
+ if kitten_cfg['parent'] and kitten_cfg['parent'].respond_to?(:id) and kitten_cfg['parent'].id
231
+ kitten_cfg['name'] = kitten_cfg['name']+kitten_cfg['parent'].id
232
+ elsif kitten_cfg['project']
233
+ kitten_cfg['name'] = kitten_cfg['name']+kitten_cfg['project']
234
+ elsif kitten_cfg['cloud_id']
235
+ kitten_cfg['name'] = kitten_cfg['name']+kitten_cfg['cloud_id'].gsub(/[^a-z0-9]/i, "-")
236
+ else
237
+ raise MU::Config::DuplicateNameError, "Saw duplicate #{res_class.cfg_name} name #{sibling['name']} and couldn't come up with a good way to differentiate them"
238
+ end
239
+ MU.log "De-duplication: Renamed #{res_class.cfg_name} name '#{sibling['name']}' => '#{kitten_cfg['name']}'", MU::NOTICE
240
+ break
241
+ end
242
+ }
243
+ }
244
+ }
245
+ }
246
+
247
+ # No matching resources isn't necessarily an error
248
+ next if count == 0 or bok.nil?
249
+
250
+ # Now walk through all of the Refs in these objects, resolve them, and minimize
251
+ # their config footprint
252
+ MU.log "Minimizing footprint of #{count.to_s} found resources", MU::DEBUG
253
+ @boks[bok['appname']] = vacuum(bok, origin: origin, save: @savedeploys)
254
+
255
+ if @diff and !deploy
256
+ MU.log "diff flag set, but no comparable deploy provided for #{bok['appname']}", MU::ERR
257
+ exit 1
258
+ end
259
+
260
+ if deploy and @diff
261
+ prevcfg = MU::Config.manxify(vacuum(deploy.original_config, deploy: deploy))
262
+ if !prevcfg
263
+ MU.log "#{deploy.deploy_id} didn't have a working original config for me to compare", MU::ERR
264
+ exit 1
265
+ end
266
+ newcfg = MU::Config.manxify(@boks[bok['appname']])
267
+
268
+ prevcfg.diff(newcfg)
269
+ exit
270
+ end
271
+ }
272
+ @boks
273
+ end
274
+
275
+ private
276
+
277
+ # Recursively walk through a BoK hash, validate all {MU::Config::Ref}
278
+ # objects, convert them to hashes, and pare them down to the minimal
279
+ # representation (remove extraneous attributes that match the parent
280
+ # object).
281
+ # Do the same for our main objects: if they all use the same credentials,
282
+ # for example, remove the explicit +credentials+ attributes and set that
283
+ # value globally, once.
284
+ def vacuum(bok, origin: nil, save: false, deploy: nil)
285
+ deploy ||= generateStubDeploy(bok)
286
+
287
+ globals = {
288
+ 'cloud' => {},
289
+ 'credentials' => {},
290
+ 'region' => {},
291
+ 'billing_acct' => {},
292
+ 'us_only' => {},
293
+ }
294
+ clouds = {}
295
+ credentials = {}
296
+ regions = {}
297
+ MU::Cloud.resource_types.each_pair { |typename, attrs|
298
+ if bok[attrs[:cfg_plural]]
299
+ processed = []
300
+ bok[attrs[:cfg_plural]].each { |resource|
301
+ globals.each_pair { |field, counts|
302
+ if resource[field]
303
+ counts[resource[field]] ||= 0
304
+ counts[resource[field]] += 1
305
+ end
306
+ }
307
+ obj = deploy.findLitterMate(type: attrs[:cfg_plural], name: resource['name'])
308
+ begin
309
+ processed << resolveReferences(resource, deploy, obj)
310
+ rescue Incomplete
311
+ end
312
+ resource.delete("cloud_id")
313
+ }
314
+ deploy.original_config[attrs[:cfg_plural]] = processed
315
+ bok[attrs[:cfg_plural]] = processed
316
+ end
317
+ }
318
+
319
+ # Pare out global values like +cloud+ or +region+ that appear to be
320
+ # universal in the deploy we're creating.
321
+ def scrub_globals(h, field)
322
+ if h.is_a?(Hash)
323
+ newhash = {}
324
+ h.each_pair { |k, v|
325
+ next if k == field
326
+ newhash[k] = scrub_globals(v, field)
327
+ }
328
+ h = newhash
329
+ elsif h.is_a?(Array)
330
+ newarr = []
331
+ h.each { |v|
332
+ newarr << scrub_globals(v, field)
333
+ }
334
+ h = newarr
335
+ end
336
+
337
+ h
338
+ end
339
+
340
+ globals.each_pair { |field, counts|
341
+ next if counts.size != 1
342
+ bok[field] = counts.keys.first
343
+ MU.log "Setting global default #{field} to #{bok[field]} (#{deploy.deploy_id})", MU::DEBUG
344
+ MU::Cloud.resource_types.each_pair { |typename, attrs|
345
+ if bok[attrs[:cfg_plural]]
346
+ new_resources = []
347
+ bok[attrs[:cfg_plural]].each { |resource|
348
+ new_resources << scrub_globals(resource, field)
349
+ }
350
+ bok[attrs[:cfg_plural]] = new_resources
351
+ end
352
+ }
353
+ }
354
+
355
+ if save
356
+ MU.log "Committing adopted deployment to #{MU.dataDir}/deployments/#{deploy.deploy_id}", MU::NOTICE, details: origin
357
+ deploy.save!(force: true, origin: origin)
358
+ end
359
+
360
+ bok
361
+ end
362
+
363
+ def resolveReferences(cfg, deploy, parent)
364
+ if cfg.is_a?(MU::Config::Ref)
365
+ hashcfg = cfg.to_h
366
+ if cfg.kitten(deploy)
367
+ littermate = deploy.findLitterMate(type: cfg.type, name: cfg.name, cloud_id: cfg.id, habitat: cfg.habitat)
368
+ if littermate and littermate.config['name']
369
+ hashcfg['name'] = littermate.config['name']
370
+ hashcfg.delete("id") if hashcfg["name"]
371
+ hashcfg
372
+ elsif cfg.deploy_id and cfg.name and @savedeploys
373
+ hashcfg.delete("id") if hashcfg["name"]
374
+ hashcfg
375
+ elsif cfg.id
376
+ littermate = deploy.findLitterMate(type: cfg.type, cloud_id: cfg.id, habitat: cfg.habitat)
377
+ if littermate and littermate.config['name']
378
+ hashcfg['name'] = littermate.config['name']
379
+ hashcfg.delete("id") if hashcfg["name"]
380
+ elsif !@savedeploys
381
+ hashcfg.delete("deploy_id")
382
+ hashcfg.delete("name")
383
+ else
384
+ hashcfg.delete("name") if cfg.id and !cfg.deploy_id
385
+ end
386
+ end
387
+ elsif hashcfg["id"] # reference to raw cloud ids is reasonable
388
+ hashcfg.delete("deploy_id")
389
+ hashcfg.delete("name")
390
+ else
391
+ pp parent.cloud_desc
392
+ raise Incomplete, "Failed to resolve reference on behalf of #{parent}"
393
+ end
394
+ hashcfg.delete("deploy_id") if hashcfg['deploy_id'] == deploy.deploy_id
395
+ cfg = hashcfg
396
+ elsif cfg.is_a?(Hash)
397
+ deletia = []
398
+ cfg.each_pair { |key, value|
399
+ begin
400
+ cfg[key] = resolveReferences(value, deploy, parent)
401
+ rescue Incomplete
402
+ MU.log "Dropping unresolved key #{key}", MU::WARN, details: cfg
403
+ deletia << key
404
+ end
405
+ }
406
+ deletia.each { |key|
407
+ cfg.delete(key)
408
+ }
409
+ cfg = nil if cfg.empty? and deletia.size > 0
410
+ elsif cfg.is_a?(Array)
411
+ new_array = []
412
+ cfg.each { |value|
413
+ begin
414
+ new_item = resolveReferences(value, deploy, parent)
415
+ if !new_item
416
+ MU.log "Dropping unresolved value", MU::WARN, details: value
417
+ else
418
+ new_array << new_item
419
+ end
420
+ rescue Incomplete
421
+ MU.log "Dropping unresolved value", MU::WARN, details: value
422
+ end
423
+ }
424
+ cfg = new_array
425
+ end
426
+
427
+ cfg
428
+ end
429
+
430
+ # @return [MU::MommaCat]
431
+ def generateStubDeploy(bok)
432
+ # hashify Ref objects before passing into here... or do we...?
433
+
434
+ time = Time.new
435
+ timestamp = time.strftime("%Y%m%d%H").to_s;
436
+ timestamp.freeze
437
+
438
+ retries = 0
439
+ deploy_id = nil
440
+ seed = nil
441
+ begin
442
+ raise MuError, "Failed to allocate an unused MU-ID after #{retries} tries!" if retries > 70
443
+ seedsize = 1 + (retries/10).abs
444
+ seed = (0...seedsize+1).map { ('a'..'z').to_a[rand(26)] }.join
445
+ deploy_id = bok['appname'].upcase + "-ADOPT-" + timestamp + "-" + seed.upcase
446
+ end while MU::MommaCat.deploy_exists?(deploy_id) or seed == "mu" or seed[0] == seed[1]
447
+
448
+ MU.setVar("deploy_id", deploy_id)
449
+ MU.setVar("appname", bok['appname'].upcase)
450
+ MU.setVar("environment", "ADOPT")
451
+ MU.setVar("timestamp", timestamp)
452
+ MU.setVar("seed", seed)
453
+ MU.setVar("handle", MU::MommaCat.generateHandle(seed))
454
+
455
+ deploy = MU::MommaCat.new(
456
+ deploy_id,
457
+ create: true,
458
+ config: bok,
459
+ environment: "adopt",
460
+ appname: bok['appname'].upcase,
461
+ timestamp: timestamp,
462
+ nocleanup: true,
463
+ no_artifacts: !(@savedeploys),
464
+ set_context_to_me: true,
465
+ mu_user: MU.mu_user
466
+ )
467
+
468
+ MU::Cloud.resource_types.each_pair { |typename, attrs|
469
+ if bok[attrs[:cfg_plural]]
470
+ bok[attrs[:cfg_plural]].each { |kitten|
471
+
472
+ if !@scraped[typename][kitten['cloud_id']]
473
+ MU.log "No object in scraped tree for #{attrs[:cfg_name]} #{kitten['cloud_id']} (#{kitten['name']})", MU::ERR, details: kitten
474
+ next
475
+ end
476
+
477
+ MU.log "Inserting #{attrs[:cfg_name]} #{kitten['name']} (#{kitten['cloud_id']}) into stub deploy", MU::DEBUG, details: @scraped[typename][kitten['cloud_id']]
478
+
479
+ @scraped[typename][kitten['cloud_id']].config!(kitten)
480
+
481
+ deploy.addKitten(
482
+ attrs[:cfg_plural],
483
+ kitten['name'],
484
+ @scraped[typename][kitten['cloud_id']]
485
+ )
486
+ }
487
+ end
488
+ }
489
+
490
+ deploy
491
+ end
492
+
493
+ # Go through everything we've scraped and update our mappings of cloud ids
494
+ # and bare name fields, so that resources can reference one another
495
+ # portably by name.
496
+ def catalogResources
497
+ end
498
+
499
+ end
500
+ end