knife-ec-backup 1.1.8 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 555db6e18f609eb180e4903ce2ca211db5f33444
4
- data.tar.gz: 07a794b5dbd08e1c383eb25072ff88e20cdfbcb5
3
+ metadata.gz: 2f6ccb75df554513932811d591b998bc003b5e2a
4
+ data.tar.gz: f483c5827dc422e42a77a1f3c0d38c6afd23ca44
5
5
  SHA512:
6
- metadata.gz: d4679a94465e27cfdbb81930aa828fef32523df2dced01c7be95141691dfe91693ae8749e8003666879f8c04fa331bed31ca9a1a805a400006b9757f0d52ee37
7
- data.tar.gz: 23e4d67586e1ff4b6c9e934ff770fdfe6c5bc14c5dcee06e6ba39ab67540f70d7bb7eec6e90f93b01ca2ddc7898c25bad3bef6c2cec1a984004cd8442132d48a
6
+ metadata.gz: 5faefbd227c50d317b3570ccb88f2c9a0a5e44e7dd5cdca7482b667eafdaf0b779e51c491a83127939da69082c11916df1acf4e48663e80300ce2ede6307dbc8
7
+ data.tar.gz: a3a8ddadea8cfd3ff190aca59120edf249e59194355e9a97f7fc438c0e692b7bed5cc270ac70735bb246124a0a8679ebde34065f3a4c507ef8af57f6d6c9252f
@@ -3,7 +3,7 @@ require 'chef/knife'
3
3
  class Chef
4
4
  class Knife
5
5
  class EcBackup < Chef::Knife
6
- banner "knife ec backup"
6
+ banner "knife ec backup DIRECTORY"
7
7
 
8
8
  option :concurrency,
9
9
  :long => '--concurrency THREADS',
@@ -25,6 +25,10 @@ class Chef
25
25
  :default => false,
26
26
  :description => "Whether to skip checking the Chef Server version. This will also skip any auto-configured options"
27
27
 
28
+ option :org,
29
+ :long => '--only-org ORGNAME',
30
+ :description => "Only back up objects in the named organization (default: all orgs)"
31
+
28
32
  deps do
29
33
  require 'chef_fs/config'
30
34
  require 'chef_fs/file_system'
@@ -140,8 +144,9 @@ class Chef
140
144
  # Download organizations
141
145
  ensure_dir("#{dest_dir}/organizations")
142
146
  rest.get_rest('/organizations').each_pair do |name, url|
147
+ do_org = (config[:org].nil? || config[:org] == name)
143
148
  org = rest.get_rest(url)
144
- if org['assigned_at']
149
+ if org['assigned_at'] and do_org
145
150
  puts "Grabbing organization #{name} ..."
146
151
  ensure_dir("#{dest_dir}/organizations/#{name}")
147
152
  download_org(dest_dir, webui_key, name)
@@ -0,0 +1,74 @@
1
+ #
2
+ # Author:: Steven Danna (<steve@getchef.com>)
3
+ # Copyright:: Copyright (c) 2014 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef/knife'
20
+
21
+ class Chef
22
+ class Knife
23
+ module EcKeyBase
24
+
25
+ def self.included(includer)
26
+ includer.class_eval do
27
+
28
+ deps do
29
+ require 'sequel'
30
+ require 'json'
31
+ end
32
+
33
+ option :sql_host,
34
+ :long => '--sql-host HOSTNAME',
35
+ :description => 'Postgresql database hostname (default: localhost)',
36
+ :default => "localhost"
37
+
38
+ option :sql_port,
39
+ :long => '--sql-port PORT',
40
+ :description => 'Postgresql database port (default: 5432)',
41
+ :default => 5432
42
+
43
+ option :sql_user,
44
+ :long => "--sql-user USERNAME",
45
+ :description => 'User used to connect to the postgresql database.'
46
+
47
+ option :sql_password,
48
+ :long => "--sql-password PASSWORD",
49
+ :description => 'Password used to connect to the postgresql database'
50
+ end
51
+ end
52
+
53
+ def db
54
+ @db ||= begin
55
+ server_string = "#{config[:sql_user]}:#{config[:sql_password]}@#{config[:sql_host]}:#{config[:sql_port]}/opscode_chef"
56
+ Sequel.connect("postgres://#{server_string}")
57
+ end
58
+ end
59
+
60
+ # Loads SQL user and password from running config if not passed
61
+ # as a command line option
62
+ def load_config_from_file!
63
+ if ! File.exists?("/etc/opscode/chef-server-running.json")
64
+ ui.fatal "SQL User or Password not provided as option and running config cannot be found!"
65
+ exit 1
66
+ else
67
+ running_config ||= JSON.parse(File.read("/etc/opscode/chef-server-running.json"))
68
+ config[:sql_user] ||= running_config['private_chef']['postgresql']['sql_user']
69
+ config[:sql_password] ||= running_config['private_chef']['postgresql']['sql_password']
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,45 @@
1
+ #
2
+ # Author:: Steven Danna (<steve@getchef.com>)
3
+ # Copyright:: Copyright (c) 2014 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef/knife'
20
+ require 'chef/knife/ec_key_base'
21
+
22
+ class Chef
23
+ class Knife
24
+ class EcKeyExport < Chef::Knife
25
+
26
+ include Knife::EcKeyBase
27
+
28
+ banner "knife ec key export [PATH]"
29
+
30
+ def run
31
+ if config[:sql_user].nil? || config[:sql_password].nil?
32
+ load_config_from_file!
33
+ end
34
+
35
+ path = @name_args[0] || "key_dump.json"
36
+ export(path)
37
+ end
38
+
39
+ def export(path)
40
+ users = db.select(:username, :public_key, :pubkey_version, :hashed_password, :salt, :hash_type).from(:users)
41
+ File.open(path, 'w') { |file| file.write(users.all.to_json) }
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,76 @@
1
+ #
2
+ # Author:: Steven Danna (<steve@getchef.com>)
3
+ # Copyright:: Copyright (c) 2014 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef/knife'
20
+ require 'chef/knife/ec_key_base'
21
+
22
+ class Chef
23
+ class Knife
24
+ class EcKeyImport < Chef::Knife
25
+
26
+ include Knife::EcKeyBase
27
+
28
+ banner "knife ec key import [PATH]"
29
+
30
+ option :skip_pivotal,
31
+ :long => "--[no-]skip-pivotal",
32
+ :default => true,
33
+ :boolean => true,
34
+ :description => "Upload pivotal key. By default the pivotal key is not uploaded."
35
+
36
+ def run
37
+ if config[:sql_user].nil? || config[:sql_password].nil?
38
+ load_config_from_file!
39
+ end
40
+
41
+ path = @name_args[0] || "key_dump.json"
42
+ import(path)
43
+ end
44
+
45
+
46
+ def import(path)
47
+ key_data = JSON.parse(File.read(path))
48
+ key_data.each do |d|
49
+ username = d['username']
50
+ key = d['public_key']
51
+ version = d['pubkey_version']
52
+ hashed_password = d['hashed_password']
53
+ hash_type = d['hash_type']
54
+ salt = d['salt']
55
+
56
+ if username == 'pivotal' && config[:skip_pivotal]
57
+ ui.warn "Skipping pivotal user."
58
+ next
59
+ end
60
+
61
+ ui.msg "Updating key for #{username}"
62
+ users_to_update = db[:users].where(:username => username)
63
+ if users_to_update.count != 1
64
+ ui.warn "Wrong number of users to update for #{username}. Skipping"
65
+ else
66
+ users_to_update.update(:public_key => key,
67
+ :pubkey_version => version,
68
+ :salt => salt,
69
+ :hashed_password => hashed_password,
70
+ :hash_type => hash_type)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -3,7 +3,7 @@ require 'chef/knife'
3
3
  class Chef
4
4
  class Knife
5
5
  class EcRestore < Chef::Knife
6
- banner "knife ec restore"
6
+ banner "knife ec restore DIRECTORY"
7
7
 
8
8
  option :concurrency,
9
9
  :long => '--concurrency THREADS',
@@ -40,6 +40,7 @@ class Chef
40
40
  require 'chef_fs/data_handler/acl_data_handler'
41
41
  require 'securerandom'
42
42
  require 'chef_fs/parallelizer'
43
+ require 'chef/tsorter'
43
44
  end
44
45
 
45
46
  def configure_chef
@@ -64,8 +65,8 @@ class Chef
64
65
  ui.error("Username not configured as pivotal and /etc/opscode/pivotal.pem does not exist. It is recommended that you run this plugin from your Chef server.")
65
66
  exit 1
66
67
  end
67
- node_name = 'pivotal'
68
- client_key = '/etc/opscode/pivotal.pem'
68
+ Chef::Config.node_name = 'pivotal'
69
+ Chef::Config.client_key = '/etc/opscode/pivotal.pem'
69
70
  end
70
71
 
71
72
  #Check for WebUI Key
@@ -268,9 +269,14 @@ class Chef
268
269
  puts "Restoring the rest of the org"
269
270
  chef_fs_config = ::ChefFS::Config.new
270
271
  top_level_paths = chef_fs_config.local_fs.children.select { |entry| entry.name != 'acls' && entry.name != 'groups' }.map { |entry| entry.path }
271
- acl_paths = ::ChefFS::FileSystem.list(chef_fs_config.local_fs, ::ChefFS::FilePattern.new('/acls/*')).select { |entry| entry.name != 'groups' }.map { |entry| entry.path }
272
+
273
+ # Topologically sort groups for upload
274
+ unsorted_groups = ::ChefFS::FileSystem.list(chef_fs_config.local_fs, ::ChefFS::FilePattern.new('/groups/*')).select { |entry| entry.name != 'billing-admins.json' }.map { |entry| JSON.parse(entry.read) }
275
+ group_paths = sort_groups_for_upload(unsorted_groups).map { |group_name| "/groups/#{group_name}.json" }
276
+
272
277
  group_acl_paths = ::ChefFS::FileSystem.list(chef_fs_config.local_fs, ::ChefFS::FilePattern.new('/acls/groups/*')).select { |entry| entry.name != 'billing-admins.json' }.map { |entry| entry.path }
273
- group_paths = ::ChefFS::FileSystem.list(chef_fs_config.local_fs, ::ChefFS::FilePattern.new('/groups/*')).select { |entry| entry.name != 'billing-admins.json' }.map { |entry| entry.path }
278
+ acl_paths = ::ChefFS::FileSystem.list(chef_fs_config.local_fs, ::ChefFS::FilePattern.new('/acls/*')).select { |entry| entry.name != 'groups' }.map { |entry| entry.path }
279
+
274
280
  (top_level_paths + group_paths + group_acl_paths + acl_paths).each do |path|
275
281
  ::ChefFS::FileSystem.copy_to(::ChefFS::FilePattern.new(path), chef_fs_config.local_fs, chef_fs_config.chef_fs, nil, config, ui, proc { |entry| chef_fs_config.format_path(entry) })
276
282
  end
@@ -279,7 +285,7 @@ class Chef
279
285
  Chef::Config[:client_key] = old_config['client_key']
280
286
  Chef::Config.custom_http_headers = {}
281
287
  ['admins', 'billing-admins'].each do |group|
282
- restore_group(::ChefFS::Config.new, group, :users => false)
288
+ restore_group(::ChefFS::Config.new, group)
283
289
  end
284
290
  ensure
285
291
  CONFIG_VARS.each do |key|
@@ -288,6 +294,25 @@ class Chef
288
294
  end
289
295
  end
290
296
 
297
+ # Takes an array of group objects
298
+ # and topologically sorts them
299
+ def sort_groups_for_upload(groups)
300
+ Chef::Tsorter.new(group_array_to_sortable_hash(groups)).tsort
301
+ end
302
+
303
+ def group_array_to_sortable_hash(groups)
304
+ ret = {}
305
+ groups.each do |group|
306
+ name = group["name"]
307
+ ret[name] = if group.key?("groups")
308
+ group["groups"]
309
+ else
310
+ []
311
+ end
312
+ end
313
+ ret
314
+ end
315
+
291
316
  def restore_group(chef_fs_config, group_name, includes = {:users => true, :clients => true})
292
317
  includes[:users] = true unless includes.key? :users
293
318
  includes[:clients] = true unless includes.key? :clients
@@ -0,0 +1,20 @@
1
+ require 'tsort'
2
+
3
+ class Chef
4
+ class Tsorter
5
+
6
+ include TSort
7
+
8
+ def initialize(data)
9
+ @data = data
10
+ end
11
+
12
+ def tsort_each_node(&block)
13
+ @data.each_key(&block)
14
+ end
15
+
16
+ def tsort_each_child(node, &block)
17
+ @data.fetch(node).each(&block)
18
+ end
19
+ end
20
+ end
@@ -1,3 +1,3 @@
1
1
  module KnifeECBackup
2
- VERSION = '1.1.8'
2
+ VERSION = '1.1.9'
3
3
  end
metadata CHANGED
@@ -1,15 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-ec-backup
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.8
4
+ version: 1.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Keiser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-31 00:00:00.000000000 Z
11
+ date: 2014-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: knife-essentials
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sequel
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pg
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
13
55
  - !ruby/object:Gem::Dependency
14
56
  name: rspec
15
57
  requirement: !ruby/object:Gem::Requirement
@@ -50,7 +92,11 @@ files:
50
92
  - README.md
51
93
  - Rakefile
52
94
  - lib/chef/knife/ec_backup.rb
95
+ - lib/chef/knife/ec_key_base.rb
96
+ - lib/chef/knife/ec_key_export.rb
97
+ - lib/chef/knife/ec_key_import.rb
53
98
  - lib/chef/knife/ec_restore.rb
99
+ - lib/chef/tsorter.rb
54
100
  - lib/knife_ec_backup/version.rb
55
101
  homepage: http://www.opscode.com
56
102
  licenses:
@@ -72,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
118
  version: '0'
73
119
  requirements: []
74
120
  rubyforge_project:
75
- rubygems_version: 2.1.5
121
+ rubygems_version: 2.0.14
76
122
  signing_key:
77
123
  specification_version: 4
78
124
  summary: Backup and Restore of Enterprise Chef