Class: Vagabond::InternalConfiguration

Inherits:
Object
  • Object
show all
Includes:
Helpers
Defined in:
lib/vagabond/internal_configuration.rb

Constant Summary

Constants included from Helpers

Helpers::GEN_NAME_LENGTH, Helpers::RAND_CHARS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helpers

included

Constructor Details

#initialize(vagabondfile, ui, options, args = {}) ⇒ InternalConfiguration

Returns a new instance of InternalConfiguration.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/vagabond/internal_configuration.rb', line 17

def initialize(vagabondfile, ui, options, args={})
  @vagabondfile = vagabondfile
  @checksums = Mash.new
  @ui = ui
  @options = options
  create_store
  load_existing
  @config = Mash.new(
    :mappings => Mash.new,
    :template_mappings => Mash.new,
    :test_mappings => Mash.new,
    :spec_mappings => Mash.new,
    :spec_clusters => Mash.new
  ).merge(config)
  @force_bases = args[:force_bases] || []
  ensure_state
  make_knife_config_if_required
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



12
13
14
# File 'lib/vagabond/internal_configuration.rb', line 12

def config
  @config
end

#force_basesObject

Returns the value of attribute force_bases.



15
16
17
# File 'lib/vagabond/internal_configuration.rb', line 15

def force_bases
  @force_bases
end

#optionsObject (readonly)

Returns the value of attribute options.



14
15
16
# File 'lib/vagabond/internal_configuration.rb', line 14

def options
  @options
end

#uiObject (readonly)

Returns the value of attribute ui.



13
14
15
# File 'lib/vagabond/internal_configuration.rb', line 13

def ui
  @ui
end

Instance Method Details

#[](k) ⇒ Object



59
60
61
# File 'lib/vagabond/internal_configuration.rb', line 59

def [](k)
  @config[k]
end

#[]=(k, v) ⇒ Object



63
64
65
# File 'lib/vagabond/internal_configuration.rb', line 63

def []=(k,v)
  @config[k] = v
end

#cache_pathObject



172
173
174
175
176
177
# File 'lib/vagabond/internal_configuration.rb', line 172

def cache_path
  unless(@cache_path)
    FileUtils.mkdir_p(@cache_path = File.join(store_path, 'chef_cache'))
  end
  @cache_path
end

#check_bases_and_customs!Object



46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/vagabond/internal_configuration.rb', line 46

def check_bases_and_customs!
  if(File.exists?(dna_path))
    dna = Mash.new(JSON.load(File.read(dna_path)))
    %w(bases customs).each do |key|
      if(dna[:vagabond][key])
        dna[:vagabond][key].each do |n, opts|
          options[:force_solo] = true unless Lxc.new(n).exists?
        end
      end
    end
  end
end

#config_pathObject



205
206
207
# File 'lib/vagabond/internal_configuration.rb', line 205

def config_path
  File.join(store_path, 'vagabond.json')
end

#cookbook_pathObject



179
180
181
182
183
184
185
# File 'lib/vagabond/internal_configuration.rb', line 179

def cookbook_path
  File.expand_path(
    File.join(
      File.dirname(__FILE__), 'cookbooks'
    )
  )
end

#create_storeObject



67
68
69
# File 'lib/vagabond/internal_configuration.rb', line 67

def create_store
  FileUtils.mkdir_p(store_path)
end

#dna_pathObject



100
101
102
# File 'lib/vagabond/internal_configuration.rb', line 100

def dna_path
  File.join(store_path, 'dna.json')
end

#ensure_stateObject



36
37
38
39
40
41
42
43
44
# File 'lib/vagabond/internal_configuration.rb', line 36

def ensure_state
  check_bases_and_customs!
  if(solo_needed?)
    store_checksums
    write_dna_json
    write_solo_rb
    run_solo if solo_needed?
  end
end

#file_changed?(path) ⇒ Boolean

Returns:

  • (Boolean)


238
239
240
241
# File 'lib/vagabond/internal_configuration.rb', line 238

def file_changed?(path)
 checksum = get_checksum(path)
 checksum unless @checksums[path] == checksum
end

#get_checksum(path) ⇒ Object



150
151
152
153
154
155
156
157
158
# File 'lib/vagabond/internal_configuration.rb', line 150

def get_checksum(path)
  if(File.exists?(path))
    s = Digest::SHA256.new
    s << File.read(path)
    s.hexdigest
  else
    ''
  end
end

#knife_config_available?Boolean

Returns:

  • (Boolean)


224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/vagabond/internal_configuration.rb', line 224

def knife_config_available?
  if(File.exists?(File.join(store_path, 'knife.rb')))
    false
  else
    cwd = @vagabondfile.directory.split('/')
    found = false
    until(found || cwd.empty?)
      found = File.exists?(File.join(*(cwd + ['.chef/knife.rb'])))
      cwd.pop
    end
    found
  end
end

#load_existing(file = nil) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/vagabond/internal_configuration.rb', line 71

def load_existing(file=nil)
  if(File.exists?(path = File.join(store_path, 'vagabond.json')))
    if(file)
      file.rewind
      content = file.read
    else
      content = File.read(path)
    end
    if(content.strip.empty?)
      config = Mash.new
    else
      config = Mash.new(
        JSON.load(content)
      )
    end
    @config = Chef::Mixin::DeepMerge.merge(config, @config)
  else
    @config = Mash.new
  end
end

#make_knife_config_if_required(force = false) ⇒ Object



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/vagabond/internal_configuration.rb', line 243

def make_knife_config_if_required(force=false)
  if((@vagabondfile[:local_chef_server] && @vagabondfile[:local_chef_server][:enabled]) || force)
    unless(knife_config_available?)
      store_dir = File.dirname(store_path)
      k_dir = File.join(store_dir, '.chef')
      FileUtils.mkdir_p(k_dir)
      unless(File.exists?(knife = File.join(k_dir, 'knife.rb')))
        File.open(knife, 'w') do |file|
          file.write <<-EOF
node_name 'dummy'
client_key File.join(File.dirname(__FILE__), 'client.pem')
validation_client_name 'dummy-validator'
validation_key File.join(File.dirname(__FILE__), 'validation.pem')
cookbook_path ['#{%w(cookbooks site-cookbooks).map{|dir|File.join(@vagabondfile.directory, dir)}.join(',')}']
EOF
        end
      end
      %w(client.pem validation.pem).each do |name|
        unless(File.exists?(pem = File.join(k_dir, name)))
          %x{openssl genrsa -out #{pem} 2048}
        end
      end
    end
  end
end

#run_soloObject



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/vagabond/internal_configuration.rb', line 187

def run_solo
  begin
    ui.info ui.color('Ensuring expected system state (creating required base containers)', :yellow)
    ui.info ui.color('   - This can take a while on first run or new templates...', :yellow)
    com = "#{options[:sudo]}chef-solo -j #{File.join(store_path, 'dna.json')} -c #{File.join(store_path, 'solo.rb')}"
    debug(com)
    cmd = Mixlib::ShellOut.new(com, :timeout => 12000, :live_stream => options[:debug])
    cmd.run_command
    cmd.error!
    ui.info ui.color('  -> COMPLETE!', :yellow)
  rescue => e
    ui.info e.to_s
    FileUtils.rm(solo_path)
    ui.info ui.color('  -> FAILED!', :red, :bold)
    raise VagabondError::HostProvisionFailed.new(e)
  end
end

#saveObject



209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/vagabond/internal_configuration.rb', line 209

def save
  mode = File.exists?(config_path) ? 'r+' : 'w+'
  File.open(config_path, mode) do |file|
    file.flock(File::LOCK_EX)
    file.rewind
    if(sha = file_changed?(file.path))
      @checksums[file.path] = sha
      load_existing(file)
    end
    file.rewind
    file.write(JSON.pretty_generate(@config))
    file.truncate(file.pos)
  end
end

#solo_needed?Boolean

Returns:

  • (Boolean)


160
161
162
163
164
165
166
167
168
169
170
# File 'lib/vagabond/internal_configuration.rb', line 160

def solo_needed?
  if(options[:force_solo])
    true
  elsif(options[:disable_solo])
    false
  else
    [dna_path, solo_path].detect do |path|
      @checksums[path] != get_checksum(path)
    end
  end
end

#solo_pathObject



104
105
106
# File 'lib/vagabond/internal_configuration.rb', line 104

def solo_path
  File.join(store_path, 'solo.rb')
end

#store_checksumsObject



144
145
146
147
148
# File 'lib/vagabond/internal_configuration.rb', line 144

def store_checksums
  [dna_path, solo_path].each do |path|
    @checksums[path] = get_checksum(path)
  end
end

#store_pathObject



92
93
94
95
96
97
98
# File 'lib/vagabond/internal_configuration.rb', line 92

def store_path
  path = File.join(File.dirname(@vagabondfile.store_path), '.vagabond')
  unless(File.directory?(path))
    FileUtils.mkdir_p(path)
  end
  path
end

#write_dna_jsonObject



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
# File 'lib/vagabond/internal_configuration.rb', line 108

def write_dna_json
  conf = Mash.new(:bases => Mash.new, :customs => Mash.new)
  (Array(@vagabondfile[:nodes]).map(&:last).map{|i| i[:template]}.compact + Array(force_bases)).uniq.each do |t|
    conf[:bases][t] = Mash.new(:enabled => true) if BASE_TEMPLATES.include?(t.to_s)
  end
  Array(@vagabondfile[:templates]).each do |t_name, opts|
    if(BASE_TEMPLATES.include?(opts[:base].to_s))
      conf[:bases][opts[:base]] = Mash.new(:enabled => true)
      if(opts.has_key?(:memory) && !opts[:memory].is_a?(Hash))
        opts[:memory][:ram] = opts[:memory].to_s
      end
      conf[:customs][generated_name(t_name)] = opts
      config[:template_mappings][t_name] = generated_name(t_name)
    else
      ui.fatal "Invalid base template encountered: #{t_name}"
      ui.info ui.color("  -> Valid base templates: #{BASE_TEMPLATES.sort.join(', ')}", :red)
      raise VagabondError::InvalidBaseTemplate.new(t_name)
    end
  end
  File.open(dna_path, 'w') do |file|
    file.write(
      JSON.dump(
        :vagabond => conf,
        :run_list => %w(recipe[vagabond])
      )
    )
  end
  save
end

#write_solo_rbObject



138
139
140
141
142
# File 'lib/vagabond/internal_configuration.rb', line 138

def write_solo_rb
  File.open(solo_path, 'w') do |file|
    file.write("\nfile_cache_path \"#{cache_path}\"\ncookbook_path \"#{cookbook_path}\"\n")
  end
end