Class: Chef::Knife::BataliSync

Inherits:
Chef::Knife show all
Defined in:
lib/chef/knife/batali_sync.rb

Overview

Batali manifest to chef server sync

Instance Method Summary collapse

Instance Method Details

#add_cookbooks(ckbks) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/chef/knife/batali_sync.rb', line 98

def add_cookbooks(ckbks)
  Batali::Command::Install.new({}, []).execute!
  ui.info "#{ui.color('[Batali]', :green, :bold)}: Adding cookbooks to Chef server."
  Knife::Upload.load_deps
  ckbks.each do |c_name, vers|
    vers.each do |version|
      c_path = [
        File.join('cookbooks', c_name),
        File.join('cookbooks', "#{c_name}-#{version}")
      ].detect do |_path|
        File.directory?(_path)
      end
      uploader = Knife::Upload.new
      uploader.configure_chef
      uploader.config = config
      uploader.name_args = [c_path]
      if(config[:verbose])
        ui.warn "Unloading cookbook #{c_name} @ #{version} - `#{c_path}`"
      end
      uploader.run
    end
  end
  ui.info "#{ui.color('[Batali]', :green, :bold)}: Chef server cookbook additions complete."
end

#display_sync_info(opts) ⇒ Object



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
# File 'lib/chef/knife/batali_sync.rb', line 123

def display_sync_info(opts)
  num_remove = ui.color(opts[:removals].size.to_s, :red, :bold)
  num_add = ui.color(opts[:additions].size.to_s, :green, :bold)
  ui.info "#{ui.color('[Batali]', :green, :bold)}: Removals - #{num_remove} Additions: #{num_add}"
  if(config[:details])
    unless(opts[:removals].empty?)
      ui.info "#{ui.color('[Batali]', :green, :bold)}: Cookbooks to be #{ui.color('removed', :red, :bold)}:"
      opts[:removals].sort.each do |name, versions|
        vers = versions.map do |v|
          Gem::Version.new(v)
        end.sort.map(&:to_s).join(', ')
        ui.info "  #{ui.color(name, :red, :bold)}: #{ui.color(vers, :red)}"
      end
    end
    unless(opts[:additions].empty?)
      ui.info "#{ui.color('[Batali]', :green, :bold)}: Cookbooks to be #{ui.color('added', :green, :bold)}:"
      opts[:additions].sort.each do |name, versions|
        vers = versions.map do |v|
          Gem::Version.new(v)
        end.sort.map(&:to_s).join(', ')
        ui.info "  #{ui.color(name, :green, :bold)}: #{ui.color(vers, :green)}"
      end
    end
    if(Chef::Config[:knife][:batali_show_remaining])
      ui.info "#{ui.color('[Batali]', :green, :bold)}: Final list of cookbooks to be available on the chef server:" # rubocop:disable Metrics/LineLength
      opts[:manifest].sort.each do |name, versions|
        vers = versions.map do |v|
          Gem::Version.new(v)
        end.sort.map(&:to_s).join(', ')
        ui.info "  #{ui.color(name, :bold)}: #{vers}"
      end
    end
  end
end

#generate_manifest_cookbooksObject



180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/chef/knife/batali_sync.rb', line 180

def generate_manifest_cookbooks
  path = File.join(Dir.pwd, 'batali.manifest')
  unless(File.exist?(path))
    raise "Failed to locate batali manifest at: #{path}"
  end
  manifest = Batali::Manifest.build(path)
  Smash.new.tap do |ckbks|
    manifest.cookbook.each do |c|
      next if Chef::Config[:knife][:batali_blacklist].include?(c.name)
      ckbks[c.name] ||= []
      ckbks[c.name] << c.version.to_s
    end
  end
end

#generate_remote_cookbooksObject



195
196
197
198
199
200
201
202
203
204
205
# File 'lib/chef/knife/batali_sync.rb', line 195

def generate_remote_cookbooks
  Smash.new.tap do |ckbks|
    rest.get('cookbooks?num_versions=all').map do |c_name, meta|
      next if Chef::Config[:knife][:batali_blacklist].include?(c_name)
      ckbks[c_name] = []
      meta['versions'].each do |info|
        ckbks[c_name] << info['version']
      end
    end
  end
end

#locate_additions(opts) ⇒ Object



169
170
171
172
173
174
175
176
177
178
# File 'lib/chef/knife/batali_sync.rb', line 169

def locate_additions(opts)
  Smash.new.tap do |add|
    opts[:manifest].each do |c_name, c_versions|
      adds = c_versions - opts[:server].fetch(c_name, [])
      unless(adds.empty?)
        add[c_name] = adds
      end
    end
  end
end

#locate_removals(opts) ⇒ Object



158
159
160
161
162
163
164
165
166
167
# File 'lib/chef/knife/batali_sync.rb', line 158

def locate_removals(opts)
  Smash.new.tap do |rm|
    opts[:server].each do |c_name, c_versions|
      kills = c_versions - opts[:manifest].fetch(c_name, [])
      unless(kills.empty?)
        rm[c_name] = kills
      end
    end
  end
end

#remove_cookbooks(ckbks) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/chef/knife/batali_sync.rb', line 85

def remove_cookbooks(ckbks)
  run_task('Removing cookbooks') do
    ckbks.each do |c_name, vers|
      vers.each do |version|
        if(config[:verbose])
          ui.warn "Deleting cookbook #{c_name} @ #{version}"
        end
        rest.delete("/cookbooks/#{c_name}/#{version}")
      end
    end
  end
end

#runObject



44
45
46
47
48
49
50
51
52
53
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
# File 'lib/chef/knife/batali_sync.rb', line 44

def run
  Chef::Config[:knife][:batali_blacklist] ||= []
  config[:verbose] = config[:verbosity].to_i > 0
  ui.info "#{ui.color('[Batali]', :green, :bold)}: Chef Server Batali Manifest Sync"
  valid_cookbooks = run_task('Generating valid cookbook versions from manifest') do
    generate_manifest_cookbooks
  end
  remote_cookbooks = run_task('Generating remote cookbook versions from chef server') do
    generate_remote_cookbooks
  end
  to_remove = run_task('Building cookbook removal list') do
    locate_removals(
      :manifest => valid_cookbooks,
      :server => remote_cookbooks
    )
  end
  to_add = run_task('Building cookbook upload list') do
    locate_additions(
      :manifest => valid_cookbooks,
      :server => remote_cookbooks
    )
  end
  if(to_add.empty? && to_remove.empty?)
    ui.info "#{ui.color('[Batali]', :green, :bold)}: Chef Server Batali Manifest Sync - #{ui.color('No Changes Detected!', :green, :bold)}" # rubocop:disable Metrics/LineLength
  else
    display_sync_info(
      :additions => to_add,
      :removals => to_remove,
      :manifest => valid_cookbooks
    )
    unless(config[:dry_run])
      ui.confirm 'Sync remote cookbooks with Batali manifest'
      remove_cookbooks(to_remove) unless to_remove.empty?
      add_cookbooks(to_add) unless to_add.empty?
      ui.info "#{ui.color('[Batali]', :green, :bold)}: Chef Server Batali Manifest Sync - #{ui.color('Sync Complete!', :green, :bold)}" # rubocop:disable Metrics/LineLength
    else
      ui.warn 'Dry run requested. No action taken.'
    end
  end
end

#run_task(task) ⇒ Object



207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/chef/knife/batali_sync.rb', line 207

def run_task(task)
  ui.stdout.print "#{ui.color('[Batali]', :green, :bold)}: #{task}... "
  begin
    value = yield if block_given?
    ui.info ui.color('complete', :green)
    value
  rescue => e
    ui.info ui.color('failed', :red, :bold)
    puts e.backtrace.join("\n")
    raise e
  end
end