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
@@ -28,6 +28,24 @@ module MU
28
28
 
29
29
  @@creds_loaded = {}
30
30
 
31
+ # Module used by {MU::Cloud} to insert additional instance methods into
32
+ # instantiated resources in this cloud layer.
33
+ module AdditionalResourceMethods
34
+ end
35
+
36
+ # A hook that is always called just before any of the instance method of
37
+ # our resource implementations gets invoked, so that we can ensure that
38
+ # repetitive setup tasks (like resolving +:resource_group+ for Azure
39
+ # resources) have always been done.
40
+ # @param cloudobj [MU::Cloud]
41
+ # @param deploy [MU::MommaCat]
42
+ def self.resourceInitHook(cloudobj, deploy)
43
+ class << self
44
+ attr_reader :cloudformation_data
45
+ end
46
+ cloudobj.instance_variable_set(:@cloudformation_data, {})
47
+ end
48
+
31
49
  # Load some credentials for using the AWS API
32
50
  # @param name [String]: The name of the mu.yaml AWS credential set to use. If not specified, will use the default credentials, and set the global Aws.config credentials to those.
33
51
  # @return [Aws::Credentials]
@@ -110,7 +128,7 @@ module MU
110
128
  else
111
129
  MU.log "AWS credentials vault:item #{cred_cfg["credentials"]} specified, but is missing access_key or access_secret elements", MU::WARN
112
130
  end
113
- rescue MU::Groomer::Chef::MuNoSuchSecret
131
+ rescue MU::Groomer::MuNoSuchSecret
114
132
  MU.log "AWS credentials vault:item #{cred_cfg["credentials"]} specified, but does not exist", MU::WARN
115
133
  end
116
134
  end
@@ -145,39 +163,99 @@ module MU
145
163
  # Given an AWS region, check the API to make sure it's a valid one
146
164
  # @param r [String]
147
165
  # @return [String]
148
- def self.validate_region(r)
149
- MU::Cloud::AWS.ec2(region: r).describe_availability_zones.availability_zones.first.region_name
166
+ def self.validate_region(r, credentials: nil)
167
+ begin
168
+ MU::Cloud::AWS.ec2(region: r, credentials: credentials).describe_availability_zones.availability_zones.first.region_name
169
+ rescue ::Aws::EC2::Errors::UnauthorizedOperation => e
170
+ MU.log "Got '#{e.message}' trying to validate region #{r} (hosted: #{hosted?.to_s})", MU::ERR, details: loadCredentials(credentials)
171
+ raise MuError, "Got '#{e.message}' trying to validate region #{r} with credentials #{credentials ? credentials : "<default>"} (hosted: #{hosted?.to_s})"
172
+ end
173
+ end
174
+
175
+ # Tag a resource with all of our standard identifying tags.
176
+ #
177
+ # @param resource [String]: The cloud provider identifier of the resource to tag
178
+ # @param region [String]: The cloud provider region
179
+ # @return [void]
180
+ def self.createStandardTags(resource = nil, region: MU.curRegion, credentials: nil)
181
+ tags = []
182
+ MU::MommaCat.listStandardTags.each_pair { |name, value|
183
+ if !value.nil?
184
+ tags << {key: name, value: value}
185
+ end
186
+ }
187
+ if MU::Cloud::CloudFormation.emitCloudFormation
188
+ return tags
189
+ end
190
+
191
+ attempts = 0
192
+ begin
193
+ MU::Cloud::AWS.ec2(region: region, credentials: credentials).create_tags(
194
+ resources: [resource],
195
+ tags: tags
196
+ )
197
+ rescue Aws::EC2::Errors::ServiceError => e
198
+ MU.log "Got #{e.inspect} tagging #{resource} in #{region}, will retry", MU::WARN, details: caller.concat(tags) if attempts > 1
199
+ if attempts < 5
200
+ attempts = attempts + 1
201
+ sleep 15
202
+ retry
203
+ else
204
+ raise e
205
+ end
206
+ end
207
+ MU.log "Created standard tags for resource #{resource}", MU::DEBUG, details: caller
208
+ end
209
+
210
+ # If we reside in this cloud, return the VPC in which we, the Mu Master, reside.
211
+ # @return [MU::Cloud::VPC]
212
+ def self.myVPCObj
213
+ return nil if !hosted?
214
+ instance = MU.myCloudDescriptor
215
+ return nil if !instance or !instance.vpc_id
216
+ vpc = MU::MommaCat.findStray("AWS", "vpc", cloud_id: instance.vpc_id, dummy_ok: true)
217
+ return nil if vpc.nil? or vpc.size == 0
218
+ vpc.first
150
219
  end
151
220
 
152
221
  # If we've configured AWS as a provider, or are simply hosted in AWS,
153
222
  # decide what our default region is.
154
- def self.myRegion
223
+ def self.myRegion(credentials = nil)
155
224
  return @@myRegion_var if @@myRegion_var
156
225
 
157
226
  if credConfig.nil? and !hosted? and !ENV['EC2_REGION']
158
227
  return nil
159
228
  end
160
229
 
161
-
162
230
  if $MU_CFG and $MU_CFG['aws']
163
231
  $MU_CFG['aws'].each_pair { |credset, cfg|
232
+ next if credentials and credset != credentials
164
233
  next if !cfg['region']
165
- if (cfg['default'] or !@@myRegion_var) and validate_region(cfg['region'])
234
+ if (cfg['default'] or !@@myRegion_var) and validate_region(cfg['region'], credentials: credset)
166
235
  @@myRegion_var = cfg['region']
167
- break if cfg['default']
236
+ break if cfg['default'] or credentials
168
237
  end
169
238
  }
170
239
  elsif ENV.has_key?("EC2_REGION") and !ENV['EC2_REGION'].empty? and
171
- validate_region(ENV['EC2_REGION'])
240
+ validate_region(ENV['EC2_REGION']) and
241
+ (
242
+ (ENV.has_key?("AWS_SECRET_ACCESS_KEY") and ENV.has_key?("AWS_SECRET_ACCESS_KEY") ) or
243
+ (Aws.config['access_key'] and Aws.config['access_secret'])
244
+ )
172
245
  # Make sure this string is valid by way of the API
173
246
  @@myRegion_var = ENV['EC2_REGION']
174
- else
247
+ end
248
+
249
+ if hosted? and !@@myRegion_var
175
250
  # hacky, but useful in a pinch (and if we're hosted in AWS)
176
251
  az_str = MU::Cloud::AWS.getAWSMetaData("placement/availability-zone")
177
252
  @@myRegion_var = az_str.sub(/[a-z]$/i, "") if az_str
178
253
  end
254
+
255
+ @@myRegion_var
179
256
  end
180
257
 
258
+
181
259
  # Is the region we're dealing with a GovCloud region?
182
260
  # @param region [String]: The region in question, defaults to the Mu Master's local region
183
261
  def self.isGovCloud?(region = myRegion)
@@ -247,9 +325,8 @@ module MU
247
325
  # @param region [String]: The region to search.
248
326
  # @return [Array<String>]: The Availability Zones in this region.
249
327
  def self.listAZs(region: MU.curRegion, account: nil, credentials: nil)
250
- if $MU_CFG and (!$MU_CFG['aws'] or !account_number)
251
- return []
252
- end
328
+ cfg = credConfig(credentials)
329
+ return [] if !cfg
253
330
  if !region.nil? and @@azs[region]
254
331
  return @@azs[region]
255
332
  end
@@ -265,6 +342,18 @@ module MU
265
342
  return @@azs[region]
266
343
  end
267
344
 
345
+ # Do cloud-specific deploy instantiation tasks, such as copying SSH keys
346
+ # around, sticking secrets in buckets, creating resource groups, etc
347
+ # @param deploy [MU::MommaCat]
348
+ def self.initDeploy(deploy)
349
+ end
350
+
351
+ # Purge cloud-specific deploy meta-artifacts (SSH keys, resource groups,
352
+ # etc)
353
+ # @param deploy_id [MU::MommaCat]
354
+ def self.cleanDeploy(deploy_id, credentials: nil, noop: false)
355
+ end
356
+
268
357
  # Plant a Mu deploy secret into a storage bucket somewhere for so our kittens can consume it
269
358
  # @param deploy_id [String]: The deploy for which we're writing the secret
270
359
  # @param value [String]: The contents of the secret
@@ -346,6 +435,14 @@ module MU
346
435
  instance_id = open("http://169.254.169.254/latest/meta-data/instance-id").read
347
436
  if !instance_id.nil? and instance_id.size > 0
348
437
  @@is_in_aws = true
438
+ region = getAWSMetaData("placement/availability-zone").sub(/[a-z]$/i, "")
439
+ begin
440
+ validate_region(region)
441
+ rescue MuError
442
+ @@creds_loaded.delete("#default")
443
+ @@is_in_aws = false
444
+ false
445
+ end
349
446
  return true
350
447
  end
351
448
  end
@@ -384,6 +481,16 @@ module MU
384
481
  sample
385
482
  end
386
483
 
484
+ # Return what we think of as a cloud object's habitat. In AWS, this means
485
+ # the +account_number+ in which it's resident. If this is not applicable,
486
+ # such as for a {Habitat} or {Folder}, returns nil.
487
+ # @param cloudobj [MU::Cloud::AWS]: The resource from which to extract the habitat id
488
+ # @return [String,nil]
489
+ def self.habitat(cloudobj, nolookup: false, deploy: nil)
490
+ cloudobj.respond_to?(:account_number) ? cloudobj.account_number : nil
491
+ end
492
+
493
+
387
494
  @@my_acct_num = nil
388
495
  @@my_hosted_cfg = nil
389
496
  @@acct_to_profile_map = {}
@@ -415,8 +522,29 @@ module MU
415
522
  # @param credentials [String]
416
523
  # @return [String]
417
524
  def self.adminBucketName(credentials = nil)
418
- #XXX find a default if this particular account doesn't have a log_bucket_name configured
419
525
  cfg = credConfig(credentials)
526
+ return nil if !cfg
527
+ if !cfg['log_bucket_name']
528
+ cfg['log_bucket_name'] = $MU_CFG['hostname']
529
+ MU.log "No AWS log bucket defined for credentials #{credentials}, attempting to use default of #{cfg['log_bucket_name']}", MU::WARN
530
+ end
531
+ resp = MU::Cloud::AWS.s3(credentials: credentials).list_buckets
532
+ found = false
533
+ resp.buckets.each { |b|
534
+ if b.name == cfg['log_bucket_name']
535
+ found = true
536
+ break
537
+ end
538
+ }
539
+ if !found
540
+ MU.log "Attempting to create log bucket #{cfg['log_bucket_name']} for credentials #{credentials}", MU::WARN
541
+ begin
542
+ resp = MU::Cloud::AWS.s3(credentials: credentials).create_bucket(bucket: cfg['log_bucket_name'], acl: "private")
543
+ rescue Aws::S3::Errors::BucketAlreadyExists => e
544
+ raise MuError, "AWS credentials #{credentials} need a log bucket, and the name #{cfg['log_bucket_name']} is unavailable. Use mu-configure to edit credentials '#{credentials}' or 'hostname'"
545
+ end
546
+ end
547
+
420
548
  cfg['log_bucket_name']
421
549
  end
422
550
 
@@ -425,7 +553,8 @@ module MU
425
553
  # @param credentials [String]
426
554
  # @return [String]
427
555
  def self.adminBucketUrl(credentials = nil)
428
- "s3://"+adminBucketName+"/"
556
+ return nil if !credConfig(credentials)
557
+ "s3://"+adminBucketName(credentials)+"/"
429
558
  end
430
559
 
431
560
  # Return the $MU_CFG data associated with a particular profile/name/set of
@@ -439,7 +568,9 @@ module MU
439
568
  # on a machine hosted in AWS, *and* that machine has an IAM profile,
440
569
  # fake it with those credentials and hope for the best.
441
570
  if !$MU_CFG['aws'] or !$MU_CFG['aws'].is_a?(Hash) or $MU_CFG['aws'].size == 0
442
- return @@my_hosted_cfg if @@my_hosted_cfg
571
+ if @@my_hosted_cfg
572
+ return name_only ? "#default" : @@my_hosted_cfg
573
+ end
443
574
 
444
575
  if hosted?
445
576
  begin
@@ -464,9 +595,9 @@ module MU
464
595
  end
465
596
 
466
597
  if name.nil?
467
- $MU_CFG['aws'].each_pair { |name, cfg|
598
+ $MU_CFG['aws'].each_pair { |set, cfg|
468
599
  if cfg['default']
469
- return name_only ? name : cfg
600
+ return name_only ? set : cfg
470
601
  end
471
602
  }
472
603
  else
@@ -496,7 +627,6 @@ module MU
496
627
  cfg['account_number'] = acct_num.to_s
497
628
  @@acct_to_profile_map[name.to_s] = cfg
498
629
  return name_only ? name.to_s : cfg
499
- return cfg
500
630
  end
501
631
  }
502
632
  end
@@ -1026,10 +1156,14 @@ module MU
1026
1156
  # @return [void]
1027
1157
  def self.openFirewallForClients
1028
1158
  MU::Cloud.loadCloudType("AWS", :FirewallRule)
1029
- if File.exists?(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
1030
- ::Chef::Config.from_file(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
1159
+ begin
1160
+ if File.exist?(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
1161
+ ::Chef::Config.from_file(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
1162
+ end
1163
+ ::Chef::Config[:environment] = MU.environment
1164
+ rescue LoadError
1165
+ # XXX why is Chef here
1031
1166
  end
1032
- ::Chef::Config[:environment] = MU.environment
1033
1167
 
1034
1168
  # This is the set of (TCP) ports we're opening to clients. We assume that
1035
1169
  # we can and and remove these without impacting anything a human has
@@ -1218,8 +1352,6 @@ module MU
1218
1352
 
1219
1353
  MU.log "Initializing #{api} object with credentials #{credentials}", MU::DEBUG, details: params
1220
1354
  @api = Object.const_get("Aws::#{api}::Client").new(params)
1221
-
1222
- @api
1223
1355
  end
1224
1356
 
1225
1357
  @instance_cache = {}
@@ -1239,7 +1371,7 @@ module MU
1239
1371
  retval = @api.method(method_sym).call
1240
1372
  end
1241
1373
  return retval
1242
- 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 => e
1374
+ 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 => e
1243
1375
  if e.class.name == "Seahorse::Client::NetworkingError" and e.message.match(/Name or service not known/)
1244
1376
  MU.log e.inspect, MU::ERR
1245
1377
  raise e
@@ -17,21 +17,11 @@ module MU
17
17
  class AWS
18
18
  # A alarm as configured in {MU::Config::BasketofKittens::alarms}
19
19
  class Alarm < MU::Cloud::Alarm
20
- @deploy = nil
21
- @config = nil
22
- attr_reader :mu_name
23
- attr_reader :config
24
- attr_reader :cloud_id
25
20
 
26
- @cloudformation_data = {}
27
- attr_reader :cloudformation_data
28
-
29
- # @param mommacat [MU::MommaCat]: A {MU::Mommacat} object containing the deploy of which this resource is/will be a member.
30
- # @param kitten_cfg [Hash]: The fully parsed and resolved {MU::Config} resource descriptor as defined in {MU::Config::BasketofKittens::alarms}
31
- def initialize(mommacat: nil, kitten_cfg: nil, mu_name: nil, cloud_id: nil)
32
- @deploy = mommacat
33
- @config = MU::Config.manxify(kitten_cfg)
34
- @cloud_id ||= cloud_id
21
+ # Initialize this cloud resource object. Calling +super+ will invoke the initializer defined under {MU::Cloud}, which should set the attribtues listed in {MU::Cloud::PUBLIC_ATTRS} as well as applicable dependency shortcuts, like +@vpc+, for us.
22
+ # @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
23
+ def initialize(**args)
24
+ super
35
25
  @mu_name ||= @deploy.getResourceName(@config["name"])
36
26
  end
37
27
 
@@ -17,22 +17,14 @@ module MU
17
17
  class AWS
18
18
  # Support for AWS S3
19
19
  class Bucket < MU::Cloud::Bucket
20
- @deploy = nil
21
- @config = nil
22
20
 
23
21
  @@region_cache = {}
24
22
  @@region_cache_semaphore = Mutex.new
25
23
 
26
- attr_reader :mu_name
27
- attr_reader :config
28
- attr_reader :cloud_id
29
-
30
- # @param mommacat [MU::MommaCat]: A {MU::Mommacat} object containing the deploy of which this resource is/will be a member.
31
- # @param kitten_cfg [Hash]: The fully parsed and resolved {MU::Config} resource descriptor as defined in {MU::Config::BasketofKittens::logs}
32
- def initialize(mommacat: nil, kitten_cfg: nil, mu_name: nil, cloud_id: nil)
33
- @deploy = mommacat
34
- @config = MU::Config.manxify(kitten_cfg)
35
- @cloud_id ||= cloud_id
24
+ # Initialize this cloud resource object. Calling +super+ will invoke the initializer defined under {MU::Cloud}, which should set the attribtues listed in {MU::Cloud::PUBLIC_ATTRS} as well as applicable dependency shortcuts, like +@vpc+, for us.
25
+ # @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
26
+ def initialize(**args)
27
+ super
36
28
  @mu_name ||= @deploy.getResourceName(@config["name"])
37
29
  end
38
30
 
@@ -145,6 +137,51 @@ module MU
145
137
  end
146
138
  end
147
139
 
140
+ # Upload a file to a bucket.
141
+ # @param url [String]: Target URL, of the form s3://bucket/folder/file
142
+ # @param acl [String]: Canned ACL permission to assign to the object we upload
143
+ # @param file [String]: Path to a local file to write to our target location. One of +file+ or +data+ must be specified.
144
+ # @param data [String]: Data to write to our target location. One of +file+ or +data+ must be specified.
145
+ def self.upload(url, acl: "private", file: nil, data: nil, credentials: nil, region: nil)
146
+ if (!file or file.empty?) and !data
147
+ raise MuError, "Must specify a file or some data to upload to bucket #{s3_url}"
148
+ end
149
+
150
+ if file and !file.empty?
151
+ if !File.exist?(file) or !File.readable?(file)
152
+ raise MuError, "Unable to read #{file} for upload to #{url}"
153
+ else
154
+ data = File.read(file)
155
+ end
156
+ end
157
+
158
+ url.match(/^(?:s3:\/\/)([^\/:]+?)[\/:]\/?(.+)?/)
159
+ bucket = Regexp.last_match[1]
160
+ path = Regexp.last_match[2]
161
+ if !path
162
+ if !file
163
+ raise MuError, "Unable to determine upload path from url #{url}"
164
+ end
165
+ end
166
+
167
+ begin
168
+ puts data
169
+ puts acl
170
+ puts bucket
171
+ puts path
172
+ MU.log "Writing #{path} to S3 bucket #{bucket}"
173
+ MU::Cloud::AWS.s3(region: region, credentials: credentials).put_object(
174
+ acl: acl,
175
+ bucket: bucket,
176
+ key: path,
177
+ body: data
178
+ )
179
+ rescue Aws::S3::Errors => e
180
+ raise MuError, "Got #{e.inspect} trying to write #{path} to #{bucket} (region: #{region}, credentials: #{credentials})"
181
+ end
182
+
183
+ end
184
+
148
185
  # Does this resource type exist as a global (cloud-wide) artifact, or
149
186
  # is it localized to a region/zone?
150
187
  # @return [Boolean]
@@ -172,13 +209,18 @@ module MU
172
209
  if @@region_cache[bucket.name]
173
210
  next if @@region_cache[bucket.name] != region
174
211
  else
175
- location = MU::Cloud::AWS.s3(credentials: credentials, region: region).get_bucket_location(bucket: bucket.name).location_constraint
176
-
177
- if location.nil? or location.empty?
178
- @@region_cache[bucket.name] = region
179
- else
180
- @@region_cache[bucket.name] = location
212
+ begin
213
+ location = MU::Cloud::AWS.s3(credentials: credentials, region: region).get_bucket_location(bucket: bucket.name).location_constraint
214
+ if location.nil? or location.empty?
215
+ @@region_cache[bucket.name] = region
216
+ else
217
+ @@region_cache[bucket.name] = location
218
+ end
219
+ rescue Aws::S3::Errors::AccessDenied => e
220
+ # this is routine- we saw a bucket that's not our business
221
+ next
181
222
  end
223
+
182
224
  end
183
225
  }
184
226
 
@@ -17,23 +17,11 @@ module MU
17
17
  class AWS
18
18
  # A cache cluster as configured in {MU::Config::BasketofKittens::cache_clusters}
19
19
  class CacheCluster < MU::Cloud::CacheCluster
20
- @deploy = nil
21
- @config = nil
22
- attr_reader :mu_name
23
- attr_reader :cloud_id
24
- attr_reader :config
25
-
26
- @cloudformation_data = {}
27
- attr_reader :cloudformation_data
28
-
29
- # @param mommacat [MU::MommaCat]: A {MU::Mommacat} object containing the deploy of which this resource is/will be a member.
30
- # @param kitten_cfg [Hash]: The fully parsed and resolved {MU::Config} resource descriptor as defined in {MU::Config::BasketofKittens::cache_clusters}
31
- def initialize(mommacat: nil, kitten_cfg: nil, mu_name: nil, cloud_id: nil)
32
- @deploy = mommacat
33
- @config = MU::Config.manxify(kitten_cfg)
34
- @cloud_id ||= cloud_id
35
- # @mu_name = mu_name ? mu_name : @deploy.getResourceName(@config["name"])
36
20
 
21
+ # Initialize this cloud resource object. Calling +super+ will invoke the initializer defined under {MU::Cloud}, which should set the attribtues listed in {MU::Cloud::PUBLIC_ATTRS} as well as applicable dependency shortcuts, like +@vpc+, for us.
22
+ # @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
23
+ def initialize(**args)
24
+ super
37
25
  @mu_name ||=
38
26
  if @config["create_replication_group"]
39
27
  @deploy.getResourceName(@config["name"], max_length: 16, need_unique_string: true)
@@ -194,8 +182,8 @@ module MU
194
182
  waiter.before_attempt do |attempts|
195
183
  MU.log "Waiting for cache replication group #{@config['identifier']} to become available", MU::NOTICE if attempts % 5 == 0
196
184
  end
197
- waiter.before_wait do |attempts, resp|
198
- throw :success if resp.replication_groups.first.status == "available"
185
+ waiter.before_wait do |attempts, r|
186
+ throw :success if r.replication_groups.first.status == "available"
199
187
  throw :failure if Time.now - wait_start_time > 1800
200
188
  end
201
189
  end
@@ -251,8 +239,8 @@ module MU
251
239
  waiter.before_attempt do |attempts|
252
240
  MU.log "Waiting for cache cluster #{@config['identifier']} to become available", MU::NOTICE if attempts % 5 == 0
253
241
  end
254
- waiter.before_wait do |attempts, resp|
255
- throw :success if resp.cache_clusters.first.cache_cluster_status == "available"
242
+ waiter.before_wait do |attempts, r|
243
+ throw :success if r.cache_clusters.first.cache_cluster_status == "available"
256
244
  throw :failure if Time.now - wait_start_time > 1800
257
245
  end
258
246
  end