cloud-mu 2.1.0beta → 3.0.0beta

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -20,21 +20,11 @@ module MU
20
20
  # An Amazon CloudFormation stack as configured in {MU::Config::BasketofKittens::collections}
21
21
  class Collection < MU::Cloud::Collection
22
22
 
23
- @deploy = nil
24
- @config = nil
25
- attr_reader :mu_name
26
- attr_reader :cloud_id
27
-
28
- # @param mommacat [MU::MommaCat]: A {MU::Mommacat} object containing the deploy of which this resource is/will be a member.
29
- # @param kitten_cfg [Hash]: The fully parsed and resolved {MU::Config} resource descriptor as defined in {MU::Config::BasketofKittens::vpcs}
30
- def initialize(mommacat: nil, kitten_cfg: nil, mu_name: nil, cloud_id: nil)
31
- @deploy = mommacat
32
- @config = MU::Config.manxify(kitten_cfg)
33
- if !mu_name.nil?
34
- @mu_name = mu_name
35
- else
36
- @mu_name = @deploy.getResourceName(@config['name'], need_unique_string: true)
37
- end
23
+ # 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.
24
+ # @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
25
+ def initialize(**args)
26
+ super
27
+ @mu_name ||= @deploy.getResourceName(@config['name'], need_unique_string: true)
38
28
  MU.setVar("curRegion", @config['region']) if !@config['region'].nil?
39
29
  end
40
30
 
@@ -104,7 +94,7 @@ module MU
104
94
  else
105
95
  # json file and template path is same
106
96
  file_dir =File.dirname(ARGV[0])
107
- if File.exists? file_dir+"/"+@config["template_file"] then
97
+ if File.exist? file_dir+"/"+@config["template_file"] then
108
98
  template_body=File.read(file_dir+"/"+@config["template_file"]);
109
99
  end
110
100
  end
@@ -158,7 +148,7 @@ module MU
158
148
 
159
149
  case resource.resource_type
160
150
  when "AWS::EC2::Instance"
161
- MU::MommaCat.createStandardTags(resource.physical_resource_id)
151
+ MU::Cloud::AWS.createStandardTags(resource.physical_resource_id)
162
152
  instance_name = MU.deploy_id+"-"+@config['name']+"-"+resource.logical_resource_id
163
153
  MU::MommaCat.createTag(resource.physical_resource_id, "Name", instance_name, credentials: @config['credentials'])
164
154
 
@@ -186,14 +176,14 @@ module MU
186
176
  end
187
177
 
188
178
  when "AWS::EC2::SecurityGroup"
189
- MU::MommaCat.createStandardTags(resource.physical_resource_id)
179
+ MU::Cloud::AWS.createStandardTags(resource.physical_resource_id)
190
180
  MU::MommaCat.createTag(resource.physical_resource_id, "Name", MU.deploy_id+"-"+@config['name']+'-'+resource.logical_resource_id, credentials: @config['credentials'])
191
181
  MU::Cloud::AWS::FirewallRule.notifyDeploy(
192
182
  @config['name']+"-"+resource.logical_resource_id,
193
183
  resource.physical_resource_id
194
184
  )
195
185
  when "AWS::EC2::Subnet"
196
- MU::MommaCat.createStandardTags(resource.physical_resource_id)
186
+ MU::Cloud::AWS.createStandardTags(resource.physical_resource_id)
197
187
  MU::MommaCat.createTag(resource.physical_resource_id, "Name", MU.deploy_id+"-"+@config['name']+'-'+resource.logical_resource_id, credentials: @config['credentials'])
198
188
  data = {
199
189
  "collection" => @config["name"],
@@ -201,7 +191,7 @@ module MU
201
191
  }
202
192
  @deploy.notify("subnets", @config['name']+"-"+resource.logical_resource_id, data)
203
193
  when "AWS::EC2::VPC"
204
- MU::MommaCat.createStandardTags(resource.physical_resource_id)
194
+ MU::Cloud::AWS.createStandardTags(resource.physical_resource_id)
205
195
  MU::MommaCat.createTag(resource.physical_resource_id, "Name", MU.deploy_id+"-"+@config['name']+'-'+resource.logical_resource_id, credentials: @config['credentials'])
206
196
  data = {
207
197
  "collection" => @config["name"],
@@ -209,10 +199,10 @@ module MU
209
199
  }
210
200
  @deploy.notify("vpcs", @config['name']+"-"+resource.logical_resource_id, data)
211
201
  when "AWS::EC2::InternetGateway"
212
- MU::MommaCat.createStandardTags(resource.physical_resource_id)
202
+ MU::Cloud::AWS.createStandardTags(resource.physical_resource_id)
213
203
  MU::MommaCat.createTag(resource.physical_resource_id, "Name", MU.deploy_id+"-"+@config['name']+'-'+resource.logical_resource_id, credentials: @config['credentials'])
214
204
  when "AWS::EC2::RouteTable"
215
- MU::MommaCat.createStandardTags(resource.physical_resource_id)
205
+ MU::Cloud::AWS.createStandardTags(resource.physical_resource_id)
216
206
  MU::MommaCat.createTag(resource.physical_resource_id, "Name", MU.deploy_id+"-"+@config['name']+'-'+resource.logical_resource_id, credentials: @config['credentials'])
217
207
 
218
208
  # The rest of these aren't anything we act on
@@ -17,26 +17,12 @@ module MU
17
17
  class AWS
18
18
  # A ContainerCluster as configured in {MU::Config::BasketofKittens::container_clusters}
19
19
  class ContainerCluster < MU::Cloud::ContainerCluster
20
- @deploy = nil
21
- @config = nil
22
- attr_reader :mu_name
23
- attr_reader :config
24
- attr_reader :cloud_id
25
-
26
- @cloudformation_data = {}
27
- attr_reader :cloudformation_data
28
- # Return the list of regions where we know EKS is supported.
29
- def self.EKSRegions
30
- # XXX would prefer to query service API for this
31
- ["us-east-1", "us-west-2", "eu-west-1"]
32
- end
33
20
 
34
- # @param mommacat [MU::MommaCat]: A {MU::Mommacat} object containing the deploy of which this resource is/will be a member.
35
- # @param kitten_cfg [Hash]: The fully parsed and resolved {MU::Config} resource descriptor as defined in {MU::Config::BasketofKittens::container_clusters}
36
- def initialize(mommacat: nil, kitten_cfg: nil, mu_name: nil, cloud_id: nil)
37
- @deploy = mommacat
38
- @config = MU::Config.manxify(kitten_cfg)
39
- @cloud_id ||= cloud_id
21
+
22
+ # 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.
23
+ # @param args [Hash]: Hash of named arguments passed via Ruby's double-splat
24
+ def initialize(**args)
25
+ super
40
26
  @mu_name ||= @deploy.getResourceName(@config["name"])
41
27
  end
42
28
 
@@ -101,14 +87,13 @@ module MU
101
87
  retry
102
88
  end
103
89
  rescue Aws::EKS::Errors::InvalidParameterException => e
104
- if e.message.match(/role with arn: #{Regexp.quote(role_arn)}.*?(could not be assumed|does not exist)/)
90
+ if e.message.match(/role with arn: #{Regexp.quote(role_arn)}.*?(could not be assumed|does not exist)/i)
105
91
  sleep 5
106
92
  retry
107
93
  else
108
94
  MU.log e.message, MU::WARN, details: role_arn
109
95
  sleep 5
110
96
  retry
111
- puts e.message
112
97
  end
113
98
  end
114
99
 
@@ -119,6 +104,9 @@ module MU
119
104
  name: @mu_name
120
105
  )
121
106
  status = resp.cluster.status
107
+ if status == "FAILED"
108
+ raise MuError, "EKS cluster #{@mu_name} had FAILED status"
109
+ end
122
110
  if retries > 0 and (retries % 3) == 0 and status != "ACTIVE"
123
111
  MU.log "Waiting for EKS cluster #{@mu_name} to become active (currently #{status})", MU::NOTICE
124
112
  end
@@ -153,8 +141,18 @@ module MU
153
141
  serverpool = @deploy.findLitterMate(type: "server_pools", name: @config["name"]+"workers")
154
142
  resource_lookup = MU::Cloud::AWS.listInstanceTypes(@config['region'])[@config['region']]
155
143
 
156
- if @config['kubernetes']
157
- kube = ERB.new(File.read(MU.myRoot+"/cookbooks/mu-tools/templates/default/kubeconfig.erb"))
144
+ if @config['flavor'] == "EKS"
145
+ # This will be needed if a loadbalancer has never been created in
146
+ # this account; EKS applications might want one, but will fail in
147
+ # confusing ways if this hasn't been done.
148
+ begin
149
+ MU::Cloud::AWS.iam(credentials: @config['credentials']).create_service_linked_role(
150
+ aws_service_name: "elasticloadbalancing.amazonaws.com"
151
+ )
152
+ rescue ::Aws::IAM::Errors::InvalidInput
153
+ end
154
+
155
+ kube = ERB.new(File.read(MU.myRoot+"/cookbooks/mu-tools/templates/default/kubeconfig-eks.erb"))
158
156
  configmap = ERB.new(File.read(MU.myRoot+"/extras/aws-auth-cm.yaml.erb"))
159
157
  tagme = [@vpc.cloud_id]
160
158
  tagme_elb = []
@@ -167,7 +165,7 @@ module MU
167
165
  ).route_tables
168
166
  tagme.concat(rtbs.map { |r| r.route_table_id } )
169
167
  main_sg = @deploy.findLitterMate(type: "firewall_rules", name: "server_pool#{@config['name']}workers")
170
- tagme << main_sg.cloud_id
168
+ tagme << main_sg.cloud_id if main_sg
171
169
  MU.log "Applying kubernetes.io tags to VPC resources", details: tagme
172
170
  MU::Cloud::AWS.createTag("kubernetes.io/cluster/#{@mu_name}", "shared", tagme, credentials: @config['credentials'])
173
171
  MU::Cloud::AWS.createTag("kubernetes.io/cluster/elb", @mu_name, tagme_elb, credentials: @config['credentials'])
@@ -192,38 +190,27 @@ module MU
192
190
  File.open(gitlab_helper, "w"){ |k|
193
191
  k.puts gitlab.result(binding)
194
192
  }
193
+ authmap_cmd = %Q{#{MU::Master.kubectl} --kubeconfig "#{kube_conf}" apply -f "#{eks_auth}"}
195
194
 
196
- authmap_cmd = %Q{/opt/mu/bin/kubectl --kubeconfig "#{kube_conf}" apply -f "#{eks_auth}"}
195
+ authmap_cmd = %Q{#{MU::Master.kubectl} --kubeconfig "#{kube_conf}" apply -f "#{eks_auth}"}
197
196
  MU.log "Configuring Kubernetes <=> IAM mapping for worker nodes", MU::NOTICE, details: authmap_cmd
198
197
  # maybe guard this mess
199
198
  %x{#{authmap_cmd}}
200
199
 
201
200
  # and this one
202
- admin_user_cmd = %Q{/opt/mu/bin/kubectl --kubeconfig "#{kube_conf}" apply -f "#{MU.myRoot}/extras/admin-user.yaml"}
203
- admin_role_cmd = %Q{/opt/mu/bin/kubectl --kubeconfig "#{kube_conf}" apply -f "#{MU.myRoot}/extras/admin-role-binding.yaml"}
201
+ admin_user_cmd = %Q{#{MU::Master.kubectl} --kubeconfig "#{kube_conf}" apply -f "#{MU.myRoot}/extras/admin-user.yaml"}
202
+ admin_role_cmd = %Q{#{MU::Master.kubectl} --kubeconfig "#{kube_conf}" apply -f "#{MU.myRoot}/extras/admin-role-binding.yaml"}
204
203
  MU.log "Configuring Kubernetes admin-user and role", MU::NOTICE, details: admin_user_cmd+"\n"+admin_role_cmd
205
204
  %x{#{admin_user_cmd}}
206
205
  %x{#{admin_role_cmd}}
207
206
 
208
207
  if @config['kubernetes_resources']
209
- count = 0
210
- @config['kubernetes_resources'].each { |blob|
211
- blobfile = @deploy.deploy_dir+"/k8s-resource-#{count.to_s}-#{@config['name']}"
212
- File.open(blobfile, "w") { |f|
213
- f.puts blob.to_yaml
214
- }
215
- %x{/opt/mu/bin/kubectl --kubeconfig "#{kube_conf}" get -f #{blobfile} > /dev/null 2>&1}
216
- arg = $?.exitstatus == 0 ? "replace" : "create"
217
- cmd = %Q{/opt/mu/bin/kubectl --kubeconfig "#{kube_conf}" #{arg} -f #{blobfile}}
218
- MU.log "Applying Kubernetes resource #{count.to_s} with kubectl #{arg}", details: cmd
219
- output = %x{#{cmd} 2>&1}
220
- if $?.exitstatus == 0
221
- MU.log "Kuberentes resource #{count.to_s} #{arg} was successful: #{output}", details: blob.to_yaml
222
- else
223
- MU.log "Kuberentes resource #{count.to_s} #{arg} failed: #{output}", MU::WARN, details: blob.to_yaml
224
- end
225
- count += 1
226
- }
208
+ MU::Master.applyKubernetesResources(
209
+ @config['name'],
210
+ @config['kubernetes_resources'],
211
+ kubeconfig: kube_conf,
212
+ outputdir: @deploy.deploy_dir
213
+ )
227
214
  end
228
215
 
229
216
  MU.log %Q{How to interact with your Kubernetes cluster\nkubectl --kubeconfig "#{kube_conf}" get all\nkubectl --kubeconfig "#{kube_conf}" create -f some_k8s_deploy.yml\nkubectl --kubeconfig "#{kube_conf}" get nodes}, MU::SUMMARY
@@ -329,7 +316,7 @@ module MU
329
316
  created_generic_loggroup = false
330
317
 
331
318
  @config['containers'].each { |c|
332
- service_name = c['service'] ? @mu_name+"-"+c['service'].upcase : @mu_name+"-"+c['name'].upcase
319
+ service_name = c['service'] ? @mu_name+"-"+c['service'].upcase : @mu_name
333
320
  tasks[service_name] ||= []
334
321
  tasks[service_name] << c
335
322
  }
@@ -339,8 +326,10 @@ module MU
339
326
  cpu_total = 0
340
327
  mem_total = 0
341
328
  role_arn = nil
329
+ lbs = []
342
330
 
343
331
  container_definitions = containers.map { |c|
332
+ container_name = @mu_name+"-"+c['name'].upcase
344
333
  cpu_total += c['cpu']
345
334
  mem_total += c['memory']
346
335
 
@@ -362,6 +351,50 @@ module MU
362
351
  raise MuError, "Unable to find execution role from #{c["role"]}"
363
352
  end
364
353
  end
354
+
355
+ if c['loadbalancers'] != []
356
+ c['loadbalancers'].each {|lb|
357
+ found = @deploy.findLitterMate(name: lb['name'], type: "loadbalancer")
358
+ if found
359
+ MU.log "Mapping LB #{found.mu_name} to service #{c['name']}", MU::INFO
360
+ if found.cloud_desc.type != "classic"
361
+ elb_groups = MU::Cloud::AWS.elb2(region: @config['region'], credentials: @config['credentials']).describe_target_groups({
362
+ load_balancer_arn: found.cloud_desc.load_balancer_arn
363
+ })
364
+ matching_target_groups = []
365
+ elb_groups.target_groups.each { |tg|
366
+ if tg.port.to_i == lb['container_port'].to_i
367
+ matching_target_groups << {
368
+ arn: tg['target_group_arn'],
369
+ name: tg['target_group_name']
370
+ }
371
+ end
372
+ }
373
+ if matching_target_groups.length >= 1
374
+ MU.log "#{matching_target_groups.length} matching target groups found. Mapping #{container_name} to target group #{matching_target_groups.first['name']}", MU::INFO
375
+ lbs << {
376
+ container_name: container_name,
377
+ container_port: lb['container_port'],
378
+ target_group_arn: matching_target_groups.first[:arn]
379
+ }
380
+ else
381
+ raise MuError, "No matching target groups found"
382
+ end
383
+ elsif @config['flavor'] == "Fargate" && found.cloud_desc.type == "classic"
384
+ raise MuError, "Classic Load Balancers are not supported with Fargate."
385
+ else
386
+ MU.log "Mapping Classic LB #{found.mu_name} to service #{container_name}", MU::INFO
387
+ lbs << {
388
+ container_name: container_name,
389
+ container_port: lb['container_port'],
390
+ load_balancer_name: found.mu_name
391
+ }
392
+ end
393
+ else
394
+ raise MuError, "Unable to find loadbalancers from #{c["loadbalancers"].first['name']}"
395
+ end
396
+ }
397
+ end
365
398
 
366
399
  params = {
367
400
  name: @mu_name+"-"+c['name'].upcase,
@@ -451,13 +484,13 @@ module MU
451
484
  resp = MU::Cloud::AWS.ecs(region: @config['region'], credentials: @config['credentials']).register_task_definition(task_params)
452
485
 
453
486
  task_def = resp.task_definition.task_definition_arn
454
-
455
487
  service_params = {
456
488
  :cluster => @mu_name,
457
489
  :desired_count => @config['instance_count'], # XXX this makes no sense
458
490
  :service_name => service_name,
459
491
  :launch_type => launch_type,
460
- :task_definition => task_def
492
+ :task_definition => task_def,
493
+ :load_balancers => lbs
461
494
  }
462
495
  if @config['vpc']
463
496
  subnet_ids = []
@@ -651,52 +684,68 @@ MU.log c.name, MU::NOTICE, details: t
651
684
  return deploy_struct
652
685
  end
653
686
 
687
+ @@eks_versions = {}
688
+ @@eks_version_semaphore = Mutex.new
654
689
  # Use the AWS SSM API to fetch the current version of the Amazon Linux
655
690
  # ECS-optimized AMI, so we can use it as a default AMI for ECS deploys.
656
691
  # @param flavor [String]: ECS or EKS
657
- def self.getECSImageId(flavor = "ECS", region = MU.myRegion)
658
- if flavor == "ECS"
659
- resp = MU::Cloud::AWS.ssm(region: region).get_parameters(
692
+ # @param region [String]: Target AWS region
693
+ # @param version [String]: Version of Kubernetes, if +flavor+ is set to +EKS+
694
+ # @param gpu [Boolean]: Whether to request an image with GPU support
695
+ def self.getStandardImage(flavor = "ECS", region = MU.myRegion, version: nil, gpu: false)
696
+ resp = if flavor == "ECS"
697
+ MU::Cloud::AWS.ssm(region: region).get_parameters(
660
698
  names: ["/aws/service/#{flavor.downcase}/optimized-ami/amazon-linux/recommended"]
661
699
  )
662
- if resp and resp.parameters and resp.parameters.size > 0
663
- image_details = JSON.parse(resp.parameters.first.value)
664
- return image_details['image_id']
665
- end
666
- elsif flavor == "EKS"
667
- # XXX this is absurd, but these don't appear to be available from an API anywhere
668
- # Here's their Packer build, should just convert to Chef: https://github.com/awslabs/amazon-eks-ami
669
- amis = {
670
- "us-east-1" => "ami-0abcb9f9190e867ab",
671
- "us-east-2" => "ami-04ea7cb66af82ae4a",
672
- "us-west-2" => "ami-0923e4b35a30a5f53",
673
- "eu-west-1" => "ami-08716b70cac884aaa",
674
- "eu-west-2" => "ami-0c7388116d474ee10",
675
- "eu-west-3" => "ami-0560aea042fec8b12",
676
- "ap-northeast-1" => "ami-0bfedee6a7845c26d",
677
- "ap-northeast-2" => "ami-0a904348b703e620c",
678
- "ap-south-1" => "ami-09c3eb35bb3be46a4",
679
- "ap-southeast-1" => "ami-07b922b9b94d9a6d2",
680
- "ap-southeast-2" => "ami-0f0121e9e64ebd3dc"
700
+ else
701
+ @@eks_version_semaphore.synchronize {
702
+ if !@@eks_versions[region]
703
+ @@eks_versions[region] ||= []
704
+ versions = {}
705
+ resp = nil
706
+ next_token = nil
707
+ begin
708
+ resp = MU::Cloud::AWS.ssm(region: region).get_parameters_by_path(
709
+ path: "/aws/service/#{flavor.downcase}",
710
+ recursive: true,
711
+ next_token: next_token
712
+ )
713
+ resp.parameters.each { |p|
714
+ p.name.match(/\/aws\/service\/eks\/optimized-ami\/([^\/]+?)\//)
715
+ versions[Regexp.last_match[1]] = true
716
+ }
717
+ next_token = resp.next_token
718
+ end while !next_token.nil?
719
+ @@eks_versions[region] = versions.keys.sort { |a, b| MU.version_sort(a, b) }
720
+ end
681
721
  }
682
- return amis[region]
722
+ if !version or version == "latest"
723
+ version = @@eks_versions[region].last
724
+ end
725
+ MU::Cloud::AWS.ssm(region: region).get_parameters(
726
+ names: ["/aws/service/#{flavor.downcase}/optimized-ami/#{version}/amazon-linux-2#{gpu ? "-gpu" : ""}/recommended"]
727
+ )
683
728
  end
684
- nil
685
- end
686
729
 
687
- # Use the AWS SSM API to fetch the current version of the Amazon Linux
688
- # EKS-optimized AMI, so we can use it as a default AMI for EKS deploys.
689
- def self.getEKSImageId(region = MU.myRegion)
690
- resp = MU::Cloud::AWS.ssm(region: region).get_parameters(
691
- names: ["/aws/service/ekss/optimized-ami/amazon-linux/recommended"]
692
- )
693
730
  if resp and resp.parameters and resp.parameters.size > 0
694
731
  image_details = JSON.parse(resp.parameters.first.value)
695
732
  return image_details['image_id']
696
733
  end
734
+
697
735
  nil
698
736
  end
699
737
 
738
+ # Return the list of regions where we know EKS is supported.
739
+ def self.EKSRegions(credentials = nil)
740
+ eks_regions = []
741
+ MU::Cloud::AWS.listRegions(credentials: credentials).each { |r|
742
+ ami = getStandardImage("EKS", r)
743
+ eks_regions << r if ami
744
+ }
745
+
746
+ eks_regions
747
+ end
748
+
700
749
  # Does this resource type exist as a global (cloud-wide) artifact, or
701
750
  # is it localized to a region/zone?
702
751
  # @return [Boolean]
@@ -718,6 +767,7 @@ MU.log c.name, MU::NOTICE, details: t
718
767
  def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
719
768
  resp = MU::Cloud::AWS.ecs(credentials: credentials, region: region).list_clusters
720
769
 
770
+
721
771
  if resp and resp.cluster_arns and resp.cluster_arns.size > 0
722
772
  resp.cluster_arns.each { |arn|
723
773
  if arn.match(/:cluster\/(#{MU.deploy_id}[^:]+)$/)
@@ -744,8 +794,8 @@ MU.log c.name, MU::NOTICE, details: t
744
794
  cluster: cluster
745
795
  })
746
796
  if instances
747
- instances.container_instance_arns.each { |arn|
748
- uuid = arn.sub(/^.*?:container-instance\//, "")
797
+ instances.container_instance_arns.each { |instance_arn|
798
+ uuid = instance_arn.sub(/^.*?:container-instance\//, "")
749
799
  MU.log "Deregistering instance #{uuid} from ECS Cluster #{cluster}"
750
800
  if !noop
751
801
  resp = MU::Cloud::AWS.ecs(credentials: credentials, region: region).deregister_container_instance({
@@ -775,6 +825,7 @@ MU.log c.name, MU::NOTICE, details: t
775
825
  tasks = MU::Cloud::AWS.ecs(region: region, credentials: credentials).list_task_definitions(
776
826
  family_prefix: MU.deploy_id
777
827
  )
828
+
778
829
  if tasks and tasks.task_definition_arns
779
830
  tasks.task_definition_arns.each { |arn|
780
831
  MU.log "Deregistering Fargate task definition #{arn}"
@@ -788,8 +839,14 @@ MU.log c.name, MU::NOTICE, details: t
788
839
 
789
840
  return if !MU::Cloud::AWS::ContainerCluster.EKSRegions.include?(region)
790
841
 
842
+ resp = begin
843
+ MU::Cloud::AWS.eks(credentials: credentials, region: region).list_clusters
844
+ rescue Aws::EKS::Errors::AccessDeniedException
845
+ # EKS isn't actually live in this region, even though SSM lists
846
+ # base images for it
847
+ return
848
+ end
791
849
 
792
- resp = MU::Cloud::AWS.eks(credentials: credentials, region: region).list_clusters
793
850
 
794
851
  if resp and resp.clusters
795
852
  resp.clusters.each { |cluster|
@@ -865,17 +922,24 @@ MU.log c.name, MU::NOTICE, details: t
865
922
  # @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
866
923
  def self.schema(config)
867
924
  toplevel_required = []
925
+
868
926
  schema = {
869
927
  "flavor" => {
870
- "enum" => ["ECS", "EKS", "Fargate"],
928
+ "enum" => ["ECS", "EKS", "Fargate", "Kubernetes"],
929
+ "type" => "string",
930
+ "description" => "The AWS container platform to deploy",
871
931
  "default" => "ECS"
872
932
  },
873
933
  "kubernetes" => {
874
- "default" => { "version" => "1.11" }
934
+ "default" => { "version" => "latest" }
935
+ },
936
+ "gpu" => {
937
+ "type" => "boolean",
938
+ "default" => false,
939
+ "description" => "Enable worker nodes with GPU capabilities"
875
940
  },
876
941
  "platform" => {
877
- "description" => "The platform to choose for worker nodes. Will default to Amazon Linux for ECS, CentOS 7 for everything else. Only valid for EKS and ECS flavors.",
878
- "default" => "centos7"
942
+ "description" => "The platform to choose for worker nodes."
879
943
  },
880
944
  "ami_id" => {
881
945
  "type" => "string",
@@ -1415,6 +1479,25 @@ MU.log c.name, MU::NOTICE, details: t
1415
1479
  "description" => "Per-driver configuration options. See also: https://docs.aws.amazon.com/sdkforruby/api/Aws/ECS/Types/ContainerDefinition.html#log_configuration-instance_method"
1416
1480
  }
1417
1481
  }
1482
+ },
1483
+ "loadbalancers" => {
1484
+ "type" => "array",
1485
+ "description" => "Array of loadbalancers to associate with this container servvice See also: https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/ECS/Client.html#create_service-instance_method",
1486
+ "default" => [],
1487
+ "items" => {
1488
+ "description" => "Load Balancers to associate with the container services",
1489
+ "type" => "object",
1490
+ "properties" => {
1491
+ "name" => {
1492
+ "type" => "string",
1493
+ "description" => "Name of the loadbalancer to associate"
1494
+ },
1495
+ "container_port" => {
1496
+ "type" => "integer",
1497
+ "description" => "container port to map to the loadbalancer"
1498
+ }
1499
+ }
1500
+ }
1418
1501
  }
1419
1502
  }
1420
1503
  }
@@ -1433,6 +1516,8 @@ MU.log c.name, MU::NOTICE, details: t
1433
1516
  cluster['size'] = MU::Cloud::AWS::Server.validateInstanceType(cluster["instance_type"], cluster["region"])
1434
1517
  ok = false if cluster['size'].nil?
1435
1518
 
1519
+ cluster["flavor"] = "EKS" if cluster["flavor"].match(/^Kubernetes$/i)
1520
+
1436
1521
  if cluster["flavor"] == "ECS" and cluster["kubernetes"] and !MU::Cloud::AWS.isGovCloud?(cluster["region"])
1437
1522
  cluster["flavor"] = "EKS"
1438
1523
  MU.log "Setting flavor of ContainerCluster '#{cluster['name']}' to EKS ('kubernetes' stanza was specified)", MU::NOTICE
@@ -1455,6 +1540,7 @@ MU.log c.name, MU::NOTICE, details: t
1455
1540
  end
1456
1541
 
1457
1542
  if cluster["flavor"] != "EKS" and cluster["containers"]
1543
+ cluster.delete("kubernetes")
1458
1544
  created_generic_loggroup = false
1459
1545
  cluster['containers'].each { |c|
1460
1546
  if c['log_configuration'] and
@@ -1485,14 +1571,14 @@ MU.log c.name, MU::NOTICE, details: t
1485
1571
  logdesc = {
1486
1572
  "name" => logname,
1487
1573
  "region" => cluster["region"],
1488
- "cloud" => cluster["cloud"]
1574
+ "cloud" => "AWS"
1489
1575
  }
1490
1576
  configurator.insertKitten(logdesc, "logs")
1491
1577
 
1492
1578
  if !c['role']
1493
1579
  roledesc = {
1494
1580
  "name" => rolename,
1495
- "cloud" => cluster["cloud"],
1581
+ "cloud" => "AWS",
1496
1582
  "can_assume" => [
1497
1583
  {
1498
1584
  "entity_id" => "ecs-tasks.amazonaws.com",
@@ -1542,19 +1628,28 @@ MU.log c.name, MU::NOTICE, details: t
1542
1628
  end
1543
1629
 
1544
1630
  if cluster["flavor"] == "EKS" and !cluster["vpc"]
1545
- if !MU::Cloud::AWS.hosted?
1546
- MU.log "EKS cluster #{cluster['name']} must declare a VPC", MU::ERR
1547
- ok = false
1631
+ if !MU::Cloud::AWS.hosted? or !MU::Cloud::AWS.myVPCObj
1632
+ siblings = configurator.haveLitterMate?(nil, "vpcs", has_multiple: true)
1633
+ if siblings.size == 1
1634
+ MU.log "EKS cluster #{cluster['name']} did not declare a VPC. Inserting into an available sibling VPC.", MU::WARN
1635
+ cluster["vpc"] = {
1636
+ "name" => siblings[0]['name'],
1637
+ "subnet_pref" => "all_private"
1638
+ }
1639
+ else
1640
+ MU.log "EKS cluster #{cluster['name']} must declare a VPC", MU::ERR
1641
+ ok = false
1642
+ end
1548
1643
  else
1549
1644
  cluster["vpc"] = {
1550
- "vpc_id" => MU.myVPC,
1645
+ "id" => MU.myVPC,
1551
1646
  "subnet_pref" => "all_private"
1552
1647
  }
1553
1648
  end
1554
1649
  end
1555
1650
 
1556
1651
  if ["ECS", "EKS"].include?(cluster["flavor"])
1557
- std_ami = getECSImageId(cluster["flavor"], cluster['region'])
1652
+ std_ami = getStandardImage(cluster["flavor"], cluster['region'], version: cluster['kubernetes']['version'], gpu: cluster['gpu'])
1558
1653
  cluster["host_image"] ||= std_ami
1559
1654
  if cluster["host_image"] != std_ami
1560
1655
  if cluster["flavor"] == "ECS"
@@ -1582,41 +1677,36 @@ MU.log c.name, MU::NOTICE, details: t
1582
1677
 
1583
1678
  end
1584
1679
 
1680
+ fwname = "container_cluster#{cluster['name']}"
1681
+
1585
1682
  cluster['ingress_rules'] ||= []
1586
- if cluster['flavor'] == "ECS"
1683
+ if ["ECS", "EKS"].include?(cluster["flavor"])
1587
1684
  cluster['ingress_rules'] << {
1588
- "sgs" => ["server_pool#{cluster['name']}workers"],
1589
- "port" => 443
1685
+ "sgs" => ["server_pool"+cluster["name"]+"workers"],
1686
+ "port" => 443,
1687
+ "proto" => "tcp",
1688
+ "ingress" => true,
1689
+ "comment" => "Allow worker nodes to access API"
1590
1690
  }
1691
+ ruleset = configurator.haveLitterMate?(fwname, "firewall_rules")
1692
+ if ruleset
1693
+ ruleset["rules"].concat(cluster['ingress_rules'])
1694
+ ruleset["rules"].uniq!
1695
+ end
1591
1696
  end
1592
- fwname = "container_cluster#{cluster['name']}"
1593
-
1594
- acl = {
1595
- "name" => fwname,
1596
- "credentials" => cluster["credentials"],
1597
- "rules" => cluster['ingress_rules'],
1598
- "region" => cluster['region'],
1599
- "optional_tags" => cluster['optional_tags']
1600
- }
1601
- acl["tags"] = cluster['tags'] if cluster['tags'] && !cluster['tags'].empty?
1602
- acl["vpc"] = cluster['vpc'].dup if cluster['vpc']
1603
-
1604
- ok = false if !configurator.insertKitten(acl, "firewall_rules")
1605
- cluster["add_firewall_rules"] = [] if cluster["add_firewall_rules"].nil?
1606
- cluster["add_firewall_rules"] << {"rule_name" => fwname}
1607
- cluster["dependencies"] << {
1608
- "name" => fwname,
1609
- "type" => "firewall_rule",
1610
- }
1611
1697
 
1612
1698
  if ["ECS", "EKS"].include?(cluster["flavor"])
1699
+ cluster["max_size"] ||= cluster["instance_count"]
1700
+ cluster["min_size"] ||= cluster["instance_count"]
1613
1701
 
1614
1702
  worker_pool = {
1615
1703
  "name" => cluster["name"]+"workers",
1704
+ "cloud" => "AWS",
1705
+ "skipinitialupdates" => (cluster["flavor"] == "EKS"),
1616
1706
  "credentials" => cluster["credentials"],
1617
1707
  "region" => cluster['region'],
1618
- "min_size" => cluster["instance_count"],
1619
- "max_size" => cluster["instance_count"],
1708
+ "min_size" => cluster["min_size"],
1709
+ "max_size" => cluster["max_size"],
1620
1710
  "wait_for_nodes" => cluster["instance_count"],
1621
1711
  "ssh_user" => cluster["host_ssh_user"],
1622
1712
  "role_strip_path" => true,
@@ -1629,7 +1719,7 @@ MU.log c.name, MU::NOTICE, details: t
1629
1719
  }
1630
1720
  if cluster["flavor"] == "EKS"
1631
1721
  worker_pool["ingress_rules"] = [
1632
- "sgs" => ["container_cluster#{cluster['name']}"],
1722
+ "sgs" => [fwname],
1633
1723
  "port_range" => "1-65535"
1634
1724
  ]
1635
1725
  worker_pool["application_attributes"] ||= {}
@@ -1681,6 +1771,7 @@ MU.log c.name, MU::NOTICE, details: t
1681
1771
  role = {
1682
1772
  "name" => cluster["name"]+"controlplane",
1683
1773
  "credentials" => cluster["credentials"],
1774
+ "cloud" => "AWS",
1684
1775
  "can_assume" => [
1685
1776
  { "entity_id" => "eks.amazonaws.com", "entity_type" => "service" }
1686
1777
  ],