Class: Chef::Knife::DataBagSync

Inherits:
Chef::Knife show all
Includes:
DataBagSecretOptions
Defined in:
lib/chef/knife/data_bag_sync.rb

Overview

DataBagSync class rubocop:disable Metrics/ClassLength

Instance Method Summary collapse

Instance Method Details

#compare(chef_data_bag, local_data_bag) ⇒ Object



52
53
54
55
56
57
58
59
60
# File 'lib/chef/knife/data_bag_sync.rb', line 52

def compare(chef_data_bag, local_data_bag)
  chef_data_bag.each do |item, data|
    if local_data_bag.key?(item)
      compare_item(item, data, local_data_bag[item])
    else
      ui.error("Data bag item '#{item}' could not be locally found")
    end
  end
end

#compare_item(item, chef_item, local_item) ⇒ Object



62
63
64
65
66
67
# File 'lib/chef/knife/data_bag_sync.rb', line 62

def compare_item(item, chef_item, local_item)
  msg = "Item '#{item}':".ljust(50)
  opts = config[:abbrev] ? {} : { array_path: true }
  diff = ::HashDiff.diff(chef_item, local_item, opts)
  diff.empty? ? show_success(msg) : show_error(msg, diff)
end

#data_bag_from_chef(data_bag) ⇒ Object



69
70
71
72
73
74
75
76
77
78
# File 'lib/chef/knife/data_bag_sync.rb', line 69

def data_bag_from_chef(data_bag)
  items = find_chef_data_bag_items(data_bag)
  if items.empty?
    ui.error("No items founded in chef data bag '#{data_bag}'")
  end
  items
rescue Net::HTTPServerException
  ui.error("Data bag '#{data_bag}' could not be found on chef server")
  {}
end

#data_bag_from_file(data_bag, list) ⇒ Object

rubocop:disable Metrics/MethodLength



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/chef/knife/data_bag_sync.rb', line 86

def data_bag_from_file(data_bag, list)
  items = nil
  data_bag_path.map do |data_bag_path|
    path = File.join(data_bag_path, data_bag)
    next unless File.directory?(path)

    items = find_local_data_bag_items(path, list)
    if items.empty?
      ui.error("No items founded in local data bag '#{data_bag}'")
    end
  end

  if items.nil?
    ui.error("Data bag '#{data_bag}' could not be locally found")
    items = {}
  end
  items
end

#data_bag_item_from_chef(data_bag, item) ⇒ Object

rubocop:enable Metrics/MethodLength



106
107
108
109
110
111
112
113
114
115
116
# File 'lib/chef/knife/data_bag_sync.rb', line 106

def data_bag_item_from_chef(data_bag, item)
  data_bag_item = Chef::DataBagItem.load(data_bag, item).raw_data
  if encrypted?(data_bag_item) && secret
    data_bag_item =
      Chef::EncryptedDataBagItem.load(data_bag, item, secret).to_h
  end
  data_bag_item
rescue Net::HTTPServerException
  ui.error("Item '#{item}' could not be found on chef server")
  nil
end

#data_bag_item_from_file(data_bag_path, item) ⇒ Object



118
119
120
121
122
123
124
125
# File 'lib/chef/knife/data_bag_sync.rb', line 118

def data_bag_item_from_file(data_bag_path, item)
  path = Pathname.new(data_bag_path)
  data = loader.load_from(path.parent, File.basename(path), item)
  encrypted?(data) ? decrypt(item, data) : data
rescue SystemExit
  ui.error("Data bag item #{item} could not be loaded")
  nil
end

#data_bag_pathObject



80
81
82
83
# File 'lib/chef/knife/data_bag_sync.rb', line 80

def data_bag_path
  config_path = Chef::Config[:data_bag_path]
  config_path.is_a?(String) ? [config_path] : config_path
end

#decrypt(name, data) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
# File 'lib/chef/knife/data_bag_sync.rb', line 127

def decrypt(name, data)
  if secret
    Chef::EncryptedDataBagItem.new(data, secret).to_hash
  else
    ui.warn(
      "Data bag item '#{name}' is encrypted, but no secret provided " \
      'for decoding (will be ignored)'
    )
    nil
  end
end

#find_chef_data_bag_items(data_bag) ⇒ Object



139
140
141
142
143
# File 'lib/chef/knife/data_bag_sync.rb', line 139

def find_chef_data_bag_items(data_bag)
  Chef::DataBag.load(data_bag).to_hash.map do |item, _|
    [item, data_bag_item_from_chef(data_bag, item)]
  end.to_h
end

#find_local_data_bag_items(data_bag_path, list) ⇒ Object



145
146
147
148
149
150
151
152
153
154
# File 'lib/chef/knife/data_bag_sync.rb', line 145

def find_local_data_bag_items(data_bag_path, list)
  items = {}
  ::Find.find(data_bag_path) do |path|
    item = File.basename(path, File.extname(path))
    if File.file?(path) && list.include?(item)
      items[item] = data_bag_item_from_file(data_bag_path, path)
    end
  end
  items.compact
end

#loaderObject



48
49
50
# File 'lib/chef/knife/data_bag_sync.rb', line 48

def loader
  @loader ||= Core::ObjectLoader.new(Chef::DataBagItem, ui)
end

#runObject



156
157
158
159
160
161
162
163
164
165
# File 'lib/chef/knife/data_bag_sync.rb', line 156

def run
  case @name_args.length
  when 0
    sync_data_bags(Chef::DataBag.list.keys)
  when 1
    sync_data_bags(@name_args)
  when 2
    sync_item(@name_args[0], @name_args[1])
  end
end

#secretObject



167
168
169
# File 'lib/chef/knife/data_bag_sync.rb', line 167

def secret
  encryption_secret_provided_ignore_encrypt_flag? ? read_secret : nil
end

#show_error(msg, diff) ⇒ Object



175
176
177
178
# File 'lib/chef/knife/data_bag_sync.rb', line 175

def show_error(msg, diff)
  ui.info(msg + ui.color('difference(s) found', :yellow))
  pp(diff) if config[:diff]
end

#show_success(msg) ⇒ Object



171
172
173
# File 'lib/chef/knife/data_bag_sync.rb', line 171

def show_success(msg)
  ui.info(msg + ui.color('properly synchronized.', :green))
end

#sync_data_bags(data_bags) ⇒ Object



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

def sync_data_bags(data_bags)
  data_bags.each do |data_bag|
    ui.info("--> Checking data bag '#{data_bag}'")
    chef_data_bag = data_bag_from_chef(data_bag)
    msg = "No items founded in chef data bag '#{data_bag}'"
    next ui.error(msg) if chef_data_bag.empty?

    local_data_bag = data_bag_from_file(data_bag, chef_data_bag.keys)
    next if local_data_bag.empty?

    compare(chef_data_bag, local_data_bag)
  end
end

#sync_item(data_bag, item) ⇒ Object



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

def sync_item(data_bag, item)
  ui.info("-> Checking item '#{item}' from data bag '#{data_bag}'")
  chef_item = data_bag_item_from_chef(data_bag, item)
  local_item = data_bag_from_file(data_bag, [item])
  if local_item.empty?
    ui.error("Data bag item '#{item}' could not be locally found")
  else
    compare_item(item, chef_item, local_item[item])
  end
end