chef_fixie 0.1.0 → 0.5.0
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 +5 -5
- data/bin/chef_fixie +2 -2
- data/doc/AccessingSQL.md +33 -1
- data/doc/BulkFixup.md +33 -0
- data/doc/CommonTasks.md +14 -3
- data/lib/chef_fixie.rb +7 -6
- data/lib/chef_fixie/authz_mapper.rb +26 -28
- data/lib/chef_fixie/authz_objects.rb +51 -41
- data/lib/chef_fixie/bulk_edit_permissions.rb +161 -0
- data/lib/chef_fixie/check_org_associations.rb +56 -59
- data/lib/chef_fixie/config.rb +58 -23
- data/lib/chef_fixie/console.rb +17 -12
- data/lib/chef_fixie/context.rb +2 -4
- data/lib/chef_fixie/sql.rb +12 -12
- data/lib/chef_fixie/sql_objects.rb +107 -31
- data/lib/chef_fixie/utility_helpers.rb +13 -9
- data/lib/chef_fixie/version.rb +1 -1
- data/spec/chef_fixie/acl_spec.rb +23 -25
- data/spec/chef_fixie/assoc_invite_spec.rb +5 -8
- data/spec/chef_fixie/check_org_associations_spec.rb +14 -17
- data/spec/chef_fixie/groups_spec.rb +7 -11
- data/spec/chef_fixie/org_spec.rb +4 -5
- data/spec/chef_fixie/orgs_spec.rb +6 -9
- data/spec/spec_helper.rb +5 -6
- metadata +13 -49
- data/bin/bundler +0 -16
- data/bin/chef-apply +0 -16
- data/bin/chef-client +0 -16
- data/bin/chef-shell +0 -16
- data/bin/chef-solo +0 -16
- data/bin/chef-zero +0 -16
- data/bin/coderay +0 -16
- data/bin/edit_json.rb +0 -16
- data/bin/erubis +0 -16
- data/bin/ffi-yajl-bench +0 -16
- data/bin/fixie~ +0 -231
- data/bin/htmldiff +0 -16
- data/bin/knife +0 -16
- data/bin/ldiff +0 -16
- data/bin/net-dhcp +0 -16
- data/bin/ohai +0 -16
- data/bin/prettify_json.rb +0 -16
- data/bin/pry +0 -16
- data/bin/rackup +0 -16
- data/bin/rake +0 -16
- data/bin/rdoc +0 -16
- data/bin/restclient +0 -16
- data/bin/ri +0 -16
- data/bin/rspec +0 -16
- data/bin/s3sh +0 -16
- data/bin/sequel +0 -16
- data/bin/serverspec-init +0 -16
- data/doc/AccessingSQL.md~ +0 -32
- data/doc/BulkFixup.md~ +0 -28
- data/doc/CommonTasks.md~ +0 -0
- data/doc/GETTING_STARTED.md~ +0 -6
- data/spec/chef_fixie/assoc_invite_spec.rb~ +0 -26
- data/spec/chef_fixie/check_org_associations_spec.rb~ +0 -34
- data/spec/chef_fixie/org_spec.rb~ +0 -53
data/lib/chef_fixie/console.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright (c) 2015 Chef Software Inc.
|
2
|
+
# Copyright (c) 2015 Chef Software Inc.
|
3
3
|
# License :: Apache License, Version 2.0
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -18,20 +18,21 @@
|
|
18
18
|
#
|
19
19
|
# Much of this code was orginally derived from the orgmapper tool, which had many varied authors.
|
20
20
|
|
21
|
-
require
|
22
|
-
require
|
23
|
-
require
|
21
|
+
require "optparse"
|
22
|
+
require "pp"
|
23
|
+
require "pry"
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
require_relative "../chef_fixie"
|
26
|
+
require_relative "context"
|
27
27
|
|
28
28
|
module ChefFixie
|
29
29
|
module Console
|
30
30
|
extend self
|
31
31
|
|
32
32
|
def start
|
33
|
+
@@started_from_command_line = true
|
33
34
|
configure
|
34
|
-
|
35
|
+
ChefFixie.setup
|
35
36
|
configure_pry
|
36
37
|
Pry.start
|
37
38
|
end
|
@@ -41,14 +42,14 @@ module ChefFixie
|
|
41
42
|
if ARGV.first && ARGV[0].chars.first != "-" && config_file = ARGV.shift
|
42
43
|
config_file = File.expand_path(config_file)
|
43
44
|
end
|
44
|
-
|
45
|
+
ChefFixie.load_config(config_file)
|
45
46
|
|
46
47
|
options = {}
|
47
48
|
OptionParser.new do |opt|
|
48
49
|
opt.banner = "Usage: fixie [config] [options]"
|
49
|
-
opt.on(
|
50
|
-
opt.on("--sql_database DATABASE",
|
51
|
-
opt.on_tail(
|
50
|
+
opt.on("--authz_uri AUTH_URI", "The URI of the opscode authz service") { |v| options[:authz_uri] = v }
|
51
|
+
opt.on("--sql_database DATABASE", "The URI of the opscode_chef database") { |v| options[:sql_database] = v }
|
52
|
+
opt.on_tail("-h", "--help", "Show this message") do
|
52
53
|
puts opt
|
53
54
|
puts "\nExample configuration file:\n\n"
|
54
55
|
puts ChefFixie::Config.instance.example_config
|
@@ -67,7 +68,7 @@ module ChefFixie
|
|
67
68
|
Pry.config.history.file = "~/.fixie_history"
|
68
69
|
Pry.config.prompt_name = "fixie"
|
69
70
|
Pry::Commands.block_command("fixie-help", "Show fixie's help") do
|
70
|
-
|
71
|
+
output.puts(<<-HALP)
|
71
72
|
** ORGS **
|
72
73
|
* access with ORGS or ORGS
|
73
74
|
* access a specific org: ORGS['orgname']
|
@@ -87,5 +88,9 @@ HALP
|
|
87
88
|
end
|
88
89
|
end
|
89
90
|
|
91
|
+
def started_from_command_line?
|
92
|
+
@@started_from_command_line == true
|
93
|
+
end
|
94
|
+
|
90
95
|
end
|
91
96
|
end
|
data/lib/chef_fixie/context.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright (c) 2015 Chef Software Inc.
|
2
|
+
# Copyright (c) 2015 Chef Software Inc.
|
3
3
|
# License :: Apache License, Version 2.0
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -18,9 +18,8 @@
|
|
18
18
|
#
|
19
19
|
# Much of this code was orginally derived from the orgmapper tool, which had many varied authors.
|
20
20
|
|
21
|
-
|
22
21
|
module ChefFixie
|
23
|
-
|
22
|
+
module Context
|
24
23
|
|
25
24
|
def describe_orgs
|
26
25
|
OrgMetrics.org_stats(orgs)
|
@@ -67,6 +66,5 @@ module ChefFixie
|
|
67
66
|
|
68
67
|
ChefFixie::Dissociator.dissociate_user(org, user)
|
69
68
|
end
|
70
|
-
|
71
69
|
end
|
72
70
|
end
|
data/lib/chef_fixie/sql.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright (c) 2014-2015 Chef Software Inc.
|
2
|
+
# Copyright (c) 2014-2015 Chef Software Inc.
|
3
3
|
# License :: Apache License, Version 2.0
|
4
4
|
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -16,20 +16,20 @@
|
|
16
16
|
#
|
17
17
|
# Author: Mark Anderson <mark@chef.io>
|
18
18
|
|
19
|
-
require
|
20
|
-
require
|
21
|
-
require
|
19
|
+
require "ffi_yajl"
|
20
|
+
require "uuidtools"
|
21
|
+
require "sequel"
|
22
22
|
|
23
|
-
|
23
|
+
require_relative "config"
|
24
24
|
|
25
25
|
Sequel.default_timezone = :utc
|
26
26
|
|
27
27
|
module ChefFixie
|
28
28
|
module Sql
|
29
|
-
|
29
|
+
|
30
30
|
class InvalidConfig < StandardError
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
# A connection string passed to Sequel.connect()
|
34
34
|
#
|
35
35
|
# Examples:
|
@@ -46,25 +46,25 @@ module ChefFixie
|
|
46
46
|
|
47
47
|
# Returns the connection string or raises an error if you didn't set one.
|
48
48
|
def self.connection_string
|
49
|
-
@connection_string ||= ChefFixie.configure {|x| x.sql_database }
|
49
|
+
@connection_string ||= ChefFixie.configure { |x| x.sql_database }
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
# Returns a Sequel::Data baseobject, which wraps access to the database.
|
53
53
|
def self.default_connection
|
54
54
|
@database ||= Sequel.connect(connection_string, :max_connections => 2)
|
55
55
|
# @database.loggers << Logger.new($stdout)
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
# Generate a new UUID. Currently uses the v1 UUID scheme.
|
59
59
|
def new_uuid
|
60
60
|
UUIDTools::UUID.timestamp_create.hexdigest
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
# Parse the portion of the object that's stored as a blob o' JSON
|
64
64
|
def from_json(serialized_data)
|
65
65
|
FFI_Yajl::Parser.parse(serialized_data, :symbolize_keys => true)
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
# Encode the portion of the object that's stored as a blob o' JSON
|
69
69
|
def as_json(data)
|
70
70
|
FFI_Yajl::Encoder.encode(data)
|
@@ -17,12 +17,12 @@
|
|
17
17
|
# Author: Mark Anderson <mark@chef.io>
|
18
18
|
#
|
19
19
|
|
20
|
-
require
|
21
|
-
require
|
20
|
+
require "pp"
|
21
|
+
require "sequel"
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
require_relative "config"
|
24
|
+
require_relative "authz_objects"
|
25
|
+
require_relative "authz_mapper"
|
26
26
|
|
27
27
|
Sequel.extension :inflector
|
28
28
|
|
@@ -39,18 +39,40 @@ module ChefFixie
|
|
39
39
|
"ChefFixie::Sql" + "::" # this should be autogenerated not hardcoded
|
40
40
|
end
|
41
41
|
|
42
|
+
def self.to_name(class_or_name)
|
43
|
+
name =
|
44
|
+
case
|
45
|
+
when class_or_name.is_a?(Symbol)
|
46
|
+
class_or_name.to_s
|
47
|
+
when class_or_name.is_a?(Class)
|
48
|
+
class_or_name.name
|
49
|
+
when class_or_name.is_a?(String)
|
50
|
+
class_or_name
|
51
|
+
else
|
52
|
+
class_or_name.class.to_s
|
53
|
+
end
|
54
|
+
name.split("::")[-1]
|
55
|
+
end
|
56
|
+
|
42
57
|
# The class for the table, e.g. Orgs
|
43
58
|
def self.table_class(name)
|
59
|
+
name = to_name(name)
|
44
60
|
(base + name.to_s.pluralize.camelize).constantize
|
45
61
|
end
|
62
|
+
|
46
63
|
# The class for one instance of the object, e.g. Org
|
47
64
|
def self.object_class(name)
|
65
|
+
name = to_name(name)
|
48
66
|
(base + name.to_s.singularize.camelize).constantize
|
49
67
|
end
|
68
|
+
|
50
69
|
def self.singular(name)
|
70
|
+
name = to_name(name)
|
51
71
|
name.to_s.singularize
|
52
72
|
end
|
73
|
+
|
53
74
|
def self.plural(name)
|
75
|
+
name = to_name(name)
|
54
76
|
name.to_s.pluralize
|
55
77
|
end
|
56
78
|
end
|
@@ -60,38 +82,51 @@ module ChefFixie
|
|
60
82
|
def initialize(data)
|
61
83
|
@data = data
|
62
84
|
end
|
85
|
+
|
63
86
|
def data
|
64
87
|
@data
|
65
88
|
end
|
66
89
|
|
90
|
+
def table
|
91
|
+
Relationships.table_class(self).new
|
92
|
+
end
|
93
|
+
|
67
94
|
# TODO rework this to use better style
|
68
95
|
def self.ro_access(*args)
|
69
96
|
args.each do |field|
|
70
97
|
fundef = "def #{field}; @data.#{field}; end"
|
71
|
-
|
98
|
+
class_eval(fundef)
|
72
99
|
end
|
73
100
|
end
|
74
101
|
# TODO figure out model for write access
|
75
102
|
|
76
103
|
def self.name_field(field)
|
77
104
|
fundef = "def name; @data.#{field}; end"
|
78
|
-
|
105
|
+
class_eval(fundef)
|
79
106
|
end
|
80
107
|
|
81
108
|
def self.std_timestamp
|
82
109
|
[:created_at, :updated_at].each do |i|
|
83
|
-
|
110
|
+
ro_access(i)
|
84
111
|
end
|
85
112
|
end
|
113
|
+
|
86
114
|
# Pretty much any object with an authz id has these fields
|
87
115
|
def self.std_authz
|
88
|
-
|
116
|
+
std_timestamp
|
89
117
|
[:authz_id, :last_updated_by].each do |i|
|
90
|
-
|
118
|
+
ro_access(i)
|
91
119
|
end
|
92
120
|
end
|
93
121
|
|
94
|
-
|
122
|
+
def delete
|
123
|
+
rows = table.by_id(id)
|
124
|
+
raise "id #{id} matches more than one object" if rows.all.count != 1
|
125
|
+
rows.inner.delete
|
126
|
+
if respond_to?(:authz_delete)
|
127
|
+
authz_delete
|
128
|
+
end
|
129
|
+
end
|
95
130
|
end
|
96
131
|
|
97
132
|
class Org < SqlObject
|
@@ -102,13 +137,14 @@ module ChefFixie
|
|
102
137
|
funname = Relationships.plural(object)
|
103
138
|
# defer evaluation of mapper to make sure we have a chance for everyone to initialize
|
104
139
|
fundef = "def #{funname}; Relationships.table_class(:#{object}).new.by_org_id(org_id); end"
|
105
|
-
|
140
|
+
class_eval(fundef)
|
106
141
|
end
|
107
142
|
end
|
108
143
|
|
109
144
|
def initialize(data)
|
110
145
|
super(data)
|
111
146
|
end
|
147
|
+
|
112
148
|
def org_id
|
113
149
|
data[:id]
|
114
150
|
end
|
@@ -116,7 +152,47 @@ module ChefFixie
|
|
116
152
|
def global_admins
|
117
153
|
name = self.name
|
118
154
|
global_admins_name = "#{name}_global_admins"
|
119
|
-
|
155
|
+
read_access_name = "#{name}_read_access_group"
|
156
|
+
ChefFixie::Sql::Groups.new[global_admins_name] || \
|
157
|
+
ChefFixie::Sql::Groups.new[read_access_name]
|
158
|
+
end
|
159
|
+
|
160
|
+
alias read_access_group global_admins
|
161
|
+
|
162
|
+
# Iterators for objects in authz; using containers to enumerate things
|
163
|
+
# It might be better to metaprogram this up instead,
|
164
|
+
#
|
165
|
+
# TODO Write some tests to validate that this stuff
|
166
|
+
# works, since it depends on a lot of name magic...
|
167
|
+
|
168
|
+
NAME_FIXUP = { "data" => "data_bags", "sandboxes" => nil }
|
169
|
+
def objects_by_container_type(container)
|
170
|
+
name = NAME_FIXUP.has_key?(container) ? NAME_FIXUP[container] : container
|
171
|
+
return [] if name.nil?
|
172
|
+
|
173
|
+
object_type = name.to_sym
|
174
|
+
# raise Exception "No such object_type #{object_type}" unless respond_to?(object_type)
|
175
|
+
send(object_type).all(:all)
|
176
|
+
end
|
177
|
+
|
178
|
+
def each_authz_object_by_class
|
179
|
+
containers = self.containers.all(:all)
|
180
|
+
containers.each do |container|
|
181
|
+
objects = objects_by_container_type(container.name)
|
182
|
+
if block_given?
|
183
|
+
yield objects
|
184
|
+
end
|
185
|
+
end
|
186
|
+
nil
|
187
|
+
end
|
188
|
+
|
189
|
+
def each_authz_object
|
190
|
+
each_authz_object_by_class do |objectlist|
|
191
|
+
objectlist.each do |object|
|
192
|
+
yield object
|
193
|
+
end
|
194
|
+
end
|
195
|
+
nil
|
120
196
|
end
|
121
197
|
|
122
198
|
scoped_type :container, :group, :client,
|
@@ -188,7 +264,6 @@ module ChefFixie
|
|
188
264
|
# org_migration_state_id_seq policy_revisions
|
189
265
|
# policy_revisions_policy_groups_association sandboxed_checksums
|
190
266
|
|
191
|
-
|
192
267
|
class CookbookArtifact < SqlObject
|
193
268
|
include AuthzObjectMixin
|
194
269
|
def initialize(data)
|
@@ -269,35 +344,37 @@ module ChefFixie
|
|
269
344
|
def self.max_count_default
|
270
345
|
50
|
271
346
|
end
|
272
|
-
|
347
|
+
|
273
348
|
def get_table
|
274
349
|
:unknown_table
|
275
350
|
end
|
351
|
+
|
276
352
|
def mk_element(x)
|
277
353
|
x
|
278
354
|
end
|
279
355
|
|
280
356
|
def initialize(tablespec = nil)
|
281
357
|
ChefFixie::Sql.default_connection
|
282
|
-
@inner = tablespec || Sequel::Model(
|
358
|
+
@inner = tablespec || Sequel::Model(get_table)
|
283
359
|
end
|
360
|
+
|
284
361
|
def inner
|
285
362
|
# Make sure we have init
|
286
363
|
@inner
|
287
364
|
end
|
288
365
|
|
289
366
|
def filter_core(field, exp)
|
290
|
-
self.class.new(inner.filter(field=>exp))
|
367
|
+
self.class.new(inner.filter(field => exp))
|
291
368
|
end
|
292
369
|
|
293
|
-
def all(max_count
|
370
|
+
def all(max_count = :default)
|
294
371
|
if max_count == :default
|
295
372
|
max_count = ChefFixie::Sql::SqlTable.max_count_default
|
296
373
|
end
|
297
374
|
if max_count != :all
|
298
|
-
return :too_many_results if
|
375
|
+
return :too_many_results if inner.count > max_count
|
299
376
|
end
|
300
|
-
elements = inner.all.map {|org| mk_element(org) }
|
377
|
+
elements = inner.all.map { |org| mk_element(org) }
|
301
378
|
end
|
302
379
|
|
303
380
|
#
|
@@ -306,7 +383,7 @@ module ChefFixie
|
|
306
383
|
# https://stackoverflow.com/questions/9658724/ruby-metaprogramming-class-eval/9658775#9658775
|
307
384
|
def self.primary(arg)
|
308
385
|
name = :"by_#{arg}"
|
309
|
-
|
386
|
+
class_eval("def [](arg); #{name}(arg).all(1).first; end")
|
310
387
|
|
311
388
|
listfun = <<EOLF
|
312
389
|
def list(max_count=:default)
|
@@ -318,26 +395,27 @@ def list(max_count=:default)
|
|
318
395
|
end
|
319
396
|
end
|
320
397
|
EOLF
|
321
|
-
|
398
|
+
class_eval(listfun)
|
322
399
|
end
|
323
400
|
|
324
401
|
def self.filter_by(*args)
|
325
402
|
args.each do |field|
|
326
403
|
name = "by_#{field}"
|
327
404
|
fundef = "def #{name}(exp); filter_core(:#{field},exp); end"
|
328
|
-
|
405
|
+
class_eval(fundef)
|
329
406
|
end
|
330
407
|
end
|
331
408
|
|
332
409
|
def self.table(name)
|
333
410
|
fundef = "def get_table; :#{name}; end"
|
334
|
-
|
411
|
+
class_eval(fundef)
|
335
412
|
end
|
413
|
+
|
336
414
|
# doesn't work yet
|
337
415
|
# element Org in class Orgs will fail because it can't find Org (undefined)
|
338
416
|
def self.element(name)
|
339
417
|
fundef = "ElementType = name; def mk_element(x); #{name}.new(x); end"
|
340
|
-
|
418
|
+
class_eval(fundef)
|
341
419
|
end
|
342
420
|
end
|
343
421
|
|
@@ -349,7 +427,7 @@ EOLF
|
|
349
427
|
primary :name
|
350
428
|
filter_by :name, :id, :full_name, :authz_id
|
351
429
|
|
352
|
-
GlobalOrg = "0"*32
|
430
|
+
GlobalOrg = "0" * 32
|
353
431
|
|
354
432
|
def self.org_guid_to_name(guid)
|
355
433
|
"global" if guid == GlobalOrg
|
@@ -370,7 +448,7 @@ EOLF
|
|
370
448
|
|
371
449
|
def by_org_id_user_id(org_id, user_id)
|
372
450
|
# db table constraint guarantees that this is unique
|
373
|
-
inner.filter(:org_id=>org_id, :user_id=>user_id).all.first
|
451
|
+
inner.filter(:org_id => org_id, :user_id => user_id).all.first
|
374
452
|
end
|
375
453
|
|
376
454
|
end
|
@@ -380,7 +458,7 @@ EOLF
|
|
380
458
|
|
381
459
|
def by_org_id_user_id(org_id, user_id)
|
382
460
|
# db table constraint guarantees that this is unique
|
383
|
-
inner.filter(:org_id=>org_id, :user_id=>user_id).all.first
|
461
|
+
inner.filter(:org_id => org_id, :user_id => user_id).all.first
|
384
462
|
end
|
385
463
|
end
|
386
464
|
class Users < SqlTable
|
@@ -482,7 +560,7 @@ EOLF
|
|
482
560
|
filter_by :name, :id, :org_id, :authz_id
|
483
561
|
end
|
484
562
|
|
485
|
-
class Roles
|
563
|
+
class Roles < SqlTable
|
486
564
|
table :roles
|
487
565
|
element Sql::Role
|
488
566
|
register_authz :role, :object
|
@@ -491,7 +569,5 @@ EOLF
|
|
491
569
|
filter_by :name, :id, :org_id, :authz_id, :last_updated_by
|
492
570
|
end
|
493
571
|
|
494
|
-
|
495
|
-
|
496
572
|
end
|
497
573
|
end
|