knife-ec-backup 2.0.0.beta.2 → 2.0.0.beta.3
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/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
|