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
@@ -18,7 +18,7 @@ module MU
18
18
  class Groomer
19
19
 
20
20
  # An exception denoting a Groomer run that has failed
21
- class RunError < MuError
21
+ class RunError < StandardError
22
22
  end
23
23
 
24
24
  # An exception denoting nonexistent secret
@@ -49,6 +49,7 @@ module MU
49
49
  # @param groomer [String]: The grooming agent to load.
50
50
  # @return [Class]: The class object implementing this groomer agent
51
51
  def self.loadGroomer(groomer)
52
+ return nil if !groomer
52
53
  if !File.size?(MU.myRoot+"/modules/mu/groomers/#{groomer.downcase}.rb")
53
54
  raise MuError, "Requested to use unsupported grooming agent #{groomer}"
54
55
  end
@@ -20,11 +20,17 @@ module MU
20
20
  # Support for Ansible as a host configuration management layer.
21
21
  class Ansible
22
22
 
23
+ # Failure to load or create a deploy
24
+ class NoAnsibleExecError < MuError;
25
+ end
23
26
 
24
- # Location in which we'll find our Ansible executables
27
+ # Location in which we'll find our Ansible executables. This only applies
28
+ # to full-grown Mu masters; minimalist gem installs will have to make do
29
+ # with whatever Ansible executables they can find in $PATH.
25
30
  BINDIR = "/usr/local/python-current/bin"
26
31
  @@pwfile_semaphore = Mutex.new
27
32
 
33
+
28
34
  # @param node [MU::Cloud::Server]: The server object on which we'll be operating
29
35
  def initialize(node)
30
36
  @config = node.config
@@ -32,9 +38,14 @@ module MU
32
38
  @inventory = Inventory.new(node.deploy)
33
39
  @mu_user = node.deploy.mu_user
34
40
  @ansible_path = node.deploy.deploy_dir+"/ansible"
41
+ @ansible_execs = MU::Groomer::Ansible.ansibleExecDir
42
+
43
+ if !@ansible_execs or @ansible_execs.empty?
44
+ raise NoAnsibleExecError, "No Ansible executables found in visible paths"
45
+ end
35
46
 
36
47
  [@ansible_path, @ansible_path+"/roles", @ansible_path+"/vars", @ansible_path+"/group_vars", @ansible_path+"/vaults"].each { |dir|
37
- if !Dir.exists?(dir)
48
+ if !Dir.exist?(dir)
38
49
  MU.log "Creating #{dir}", MU::DEBUG
39
50
  Dir.mkdir(dir, 0755)
40
51
  end
@@ -77,19 +88,20 @@ module MU
77
88
  end
78
89
  path = dir+"/"+item
79
90
 
80
- if !Dir.exists?(dir)
91
+ if !Dir.exist?(dir)
81
92
  FileUtils.mkdir_p(dir, mode: 0700)
82
93
  end
83
94
 
84
- if File.exists?(path)
95
+ if File.exist?(path)
85
96
  MU.log "Overwriting existing vault #{vault} item #{item}"
86
97
  end
87
98
  File.open(path, File::CREAT|File::RDWR|File::TRUNC, 0600) { |f|
88
99
  f.write data
89
100
  }
90
- cmd = %Q{#{BINDIR}/ansible-vault encrypt #{path} --vault-id #{pwfile}}
101
+
102
+ cmd = %Q{#{ansibleExecDir}/ansible-vault encrypt #{path} --vault-password-file #{pwfile}}
91
103
  MU.log cmd
92
- system(cmd)
104
+ raise MuError, "Failed Ansible command: #{cmd}" if !system(cmd)
93
105
  end
94
106
 
95
107
  # see {MU::Groomer::Ansible.saveSecret}
@@ -110,17 +122,17 @@ module MU
110
122
 
111
123
  pwfile = vaultPasswordFile
112
124
  dir = secret_dir+"/"+vault
113
- if !Dir.exists?(dir)
125
+ if !Dir.exist?(dir)
114
126
  raise MuNoSuchSecret, "No such vault #{vault}"
115
127
  end
116
128
 
117
129
  data = nil
118
130
  if item
119
131
  itempath = dir+"/"+item
120
- if !File.exists?(itempath)
132
+ if !File.exist?(itempath)
121
133
  raise MuNoSuchSecret, "No such item #{item} in vault #{vault}"
122
134
  end
123
- cmd = %Q{#{BINDIR}/ansible-vault view #{itempath} --vault-id #{pwfile}}
135
+ cmd = %Q{#{ansibleExecDir}/ansible-vault view #{itempath} --vault-password-file #{pwfile}}
124
136
  MU.log cmd
125
137
  a = `#{cmd}`
126
138
  # If we happen to have stored recognizeable JSON, return it as parsed,
@@ -158,14 +170,14 @@ module MU
158
170
  raise MuError, "Must call deleteSecret with at least a vault name"
159
171
  end
160
172
  dir = secret_dir+"/"+vault
161
- if !Dir.exists?(dir)
173
+ if !Dir.exist?(dir)
162
174
  raise MuNoSuchSecret, "No such vault #{vault}"
163
175
  end
164
176
 
165
177
  data = nil
166
178
  if item
167
179
  itempath = dir+"/"+item
168
- if !File.exists?(itempath)
180
+ if !File.exist?(itempath)
169
181
  raise MuNoSuchSecret, "No such item #{item} in vault #{vault}"
170
182
  end
171
183
  MU.log "Deleting Ansible vault #{vault} item #{item}", MU::NOTICE
@@ -189,13 +201,28 @@ module MU
189
201
  # @param output [Boolean]: Display Ansible's regular (non-error) output to the console
190
202
  # @param override_runlist [String]: Use the specified run list instead of the node's configured list
191
203
  def run(purpose: "Ansible run", update_runlist: true, max_retries: 5, output: true, override_runlist: nil, reboot_first_fail: false, timeout: 1800)
204
+ bootstrap
192
205
  pwfile = MU::Groomer::Ansible.vaultPasswordFile
193
206
  stashHostSSLCertSecret
194
207
 
195
- cmd = %Q{cd #{@ansible_path} && #{BINDIR}/ansible-playbook -i hosts #{@server.config['name']}.yml --limit=#{@server.mu_name} --vault-id #{pwfile} --vault-id #{@ansible_path}/.vault_pw}
208
+ ssh_user = @server.config['ssh_user'] || "root"
196
209
 
197
- MU.log cmd
198
- system(cmd)
210
+ cmd = %Q{cd #{@ansible_path} && #{@ansible_execs}/ansible-playbook -i hosts #{@server.config['name']}.yml --limit=#{@server.mu_name} --vault-password-file #{pwfile} --vault-password-file #{@ansible_path}/.vault_pw -u #{ssh_user}}
211
+
212
+ retries = 0
213
+ begin
214
+ MU.log cmd
215
+ raise MU::Groomer::RunError, "Failed Ansible command: #{cmd}" if !system(cmd)
216
+ rescue MU::Groomer::RunError => e
217
+ if retries < max_retries
218
+ sleep 30
219
+ retries += 1
220
+ MU.log "Failed Ansible run, will retry (#{retries.to_s}/#{max_retries.to_s})", MU::NOTICE, details: cmd
221
+ retry
222
+ else
223
+ raise MuError, "Failed Ansible command: #{cmd}"
224
+ end
225
+ end
199
226
  end
200
227
 
201
228
  # This is a stub; since Ansible is effectively agentless, this operation
@@ -224,6 +251,10 @@ module MU
224
251
  play["roles"] = @server.config['run_list']
225
252
  end
226
253
 
254
+ if @server.config['ansible_vars']
255
+ play["vars"] = @server.config['ansible_vars']
256
+ end
257
+
227
258
  File.open(@ansible_path+"/"+@server.config['name']+".yml", File::CREAT|File::RDWR|File::TRUNC, 0600) { |f|
228
259
  f.flock(File::LOCK_EX)
229
260
  f.puts [play].to_yaml
@@ -237,12 +268,13 @@ module MU
237
268
  @server.describe(update_cache: true) # Make sure we're fresh
238
269
 
239
270
  allvars = {
240
- "deployment" => @server.deploy.deployment,
241
- "service_name" => @config["name"],
242
- "windows_admin_username" => @config['windows_admin_username'],
243
- "mu_environment" => MU.environment.downcase,
271
+ "mu_deployment" => MU.structToHash(@server.deploy.deployment),
272
+ "mu_service_name" => @config["name"],
273
+ "mu_canonical_ip" => @server.canonicalIP,
274
+ "mu_admin_email" => $MU_CFG['mu_admin_email'],
275
+ "mu_environment" => MU.environment.downcase
244
276
  }
245
- allvars['deployment']['ssh_public_key'] = @server.deploy.ssh_public_key
277
+ allvars['mu_deployment']['ssh_public_key'] = @server.deploy.ssh_public_key
246
278
 
247
279
  if @server.config['cloud'] == "AWS"
248
280
  allvars["ec2"] = MU.structToHash(@server.cloud_desc, stringify_keys: true)
@@ -262,7 +294,7 @@ module MU
262
294
  f.flock(File::LOCK_UN)
263
295
  }
264
296
 
265
- groupvars = {}
297
+ groupvars = allvars.dup
266
298
  if @server.deploy.original_config.has_key?('parameters')
267
299
  groupvars["mu_parameters"] = @server.deploy.original_config['parameters']
268
300
  end
@@ -312,18 +344,41 @@ module MU
312
344
  # @param for_user [String]: Encrypt using the Vault password of the specified Mu user
313
345
  def self.encryptString(name, string, for_user = nil)
314
346
  pwfile = vaultPasswordFile
315
- cmd = %Q{#{BINDIR}/ansible-vault}
316
- system(cmd, "encrypt_string", string, "--name", name, "--vault-id", pwfile)
347
+ cmd = %Q{#{ansibleExecDir}/ansible-vault}
348
+ if !system(cmd, "encrypt_string", string, "--name", name, "--vault-password-file", pwfile)
349
+ raise MuError, "Failed Ansible command: #{cmd} encrypt_string <redacted> --name #{name} --vault-password-file"
350
+ end
317
351
  end
318
352
 
319
353
  private
320
354
 
355
+ def self.ansibleExecDir
356
+ path = nil
357
+ if File.exist?(BINDIR+"/ansible-playbook")
358
+ path = BINDIR
359
+ else
360
+ ENV['PATH'].split(/:/).each { |bindir|
361
+ if File.exist?(bindir+"/ansible-playbook")
362
+ path = bindir
363
+ if !File.exist?(bindir+"/ansible-vault")
364
+ MU.log "Found ansible-playbook executable in #{bindir}, but no ansible-vault. Vault functionality will not work!", MU::WARN
365
+ end
366
+ if !File.exist?(bindir+"/ansible-galaxy")
367
+ MU.log "Found ansible-playbook executable in #{bindir}, but no ansible-galaxy. Automatic community role fetch will not work!", MU::WARN
368
+ end
369
+ break
370
+ end
371
+ }
372
+ end
373
+ path
374
+ end
375
+
321
376
  # Get the +.vault_pw+ file for the appropriate user. If it doesn't exist,
322
377
  # generate one.
323
378
  def self.vaultPasswordFile(for_user = nil, pwfile: nil)
324
379
  pwfile ||= secret_dir(for_user)+"/.vault_pw"
325
380
  @@pwfile_semaphore.synchronize {
326
- if !File.exists?(pwfile)
381
+ if !File.exist?(pwfile)
327
382
  MU.log "Generating Ansible vault password file at #{pwfile}", MU::DEBUG
328
383
  File.open(pwfile, File::CREAT|File::RDWR|File::TRUNC, 0400) { |f|
329
384
  f.write Password.random(12..14)
@@ -341,7 +396,7 @@ module MU
341
396
  # Figure out where our main stash of secrets is, and make sure it exists
342
397
  def self.secret_dir(user = MU.mu_user)
343
398
  path = MU.dataDir(user) + "/ansible-secrets"
344
- Dir.mkdir(path, 0755) if !Dir.exists?(path)
399
+ Dir.mkdir(path, 0755) if !Dir.exist?(path)
345
400
 
346
401
  path
347
402
  end
@@ -350,6 +405,7 @@ module MU
350
405
  # artifacts, since 'roles' is an awfully generic name for a directory.
351
406
  # Short of a full, slow syntax check, this is the best we're liable to do.
352
407
  def isAnsibleRole?(path)
408
+ begin
353
409
  Dir.foreach(path) { |entry|
354
410
  if File.directory?(path+"/"+entry) and
355
411
  ["tasks", "vars"].include?(entry)
@@ -358,6 +414,8 @@ module MU
358
414
  return false
359
415
  end
360
416
  }
417
+ rescue Errno::ENOTDIR
418
+ end
361
419
  false
362
420
  end
363
421
 
@@ -368,20 +426,34 @@ module MU
368
426
 
369
427
  canon_links = {}
370
428
 
429
+ repodirs = []
430
+
431
+ # Make sure we search the global ansible_dir, if any is set
432
+ if $MU_CFG and $MU_CFG['ansible_dir'] and !$MU_CFG['ansible_dir'].empty?
433
+ if !Dir.exist?($MU_CFG['ansible_dir'])
434
+ MU.log "Config lists an Ansible directory at #{$MU_CFG['ansible_dir']}, but I see no such directory", MU::WARN
435
+ else
436
+ repodirs << $MU_CFG['ansible_dir']
437
+ end
438
+ end
439
+
371
440
  # Hook up any Ansible roles listed in our platform repos
372
441
  $MU_CFG['repos'].each { |repo|
373
442
  repo.match(/\/([^\/]+?)(\.git)?$/)
374
443
  shortname = Regexp.last_match(1)
375
- repodir = MU.dataDir + "/" + shortname
444
+ repodirs << MU.dataDir + "/" + shortname
445
+ }
446
+
447
+ repodirs.each { |repodir|
376
448
  ["roles", "ansible/roles"].each { |subdir|
377
- next if !Dir.exists?(repodir+"/"+subdir)
449
+ next if !Dir.exist?(repodir+"/"+subdir)
378
450
  Dir.foreach(repodir+"/"+subdir) { |role|
379
451
  next if [".", ".."].include?(role)
380
452
  realpath = repodir+"/"+subdir+"/"+role
381
453
  link = roledir+"/"+role
382
454
 
383
455
  if isAnsibleRole?(realpath)
384
- if !File.exists?(link)
456
+ if !File.exist?(link)
385
457
  File.symlink(realpath, link)
386
458
  canon_links[role] = realpath
387
459
  elsif File.symlink?(link)
@@ -402,16 +474,16 @@ module MU
402
474
  # Now layer on everything bundled in the main Mu repo
403
475
  Dir.foreach(MU.myRoot+"/ansible/roles") { |role|
404
476
  next if [".", ".."].include?(role)
405
- next if File.exists?(roledir+"/"+role)
477
+ next if File.exist?(roledir+"/"+role)
406
478
  File.symlink(MU.myRoot+"/ansible/roles/"+role, roledir+"/"+role)
407
479
  }
408
480
 
409
481
  if @server.config['run_list']
410
482
  @server.config['run_list'].each { |role|
411
483
  found = false
412
- if !File.exists?(roledir+"/"+role)
484
+ if !File.exist?(roledir+"/"+role)
413
485
  if role.match(/[^\.]\.[^\.]/) and @server.config['groomer_autofetch']
414
- system(%Q{#{BINDIR}/ansible-galaxy}, "--roles-path", roledir, "install", role)
486
+ system(%Q{#{@ansible_execs}/ansible-galaxy}, "--roles-path", roledir, "install", role)
415
487
  found = true
416
488
  # XXX check return value
417
489
  else
@@ -455,7 +527,7 @@ module MU
455
527
  def initialize(deploy)
456
528
  @deploy = deploy
457
529
  @ansible_path = @deploy.deploy_dir+"/ansible"
458
- if !Dir.exists?(@ansible_path)
530
+ if !Dir.exist?(@ansible_path)
459
531
  Dir.mkdir(@ansible_path, 0755)
460
532
  end
461
533
 
@@ -528,7 +600,7 @@ module MU
528
600
 
529
601
  def read
530
602
  @inv = {}
531
- if File.exists?(@ansible_path+"/hosts")
603
+ if File.exist?(@ansible_path+"/hosts")
532
604
  section = nil
533
605
  File.readlines(@ansible_path+"/hosts").each { |l|
534
606
  l.chomp!
@@ -71,7 +71,7 @@ module MU
71
71
  require 'chef/knife/bootstrap_windows_winrm'
72
72
  require 'chef/knife/bootstrap_windows_ssh'
73
73
  ::Chef::Config[:chef_server_url] = "https://#{MU.mu_public_addr}:7443/organizations/#{user}"
74
- if File.exists?("#{Etc.getpwnam(mu_user).dir}/.chef/knife.rb")
74
+ if File.exist?("#{Etc.getpwnam(mu_user).dir}/.chef/knife.rb")
75
75
  MU.log "Loading Chef configuration from #{Etc.getpwnam(mu_user).dir}/.chef/knife.rb", MU::DEBUG
76
76
  ::Chef::Config.from_file("#{Etc.getpwnam(mu_user).dir}/.chef/knife.rb")
77
77
  end
@@ -218,7 +218,7 @@ module MU
218
218
  loadChefLib
219
219
  raise MuError, "No vault specified, nothing to delete" if vault.nil?
220
220
  MU.log "Deleting #{vault}:#{item} from vaults"
221
- knife_db = nil
221
+
222
222
  knife_cmds = []
223
223
  if item.nil?
224
224
  knife_cmds << ::Chef::Knife::DataBagDelete.new(['data', 'bag', 'delete', vault])
@@ -270,7 +270,7 @@ module MU
270
270
 
271
271
  retries = 0
272
272
  try_upgrade = false
273
- output = []
273
+ output_lines = []
274
274
  error_signal = "CHEF EXITED BADLY: "+(0...25).map { ('a'..'z').to_a[rand(26)] }.join
275
275
  runstart = nil
276
276
  cmd = nil
@@ -294,9 +294,26 @@ module MU
294
294
  Timeout::timeout(timeout) {
295
295
  retval = ssh.exec!(cmd) { |ch, stream, data|
296
296
  puts data
297
- output << data
298
- raise MU::Cloud::BootstrapTempFail if data.match(/REBOOT_SCHEDULED| WARN: Reboot requested:/)
299
- raise MU::Groomer::RunError, output.grep(/ ERROR: /).last if data.match(/#{error_signal}/)
297
+ output_lines << data
298
+ raise MU::Cloud::BootstrapTempFail if data.match(/REBOOT_SCHEDULED| WARN: Reboot requested:|Rebooting server at a recipe's request|Chef::Exceptions::Reboot/)
299
+ if data.match(/#{error_signal}/)
300
+ error_msg = ""
301
+ clip = false
302
+ output_lines.each { |chunk|
303
+ chunk.split(/\n/).each { |line|
304
+ if !clip and line.match(/^========+/)
305
+ clip = true
306
+ elsif clip and line.match(/^Running handlers:/)
307
+ break
308
+ end
309
+
310
+ if clip and line.match(/[a-z0-9]/)
311
+ error_msg += line.gsub(/\e\[(\d+)m/, '')+"\n"
312
+ end
313
+ }
314
+ }
315
+ raise MU::Groomer::RunError, error_msg
316
+ end
300
317
  }
301
318
  }
302
319
  else
@@ -314,7 +331,7 @@ module MU
314
331
  if try_upgrade
315
332
  pp winrm.run("Invoke-WebRequest -useb https://omnitruck.chef.io/install.ps1 | Invoke-Expression; Install-Project -version:#{MU.chefVersion} -download_directory:$HOME")
316
333
  end
317
- output = []
334
+ output_lines = []
318
335
  cmd = "c:/opscode/chef/bin/chef-client.bat --color"
319
336
  if override_runlist
320
337
  cmd = cmd + " -o '#{override_runlist}'"
@@ -324,20 +341,20 @@ module MU
324
341
  resp = winrm.run(cmd) do |stdout, stderr|
325
342
  if stdout
326
343
  print stdout if output
327
- output << stdout
344
+ output_lines << stdout
328
345
  end
329
346
  if stderr
330
347
  MU.log stderr, MU::ERR
331
- output << stderr
348
+ output_lines << stderr
332
349
  end
333
350
  end
334
351
  }
335
352
 
336
- if resp.exitcode == 1 and output.join("\n").match(/Chef Client finished/)
353
+ if resp.exitcode == 1 and output_lines.join("\n").match(/Chef Client finished/)
337
354
  MU.log "resp.exit code 1"
338
355
  elsif resp.exitcode != 0
339
- raise MU::Cloud::BootstrapTempFail if resp.exitcode == 35 or output.join("\n").match(/REBOOT_SCHEDULED| WARN: Reboot requested:/)
340
- raise MU::Groomer::RunError, output.slice(output.length-50, output.length).join("")
356
+ raise MU::Cloud::BootstrapTempFail if resp.exitcode == 35 or output_lines.join("\n").match(/REBOOT_SCHEDULED| WARN: Reboot requested:|Rebooting server at a recipe's request|Chef::Exceptions::Reboot/)
357
+ raise MU::Groomer::RunError, output_lines.slice(output_lines.length-50, output_lines.length).join("")
341
358
  end
342
359
  end
343
360
  rescue MU::Cloud::BootstrapTempFail
@@ -397,10 +414,12 @@ module MU
397
414
  sleep 30
398
415
  retry
399
416
  else
417
+ @server.deploy.sendAdminSlack("Chef run '#{purpose}' failed on `#{@server.mu_name}` :crying_cat_face:", msg: e.message)
400
418
  raise MU::Groomer::RunError, "#{@server.mu_name}: Chef run '#{purpose}' failed #{max_retries} times, last error was: #{e.message}"
401
419
  end
402
420
  rescue Exception => e
403
- raise MU::Groomer::RunError, "Caught unexpected #{e.inspect} on #{@server.mu_name} in @groomer.run"
421
+ @server.deploy.sendAdminSlack("Chef run '#{purpose}' failed on `#{@server.mu_name}` :crying_cat_face:", msg: e.inspect)
422
+ raise MU::Groomer::RunError, "Caught unexpected #{e.inspect} on #{@server.mu_name} in @groomer.run at #{e.backtrace[0]}"
404
423
 
405
424
  end
406
425
 
@@ -440,20 +459,33 @@ module MU
440
459
  end
441
460
  guardfile = "/opt/mu_installed_chef"
442
461
 
443
- ssh = @server.getSSHSession(15)
444
- if leave_ours
445
- MU.log "Expunging pre-existing Chef install on #{@server.mu_name}, if we didn't create it", MU::NOTICE
446
- begin
447
- ssh.exec!(%Q{test -f #{guardfile} || (#{remove_cmd}) ; touch #{guardfile}})
448
- rescue IOError => e
449
- # TO DO - retry this in a cleaner way
450
- MU.log "Got #{e.inspect} while trying to clean up chef, retrying", MU::NOTICE, details: %Q{test -f #{guardfile} || (#{remove_cmd}) ; touch #{guardfile}}
451
- ssh = @server.getSSHSession(15)
452
- ssh.exec!(%Q{test -f #{guardfile} || (#{remove_cmd}) ; touch #{guardfile}})
462
+ retries = 0
463
+ begin
464
+ ssh = @server.getSSHSession(15)
465
+ Timeout::timeout(60) {
466
+ if leave_ours
467
+ MU.log "Expunging pre-existing Chef install on #{@server.mu_name}, if we didn't create it", MU::NOTICE
468
+ begin
469
+ ssh.exec!(%Q{test -f #{guardfile} || (#{remove_cmd}) ; touch #{guardfile}})
470
+ rescue IOError => e
471
+ # TO DO - retry this in a cleaner way
472
+ MU.log "Got #{e.inspect} while trying to clean up chef, retrying", MU::NOTICE, details: %Q{test -f #{guardfile} || (#{remove_cmd}) ; touch #{guardfile}}
473
+ ssh = @server.getSSHSession(15)
474
+ ssh.exec!(%Q{test -f #{guardfile} || (#{remove_cmd}) ; touch #{guardfile}})
475
+ end
476
+ else
477
+ MU.log "Expunging pre-existing Chef install on #{@server.mu_name}", MU::NOTICE
478
+ ssh.exec!(remove_cmd)
479
+ end
480
+ }
481
+ rescue Timeout::Error
482
+ if retries < 5
483
+ retries += 1
484
+ sleep 5
485
+ retry
486
+ else
487
+ raise MuError, "Failed to preClean #{@server.mu_name} after repeated timeouts"
453
488
  end
454
- else
455
- MU.log "Expunging pre-existing Chef install on #{@server.mu_name}", MU::NOTICE
456
- ssh.exec!(remove_cmd)
457
489
  end
458
490
 
459
491
  ssh.close
@@ -523,6 +555,7 @@ module MU
523
555
  def bootstrap
524
556
  self.class.loadChefLib
525
557
  stashHostSSLCertSecret
558
+ splunkVaultInit
526
559
  if !@config['cleaned_chef']
527
560
  begin
528
561
  leave_ours = @config['scrub_groomer'] ? false : true
@@ -654,8 +687,8 @@ retry
654
687
  end
655
688
  }
656
689
  knifeAddToRunList("role[mu-node]")
690
+ knifeAddToRunList("mu-tools::selinux")
657
691
 
658
- splunkVaultInit
659
692
  grantSecretAccess(@server.mu_name, "windows_credentials") if @server.windows?
660
693
  grantSecretAccess(@server.mu_name, "ssl_cert")
661
694
 
@@ -669,6 +702,7 @@ retry
669
702
  run(purpose: "Base configuration", update_runlist: false, max_retries: 20)
670
703
  end
671
704
  ::Chef::Knife.run(['node', 'run_list', 'remove', @server.mu_name, "recipe[mu-tools::updates]"], {}) if !@config['skipinitialupdates']
705
+ ::Chef::Knife.run(['node', 'run_list', 'remove', @server.mu_name, "recipe[mu-tools::selinux]"], {})
672
706
 
673
707
  # This will deal with Active Directory integration.
674
708
  if !@config['active_directory'].nil?
@@ -696,6 +730,11 @@ retry
696
730
  # @return [Hash]: The data synchronized.
697
731
  def saveDeployData
698
732
  self.class.loadChefLib
733
+ if !haveBootstrapped?
734
+ MU.log "saveDeployData invoked on #{@server.to_s} before Chef has been bootstrapped!", MU::WARN, details: caller
735
+ return
736
+ end
737
+
699
738
  @server.describe(update_cache: true) # Make sure we're fresh
700
739
  saveChefMetadata
701
740
  begin
@@ -724,10 +763,12 @@ retry
724
763
  }
725
764
  end
726
765
 
727
- if chef_node.normal['deployment'] != @server.deploy.deployment
766
+ if !@server.deploy.deployment.nil? and
767
+ (chef_node.normal['deployment'].nil? or
768
+ (chef_node.normal['deployment'].to_h <=> @server.deploy.deployment) != 0
769
+ )
728
770
  MU.log "Updating node: #{@server.mu_name} deployment attributes", details: @server.deploy.deployment
729
771
  chef_node.normal['deployment'].merge!(@server.deploy.deployment)
730
- chef_node.normal['deployment']['ssh_public_key'] = @server.deploy.ssh_public_key
731
772
  chef_node.save
732
773
  end
733
774
  return chef_node['deployment']
@@ -770,6 +811,15 @@ retry
770
811
  rescue Net::HTTPServerException
771
812
  end
772
813
  end
814
+ MU.log "knife data bag delete #{node}"
815
+ if !noop
816
+ knife_cd = ::Chef::Knife::ClientDelete.new(['data', 'bag', 'delete', node])
817
+ knife_cd.config[:yes] = true
818
+ begin
819
+ knife_cd.run
820
+ rescue Net::HTTPServerException
821
+ end
822
+ end
773
823
 
774
824
  return if nodeonly
775
825
 
@@ -778,7 +828,7 @@ retry
778
828
  rescue MuNoSuchSecret
779
829
  end
780
830
  ["crt", "key", "csr"].each { |ext|
781
- if File.exists?("#{MU.mySSLDir}/#{node}.#{ext}")
831
+ if File.exist?("#{MU.mySSLDir}/#{node}.#{ext}")
782
832
  MU.log "Removing #{MU.mySSLDir}/#{node}.#{ext}"
783
833
  File.unlink("#{MU.mySSLDir}/#{node}.#{ext}") if !noop
784
834
  end
@@ -812,6 +862,7 @@ retry
812
862
  begin
813
863
  chef_node = ::Chef::Node.load(@server.mu_name)
814
864
  rescue Net::HTTPServerException
865
+ @server.deploy.sendAdminSlack("Couldn't load Chef metadata on `#{@server.mu_name}` :crying_cat_face:")
815
866
  raise MU::Groomer::RunError, "Couldn't load Chef node #{@server.mu_name}"
816
867
  end
817
868
 
@@ -821,6 +872,7 @@ retry
821
872
 
822
873
  chef_node.normal.app = @config['application_cookbook'] if !@config['application_cookbook'].nil?
823
874
  chef_node.normal["service_name"] = @config["name"]
875
+ chef_node.normal["credentials"] = @config["credentials"]
824
876
  chef_node.normal["windows_admin_username"] = @config['windows_admin_username']
825
877
  chef_node.chef_environment = MU.environment.downcase
826
878
  if @server.config['cloud'] == "AWS"
@@ -965,9 +1017,9 @@ retry
965
1017
  if multiple.size == 0
966
1018
  multiple = [rl_entry]
967
1019
  end
968
- multiple.each { |rl_entry|
969
- if !rl_entry.match(/^role|recipe\[/)
970
- rl_entry = "#{type}[#{rl_entry}]"
1020
+ multiple.each { |entry|
1021
+ if !entry.match(/^role|recipe\[/)
1022
+ entry = "#{type}[#{entry}]"
971
1023
  end
972
1024
  }
973
1025
 
@@ -975,27 +1027,27 @@ retry
975
1027
  role_list = nil
976
1028
  recipe_list = nil
977
1029
  missing = false
978
- multiple.each { |rl_entry|
979
- # Rather than argue about whether to expect a bare rl_entry name or
980
- # require rl_entry[rolename], let's just accomodate.
981
- if rl_entry.match(/^role\[(.+?)\]/)
982
- rl_entry_name = Regexp.last_match(1)
1030
+ multiple.each { |entry|
1031
+ # Rather than argue about whether to expect a bare entry name or
1032
+ # require entry[rolename], let's just accomodate.
1033
+ if entry.match(/^role\[(.+?)\]/)
1034
+ entry_name = Regexp.last_match(1)
983
1035
  if role_list.nil?
984
1036
  query=%Q{#{MU::Groomer::Chef.knife} role list};
985
1037
  role_list = %x{#{query}}
986
1038
  end
987
- if !role_list.match(/(^|\n)#{rl_entry_name}($|\n)/)
988
- MU.log "Attempting to add non-existent #{rl_entry} to #{@server.mu_name}", MU::WARN
1039
+ if !role_list.match(/(^|\n)#{entry_name}($|\n)/)
1040
+ MU.log "Attempting to add non-existent #{entry} to #{@server.mu_name}", MU::WARN
989
1041
  missing = true
990
1042
  end
991
- elsif rl_entry.match(/^recipe\[(.+?)\]/)
992
- rl_entry_name = Regexp.last_match(1)
1043
+ elsif entry.match(/^recipe\[(.+?)\]/)
1044
+ entry_name = Regexp.last_match(1)
993
1045
  if recipe_list.nil?
994
1046
  query=%Q{#{MU::Groomer::Chef.knife} recipe list};
995
1047
  recipe_list = %x{#{query}}
996
1048
  end
997
- if !recipe_list.match(/(^|\n)#{rl_entry_name}($|\n)/)
998
- MU.log "Attempting to add non-existent #{rl_entry} to #{@server.mu_name}", MU::WARN
1049
+ if !recipe_list.match(/(^|\n)#{entry_name}($|\n)/)
1050
+ MU.log "Attempting to add non-existent #{entry} to #{@server.mu_name}", MU::WARN
999
1051
  missing = true
1000
1052
  end
1001
1053
  end