knife-ec-backup 2.0.0.beta.2 → 2.0.0.beta.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +127 -16
- data/lib/chef/knife/ec_backup.rb +109 -191
- data/lib/chef/knife/ec_base.rb +148 -0
- data/lib/chef/knife/ec_restore.rb +97 -210
- data/lib/chef/server.rb +38 -0
- data/lib/knife_ec_backup/version.rb +1 -1
- data/spec/chef/knife/ec_backup_spec.rb +158 -0
- data/spec/chef/knife/ec_base_spec.rb +73 -0
- data/spec/chef/knife/ec_key_base_spec.rb +2 -0
- data/spec/chef/knife/ec_key_export_spec.rb +2 -0
- data/spec/chef/knife/ec_key_import_spec.rb +2 -0
- data/spec/chef/knife/ec_restore_spec.rb +138 -0
- data/spec/chef/server_spec.rb +50 -0
- data/spec/chef/tsorter_spec.rb +9 -0
- data/spec/spec_helper.rb +6 -0
- metadata +44 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2078c6252a1d006cfb49b5f6c3c2a7fc8e47ad30
|
4
|
+
data.tar.gz: b67b59762f716a2b66677d56beb86de993020682
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad00c21eb5460532a51301a12d91c786aca6c8cd77b745024b639a4bcdf082b8fb25e416bc68eee84a4b1bcd942e0d3915dfd0e5dc2fba69a4971c372bb9451f
|
7
|
+
data.tar.gz: 091c6bf72543e5d197c361f906d998904d89dcc7e22a5935b88fc170565f5cc303e6cad38b25ef4a512a8889647bc1bfca739cd9772f6853c965cc1c3ecefcf6
|
data/README.md
CHANGED
@@ -2,7 +2,14 @@
|
|
2
2
|
|
3
3
|
# Description
|
4
4
|
|
5
|
-
|
5
|
+
knife-ec-backup can backup and restore the data in an Enterprise Chef
|
6
|
+
Server installation, preserving the data in an intermediate, editable
|
7
|
+
text format. It is similar to the `knife download` and `knife upload`
|
8
|
+
commands and uses the same underlying libraries, but also includes
|
9
|
+
workarounds for objects not yet supported by those tools and various
|
10
|
+
Server API deficiencies. The long-run goal is to improve `knife
|
11
|
+
donwload`, `knife upload` and the Chef Server API and deprecate this
|
12
|
+
tool.
|
6
13
|
|
7
14
|
# Requirements
|
8
15
|
|
@@ -20,6 +27,13 @@ This will install the plugin directly on the Chef Server:
|
|
20
27
|
|
21
28
|
/opt/opscode/embedded/bin/gem install knife-ec-backup
|
22
29
|
|
30
|
+
The latest versions of knife-ec-backup require gems with native
|
31
|
+
extensions, thus you must install a standard build toolchain. To
|
32
|
+
install knife-ec-backup without installing libpq development headers
|
33
|
+
on your system, try the following:
|
34
|
+
|
35
|
+
/opt/opscode/embedded/bin/gem install knife-ec-backup -- --with-pg-config=/opt/opscode/embedded/postgresql/9.2/bin/pg_config
|
36
|
+
|
23
37
|
## Build from source
|
24
38
|
Clone the git repository and run the following from inside:
|
25
39
|
|
@@ -29,22 +43,61 @@ Clone the git repository and run the following from inside:
|
|
29
43
|
# Configuration
|
30
44
|
|
31
45
|
## Permissions
|
46
|
+
|
32
47
|
Note that most users in an EC installation lack the permissions to pull all of the data from all organizations and other users.
|
33
48
|
This plugin **REQUIRES THE PIVOTAL KEY AND WEBUI KEY** from the Chef Server.
|
34
49
|
It is recommended that you run this from a frontend Enterprise Chef Server, you can use --user and --key to pass the pivotal information along.
|
35
50
|
|
36
51
|
# Subcommands
|
37
52
|
|
53
|
+
## Common Option
|
54
|
+
|
55
|
+
The following options are supported across all subcommands:
|
56
|
+
|
57
|
+
* `--sql_host`:
|
58
|
+
The hostname of the Chef Server's postgresql server. (default: localhost)
|
59
|
+
|
60
|
+
* `--sql_port`:
|
61
|
+
The postgresql listening port on the Chef Server. (default: 5432)
|
62
|
+
|
63
|
+
* `--sql_user`:
|
64
|
+
The username of postgresql user with access to the opscode_chef
|
65
|
+
database. (default: autoconfigured from
|
66
|
+
/etc/opscode/chef-server-running.json)
|
67
|
+
|
68
|
+
* `--sql_password`:
|
69
|
+
The password for the sql_user. (default: autoconfigured from /etc/opscode/chef-server-running.json)
|
70
|
+
|
38
71
|
## knife ec backup DEST_DIR (options)
|
39
72
|
|
40
73
|
*Options*
|
41
74
|
|
75
|
+
* `--concurrency THREAD_COUNT`:
|
76
|
+
The maximum number of concurrent requests to make to the Chef
|
77
|
+
Server. (default: 10)
|
78
|
+
|
42
79
|
* `--webui-key`:
|
43
80
|
Used to set the path to the WebUI Key (default: /etc/opscode/webui_priv.pem)
|
81
|
+
skip any auto-configured options (default: false)
|
82
|
+
|
83
|
+
* `--with-user-sql`:
|
84
|
+
Whether to backup/restore user data directly from the database. This
|
85
|
+
requires access to the listening postgresql port on the Chef
|
86
|
+
Server. This is required to correctly handle user passwords and
|
87
|
+
to ensure user-specific association groups are not duplicated.
|
88
|
+
|
44
89
|
* `--skip-useracl`:
|
45
|
-
|
46
|
-
|
47
|
-
|
90
|
+
Skip download/restore of the user ACLs. User ACLs are the
|
91
|
+
permissions that actors have *on other global users*. These are
|
92
|
+
not the ACLs that control what permissions users have on various
|
93
|
+
Chef objects.
|
94
|
+
|
95
|
+
* `--skip-version-check`:
|
96
|
+
Skip Chef Server version check. This will also skip any auto-configured options (default: false)
|
97
|
+
|
98
|
+
* `--only-org ORG`:
|
99
|
+
Only donwload/restore objects in the named organization. Global
|
100
|
+
objects such as users will still be downloaded/restored.
|
48
101
|
|
49
102
|
Creates a repository of an entire Enterprise Chef / Private Chef server.
|
50
103
|
|
@@ -100,24 +153,82 @@ This compares very closely with the "knife download /" from an OSC server:
|
|
100
153
|
|
101
154
|
## knife ec restore DEST_DIR (options)
|
102
155
|
|
156
|
+
Restores all data from the specified DEST_DIR to an Enterprise Chef /
|
157
|
+
Private Chef server. DEST_DIR should be a backup directory created by
|
158
|
+
`knife ec restore`
|
159
|
+
|
103
160
|
*Options*
|
104
161
|
|
105
162
|
* `--webui-key`:
|
106
163
|
Used to set the path to the WebUI Key (default: /etc/opscode/webui_priv.pem)
|
164
|
+
|
107
165
|
* `--overwrite-pivotal`:
|
108
|
-
Whether to overwrite pivotal's key. Once this is done, future
|
166
|
+
Whether to overwrite pivotal's key. Once this is done, future
|
167
|
+
requests will fail until you fix the private key (default: false)
|
168
|
+
|
169
|
+
* `--skip-users`:
|
170
|
+
Skip the restore of global users. This may cause organization
|
171
|
+
uploading to fail if the necessary users do not exist on the Chef
|
172
|
+
Server.
|
173
|
+
|
174
|
+
* `--concurrency THREAD_COUNT`:
|
175
|
+
The maximum number of concurrent requests to make to the Chef
|
176
|
+
Server. (default: 10)
|
177
|
+
|
178
|
+
* `--skip-version-check`:
|
179
|
+
Skip Chef Server version check. This will
|
180
|
+
also skip any auto-configured options (default: false)
|
181
|
+
|
182
|
+
* `--with-user-sql`:
|
183
|
+
Whether to backup/restore user data directly from the database. This
|
184
|
+
requires access to the listening postgresql port on the Chef
|
185
|
+
Server. This is required to correctly handle user passwords and
|
186
|
+
to ensure user-specific association groups are not
|
187
|
+
duplicated. This option will only work on `restore` if it was also
|
188
|
+
used during the `backup`.
|
189
|
+
|
109
190
|
* `--skip-useracl`:
|
110
|
-
|
111
|
-
|
112
|
-
|
191
|
+
Skip download/restore of the user ACLs. User ACLs are the
|
192
|
+
permissions that actors have *on other global users*. These are
|
193
|
+
not the ACLs that control what permissions users have on various
|
194
|
+
Chef objects.
|
195
|
+
|
196
|
+
* `--only-org ORG`:
|
197
|
+
Only donwload/restore objects in the named organization. Global
|
198
|
+
objects such as users will still be downloaded/restored.
|
199
|
+
|
200
|
+
## knife ec key export [FILENAME]
|
201
|
+
|
202
|
+
Create a json representation of the users table from the Chef Server
|
203
|
+
database. If no argument is given, the name of the backup is
|
204
|
+
`key_dump.json`.
|
205
|
+
|
206
|
+
Please note, most users should use `knife ec backup` with the
|
207
|
+
`--with-user-sql` option rather than this command.
|
208
|
+
|
209
|
+
## knife ec key import [FILENAME]
|
210
|
+
|
211
|
+
Import a json representation of the users table from FILENAME to the
|
212
|
+
the Chef Server database. If no argument is given, the filename is
|
213
|
+
assumed to be `key_dump.json`.
|
214
|
+
|
215
|
+
Please note, most user should use `knife ec restore` with the
|
216
|
+
`--with-user-sql` option rather than this command.
|
217
|
+
|
218
|
+
# Known Bugs
|
219
|
+
|
220
|
+
- `knife ec restore` can fail to restore cookbooks, failing with an
|
221
|
+
internal server error. A common cause of this problem is a
|
222
|
+
concurrency bug in Chef Server. Setting `--concurrency 1` can often
|
223
|
+
work around the issue.
|
113
224
|
|
114
|
-
|
225
|
+
- `knife ec restore` can fail if the pool of pre-created organizations
|
226
|
+
can not keep up with the newly created organizations. This can
|
227
|
+
typically be resolved simply be restarting the restore. To avoid
|
228
|
+
this error for backups with large number of organizations, try
|
229
|
+
setting (in /etc/opscode/private-chef.rb):
|
115
230
|
|
116
|
-
|
231
|
+
opscode_org_creator['ready_org_depth']
|
117
232
|
|
118
|
-
|
119
|
-
|
120
|
-
* Single org backups.
|
121
|
-
* This plugin does **NOT** currently backup user passwords. **They will have to be reset after a restore.**
|
122
|
-
* This plugin does **NOT** currently restore user public keys. **Private keys will have to be reset after a restore.**
|
123
|
-
* This plugin does **NOT** currently restore custom user ACLs. **It will revert back to default ACLs on a restore.**
|
233
|
+
to the number of organizations in your backup and waiting for the
|
234
|
+
pool to fill before running `knife ec restore`
|
data/lib/chef/knife/ec_backup.rb
CHANGED
@@ -1,214 +1,133 @@
|
|
1
1
|
require 'chef/knife'
|
2
|
+
require 'chef/knife/ec_base'
|
2
3
|
|
3
4
|
class Chef
|
4
5
|
class Knife
|
5
6
|
class EcBackup < Chef::Knife
|
6
|
-
banner "knife ec backup DIRECTORY"
|
7
|
-
|
8
|
-
option :concurrency,
|
9
|
-
:long => '--concurrency THREADS',
|
10
|
-
:description => 'Maximum number of simultaneous requests to send (default: 10)'
|
11
|
-
|
12
|
-
option :webui_key,
|
13
|
-
:long => '--webui-key KEYPATH',
|
14
|
-
:description => 'Used to set the path to the WebUI Key (default: /etc/opscode/webui_priv.pem)'
|
15
|
-
|
16
|
-
option :skip_useracl,
|
17
|
-
:long => '--skip-useracl',
|
18
|
-
:boolean => true,
|
19
|
-
:default => false,
|
20
|
-
:description => "Whether to skip downloading User ACLs. This is required for EC 11.0.0 and lower"
|
21
|
-
|
22
|
-
option :skip_version,
|
23
|
-
:long => '--skip-version-check',
|
24
|
-
:boolean => true,
|
25
|
-
:default => false,
|
26
|
-
:description => "Whether to skip checking the Chef Server version. This will also skip any auto-configured options"
|
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
|
-
|
32
|
-
option :org,
|
33
|
-
:long => '--only-org ORGNAME',
|
34
|
-
:description => "Only back up objects in the named organization (default: all orgs)"
|
35
|
-
|
36
|
-
option :sql_host,
|
37
|
-
:long => '--sql-host HOSTNAME',
|
38
|
-
:description => 'Postgresql database hostname (default: localhost)',
|
39
|
-
:default => "localhost"
|
40
7
|
|
41
|
-
|
42
|
-
:long => '--sql-port PORT',
|
43
|
-
:description => 'Postgresql database port (default: 5432)',
|
44
|
-
:default => 5432
|
45
|
-
|
46
|
-
option :sql_user,
|
47
|
-
:long => "--sql-user USERNAME",
|
48
|
-
:description => 'User used to connect to the postgresql database.'
|
49
|
-
|
50
|
-
option :sql_password,
|
51
|
-
:long => "--sql-password PASSWORD",
|
52
|
-
:description => 'Password used to connect to the postgresql database'
|
8
|
+
include Knife::EcBase
|
53
9
|
|
10
|
+
banner "knife ec backup DIRECTORY"
|
54
11
|
|
55
12
|
deps do
|
56
13
|
require 'chef/chef_fs/config'
|
57
14
|
require 'chef/chef_fs/file_system'
|
58
15
|
require 'chef/chef_fs/file_pattern'
|
59
16
|
require 'chef/chef_fs/parallelizer'
|
60
|
-
|
61
|
-
|
62
|
-
def configure_chef
|
63
|
-
super
|
64
|
-
Chef::Config[:concurrency] = config[:concurrency].to_i if config[:concurrency]
|
65
|
-
Chef::ChefFS::Parallelizer.threads = (Chef::Config[:concurrency] || 10) - 1
|
17
|
+
require 'chef/server'
|
18
|
+
require 'fileutils'
|
66
19
|
end
|
67
20
|
|
68
21
|
def run
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
74
|
-
dest_dir = name_args[0]
|
75
|
-
|
22
|
+
set_dest_dir_from_args!
|
23
|
+
set_client_config!
|
24
|
+
set_skip_user_acl!
|
25
|
+
ensure_webui_key_exists!
|
76
26
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
exit 1
|
27
|
+
for_each_user do |username, url|
|
28
|
+
download_user(username, url)
|
29
|
+
if config[:skip_useracl]
|
30
|
+
ui.warn("Skipping user ACL download for #{username}. To download this ACL, remove --skip-useracl or upgrade your Enterprise Chef Server.")
|
31
|
+
else
|
32
|
+
download_user_acl(username)
|
84
33
|
end
|
85
|
-
Chef::Config.node_name = 'pivotal'
|
86
|
-
Chef::Config.client_key = '/etc/opscode/pivotal.pem'
|
87
34
|
end
|
88
35
|
|
89
|
-
|
90
|
-
|
91
|
-
if !File.exist?("/etc/opscode/webui_priv.pem")
|
92
|
-
ui.error("WebUI not specified and /etc/opscode/webui_priv.pem does not exist. It is recommended that you run this plugin from your Chef server.")
|
93
|
-
exit 1
|
94
|
-
end
|
95
|
-
ui.warn("WebUI not specified. Using /etc/opscode/webui_priv.pem")
|
96
|
-
webui_key = '/etc/opscode/webui_priv.pem'
|
97
|
-
else
|
98
|
-
webui_key = config[:webui_key]
|
36
|
+
if config[:with_user_sql]
|
37
|
+
export_users_from_sql
|
99
38
|
end
|
100
39
|
|
101
|
-
#
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
40
|
+
ensure_dir("#{dest_dir}/organizations")
|
41
|
+
for_each_organization do |org_object|
|
42
|
+
name = org_object['name']
|
43
|
+
write_org_object_to_disk(org_object)
|
44
|
+
download_org_data(name)
|
45
|
+
download_org_members(name)
|
46
|
+
download_org_invitations(name)
|
107
47
|
end
|
48
|
+
end
|
108
49
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
elsif config[:skip_version] && !config[:skip_useracl]
|
115
|
-
ui.warn("Skipping the Chef Server version check. This will also skip any auto-configured options")
|
116
|
-
user_acl_rest = rest
|
117
|
-
else # Grab Chef Server version number so that we can auto set options
|
118
|
-
uri = URI.parse("#{Chef::Config.chef_server_root}/version")
|
119
|
-
server_version = open(uri, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE}).each_line.first.split(' ').last
|
120
|
-
server_version_parts = server_version.split('.')
|
121
|
-
|
122
|
-
if server_version_parts.count == 3
|
123
|
-
puts "Detected Enterprise Chef Server version: #{server_version}"
|
124
|
-
|
125
|
-
# All versions of Chef Server below 11.0.1 are missing the GET User ACL helper in nginx
|
126
|
-
if server_version_parts[0].to_i < 11 || (server_version_parts[0].to_i == 11 && server_version_parts[1].to_i == 0 && server_version_parts[0].to_i < 1)
|
127
|
-
#Check to see if Opscode-Account can be directly from the local machine
|
128
|
-
begin
|
129
|
-
user_acl_rest.get('users')
|
130
|
-
ui.warn("Your version of Enterprise Chef Server does not support the downloading of User ACLs. Using local connection to backup")
|
131
|
-
user_acl_rest = Chef::REST.new("http://127.0.0.1:9465")
|
132
|
-
rescue
|
133
|
-
ui.warn("Your version of Enterprise Chef Server does not support the downloading of User ACLs. Setting skip-useracl to TRUE")
|
134
|
-
config[:skip_useracl] = true
|
135
|
-
user_acl_rest = nil
|
136
|
-
end
|
137
|
-
else
|
138
|
-
user_acl_rest = rest
|
139
|
-
end
|
50
|
+
def for_each_user
|
51
|
+
rest.get_rest('/users').each_pair do |name, url|
|
52
|
+
yield name, url
|
53
|
+
end
|
54
|
+
end
|
140
55
|
|
56
|
+
def for_each_organization
|
57
|
+
rest.get_rest('/organizations').each_pair do |name, url|
|
58
|
+
next unless (config[:org].nil? || config[:org] == name)
|
59
|
+
ui.msg "Downloading organization object for #{name} from #{url}"
|
60
|
+
org = rest.get_rest(url)
|
61
|
+
# Enterprise Chef 11 and below uses a pool of precreated
|
62
|
+
# organizations to account for slow organization creation
|
63
|
+
# using CouchDB. Thus, on server versions < 12 we want to
|
64
|
+
# skip any of these precreated organizations by checking if
|
65
|
+
# they have been assigned or not. The Chef 12 API does not
|
66
|
+
# return an assigned_at field.
|
67
|
+
if org['assigned_at'] || server.version >= Gem::Version.new("12")
|
68
|
+
yield org
|
141
69
|
else
|
142
|
-
ui.
|
70
|
+
ui.msg "Skipping pre-created org #{name}"
|
143
71
|
end
|
144
72
|
end
|
73
|
+
end
|
145
74
|
|
146
|
-
|
147
|
-
puts "Grabbing users ..."
|
75
|
+
def download_user(username, url)
|
148
76
|
ensure_dir("#{dest_dir}/users")
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
file.write(Chef::JSONCompat.to_json_pretty(rest.get_rest(url)))
|
154
|
-
end
|
155
|
-
|
156
|
-
if config[:skip_useracl]
|
157
|
-
ui.warn("Skipping user ACL download for #{name}. To download this ACL, remove --skip-useracl or upgrade your Enterprise Chef Server.")
|
158
|
-
next
|
159
|
-
end
|
77
|
+
File.open("#{dest_dir}/users/#{username}.json", 'w') do |file|
|
78
|
+
file.write(Chef::JSONCompat.to_json_pretty(rest.get_rest(url)))
|
79
|
+
end
|
80
|
+
end
|
160
81
|
|
161
|
-
|
162
|
-
|
163
|
-
|
82
|
+
def download_user_acl(username)
|
83
|
+
ensure_dir("#{dest_dir}/user_acls")
|
84
|
+
File.open("#{dest_dir}/user_acls/#{username}.json", 'w') do |file|
|
85
|
+
file.write(Chef::JSONCompat.to_json_pretty(user_acl_rest.get_rest("users/#{username}/_acl")))
|
164
86
|
end
|
87
|
+
end
|
165
88
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
89
|
+
def export_users_from_sql
|
90
|
+
require 'chef/knife/ec_key_export'
|
91
|
+
Chef::Knife::EcKeyExport.deps
|
92
|
+
k = Chef::Knife::EcKeyExport.new
|
93
|
+
k.name_args = ["#{dest_dir}/key_dump.json"]
|
94
|
+
k.config[:sql_host] = config[:sql_host]
|
95
|
+
k.config[:sql_port] = config[:sql_port]
|
96
|
+
k.config[:sql_user] = config[:sql_user]
|
97
|
+
k.config[:sql_password] = config[:sql_password]
|
98
|
+
k.run
|
99
|
+
end
|
100
|
+
|
101
|
+
def write_org_object_to_disk(org_object)
|
102
|
+
name = org_object['name']
|
103
|
+
ensure_dir("#{dest_dir}/organizations/#{name}")
|
104
|
+
File.open("#{dest_dir}/organizations/#{name}/org.json", 'w') do |file|
|
105
|
+
file.write(Chef::JSONCompat.to_json_pretty(org_object))
|
176
106
|
end
|
107
|
+
end
|
177
108
|
|
178
|
-
|
179
|
-
ensure_dir("#{dest_dir}/organizations")
|
180
|
-
|
181
|
-
|
182
|
-
org = rest.get_rest(url)
|
183
|
-
if org['assigned_at'] and do_org
|
184
|
-
puts "Grabbing organization #{name} ..."
|
185
|
-
ensure_dir("#{dest_dir}/organizations/#{name}")
|
186
|
-
download_org(dest_dir, webui_key, name)
|
187
|
-
File.open("#{dest_dir}/organizations/#{name}/org.json", 'w') do |file|
|
188
|
-
file.write(Chef::JSONCompat.to_json_pretty(org))
|
189
|
-
end
|
190
|
-
File.open("#{dest_dir}/organizations/#{name}/members.json", 'w') do |file|
|
191
|
-
file.write(Chef::JSONCompat.to_json_pretty(rest.get_rest("#{url}/users")))
|
192
|
-
end
|
193
|
-
File.open("#{dest_dir}/organizations/#{name}/invitations.json", 'w') do |file|
|
194
|
-
file.write(Chef::JSONCompat.to_json_pretty(rest.get_rest("#{url}/association_requests")))
|
195
|
-
end
|
196
|
-
end
|
109
|
+
def download_org_members(name)
|
110
|
+
ensure_dir("#{dest_dir}/organizations/#{name}")
|
111
|
+
File.open("#{dest_dir}/organizations/#{name}/members.json", 'w') do |file|
|
112
|
+
file.write(Chef::JSONCompat.to_json_pretty(rest.get_rest("/organizations/#{name}/users")))
|
197
113
|
end
|
114
|
+
end
|
198
115
|
|
199
|
-
|
200
|
-
|
116
|
+
def download_org_invitations(name)
|
117
|
+
ensure_dir("#{dest_dir}/organizations/#{name}")
|
118
|
+
File.open("#{dest_dir}/organizations/#{name}/invitations.json", 'w') do |file|
|
119
|
+
file.write(Chef::JSONCompat.to_json_pretty(rest.get_rest("/organizations/#{name}/association_requests")))
|
201
120
|
end
|
202
121
|
end
|
203
122
|
|
204
123
|
def ensure_dir(dir)
|
205
124
|
if !File.exist?(dir)
|
206
|
-
|
125
|
+
FileUtils.mkdir_p(dir)
|
207
126
|
end
|
208
127
|
end
|
209
128
|
|
210
129
|
PATHS = %w(chef_repo_path cookbook_path environment_path data_bag_path role_path node_path client_path acl_path group_path container_path)
|
211
|
-
def
|
130
|
+
def download_org_data(name)
|
212
131
|
old_config = Chef::Config.save
|
213
132
|
|
214
133
|
begin
|
@@ -219,48 +138,47 @@ class Chef
|
|
219
138
|
Chef::Config.chef_repo_path = "#{dest_dir}/organizations/#{name}"
|
220
139
|
Chef::Config.versioned_cookbooks = true
|
221
140
|
|
222
|
-
Chef::Config.chef_server_url = "#{
|
141
|
+
Chef::Config.chef_server_url = "#{server.root_url}/organizations/#{name}"
|
223
142
|
|
224
143
|
ensure_dir(Chef::Config.chef_repo_path)
|
225
144
|
|
226
145
|
# Download the billing-admins ACL and group as pivotal
|
227
146
|
chef_fs_config = Chef::ChefFS::Config.new
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
end
|
232
|
-
pattern = Chef::ChefFS::FilePattern.new('/groups/billing-admins.json')
|
233
|
-
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) })
|
234
|
-
@error = true
|
235
|
-
end
|
236
|
-
pattern = Chef::ChefFS::FilePattern.new('/groups/admins.json')
|
237
|
-
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) })
|
238
|
-
@error = true
|
239
|
-
end
|
147
|
+
chef_fs_copy_pattern('/acls/groups/billing-admins.json', chef_fs_config)
|
148
|
+
chef_fs_copy_pattern('/groups/billing-admins.json', chef_fs_config)
|
149
|
+
chef_fs_copy_pattern('/groups/admins.json', chef_fs_config)
|
240
150
|
|
241
|
-
#
|
242
|
-
|
243
|
-
admin_users = rest.get_rest('groups/admins')['users']
|
244
|
-
org_members = rest.get_rest('users').map { |user| user['user']['username'] }
|
245
|
-
admin_users.delete_if { |user| !org_members.include?(user) }
|
246
|
-
Chef::Config.node_name = admin_users[0]
|
247
|
-
Chef::Config.client_key = webui_key
|
248
|
-
Chef::Config.custom_http_headers = (Chef::Config.custom_http_headers || {}).merge({'x-ops-request-source' => 'web'})
|
151
|
+
# Set Chef::Config to use an organization administrator
|
152
|
+
Chef::Config.node_name = org_admin
|
249
153
|
|
250
154
|
# Download the entire org skipping the billing admins group ACL and the group itself
|
251
155
|
chef_fs_config = Chef::ChefFS::Config.new
|
252
156
|
top_level_paths = chef_fs_config.chef_fs.children.select { |entry| entry.name != 'acls' && entry.name != 'groups' }.map { |entry| entry.path }
|
253
|
-
acl_paths
|
254
|
-
group_acl_paths =
|
255
|
-
group_paths
|
157
|
+
acl_paths = chef_fs_paths('/acls/*', chef_fs_config, 'groups')
|
158
|
+
group_acl_paths = chef_fs_paths('/acls/groups/*', chef_fs_config, 'billing-admins.json')
|
159
|
+
group_paths = chef_fs_paths('/groups/*', chef_fs_config, 'billing-admins.json')
|
256
160
|
(top_level_paths + group_acl_paths + acl_paths + group_paths).each do |path|
|
257
|
-
|
161
|
+
chef_fs_copy_pattern(path, chef_fs_config)
|
258
162
|
end
|
259
|
-
|
260
163
|
ensure
|
261
164
|
Chef::Config.restore(old_config)
|
262
165
|
end
|
263
166
|
end
|
167
|
+
|
168
|
+
def chef_fs_paths(pattern_str, chef_fs_config, exclude=nil)
|
169
|
+
pattern = Chef::ChefFS::FilePattern.new(pattern_str)
|
170
|
+
list = Chef::ChefFS::FileSystem.list(chef_fs_config.chef_fs, pattern)
|
171
|
+
list = list.select { |entry| entry.name != exclude } if ! exclude.nil?
|
172
|
+
list.map {|entry| entry.path }
|
173
|
+
end
|
174
|
+
|
175
|
+
def chef_fs_copy_pattern(pattern_str, chef_fs_config)
|
176
|
+
pattern = Chef::ChefFS::FilePattern.new(pattern_str)
|
177
|
+
Chef::ChefFS::FileSystem.copy_to(pattern, chef_fs_config.chef_fs,
|
178
|
+
chef_fs_config.local_fs, nil,
|
179
|
+
config, ui,
|
180
|
+
proc { |entry| chef_fs_config.format_path(entry) })
|
181
|
+
end
|
264
182
|
end
|
265
183
|
end
|
266
184
|
end
|