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 +4 -4
- data/lib/chef/knife/ec_backup.rb +7 -2
- data/lib/chef/knife/ec_key_base.rb +74 -0
- data/lib/chef/knife/ec_key_export.rb +45 -0
- data/lib/chef/knife/ec_key_import.rb +76 -0
- data/lib/chef/knife/ec_restore.rb +31 -6
- data/lib/chef/tsorter.rb +20 -0
- data/lib/knife_ec_backup/version.rb +1 -1
- metadata +49 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f6ccb75df554513932811d591b998bc003b5e2a
|
4
|
+
data.tar.gz: f483c5827dc422e42a77a1f3c0d38c6afd23ca44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5faefbd227c50d317b3570ccb88f2c9a0a5e44e7dd5cdca7482b667eafdaf0b779e51c491a83127939da69082c11916df1acf4e48663e80300ce2ede6307dbc8
|
7
|
+
data.tar.gz: a3a8ddadea8cfd3ff190aca59120edf249e59194355e9a97f7fc438c0e692b7bed5cc270ac70735bb246124a0a8679ebde34065f3a4c507ef8af57f6d6c9252f
|
data/lib/chef/knife/ec_backup.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
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
|
data/lib/chef/tsorter.rb
ADDED
@@ -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
|
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.
|
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-
|
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.
|
121
|
+
rubygems_version: 2.0.14
|
76
122
|
signing_key:
|
77
123
|
specification_version: 4
|
78
124
|
summary: Backup and Restore of Enterprise Chef
|