Module: KnifeSpork::Runner::InstanceMethods

Defined in:
lib/knife-spork/runner.rb

Instance Method Summary collapse

Instance Method Details

#all_cookbooksObject



157
158
159
# File 'lib/knife-spork/runner.rb', line 157

def all_cookbooks
  ::Chef::CookbookLoader.new(::Chef::Config.cookbook_path)
end

#calc_diff(cookbook, version) ⇒ Object



273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
# File 'lib/knife-spork/runner.rb', line 273

def calc_diff(cookbook, version)
  components =  version.map{|v|v.split(".")}

  if components.length < 2
    ui.warn "#{cookbook} has no remote version to diff against!"
    return 0
  end

  if components[1][0].to_i != components[0][0].to_i
    return (components[1][0].to_i - components[0][0].to_i)*100
  elsif components[1][1].to_i != components[0][1].to_i
    return (components[1][1].to_i - components[0][1].to_i)*10
  else
    return (components[1][2].to_i - components[0][2].to_i)
  end
end

#constraints_diff(environment_diff) ⇒ Object



269
270
271
# File 'lib/knife-spork/runner.rb', line 269

def constraints_diff (environment_diff)
  Hash[Hash[environment_diff.map{|k,v| [k, v.split(" changed to ").map{|x|x.gsub("= ","")}]}].map{|k,v|[k,calc_diff(k,v)]}]
end

#cookbook_pathObject

It’s not feasible to try and “guess” which cookbook path to use, so we will always just use the first one in the path.



132
133
134
135
# File 'lib/knife-spork/runner.rb', line 132

def cookbook_path
  ensure_cookbook_path!
  [config[:cookbook_path] ||= ::Chef::Config.cookbook_path].flatten[0]
end

#default_environmentsObject



98
99
100
# File 'lib/knife-spork/runner.rb', line 98

def default_environments
  [ spork_config.default_environment || spork_config.default_environments ].flatten.compact
end

#ensure_cookbook_path!Object



290
291
292
293
294
295
296
# File 'lib/knife-spork/runner.rb', line 290

def ensure_cookbook_path!
  if config[:cookbook_path].nil?
    ui.fatal "No default cookbook_path; Specify with -o or fix your knife.rb."
    show_usage
    exit(1)
  end
end

#ensure_environment_and_cookbook_provided!Object



84
85
86
87
88
89
# File 'lib/knife-spork/runner.rb', line 84

def ensure_environment_and_cookbook_provided!
  if default_environments.empty? && @name_args.size < 2
    ui.error('You must specify an environment or environment group and a cookbook name')
    exit(1)
  end
end

#ensure_environment_provided!Object



91
92
93
94
95
96
# File 'lib/knife-spork/runner.rb', line 91

def ensure_environment_provided!
  if default_environments.empty? && @name_args.size < 1
    ui.error('You must specify an environment or configure default environments.')
    exit(1)
  end
end

#environment_diff(local_environment, remote_environment) ⇒ Object



248
249
250
251
252
# File 'lib/knife-spork/runner.rb', line 248

def environment_diff(local_environment, remote_environment)
  local_environment_versions = local_environment.to_hash['cookbook_versions']
  remote_environment_versions = remote_environment.to_hash['cookbook_versions']
  hash_diff remote_environment_versions, local_environment_versions
end

#environment_loaderObject



122
123
124
# File 'lib/knife-spork/runner.rb', line 122

def environment_loader
  @environment_loader ||= Chef::Knife::Core::ObjectLoader.new(::Chef::Environment, ui)
end

#environment_pathObject



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/knife-spork/runner.rb', line 137

def environment_path
  if spork_config[:environment_path]
    if spork_config[:environment_path].kind_of?(Array)
      spork_config[:environment_path].first
    else
      spork_config[:environment_path]
    end
  elsif Chef::Config.environment_path && Chef::Config.environment_path.kind_of?(Array)
    Chef::Config.environment_path.first
  elsif Chef::Config.environment_path && Chef::Config.environment_path.kind_of?(String)
    Chef::Config.environment_path
  else
    cookbook_path.gsub("/cookbooks","/environments")
  end
end

#hash_diff(hash, other) ⇒ Object



260
261
262
263
264
265
266
267
# File 'lib/knife-spork/runner.rb', line 260

def hash_diff(hash, other)
  hash.keys.inject({}) do |memo, key|
    unless hash[key] == other[key]
      memo[key] = "#{hash[key]} changed to #{other[key]}"
    end
    memo
  end
end

#json_diff(a, b) ⇒ Object



254
255
256
257
258
# File 'lib/knife-spork/runner.rb', line 254

def json_diff(a, b)
  pre_json =  JSON.parse(a.respond_to?(:to_json) ? a.to_json : a)
  post_json =  JSON.parse(b.respond_to?(:to_json) ? b.to_json : b)
  Diffy::Diff.new(JSON.pretty_generate(pre_json), JSON.pretty_generate(post_json), :diff=>"-U 3").to_s.gsub(/[()]/, '\\\\\0')
end

#load_cookbook(name) ⇒ Object



161
162
163
164
165
166
167
168
# File 'lib/knife-spork/runner.rb', line 161

def load_cookbook(name)
  return name if name.is_a?(Chef::CookbookVersion)

  cookbook = load_from_chef(name) || load_from_berkshelf(name) || load_from_librarian(name)

  cookbook || raise(Chef::Exceptions::CookbookNotFound,
    "Could not find cookbook '#{name}' in any of the sources!")
end

#load_cookbooks(cookbook_names) ⇒ Object



201
202
203
204
# File 'lib/knife-spork/runner.rb', line 201

def load_cookbooks(cookbook_names)
  cookbook_names = [cookbook_names].flatten
  cookbook_names.collect{ |cookbook_name| load_cookbook(cookbook_name) }
end

#load_databag(bag) ⇒ Object



219
220
221
# File 'lib/knife-spork/runner.rb', line 219

def load_databag(bag)
  Chef::DataBag.load(bag)
end

#load_databag_item(bag, item_name) ⇒ Object



223
224
225
# File 'lib/knife-spork/runner.rb', line 223

def load_databag_item(bag, item_name)
  Chef::DataBagItem.load(bag, item_name)
end

#load_environment(environment_name) ⇒ Object



227
228
229
# File 'lib/knife-spork/runner.rb', line 227

def load_environment(environment_name)
  Chef::Environment.load(environment_name)
end

#load_environment_from_file(environment_name) ⇒ Object



231
232
233
234
235
236
237
# File 'lib/knife-spork/runner.rb', line 231

def load_environment_from_file(environment_name)
  begin
    environment_loader.object_from_file("#{environment_path}/#{environment_name}.json")
  rescue Yajl::ParseError => e
    raise "#{environment_name} environment file has syntactically incorrect json.\n #{e.to_s}" 
  end
end

#load_environments_and_cookbookObject



55
56
57
58
59
60
61
62
63
64
# File 'lib/knife-spork/runner.rb', line 55

def load_environments_and_cookbook
  ensure_environment_and_cookbook_provided!
 
  if @name_args.size == 2
    environments = @name_args[0].split(",").map{ |env| load_specified_environment_group(env) }
    [ environments.flatten, @name_args[1] ]
  elsif @name_args.size == 1
    [ [default_environments].flatten, @name_args[0] ]
  end
end

#load_from_berkshelf(name) ⇒ Object

Raises:

  • (Berkshelf::BerkshelfError)


177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/knife-spork/runner.rb', line 177

def load_from_berkshelf(name)
  return unless defined?(::Berkshelf)
  return unless ::File.exist?(self.config[:berksfile])
  berksfile = ::Berkshelf::Berksfile.from_file(self.config[:berksfile])
  lockfile = ::Berkshelf::Lockfile.new(berksfile)

  raise Berkshelf::BerkshelfError, "LockFileNotFound" unless File.exists?(lockfile.filepath)

  cookbook = Berkshelf.ui.mute {
    self.config[:skip_dependencies] ||= false
    berksfile.resolve(lockfile.find(name), {skip_dependencies: self.config[:skip_dependencies]})[:solution].first
  }

  #convert Berkshelf::CachedCookbook to Chef::CookbookVersion
  ::Chef::CookbookLoader.new(File.dirname(cookbook.path))[name]

end

#load_from_chef(name) ⇒ Object



170
171
172
173
174
175
# File 'lib/knife-spork/runner.rb', line 170

def load_from_chef(name)
  all_cookbooks[name]
rescue Chef::Exceptions::CookbookNotFound,
       Chef::Exceptions::CookbookNotFoundInRepo
  nil
end

#load_from_librarian(name) ⇒ Object

TODO:

#opensource



196
197
198
199
# File 'lib/knife-spork/runner.rb', line 196

def load_from_librarian(name)
  # Your code here :)
  nil
end

#load_node(node) ⇒ Object



215
216
217
# File 'lib/knife-spork/runner.rb', line 215

def load_node(node)
  Chef::Node.load(node)
end

#load_remote_environment(environment_name) ⇒ Object



239
240
241
242
243
244
245
246
# File 'lib/knife-spork/runner.rb', line 239

def load_remote_environment(environment_name)
  begin
    Chef::Environment.load(environment_name)
  rescue Net::HTTPServerException => e
    ui.error "Could not load #{environment_name} from Chef Server. You must upload the environment manually the first time."
    exit(1)
  end
end

#load_role(role_name) ⇒ Object



211
212
213
# File 'lib/knife-spork/runner.rb', line 211

def load_role(role_name)
  Chef::Role.load(role_name)
end

#load_role_from_file(role_name) ⇒ Object



207
208
209
# File 'lib/knife-spork/runner.rb', line 207

def load_role_from_file(role_name)
  role_loader.object_from_file("#{role_path}/#{role_name}.json")
end

#load_specified_environment_group(name) ⇒ Object



76
77
78
79
80
81
82
# File 'lib/knife-spork/runner.rb', line 76

def load_specified_environment_group(name)
  if !spork_config.environment_groups.nil? && spork_config.environment_groups.keys.include?(name)
    spork_config.environment_groups[name]
  else
    [name]
  end
end

#pretty_print_json(json) ⇒ Object



102
103
104
105
106
107
# File 'lib/knife-spork/runner.rb', line 102

def pretty_print_json(json)
  options = spork_config[:json_options] || {}
  # generate requires a hash where the keys are symbols
  options = Hash[ options.to_hash.map {|(k,v)| [k.to_sym,v] }] unless options == {}
  JSON.pretty_generate(json, options.to_hash)
end

#role_loaderObject



126
127
128
# File 'lib/knife-spork/runner.rb', line 126

def role_loader
  @role_loader ||= Chef::Knife::Core::ObjectLoader.new(::Chef::Role, ui)
end

#role_pathObject



153
154
155
# File 'lib/knife-spork/runner.rb', line 153

def role_path
  spork_config[:role_path] || cookbook_path.gsub("/cookbooks","/roles")
end

#run_plugins(hook) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/knife-spork/runner.rb', line 28

def run_plugins(hook)
  cookbooks = [ @cookbooks || @cookbook ].flatten.compact.collect{|cookbook| cookbook.is_a?(::Chef::CookbookVersion) ? cookbook : load_cookbook(cookbook)}.sort{|a,b| a.name.to_s <=> b.name.to_s}

  # Affects promote only:
  # Set loaded cookbook version if the -v or --version parameter was specified
  # Otherwise the version on disk, often more recent will be used.
  # We know cookbooks will only contain one cookbook in the case of promote.
  cookbooks.map{|c|c.version = config[:version]} if config[:version]

  environments = [ @environments || @environment ].flatten.compact.collect{|environment| environment.is_a?(::Chef::Environment) ? environment : load_environment_from_file(environment)}.sort{|a,b| a.name.to_s <=> b.name.to_s}
  environment_diffs = @environment_diffs
  
  KnifeSpork::Plugins.run(
    :config => spork_config,
    :hook => hook.to_sym,
    :cookbooks => cookbooks,
    :environments => environments,
    :environment_diffs => environment_diffs,
    :environment_path => environment_path,
    :cookbook_path => cookbook_path,
    :object_name => @object_name,
    :object_secondary_name => @object_secondary_name,
    :object_difference => @object_difference,
    :ui => ui
  )
end

#spork_configObject



14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/knife-spork/runner.rb', line 14

def spork_config
  return @spork_config unless @spork_config.nil?

  @spork_config = AppConf.new
  load_paths = [ File.expand_path("#{cookbook_path.gsub('cookbooks','')}/config/spork-config.yml"), File.expand_path('config/spork-config.yml'), '/etc/spork-config.yml', File.expand_path('~/.chef/spork-config.yml') ]
  load_paths.each do |load_path|
    if File.exists?(load_path)
      @spork_config.load(load_path)
    end
  end

  @spork_config
end

#unload_berkshelf_if_specifiedObject



298
299
300
301
302
303
304
305
# File 'lib/knife-spork/runner.rb', line 298

def unload_berkshelf_if_specified
  # Temporary fix for #138 to allow Berkshelf functionality
  # to be bypassed until #85 has been completed and Berkshelf 3 support added
  if spork_config.skip_berkshelf
    ui.warn "Unloading Berkshelf as skip_berkshelf option found in config"
    Object.send(:remove_const, :Berkshelf)
  end
end

#valid_version?(version) ⇒ Boolean

Returns:

  • (Boolean)


109
110
111
112
113
# File 'lib/knife-spork/runner.rb', line 109

def valid_version?(version)
  version_keys = version.split('.')
  return false unless version_keys.size == 3 && version_keys.any?{ |k| begin Float(k); rescue false; else true; end }
  true
end

#validate_version!(version) ⇒ Object



115
116
117
118
119
120
# File 'lib/knife-spork/runner.rb', line 115

def validate_version!(version)
  if version && !valid_version?(version)
    ui.error("#{version} is not a valid version!")
    exit(1)
  end
end

#verify_and_load_environmentsObject



66
67
68
69
70
71
72
73
74
# File 'lib/knife-spork/runner.rb', line 66

def verify_and_load_environments
  ensure_environment_provided!

  if @name_args.size == 0
    default_environments
  elsif @name_args.size == 1
    [@name_args[0]]
  end
end