Class: Mccloud::Provisioner::ChefSolo

Inherits:
Object
  • Object
show all
Defined in:
lib/mccloud/provisioner/chef_solo.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(env) ⇒ ChefSolo

Returns a new instance of ChefSolo.



39
40
41
42
43
44
45
46
47
48
49
# File 'lib/mccloud/provisioner/chef_solo.rb', line 39

def initialize(env)
  @env=env
  @provisioning_path="/tmp/mccloud-chef"
  @json={ :instance_role => "mccloud"}
  @json_erb=true
  @name ="chef_solo"
  @log_level="info"
  @cookbooks_path =  []
  @run_list = []
  @clean_after_run = true
end

Instance Attribute Details

#clean_after_runObject

Returns the value of attribute clean_after_run.



26
27
28
# File 'lib/mccloud/provisioner/chef_solo.rb', line 26

def clean_after_run
  @clean_after_run
end

#cookbooks_pathObject

Returns the value of attribute cookbooks_path.



19
20
21
# File 'lib/mccloud/provisioner/chef_solo.rb', line 19

def cookbooks_path
  @cookbooks_path
end

#data_bags_pathObject

Returns the value of attribute data_bags_path.



22
23
24
# File 'lib/mccloud/provisioner/chef_solo.rb', line 22

def data_bags_path
  @data_bags_path
end

#encrypted_data_bag_secret_key_pathObject

Returns the value of attribute encrypted_data_bag_secret_key_path.



23
24
25
# File 'lib/mccloud/provisioner/chef_solo.rb', line 23

def encrypted_data_bag_secret_key_path
  @encrypted_data_bag_secret_key_path
end

#envObject (readonly)

Returns the value of attribute env.



17
18
19
# File 'lib/mccloud/provisioner/chef_solo.rb', line 17

def env
  @env
end

#http_proxyObject

Returns the value of attribute http_proxy.



31
32
33
# File 'lib/mccloud/provisioner/chef_solo.rb', line 31

def http_proxy
  @http_proxy
end

#http_proxy_passObject

Returns the value of attribute http_proxy_pass.



33
34
35
# File 'lib/mccloud/provisioner/chef_solo.rb', line 33

def http_proxy_pass
  @http_proxy_pass
end

#http_proxy_userObject

Returns the value of attribute http_proxy_user.



32
33
34
# File 'lib/mccloud/provisioner/chef_solo.rb', line 32

def http_proxy_user
  @http_proxy_user
end

#https_proxyObject

Returns the value of attribute https_proxy.



34
35
36
# File 'lib/mccloud/provisioner/chef_solo.rb', line 34

def https_proxy
  @https_proxy
end

#https_proxy_passObject

Returns the value of attribute https_proxy_pass.



36
37
38
# File 'lib/mccloud/provisioner/chef_solo.rb', line 36

def https_proxy_pass
  @https_proxy_pass
end

#https_proxy_userObject

Returns the value of attribute https_proxy_user.



35
36
37
# File 'lib/mccloud/provisioner/chef_solo.rb', line 35

def https_proxy_user
  @https_proxy_user
end

#jsonObject

Returns the value of attribute json.



24
25
26
# File 'lib/mccloud/provisioner/chef_solo.rb', line 24

def json
  @json
end

#json_erbObject

Returns the value of attribute json_erb.



25
26
27
# File 'lib/mccloud/provisioner/chef_solo.rb', line 25

def json_erb
  @json_erb
end

#log_levelObject

Returns the value of attribute log_level.



30
31
32
# File 'lib/mccloud/provisioner/chef_solo.rb', line 30

def log_level
  @log_level
end

#nameObject (readonly)

Returns the value of attribute name.



16
17
18
# File 'lib/mccloud/provisioner/chef_solo.rb', line 16

def name
  @name
end

#no_proxyObject

Returns the value of attribute no_proxy.



37
38
39
# File 'lib/mccloud/provisioner/chef_solo.rb', line 37

def no_proxy
  @no_proxy
end

#node_nameObject

Returns the value of attribute node_name.



29
30
31
# File 'lib/mccloud/provisioner/chef_solo.rb', line 29

def node_name
  @node_name
end

#provisioning_pathObject

Returns the value of attribute provisioning_path.



21
22
23
# File 'lib/mccloud/provisioner/chef_solo.rb', line 21

def provisioning_path
  @provisioning_path
end

#rolesObject (readonly)

Returns the value of attribute roles.



27
28
29
# File 'lib/mccloud/provisioner/chef_solo.rb', line 27

def roles
  @roles
end

#roles_pathObject

Returns the value of attribute roles_path.



20
21
22
# File 'lib/mccloud/provisioner/chef_solo.rb', line 20

def roles_path
  @roles_path
end

Instance Method Details

#add_recipe(name) ⇒ Object



224
225
226
227
# File 'lib/mccloud/provisioner/chef_solo.rb', line 224

def add_recipe(name)
  name = "recipe[#{name}]" unless name =~ /^recipe\[(.+?)\]$/
  @run_list << name
end

#add_role(name) ⇒ Object



220
221
222
223
# File 'lib/mccloud/provisioner/chef_solo.rb', line 220

def add_role(name)
  name = "role[#{name}]" unless name =~ /^role\[(.+?)\]$/
  @run_list << name
end

#mccloudconfig_to_jsonObject



51
52
# File 'lib/mccloud/provisioner/chef_solo.rb', line 51

def mccloudconfig_to_json
end

#prepareObject



255
256
257
258
# File 'lib/mccloud/provisioner/chef_solo.rb', line 255

def prepare
  share_cookbook_folders
  share_role_folder
end

#provision!Object



260
261
262
263
264
265
266
# File 'lib/mccloud/provisioner/chef_solo.rb', line 260

def provision!
  verify_binary("chef-solo")
  chown_provisioning_folder
  setup_json
  setup_solo_config
  run_chef_solo
end

#run(server) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/mccloud/provisioner/chef_solo.rb', line 54

def run(server)
  if @json_erb
    # http://stackoverflow.com/questions/1338960/ruby-templates-how-to-pass-variables-into-inlined-erb

    public_ips=Hash.new
    private_ips=Hash.new

    providers = Hash.new
    # Add all providers
    server.provider.vms.each do |name,vm|
      providers[vm.provider.name] = vm.provider if providers[vm.provider.name].nil?
    end

    providers.each do |providername,provider|
      hosts = providers[providername].hosts
      hosts.each do |name,host|
        public_ips[name]=host['public_ip_address']
        private_ips[name]=host['private_ip_address']
      end
    end

=begin

    # For each provider , get the ip-addresses
    providers.each do |providername, provider|
      #namespace = provider.namespace
      filter = provider.filter

      provider.raw.servers.each do |s|
        name = s.tags["Name"].sub(/^#{filter}/,'')
        public_ips[name]=s.public_ip_address
        private_ips[name]=s.private_ip_address
      end
    end
=end

    # http://www.techques.com/question/1-3242470/Problem-using-OpenStruct-with-ERB
    # We only want specific variables for ERB
    data = { :public_ips => public_ips, :private_ips => private_ips}

    vars = ErbBinding.new(data)

    # Added vmname in mccloud
    @json.merge!({ :mccloud => {
      :name => server.name,
      :private_ips => private_ips,
      :public_ips => public_ips
    } })

    template = @json.to_json.to_s
    erb = ERB.new(template)

    vars_binding = vars.send(:get_binding)
    result=erb.result(vars_binding)

    #Result = String
    #JSON.parse result = Hash
    #.to_json = String containing JSON formatting of Hash

    @json.merge!(JSON.parse(result))

  else
  end

  @json.merge!({:run_list => @run_list })
  json=@json.to_json

  cooks=Array.new
  @cookbooks_path.each do |cook|
    cooks << File.join("/tmp/"+File.basename(cook))
  end

  # Prepare solo.rb
  configfile=['file_cache_path "/var/chef-solo"']
  configfile << "cookbook_path [\""+cooks.join("\",\"")+"\"]"
  configfile << "log_level #{log_level}"
  configfile << "role_path \"/tmp/#{File.basename(roles_path)}\"" unless roles_path.nil?
  configfile << "data_bag_path \"/tmp/#{File.basename(data_bags_path)}\"" unless data_bags_path.nil?
  configfile << "encrypted_data_bag_secret \"/tmp/#{File.basename(encrypted_data_bag_secret_key_path)}\"" unless encrypted_data_bag_secret_key_path.nil?

  #convert string to Tempfile (instead of StringIO), as server.transfer expects a file with a filename
  temp_file_json = Tempfile.new("dna_json")
  temp_file_json.write(json)
  temp_file_json.close

  temp_file_solo = Tempfile.new("solo_rb")
  temp_file_solo.write(configfile.join("\n"))
  temp_file_solo.close

  server.transfer(temp_file_json.path,"/tmp/dna.json")
  server.transfer(temp_file_solo.path,"/tmp/solo.rb")

  # Share the cookbooks
  i=0
  cookbooks_path.each do |path|
    server.share_folder("cookbook_path-#{i}","/tmp/" + File.basename(path),path,{:mute => true})
    i=i+1
  end

  unless roles_path.nil?
    server.share_folder("roles_path","/tmp/" + File.basename(roles_path),roles_path,{:mute => true})
  end

  unless data_bags_path.nil?
    server.share_folder("databags_path","/tmp/" + File.basename(data_bags_path),data_bags_path,{:mute => true})
  end

  unless encrypted_data_bag_secret_key_path.nil?
    server.share_file("encrypted_databag_secret","/tmp/" + File.basename(encrypted_data_bag_secret_key_path),encrypted_data_bag_secret_key_path,{:mute => true})
  end

  server.share

  env.ui.info "[#{server.name}] - [#{@name}] - running chef-solo"
  env.ui.info "[#{server.name}] - [#{@name}] - login as #{server.user}"

  exec_results = ''

  begin
    if server.user=="root"
      exec_results = server.execute("chef-solo --force-formatter -c /tmp/solo.rb -j /tmp/dna.json -l #{@log_level}")
    else
      exec_results = server.execute("sudo -i chef-solo --force-formatter -c /tmp/solo.rb -j /tmp/dna.json -l #{@log_level}")

      #server.execute("sudo chef-solo -c /tmp/solo.rb -j /tmp/dna.json -l #{@log_level}")
    end
  rescue Exception
  ensure
    if @clean_after_run == true
      env.ui.info "[#{server.name}] - [#{@name}] - Cleaning up dna.json"
      server.execute("rm /tmp/dna.json",{:mute => true})
      env.ui.info "[#{server.name}] - [#{@name}] - Cleaning up solo.json"
      server.execute("rm /tmp/solo.rb", {:mute => true})
      cookbooks_path.each do |path|
        env.ui.info "[#{server.name}] - [#{@name}] - Cleaning cookbook_path #{path}"
        server.execute("rm -rf /tmp/#{File.basename(path)}",{:mute => true})
      end

      unless roles_path.nil?
          env.ui.info "[#{server.name}] - [#{@name}] - Cleaning roles_path #{roles_path}"
          server.execute("rm -rf /tmp/#{File.basename(roles_path)}",{:mute => true})
      end

      unless data_bags_path.nil?
          env.ui.info "[#{server.name}] - [#{@name}] - Cleaning data_bags_path #{data_bags_path}"
          server.execute("rm -rf /tmp/#{File.basename(data_bags_path)}",{:mute => true})
      end

      unless encrypted_data_bag_secret_key_path.nil?
          env.ui.info "[#{server.name}] - [#{@name}] - Cleaning encrypted_databag_secret #{encrypted_data_bag_secret_key_path}"
          server.execute("rm -rf /tmp/#{File.basename(encrypted_data_bag_secret_key_path)}",{:mute => true})
      end
    end

    if (exec_results.status != 0)
      raise ::Mccloud::Error,"Chef solo exit with a non-zero exitcode #{exec_results.status}"
    end
  end

  #Cleaning up

end

#run_chef_soloObject



292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'lib/mccloud/provisioner/chef_solo.rb', line 292

def run_chef_solo
  commands = ["cd #{config.provisioning_path}", "chef-solo -c solo.rb -j dna.json"]

  server.execute.execute do |execute|
    execute.sudo!(commands) do |channel, type, data|
      if type == :exit_status
        execute.check_exit_status(data, commands)
      else
        env.ui.info("#{data}: #{type}")
      end
    end
  end
end

#run_listObject

Returns the run list for the provisioning



217
218
219
# File 'lib/mccloud/provisioner/chef_solo.rb', line 217

def run_list
  json[:run_list] ||= []
end

#setup_config(template, filename, template_vars) ⇒ Object



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/mccloud/provisioner/chef_solo.rb', line 229

def setup_config(template, filename, template_vars)
  config_file = TemplateRenderer.render(template, {
    :log_level => config.log_level.to_sym,
    :http_proxy => config.http_proxy,
    :http_proxy_user => config.http_proxy_user,
    :http_proxy_pass => config.http_proxy_pass,
    :https_proxy => config.https_proxy,
    :https_proxy_user => config.https_proxy_user,
    :https_proxy_pass => config.https_proxy_pass,
    :data_bag_path => config.data_bag_path,
    :roles_path => config.roles_path,
    :no_proxy => config.no_proxy
  }.merge(template_vars))

  # file_cache_path "/var/chef-solo"

  #server.execute.upload!(StringIO.new(config_file), File.join(config.provisioning_path, filename))
end

#setup_jsonObject



248
249
250
251
252
253
# File 'lib/mccloud/provisioner/chef_solo.rb', line 248

def setup_json

  json = Mccloud::Config.config.chef.json.to_json
  #server.execute.upload!(StringIO.new(json), File.join(config.provisioning_path, "dna.json"))
  return json
end

#setup_solo_configObject



280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/mccloud/provisioner/chef_solo.rb', line 280

def setup_solo_config
  setup_config("chef_solo_solo", "solo.rb", {
    :node_name => config.node_name,
    :provisioning_path => config.provisioning_path,
    :cookbooks_path => cookbooks_path,
    :log_level        => :debug,
    :recipe_url => config.recipe_url,
    :roles_path => roles_path,
    :data_bags_path => data_bags_path,
    :encrypted_data_bag_secret_key_path => encrypted_data_bag_secret_key_path
  })
end

#share_cookbook_foldersObject



268
269
270
271
272
# File 'lib/mccloud/provisioner/chef_solo.rb', line 268

def share_cookbook_folders
  host_cookbook_paths.each_with_index do |cookbook, i|
    env.config.vm.share_folder("v-csc-#{i}", cookbook_path(i), cookbook)
  end
end

#share_role_folderObject



274
275
276
277
278
# File 'lib/mccloud/provisioner/chef_solo.rb', line 274

def share_role_folder
  host_roles_path.each_with_index do |role, i|
    env.config.vm.share_folder("v-csr-#{i}", roles_path(i), role)
  end
end