knife-ec-backup 1.2.0 → 2.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -4
- data/lib/chef/knife/ec_backup.rb +36 -28
- data/lib/chef/knife/ec_key_base.rb +2 -1
- data/lib/chef/knife/ec_key_export.rb +1 -1
- data/lib/chef/knife/ec_key_import.rb +15 -5
- data/lib/chef/knife/ec_restore.rb +91 -67
- data/lib/knife_ec_backup/version.rb +1 -1
- metadata +14 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 24f0f5bf6187090c18829999dd6ae339b8f97f44
|
4
|
+
data.tar.gz: c90dc04b94f007fb059a03021e2d951411e60d92
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8f804e4a2a9bcc0486c86f618af446f3d8cea3a8ce002a39705db49652d6301ac5d68d65b1224c0f5b2db60a8eca620b50c0012a3fabff08ce40762555f1389
|
7
|
+
data.tar.gz: 0c5f596befa740f26deb0b7bc4bc50065333904d039ce22ded2e9bf02768e5c0475660c4a2d7723d1359901372a58b50463408b2683b6f6e9cfc56f65e469f69
|
data/README.md
CHANGED
@@ -6,9 +6,12 @@ This is an UNOFFICIAL and EXPERIMENTAL knife plugin intended to back up and rest
|
|
6
6
|
|
7
7
|
# Requirements
|
8
8
|
|
9
|
-
This knife plugin
|
9
|
+
This knife plugin requires Chef 11.8+.
|
10
10
|
|
11
|
-
|
11
|
+
## Chef 10
|
12
|
+
|
13
|
+
Users who are still using Chef 10 can use the most recent 1.x version
|
14
|
+
of this gem. Version 1.x additionally depends on knife-essentials.
|
12
15
|
|
13
16
|
# Installation
|
14
17
|
|
@@ -16,7 +19,6 @@ This knife plugin currently requires the Knife-Essentials gem to be installed in
|
|
16
19
|
This will install the plugin directly on the Chef Server:
|
17
20
|
|
18
21
|
/opt/opscode/embedded/bin/gem install knife-ec-backup
|
19
|
-
/opt/opscode/embedded/bin/gem install knife-ec-backup
|
20
22
|
|
21
23
|
## Build from source
|
22
24
|
Clone the git repository and run the following from inside:
|
@@ -118,4 +120,4 @@ Restores all data from a repository to an Enterprise Chef / Private Chef server.
|
|
118
120
|
* Single org backups.
|
119
121
|
* This plugin does **NOT** currently backup user passwords. **They will have to be reset after a restore.**
|
120
122
|
* This plugin does **NOT** currently restore user public keys. **Private keys will have to be reset after a restore.**
|
121
|
-
* This plugin does **NOT** currently restore custom user ACLs. **It will revert back to default ACLs on a restore.**
|
123
|
+
* This plugin does **NOT** currently restore custom user ACLs. **It will revert back to default ACLs on a restore.**
|
data/lib/chef/knife/ec_backup.rb
CHANGED
@@ -25,21 +25,25 @@ 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 :with_user_sql,
|
29
|
+
:long => '--with-user-sql',
|
30
|
+
:description => 'Whether to try direct data base access for user export. Required to properly handle passwords, keys, and USAGs'
|
31
|
+
|
28
32
|
option :org,
|
29
33
|
:long => '--only-org ORGNAME',
|
30
34
|
:description => "Only back up objects in the named organization (default: all orgs)"
|
31
35
|
|
32
36
|
deps do
|
33
|
-
require 'chef_fs/config'
|
34
|
-
require 'chef_fs/file_system'
|
35
|
-
require 'chef_fs/file_pattern'
|
36
|
-
require 'chef_fs/parallelizer'
|
37
|
+
require 'chef/chef_fs/config'
|
38
|
+
require 'chef/chef_fs/file_system'
|
39
|
+
require 'chef/chef_fs/file_pattern'
|
40
|
+
require 'chef/chef_fs/parallelizer'
|
37
41
|
end
|
38
42
|
|
39
43
|
def configure_chef
|
40
44
|
super
|
41
45
|
Chef::Config[:concurrency] = config[:concurrency].to_i if config[:concurrency]
|
42
|
-
::ChefFS::Parallelizer.threads = (Chef::Config[:concurrency] || 10) - 1
|
46
|
+
Chef::ChefFS::Parallelizer.threads = (Chef::Config[:concurrency] || 10) - 1
|
43
47
|
end
|
44
48
|
|
45
49
|
def run
|
@@ -122,7 +126,6 @@ class Chef
|
|
122
126
|
|
123
127
|
# Grab users
|
124
128
|
puts "Grabbing users ..."
|
125
|
-
|
126
129
|
ensure_dir("#{dest_dir}/users")
|
127
130
|
ensure_dir("#{dest_dir}/user_acls")
|
128
131
|
|
@@ -141,6 +144,16 @@ class Chef
|
|
141
144
|
end
|
142
145
|
end
|
143
146
|
|
147
|
+
if config[:with_user_sql]
|
148
|
+
require 'chef/knife/ec_key_export'
|
149
|
+
Chef::Knife::EcKeyExport.deps
|
150
|
+
k = Chef::Knife::EcKeyExport.new
|
151
|
+
k.name_args = ["#{dest_dir}/key_dump.json"]
|
152
|
+
k.config[:sql_host] = "localhost"
|
153
|
+
k.config[:sql_port] = 5432
|
154
|
+
k.run
|
155
|
+
end
|
156
|
+
|
144
157
|
# Download organizations
|
145
158
|
ensure_dir("#{dest_dir}/organizations")
|
146
159
|
rest.get_rest('/organizations').each_pair do |name, url|
|
@@ -174,16 +187,13 @@ class Chef
|
|
174
187
|
end
|
175
188
|
|
176
189
|
PATHS = %w(chef_repo_path cookbook_path environment_path data_bag_path role_path node_path client_path acl_path group_path container_path)
|
177
|
-
CONFIG_VARS = %w(chef_server_url chef_server_root custom_http_headers node_name client_key versioned_cookbooks) + PATHS
|
178
190
|
def download_org(dest_dir, webui_key, name)
|
179
|
-
old_config =
|
180
|
-
|
181
|
-
old_config[key] = Chef::Config[key.to_sym]
|
182
|
-
end
|
191
|
+
old_config = Chef::Config.save
|
192
|
+
|
183
193
|
begin
|
184
194
|
# Clear out paths
|
185
|
-
PATHS.each do |
|
186
|
-
Chef::Config
|
195
|
+
PATHS.each do |path|
|
196
|
+
Chef::Config.delete(path.to_sym)
|
187
197
|
end
|
188
198
|
Chef::Config.chef_repo_path = "#{dest_dir}/organizations/#{name}"
|
189
199
|
Chef::Config.versioned_cookbooks = true
|
@@ -193,17 +203,17 @@ class Chef
|
|
193
203
|
ensure_dir(Chef::Config.chef_repo_path)
|
194
204
|
|
195
205
|
# Download the billing-admins ACL and group as pivotal
|
196
|
-
chef_fs_config = ::ChefFS::Config.new
|
197
|
-
pattern = ::ChefFS::FilePattern.new('/acls/groups/billing-admins.json')
|
198
|
-
if ::ChefFS::FileSystem.copy_to(pattern, chef_fs_config.chef_fs, chef_fs_config.local_fs, nil, config, ui, proc { |entry| chef_fs_config.format_path(entry) })
|
206
|
+
chef_fs_config = Chef::ChefFS::Config.new
|
207
|
+
pattern = Chef::ChefFS::FilePattern.new('/acls/groups/billing-admins.json')
|
208
|
+
if Chef::ChefFS::FileSystem.copy_to(pattern, chef_fs_config.chef_fs, chef_fs_config.local_fs, nil, config, ui, proc { |entry| chef_fs_config.format_path(entry) })
|
199
209
|
@error = true
|
200
210
|
end
|
201
|
-
pattern = ::ChefFS::FilePattern.new('/groups/billing-admins.json')
|
202
|
-
if ::ChefFS::FileSystem.copy_to(pattern, chef_fs_config.chef_fs, chef_fs_config.local_fs, nil, config, ui, proc { |entry| chef_fs_config.format_path(entry) })
|
211
|
+
pattern = Chef::ChefFS::FilePattern.new('/groups/billing-admins.json')
|
212
|
+
if Chef::ChefFS::FileSystem.copy_to(pattern, chef_fs_config.chef_fs, chef_fs_config.local_fs, nil, config, ui, proc { |entry| chef_fs_config.format_path(entry) })
|
203
213
|
@error = true
|
204
214
|
end
|
205
|
-
pattern = ::ChefFS::FilePattern.new('/groups/admins.json')
|
206
|
-
if ::ChefFS::FileSystem.copy_to(pattern, chef_fs_config.chef_fs, chef_fs_config.local_fs, nil, config, ui, proc { |entry| chef_fs_config.format_path(entry) })
|
215
|
+
pattern = Chef::ChefFS::FilePattern.new('/groups/admins.json')
|
216
|
+
if Chef::ChefFS::FileSystem.copy_to(pattern, chef_fs_config.chef_fs, chef_fs_config.local_fs, nil, config, ui, proc { |entry| chef_fs_config.format_path(entry) })
|
207
217
|
@error = true
|
208
218
|
end
|
209
219
|
|
@@ -217,19 +227,17 @@ class Chef
|
|
217
227
|
Chef::Config.custom_http_headers = (Chef::Config.custom_http_headers || {}).merge({'x-ops-request-source' => 'web'})
|
218
228
|
|
219
229
|
# Download the entire org skipping the billing admins group ACL and the group itself
|
220
|
-
chef_fs_config = ::ChefFS::Config.new
|
230
|
+
chef_fs_config = Chef::ChefFS::Config.new
|
221
231
|
top_level_paths = chef_fs_config.chef_fs.children.select { |entry| entry.name != 'acls' && entry.name != 'groups' }.map { |entry| entry.path }
|
222
|
-
acl_paths = ::ChefFS::FileSystem.list(chef_fs_config.chef_fs, ::ChefFS::FilePattern.new('/acls/*')).select { |entry| entry.name != 'groups' }.map { |entry| entry.path }
|
223
|
-
group_acl_paths = ::ChefFS::FileSystem.list(chef_fs_config.chef_fs, ::ChefFS::FilePattern.new('/acls/groups/*')).select { |entry| entry.name != 'billing-admins.json' }.map { |entry| entry.path }
|
224
|
-
group_paths = ::ChefFS::FileSystem.list(chef_fs_config.chef_fs, ::ChefFS::FilePattern.new('/groups/*')).select { |entry| entry.name != 'billing-admins.json' }.map { |entry| entry.path }
|
232
|
+
acl_paths = Chef::ChefFS::FileSystem.list(chef_fs_config.chef_fs, Chef::ChefFS::FilePattern.new('/acls/*')).select { |entry| entry.name != 'groups' }.map { |entry| entry.path }
|
233
|
+
group_acl_paths = Chef::ChefFS::FileSystem.list(chef_fs_config.chef_fs, Chef::ChefFS::FilePattern.new('/acls/groups/*')).select { |entry| entry.name != 'billing-admins.json' }.map { |entry| entry.path }
|
234
|
+
group_paths = Chef::ChefFS::FileSystem.list(chef_fs_config.chef_fs, Chef::ChefFS::FilePattern.new('/groups/*')).select { |entry| entry.name != 'billing-admins.json' }.map { |entry| entry.path }
|
225
235
|
(top_level_paths + group_acl_paths + acl_paths + group_paths).each do |path|
|
226
|
-
::ChefFS::FileSystem.copy_to(::ChefFS::FilePattern.new(path), chef_fs_config.chef_fs, chef_fs_config.local_fs, nil, config, ui, proc { |entry| chef_fs_config.format_path(entry) })
|
236
|
+
Chef::ChefFS::FileSystem.copy_to(Chef::ChefFS::FilePattern.new(path), chef_fs_config.chef_fs, chef_fs_config.local_fs, nil, config, ui, proc { |entry| chef_fs_config.format_path(entry) })
|
227
237
|
end
|
228
238
|
|
229
239
|
ensure
|
230
|
-
|
231
|
-
Chef::Config[key.to_sym] = old_config[key]
|
232
|
-
end
|
240
|
+
Chef::Config.restore(old_config)
|
233
241
|
end
|
234
242
|
end
|
235
243
|
end
|
@@ -52,8 +52,9 @@ class Chef
|
|
52
52
|
|
53
53
|
def db
|
54
54
|
@db ||= begin
|
55
|
+
require 'sequel'
|
55
56
|
server_string = "#{config[:sql_user]}:#{config[:sql_password]}@#{config[:sql_host]}:#{config[:sql_port]}/opscode_chef"
|
56
|
-
Sequel.connect("postgres://#{server_string}")
|
57
|
+
::Sequel.connect("postgres://#{server_string}")
|
57
58
|
end
|
58
59
|
end
|
59
60
|
|
@@ -37,7 +37,7 @@ class Chef
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def export(path)
|
40
|
-
users = db.select(:username, :public_key, :pubkey_version, :hashed_password, :salt, :hash_type).from(:users)
|
40
|
+
users = db.select(:username, :id, :public_key, :pubkey_version, :hashed_password, :salt, :hash_type).from(:users)
|
41
41
|
File.open(path, 'w') { |file| file.write(users.all.to_json) }
|
42
42
|
end
|
43
43
|
end
|
@@ -33,6 +33,12 @@ class Chef
|
|
33
33
|
:boolean => true,
|
34
34
|
:description => "Upload pivotal key. By default the pivotal key is not uploaded."
|
35
35
|
|
36
|
+
option :skip_ids,
|
37
|
+
:long => "--[no-]skip-user-ids",
|
38
|
+
:default => true,
|
39
|
+
:boolean => true,
|
40
|
+
:description => "Upload user ids."
|
41
|
+
|
36
42
|
def run
|
37
43
|
if config[:sql_user].nil? || config[:sql_password].nil?
|
38
44
|
load_config_from_file!
|
@@ -46,6 +52,7 @@ class Chef
|
|
46
52
|
def import(path)
|
47
53
|
key_data = JSON.parse(File.read(path))
|
48
54
|
key_data.each do |d|
|
55
|
+
id = d['id']
|
49
56
|
username = d['username']
|
50
57
|
key = d['public_key']
|
51
58
|
version = d['pubkey_version']
|
@@ -63,11 +70,14 @@ class Chef
|
|
63
70
|
if users_to_update.count != 1
|
64
71
|
ui.warn "Wrong number of users to update for #{username}. Skipping"
|
65
72
|
else
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
73
|
+
data = { :public_key => key,
|
74
|
+
:pubkey_version => version,
|
75
|
+
:salt => salt,
|
76
|
+
:hashed_password => hashed_password,
|
77
|
+
:hash_type => hash_type
|
78
|
+
}
|
79
|
+
data[:id] = id unless config[:skip_ids]
|
80
|
+
users_to_update.update(data)
|
71
81
|
end
|
72
82
|
end
|
73
83
|
end
|
@@ -31,22 +31,36 @@ class Chef
|
|
31
31
|
:default => false,
|
32
32
|
:description => "Whether to skip checking the Chef Server version. This will also skip any auto-configured options"
|
33
33
|
|
34
|
+
option :org,
|
35
|
+
:long => "--only-org ORG",
|
36
|
+
:description => "Only restore objects in the named organization (default: all orgs)"
|
37
|
+
|
38
|
+
option :skip_users,
|
39
|
+
:long => "--skip-users",
|
40
|
+
:description => "Skip restoring users"
|
41
|
+
|
42
|
+
option :with_user_sql,
|
43
|
+
:long => "--with-user-sql",
|
44
|
+
:description => "Restore user id's, passwords, and keys from sql export"
|
45
|
+
|
34
46
|
deps do
|
35
47
|
require 'chef/json_compat'
|
36
|
-
require 'chef_fs/config'
|
37
|
-
require 'chef_fs/file_system'
|
38
|
-
require 'chef_fs/file_pattern'
|
39
|
-
|
40
|
-
require 'chef_fs/
|
48
|
+
require 'chef/chef_fs/config'
|
49
|
+
require 'chef/chef_fs/file_system'
|
50
|
+
require 'chef/chef_fs/file_pattern'
|
51
|
+
# Work around bug in chef_fs
|
52
|
+
require 'chef/chef_fs/command_line'
|
53
|
+
require 'chef/chef_fs/file_system/acl_entry'
|
54
|
+
require 'chef/chef_fs/data_handler/acl_data_handler'
|
41
55
|
require 'securerandom'
|
42
|
-
require 'chef_fs/parallelizer'
|
56
|
+
require 'chef/chef_fs/parallelizer'
|
43
57
|
require 'chef/tsorter'
|
44
58
|
end
|
45
59
|
|
46
60
|
def configure_chef
|
47
61
|
super
|
48
62
|
Chef::Config[:concurrency] = config[:concurrency].to_i if config[:concurrency]
|
49
|
-
::ChefFS::Parallelizer.threads = (Chef::Config[:concurrency] || 10) - 1
|
63
|
+
Chef::ChefFS::Parallelizer.threads = (Chef::Config[:concurrency] || 10) - 1
|
50
64
|
end
|
51
65
|
|
52
66
|
def run
|
@@ -109,46 +123,22 @@ class Chef
|
|
109
123
|
config[:skip_useracl] = true
|
110
124
|
user_acl_rest = nil
|
111
125
|
else
|
112
|
-
user_acl_rest = rest
|
113
|
-
end
|
126
|
+
user_acl_rest = rest
|
127
|
+
end
|
114
128
|
else
|
115
129
|
ui.warn("Unable to detect Chef Server version.")
|
116
130
|
end
|
117
131
|
end
|
118
132
|
|
119
|
-
# Restore users
|
120
|
-
puts "Restoring users ..."
|
121
|
-
|
122
133
|
rest = Chef::REST.new(Chef::Config.chef_server_root)
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
name = $1
|
127
|
-
if name == 'pivotal' && !config[:overwrite_pivotal]
|
128
|
-
ui.warn("Skipping pivotal update. To overwrite pivotal, pass --overwrite-pivotal.")
|
129
|
-
next
|
130
|
-
end
|
131
|
-
|
132
|
-
# Update user object
|
133
|
-
user = JSONCompat.from_json(IO.read("#{dest_dir}/users/#{name}.json"))
|
134
|
-
begin
|
135
|
-
# Supply password for new user
|
136
|
-
user_with_password = user.dup
|
137
|
-
user_with_password['password'] = SecureRandom.hex
|
138
|
-
rest.post_rest('users', user_with_password)
|
139
|
-
rescue Net::HTTPServerException => e
|
140
|
-
if e.response.code == "409"
|
141
|
-
rest.put_rest("users/#{name}", user)
|
142
|
-
else
|
143
|
-
raise
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
end
|
134
|
+
# Restore users
|
135
|
+
restore_users(dest_dir, rest) unless config[:skip_users]
|
136
|
+
restore_user_sql(dest_dir) if config[:with_user_sql]
|
148
137
|
|
149
138
|
# Restore organizations
|
150
139
|
Dir.foreach("#{dest_dir}/organizations") do |name|
|
151
140
|
next if name == '..' || name == '.' || !File.directory?("#{dest_dir}/organizations/#{name}")
|
141
|
+
next unless (config[:org].nil? || config[:org] == name)
|
152
142
|
puts "Restoring org #{name} ..."
|
153
143
|
|
154
144
|
# Create organization
|
@@ -170,7 +160,7 @@ class Chef
|
|
170
160
|
rest.post_rest("organizations/#{name}/association_requests", { 'user' => invitation['username'] })
|
171
161
|
rescue Net::HTTPServerException => e
|
172
162
|
if e.response.code != "409"
|
173
|
-
|
163
|
+
ui.error("Cannot create invitation #{invitation['id']}")
|
174
164
|
end
|
175
165
|
end
|
176
166
|
end
|
@@ -210,7 +200,7 @@ class Chef
|
|
210
200
|
|
211
201
|
# Update user acl
|
212
202
|
user_acl = JSONCompat.from_json(IO.read("#{dest_dir}/user_acls/#{name}.json"))
|
213
|
-
put_acl(rest, "users/#{name}/_acl", user_acl)
|
203
|
+
put_acl(rest, "users/#{name}/_acl", user_acl)
|
214
204
|
end
|
215
205
|
|
216
206
|
|
@@ -219,18 +209,54 @@ class Chef
|
|
219
209
|
end
|
220
210
|
end
|
221
211
|
|
212
|
+
def restore_users(dest_dir, rest)
|
213
|
+
puts "Restoring users ..."
|
214
|
+
Dir.foreach("#{dest_dir}/users") do |filename|
|
215
|
+
next if filename !~ /(.+)\.json/
|
216
|
+
name = $1
|
217
|
+
if name == 'pivotal' && !config[:overwrite_pivotal]
|
218
|
+
ui.warn("Skipping pivotal update. To overwrite pivotal, pass --overwrite-pivotal.")
|
219
|
+
next
|
220
|
+
end
|
221
|
+
|
222
|
+
# Update user object
|
223
|
+
user = JSONCompat.from_json(IO.read("#{dest_dir}/users/#{name}.json"))
|
224
|
+
begin
|
225
|
+
# Supply password for new user
|
226
|
+
user_with_password = user.dup
|
227
|
+
user_with_password['password'] = SecureRandom.hex
|
228
|
+
rest.post_rest('users', user_with_password)
|
229
|
+
rescue Net::HTTPServerException => e
|
230
|
+
if e.response.code == "409"
|
231
|
+
rest.put_rest("users/#{name}", user)
|
232
|
+
else
|
233
|
+
raise
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def restore_user_sql(dest_dir)
|
240
|
+
require 'chef/knife/ec_key_import'
|
241
|
+
k = Chef::Knife::EcKeyImport.new
|
242
|
+
k.name_args = ["#{dest_dir}/key_dump.json"]
|
243
|
+
k.config[:skip_pivotal] = true
|
244
|
+
k.config[:skip_ids] = false
|
245
|
+
k.config[:sql_host] = "localhost"
|
246
|
+
k.config[:sql_port] = 5432
|
247
|
+
k.run
|
248
|
+
end
|
249
|
+
|
222
250
|
PATHS = %w(chef_repo_path cookbook_path environment_path data_bag_path role_path node_path client_path acl_path group_path container_path)
|
223
|
-
CONFIG_VARS = %w(chef_server_url chef_server_root custom_http_headers node_name client_key versioned_cookbooks) + PATHS
|
224
251
|
def upload_org(dest_dir, webui_key, name)
|
225
|
-
old_config =
|
226
|
-
|
227
|
-
old_config[key] = Chef::Config[key.to_sym]
|
228
|
-
end
|
252
|
+
old_config = Chef::Config.save
|
253
|
+
|
229
254
|
begin
|
230
255
|
# Clear out paths
|
231
|
-
PATHS.each do |
|
232
|
-
Chef::Config
|
256
|
+
PATHS.each do |path|
|
257
|
+
Chef::Config.delete(path.to_sym)
|
233
258
|
end
|
259
|
+
|
234
260
|
Chef::Config.chef_repo_path = "#{dest_dir}/organizations/#{name}"
|
235
261
|
Chef::Config.versioned_cookbooks = true
|
236
262
|
|
@@ -238,15 +264,15 @@ class Chef
|
|
238
264
|
|
239
265
|
# Upload the admins group and billing-admins acls
|
240
266
|
puts "Restoring the org admin data"
|
241
|
-
chef_fs_config = ::ChefFS::Config.new
|
267
|
+
chef_fs_config = Chef::ChefFS::Config.new
|
242
268
|
|
243
269
|
# Restore users w/o clients (which don't exist yet)
|
244
270
|
['admins', 'billing-admins'].each do |group|
|
245
271
|
restore_group(chef_fs_config, group, :clients => false)
|
246
272
|
end
|
247
273
|
|
248
|
-
pattern = ::ChefFS::FilePattern.new('/acls/groups/billing-admins.json')
|
249
|
-
if ::ChefFS::FileSystem.copy_to(pattern, chef_fs_config.local_fs, chef_fs_config.chef_fs, nil, config, ui, proc { |entry| chef_fs_config.format_path(entry) })
|
274
|
+
pattern = Chef::ChefFS::FilePattern.new('/acls/groups/billing-admins.json')
|
275
|
+
if Chef::ChefFS::FileSystem.copy_to(pattern, chef_fs_config.local_fs, chef_fs_config.chef_fs, nil, config, ui, proc { |entry| chef_fs_config.format_path(entry) })
|
250
276
|
@error = true
|
251
277
|
end
|
252
278
|
|
@@ -267,30 +293,28 @@ class Chef
|
|
267
293
|
|
268
294
|
# Restore the entire org skipping the admin data and restoring groups and acls last
|
269
295
|
puts "Restoring the rest of the org"
|
270
|
-
chef_fs_config = ::ChefFS::Config.new
|
296
|
+
chef_fs_config = Chef::ChefFS::Config.new
|
271
297
|
top_level_paths = chef_fs_config.local_fs.children.select { |entry| entry.name != 'acls' && entry.name != 'groups' }.map { |entry| entry.path }
|
272
298
|
|
273
299
|
# 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) }
|
300
|
+
unsorted_groups = Chef::ChefFS::FileSystem.list(chef_fs_config.local_fs, Chef::ChefFS::FilePattern.new('/groups/*')).select { |entry| entry.name != 'billing-admins.json' }.map { |entry| JSON.parse(entry.read) }
|
275
301
|
group_paths = sort_groups_for_upload(unsorted_groups).map { |group_name| "/groups/#{group_name}.json" }
|
276
302
|
|
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 }
|
278
|
-
acl_paths = ::ChefFS::FileSystem.list(chef_fs_config.local_fs, ::ChefFS::FilePattern.new('/acls/*')).select { |entry| entry.name != 'groups' }.map { |entry| entry.path }
|
303
|
+
group_acl_paths = Chef::ChefFS::FileSystem.list(chef_fs_config.local_fs, Chef::ChefFS::FilePattern.new('/acls/groups/*')).select { |entry| entry.name != 'billing-admins.json' }.map { |entry| entry.path }
|
304
|
+
acl_paths = Chef::ChefFS::FileSystem.list(chef_fs_config.local_fs, Chef::ChefFS::FilePattern.new('/acls/*')).select { |entry| entry.name != 'groups' }.map { |entry| entry.path }
|
279
305
|
|
280
306
|
(top_level_paths + group_paths + group_acl_paths + acl_paths).each do |path|
|
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) })
|
307
|
+
Chef::ChefFS::FileSystem.copy_to(Chef::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) })
|
282
308
|
end
|
283
309
|
# restore clients to groups, using the pivotal key again
|
284
310
|
Chef::Config[:node_name] = old_config['node_name']
|
285
|
-
Chef::Config[:client_key] = old_config['client_key']
|
311
|
+
Chef::Config[:client_key] = old_config['client_key']
|
286
312
|
Chef::Config.custom_http_headers = {}
|
287
313
|
['admins', 'billing-admins'].each do |group|
|
288
|
-
restore_group(::ChefFS::Config.new, group)
|
314
|
+
restore_group(Chef::ChefFS::Config.new, group)
|
289
315
|
end
|
290
316
|
ensure
|
291
|
-
|
292
|
-
Chef::Config[key.to_sym] = old_config[key]
|
293
|
-
end
|
317
|
+
Chef::Config.restore(old_config)
|
294
318
|
end
|
295
319
|
end
|
296
320
|
|
@@ -316,13 +340,13 @@ class Chef
|
|
316
340
|
def restore_group(chef_fs_config, group_name, includes = {:users => true, :clients => true})
|
317
341
|
includes[:users] = true unless includes.key? :users
|
318
342
|
includes[:clients] = true unless includes.key? :clients
|
319
|
-
|
320
|
-
group = ::ChefFS::FileSystem.resolve_path(
|
343
|
+
|
344
|
+
group = Chef::ChefFS::FileSystem.resolve_path(
|
321
345
|
chef_fs_config.chef_fs,
|
322
346
|
"/groups/#{group_name}.json"
|
323
347
|
)
|
324
348
|
|
325
|
-
members_json = ::ChefFS::FileSystem.resolve_path(
|
349
|
+
members_json = Chef::ChefFS::FileSystem.resolve_path(
|
326
350
|
chef_fs_config.local_fs,
|
327
351
|
"/groups/#{group_name}.json"
|
328
352
|
).read
|
@@ -336,20 +360,20 @@ class Chef
|
|
336
360
|
member == 'clients'
|
337
361
|
end
|
338
362
|
end
|
339
|
-
|
363
|
+
|
340
364
|
group.write(members.to_json)
|
341
365
|
end
|
342
366
|
|
343
367
|
def parallelize(entries, options = {}, &block)
|
344
|
-
::ChefFS::Parallelizer.parallelize(entries, options, &block)
|
368
|
+
Chef::ChefFS::Parallelizer.parallelize(entries, options, &block)
|
345
369
|
end
|
346
370
|
|
347
371
|
def put_acl(rest, url, acls)
|
348
372
|
old_acls = rest.get_rest(url)
|
349
|
-
old_acls = ::ChefFS::DataHandler::AclDataHandler.new.normalize(old_acls, nil)
|
350
|
-
acls = ::ChefFS::DataHandler::AclDataHandler.new.normalize(acls, nil)
|
373
|
+
old_acls = Chef::ChefFS::DataHandler::AclDataHandler.new.normalize(old_acls, nil)
|
374
|
+
acls = Chef::ChefFS::DataHandler::AclDataHandler.new.normalize(acls, nil)
|
351
375
|
if acls != old_acls
|
352
|
-
::ChefFS::FileSystem::AclEntry::PERMISSIONS.each do |permission|
|
376
|
+
Chef::ChefFS::FileSystem::AclEntry::PERMISSIONS.each do |permission|
|
353
377
|
rest.put_rest("#{url}/#{permission}", { permission => acls[permission] })
|
354
378
|
end
|
355
379
|
end
|
metadata
CHANGED
@@ -1,31 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-ec-backup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.beta.1
|
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-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: sequel
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: pg
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
@@ -39,19 +39,19 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: chef
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '11.8'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '11.8'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -113,12 +113,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
113
113
|
version: '0'
|
114
114
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
115
|
requirements:
|
116
|
-
- - "
|
116
|
+
- - ">"
|
117
117
|
- !ruby/object:Gem::Version
|
118
|
-
version:
|
118
|
+
version: 1.3.1
|
119
119
|
requirements: []
|
120
120
|
rubyforge_project:
|
121
|
-
rubygems_version: 2.2.
|
121
|
+
rubygems_version: 2.2.2
|
122
122
|
signing_key:
|
123
123
|
specification_version: 4
|
124
124
|
summary: Backup and Restore of Enterprise Chef
|