gtool 0.0.1
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.
- data/LICENSE +14 -0
- data/README.markdown +99 -0
- data/Rakefile +5 -0
- data/bin/gtool +19 -0
- data/lib/gtool.rb +17 -0
- data/lib/gtool/auth.rb +81 -0
- data/lib/gtool/cli.rb +5 -0
- data/lib/gtool/provision/customerid.rb +25 -0
- data/lib/gtool/provision/group.rb +172 -0
- data/lib/gtool/provision/orgmember.rb +67 -0
- data/lib/gtool/provision/orgunit.rb +50 -0
- data/lib/gtool/provision/user.rb +128 -0
- data/lib/gtool/util/ask_default.rb +10 -0
- data/lib/gtool/version.rb +4 -0
- metadata +93 -0
data/LICENSE
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Copyright 2011 Puppet Labs
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
14
|
+
|
data/README.markdown
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
Gtool
|
2
|
+
=====
|
3
|
+
|
4
|
+
Interact with the Google Provisioning API from the command line.
|
5
|
+
|
6
|
+
Description
|
7
|
+
-----------
|
8
|
+
|
9
|
+
Gtool provides a command line interface for inspecting and interacting with
|
10
|
+
the Google Apps Provisioning API. You can create, view, edit and remove
|
11
|
+
pretty much any entity available.
|
12
|
+
|
13
|
+
Installation
|
14
|
+
------------
|
15
|
+
|
16
|
+
**as a gem**
|
17
|
+
|
18
|
+
Wait for someone to turn this into a gem.
|
19
|
+
|
20
|
+
**from source**
|
21
|
+
|
22
|
+
git clone git://github.com/adrienthebo/ruby-gprov
|
23
|
+
git clone git://github.com/adrienthebo/gtool
|
24
|
+
|
25
|
+
export RUBYLIB="${RUBYLIB}:`pwd`/ruby-gprov/lib:`pwd`/gtool/lib"
|
26
|
+
export PATH="${PATH}:`pwd`/gtool/bin"
|
27
|
+
|
28
|
+
% gtool # magic!
|
29
|
+
|
30
|
+
Usage
|
31
|
+
-----
|
32
|
+
|
33
|
+
**General Usage**
|
34
|
+
|
35
|
+
% gtool
|
36
|
+
Tasks:
|
37
|
+
gtool auth [COMMAND] # GProv authentication operations
|
38
|
+
gtool customerid # Display Customer ID for the domain
|
39
|
+
gtool group [COMMAND] # GProv group provisioning
|
40
|
+
gtool help [TASK] # Describe available tasks or one specific task
|
41
|
+
gtool orgunit [COMMAND] # GProv user provisioning
|
42
|
+
gtool user [COMMAND] # GProv user provisioning
|
43
|
+
|
44
|
+
- - -
|
45
|
+
|
46
|
+
**Authentication**
|
47
|
+
|
48
|
+
% gtool auth
|
49
|
+
Tasks:
|
50
|
+
gtool auth display # Displays the cached credentials
|
51
|
+
gtool auth generate # Generate a token using the clientlogin method
|
52
|
+
|
53
|
+
% gtool auth generate
|
54
|
+
Username: user@example.com
|
55
|
+
Password:
|
56
|
+
Service (defaults to apps):
|
57
|
+
Domain: example.com
|
58
|
+
Authentication accepted, token valid till Sun Dec 04 22:32:29 -0800 2011
|
59
|
+
|
60
|
+
% gtool auth display
|
61
|
+
created: Sat Dec 03 22:32:29 -0800 2011 (valid)
|
62
|
+
token: API_TOKEN_HERE
|
63
|
+
|
64
|
+
- - -
|
65
|
+
|
66
|
+
**Users**
|
67
|
+
|
68
|
+
% gtool user
|
69
|
+
Tasks:
|
70
|
+
gtool user create USER # Create a new user
|
71
|
+
gtool user delete USER # Delete a user
|
72
|
+
gtool user get USER # Get a user
|
73
|
+
gtool user list # List users
|
74
|
+
|
75
|
+
- - -
|
76
|
+
|
77
|
+
**Groups**
|
78
|
+
|
79
|
+
% gtool group
|
80
|
+
Tasks:
|
81
|
+
gtool group addmember GROUP MEMBER # Add a member to a group
|
82
|
+
gtool group delmember GROUP MEMBER # Remove a member from a group
|
83
|
+
gtool group get GROUP # Get a particular group instance
|
84
|
+
gtool group list # List groups
|
85
|
+
gtool group members GROUP # Display members of a group
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
**Organizational Units**
|
90
|
+
|
91
|
+
% gtool orgunit
|
92
|
+
Tasks:
|
93
|
+
gtool orgunit get ORGUNIT # Get an orgunit
|
94
|
+
gtool orgunit list # List organizational units
|
95
|
+
gtool orgunit members ORGUNIT # Get the members of an orgunit
|
96
|
+
|
97
|
+
- - -
|
98
|
+
|
99
|
+
More complete documentation is pending on a more complete codebase.
|
data/Rakefile
ADDED
data/bin/gtool
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'gtool'
|
3
|
+
require 'gprov/error'
|
4
|
+
require 'thor/shell/color'
|
5
|
+
begin
|
6
|
+
Gtool::CLI.start
|
7
|
+
rescue GData::Error::TokenInvalid
|
8
|
+
Thor::Shell::Color.new.say "Invalid token, run '#{$0} auth generate' to generate a valid token.", :red
|
9
|
+
rescue GData::Error::QuotaExceeded
|
10
|
+
Thor::Shell::Color.new.say "API quota exceeded, try again later.", :red
|
11
|
+
rescue GData::Error::InputInvalid => e
|
12
|
+
Thor::Shell::Color.new.say "Request failed; sent invalid input", :red
|
13
|
+
$stderr.puts e.request.inspect
|
14
|
+
rescue GData::Error => e
|
15
|
+
$stderr.puts "Generic GData API error occurred"
|
16
|
+
$stderr.puts e.request.inspect
|
17
|
+
rescue Interrupt
|
18
|
+
$stderr.puts "\nAborted!"
|
19
|
+
end
|
data/lib/gtool.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
begin
|
2
|
+
require 'thor'
|
3
|
+
require 'thor/group'
|
4
|
+
rescue LoadError
|
5
|
+
require 'rubygems'
|
6
|
+
require 'thor'
|
7
|
+
require 'thor/group'
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'gtool/version'
|
11
|
+
require 'gtool/cli'
|
12
|
+
require 'gtool/auth'
|
13
|
+
require 'gtool/provision/user'
|
14
|
+
require 'gtool/provision/group'
|
15
|
+
require 'gtool/provision/customerid'
|
16
|
+
require 'gtool/provision/orgunit'
|
17
|
+
require 'gtool/provision/orgmember'
|
data/lib/gtool/auth.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'gtool'
|
2
|
+
require 'gtool/util/ask_default'
|
3
|
+
require 'gprov'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
module Gtool
|
7
|
+
class Auth < Thor
|
8
|
+
include Gtool::Util
|
9
|
+
Gtool::CLI.register self, "auth", "auth [COMMAND]", "GProv authentication operations"
|
10
|
+
namespace :auth
|
11
|
+
|
12
|
+
TOKEN_DURATION = 60 * 60 * 24 * 14
|
13
|
+
|
14
|
+
desc "generate", "Generate a token using the clientlogin method"
|
15
|
+
method_option "debug", :type => :boolean, :desc => "Enable debug output", :aliases => "-d"
|
16
|
+
method_option "noop", :type => :boolean, :desc => "Enable noop mode", :aliases => "-n"
|
17
|
+
def generate
|
18
|
+
user = ask "Username:"
|
19
|
+
%x{stty -echo}
|
20
|
+
pass = ask "Password:"
|
21
|
+
%x{stty echo}
|
22
|
+
puts
|
23
|
+
|
24
|
+
service = ask_default "apps", "Service (defaults to apps):"
|
25
|
+
|
26
|
+
domain = ask "Domain:"
|
27
|
+
|
28
|
+
authject = GProv::Auth::ClientLogin.new(user, pass, service, options)
|
29
|
+
token = authject.token
|
30
|
+
|
31
|
+
if token.nil?
|
32
|
+
say "Authentication failed!", :red
|
33
|
+
else
|
34
|
+
say "Authentication accepted, token valid till #{Time.now + TOKEN_DURATION}", :green
|
35
|
+
credentials = {:token => token, :created => Time.now, :domain => domain}
|
36
|
+
|
37
|
+
File.open("#{ENV['HOME']}/.gtool.yaml", "w") do |f|
|
38
|
+
f.write(YAML.dump(credentials))
|
39
|
+
f.chmod 0600
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "display", "Displays the cached credentials"
|
45
|
+
def display
|
46
|
+
settings = self.class.settings
|
47
|
+
|
48
|
+
expiration = Time.at(settings[:created]) + TOKEN_DURATION
|
49
|
+
|
50
|
+
if Time.now > expiration
|
51
|
+
say "created: #{settings[:created]} (expired)", :red
|
52
|
+
else
|
53
|
+
say "created: #{settings[:created]} (valid)", :green
|
54
|
+
say "expires: #{expiration}", :green
|
55
|
+
end
|
56
|
+
say "token: #{settings[:token]}", :cyan
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.settings
|
60
|
+
settings = nil
|
61
|
+
creds_file = "#{ENV['HOME']}/.gtool.yaml"
|
62
|
+
begin
|
63
|
+
File.open creds_file do |f|
|
64
|
+
settings = YAML::load f.read
|
65
|
+
end
|
66
|
+
rescue Errno::ENOENT
|
67
|
+
puts "#{creds_file} does not exist, run 'gtool auth generate'"
|
68
|
+
exit
|
69
|
+
end
|
70
|
+
settings
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.connection(options)
|
74
|
+
connection = GProv::Connection.new(settings[:domain], settings[:token], options)
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.banner(task, namespace = true, subcommand = false)
|
78
|
+
"#{basename} #{task.formatted_usage(self, true, subcommand)}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/gtool/cli.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'thor/group'
|
3
|
+
require 'gtool'
|
4
|
+
require 'gprov'
|
5
|
+
|
6
|
+
module Gtool
|
7
|
+
module Provision
|
8
|
+
class CustomerID < Thor::Group
|
9
|
+
Gtool::CLI.register self, "customerid", "customerid", "Display Customer ID for the domain"
|
10
|
+
|
11
|
+
class_option "debug", :type => :boolean, :default => false, :desc => "Enable debug output", :aliases => "-d"
|
12
|
+
class_option "noop", :type => :boolean, :default => false, :desc => "Enable noop mode", :aliases => "-n"
|
13
|
+
|
14
|
+
def display
|
15
|
+
connection = Gtool::Auth.connection(options)
|
16
|
+
fields = GProv::Provision::CustomerID.attribute_names
|
17
|
+
field_names = GProv::Provision::CustomerID.attribute_titles
|
18
|
+
id = GProv::Provision::CustomerID.get(connection)
|
19
|
+
|
20
|
+
properties = fields.map {|f| id.send f}
|
21
|
+
print_table field_names.zip(properties)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'gtool'
|
3
|
+
require 'gtool/util/ask_default'
|
4
|
+
require 'gprov'
|
5
|
+
|
6
|
+
module Gtool
|
7
|
+
module Provision
|
8
|
+
class Group < Thor
|
9
|
+
include Gtool::Util
|
10
|
+
Gtool::CLI.register self, "group", "group [COMMAND]", "GProv group provisioning"
|
11
|
+
namespace :group
|
12
|
+
|
13
|
+
class_option "debug", :type => :boolean, :default => false, :desc => "Enable debug output", :aliases => "-d"
|
14
|
+
class_option "noop", :type => :boolean, :default => false, :desc => "Enable noop mode", :aliases => "-n"
|
15
|
+
|
16
|
+
desc "list", "List groups"
|
17
|
+
def list
|
18
|
+
connection = Gtool::Auth.connection(options)
|
19
|
+
groups = GProv::Provision::Group.all(connection)
|
20
|
+
fields = GProv::Provision::Group.attribute_names
|
21
|
+
field_names = GProv::Provision::Group.attribute_titles
|
22
|
+
|
23
|
+
rows = groups.map do |group|
|
24
|
+
fields.map {|f| group.send f}
|
25
|
+
end
|
26
|
+
|
27
|
+
rows.unshift field_names
|
28
|
+
print_table rows
|
29
|
+
say "#{rows.length - 1} entries.", :cyan
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "get GROUP", "Get a particular group instance"
|
33
|
+
def get(groupname)
|
34
|
+
connection = Gtool::Auth.connection(options)
|
35
|
+
group = GProv::Provision::Group.get(connection, groupname)
|
36
|
+
fields = GProv::Provision::Group.attribute_names
|
37
|
+
field_names = GProv::Provision::Group.attribute_titles
|
38
|
+
|
39
|
+
if group.nil?
|
40
|
+
say "Group '#{groupname}' not found!", :red
|
41
|
+
else
|
42
|
+
properties = fields.map {|f| group.send f}
|
43
|
+
print_table field_names.zip(properties)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "create GROUP", "Create a new group"
|
48
|
+
def create(groupname)
|
49
|
+
connection = Gtool::Auth.connection(options)
|
50
|
+
group = GProv::Provision::Group.new(:connection => connection)
|
51
|
+
|
52
|
+
group.group_id = groupname
|
53
|
+
group.group_name = ask "Group name:"
|
54
|
+
group.email_permission = ask "Email Permission:"
|
55
|
+
group.permission_preset = ask "Permission Preset:"
|
56
|
+
group.description = ask "Group Description:"
|
57
|
+
|
58
|
+
group.create!
|
59
|
+
|
60
|
+
invoke "group:get", [group.group_id]
|
61
|
+
end
|
62
|
+
|
63
|
+
# TODO update group This is pending on the the backing group being able
|
64
|
+
# to store the group_id for the case that the group_id here is changed,
|
65
|
+
# but needs to post back to a specific url
|
66
|
+
|
67
|
+
desc "members GROUP", "Display members of a group"
|
68
|
+
def members(groupname)
|
69
|
+
connection = Gtool::Auth.connection(options)
|
70
|
+
group = GProv::Provision::Group.get(connection, groupname)
|
71
|
+
fields = GProv::Provision::Member.attribute_names
|
72
|
+
field_names = GProv::Provision::Member.attribute_titles
|
73
|
+
|
74
|
+
if group.nil?
|
75
|
+
say "Group '#{groupname}' not found!", :red
|
76
|
+
else
|
77
|
+
members = group.list_members
|
78
|
+
|
79
|
+
rows = members.map do |member|
|
80
|
+
fields.map {|f| member.send f}
|
81
|
+
end
|
82
|
+
|
83
|
+
rows.unshift field_names
|
84
|
+
print_table rows
|
85
|
+
say "#{rows.length - 1} entries.", :cyan
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
desc "addmember GROUP MEMBER", "Add a member to a group"
|
90
|
+
def addmember(groupname, member)
|
91
|
+
connection = Gtool::Auth.connection(options)
|
92
|
+
group = GProv::Provision::Group.get(connection, groupname)
|
93
|
+
|
94
|
+
if group.nil?
|
95
|
+
say "Group '#{groupname}' not found!", :red
|
96
|
+
else
|
97
|
+
group.add_member member
|
98
|
+
invoke "group:members", [groupname]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
desc "delmember GROUP MEMBER", "Remove a member from a group"
|
103
|
+
def delmember(groupname, member)
|
104
|
+
connection = Gtool::Auth.connection(options)
|
105
|
+
group = GProv::Provision::Group.get(connection, groupname)
|
106
|
+
|
107
|
+
if group.nil?
|
108
|
+
say "Group '#{groupname}' not found!", :red
|
109
|
+
else
|
110
|
+
group.del_member member
|
111
|
+
invoke "group:members", [groupname]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
desc "owners GROUP", "Display owners of a group"
|
116
|
+
def owners(groupname)
|
117
|
+
connection = Gtool::Auth.connection(options)
|
118
|
+
group = GProv::Provision::Group.get(connection, groupname)
|
119
|
+
fields = GProv::Provision::Owner.attribute_names
|
120
|
+
field_names = GProv::Provision::Owner.attribute_titles
|
121
|
+
|
122
|
+
if group.nil?
|
123
|
+
say "Group '#{groupname}' not found!", :red
|
124
|
+
else
|
125
|
+
owners = group.list_owners
|
126
|
+
|
127
|
+
if owners.nil?
|
128
|
+
say "Group #{groupname} has no owners!", :red
|
129
|
+
else
|
130
|
+
rows = owners.map { |owner| fields.map {|f| owner.send f} }
|
131
|
+
|
132
|
+
rows.unshift field_names
|
133
|
+
# XXX https://github.com/wycats/thor/issues/100
|
134
|
+
# print_table rows
|
135
|
+
puts rows.join("\n")
|
136
|
+
say "#{rows.length - 1} entries.", :cyan
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
desc "addowner GROUP OWNER", "Add an owner to a group"
|
142
|
+
def addowner(groupname, owner)
|
143
|
+
connection = Gtool::Auth.connection(options)
|
144
|
+
group = GProv::Provision::Group.get(connection, groupname)
|
145
|
+
|
146
|
+
if group.nil?
|
147
|
+
say "Group '#{groupname}' not found!", :red
|
148
|
+
else
|
149
|
+
group.add_owner owner
|
150
|
+
invoke "group:owners", [groupname]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
desc "delowner GROUP OWNER", "Remove an owner from a group"
|
155
|
+
def delowner(groupname, owner)
|
156
|
+
connection = Gtool::Auth.connection(options)
|
157
|
+
group = GProv::Provision::Group.get(connection, groupname)
|
158
|
+
|
159
|
+
if group.nil?
|
160
|
+
say "Group '#{groupname}' not found!", :red
|
161
|
+
else
|
162
|
+
group.del_owner owner
|
163
|
+
invoke "group:owners", [groupname]
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.banner(task, namespace = true, subcommand = false)
|
168
|
+
"#{basename} #{task.formatted_usage(self, true, subcommand)}"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'gtool'
|
3
|
+
require 'gprov'
|
4
|
+
|
5
|
+
module Gtool
|
6
|
+
module Provision
|
7
|
+
class OrgMember < Thor
|
8
|
+
Gtool::CLI.register self, "orgmember", "orgmember [COMMAND]", "GProv organizational member provisioning"
|
9
|
+
namespace :orgmember
|
10
|
+
|
11
|
+
class_option "debug", :type => :boolean, :desc => "Enable debug output", :aliases => "-d"
|
12
|
+
class_option "noop", :type => :boolean, :desc => "Enable noop mode", :aliases => "-n"
|
13
|
+
|
14
|
+
desc "list", "Get the members of an orgunit"
|
15
|
+
method_option "orgunit", :type => :string, :desc => "The orgunit from which to retrive users"
|
16
|
+
def list
|
17
|
+
if options[:orgunit]
|
18
|
+
options_hash = {:target => :orgunit, :orgunit => options[:orgunit]}
|
19
|
+
else
|
20
|
+
options_hash = {:target => :all}
|
21
|
+
end
|
22
|
+
|
23
|
+
connection = Gtool::Auth.connection(options)
|
24
|
+
orgmembers = GProv::Provision::OrgMember.all(connection, options_hash)
|
25
|
+
fields = GProv::Provision::OrgMember.attribute_names
|
26
|
+
field_names = GProv::Provision::OrgMember.attribute_titles
|
27
|
+
|
28
|
+
rows = orgmembers.map do |member|
|
29
|
+
fields.map {|f| member.send f}
|
30
|
+
end
|
31
|
+
|
32
|
+
rows.unshift field_names
|
33
|
+
print_table rows
|
34
|
+
say "#{rows.length - 1} entries.", :cyan
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "get MEMBER", "Retrieve a specific orgunit member"
|
38
|
+
def get(membername)
|
39
|
+
connection = Gtool::Auth.connection(options)
|
40
|
+
orgmember = GProv::Provision::OrgMember.get(connection, membername)
|
41
|
+
fields = GProv::Provision::OrgMember.attribute_names
|
42
|
+
field_names = GProv::Provision::OrgUnit.attribute_titles
|
43
|
+
|
44
|
+
if orgmember.nil?
|
45
|
+
say "Organizational unit '#{orgmember}' not found!", :red
|
46
|
+
else
|
47
|
+
properties = fields.map {|f| orgmember.send f}
|
48
|
+
print_table field_names.zip(properties)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "move ORG_MEMBER, NEW_ORGUNIT", "Move an organization unit member"
|
53
|
+
def move(membername, orgunit)
|
54
|
+
connection = Gtool::Auth.connection(options)
|
55
|
+
orgmember = GProv::Provision::OrgMember.get(connection, membername)
|
56
|
+
orgmember.org_unit_path = orgunit
|
57
|
+
orgmember.update!
|
58
|
+
|
59
|
+
invoke "orgmember:get", [membername]
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.banner(task, namespace = true, subcommand = false)
|
63
|
+
"#{basename} #{task.formatted_usage(self, true, subcommand)}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'gtool'
|
3
|
+
require 'gprov'
|
4
|
+
|
5
|
+
module Gtool
|
6
|
+
module Provision
|
7
|
+
class OrgUnit < Thor
|
8
|
+
Gtool::CLI.register self, "orgunit", "orgunit [COMMAND]", "GProv organizational unit provisioning"
|
9
|
+
namespace :orgunit
|
10
|
+
|
11
|
+
class_option "debug", :type => :boolean, :desc => "Enable debug output", :aliases => "-d"
|
12
|
+
class_option "noop", :type => :boolean, :desc => "Enable noop mode", :aliases => "-n"
|
13
|
+
|
14
|
+
desc "list", "List organizational units"
|
15
|
+
def list
|
16
|
+
connection = Gtool::Auth.connection(options)
|
17
|
+
orgunits = GProv::Provision::OrgUnit.all(connection)
|
18
|
+
fields = GProv::Provision::OrgUnit.attribute_names
|
19
|
+
field_names = GProv::Provision::OrgUnit.attribute_titles
|
20
|
+
|
21
|
+
rows = orgunits.map do |orgunit|
|
22
|
+
fields.map {|f| orgunit.send f}
|
23
|
+
end
|
24
|
+
|
25
|
+
rows.unshift field_names
|
26
|
+
print_table rows
|
27
|
+
say "#{rows.length - 1} entries.", :cyan
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "get ORGUNIT", "Get an orgunit"
|
31
|
+
def get(orgunit_name)
|
32
|
+
connection = Gtool::Auth.connection(options)
|
33
|
+
orgunit = GProv::Provision::OrgUnit.get(connection, orgunit_name)
|
34
|
+
fields = GProv::Provision::OrgUnit.attribute_names
|
35
|
+
field_names = GProv::Provision::OrgUnit.attribute_titles
|
36
|
+
|
37
|
+
if orgunit.nil?
|
38
|
+
say "Organizational unit '#{orgunit_name}' not found!", :red
|
39
|
+
else
|
40
|
+
properties = fields.map {|f| orgunit.send f}
|
41
|
+
print_table field_names.zip(properties)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.banner(task, namespace = true, subcommand = false)
|
46
|
+
"#{basename} #{task.formatted_usage(self, true, subcommand)}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'gtool'
|
3
|
+
require 'gtool/util/ask_default'
|
4
|
+
require 'gprov'
|
5
|
+
require 'digest/sha1'
|
6
|
+
|
7
|
+
module Gtool
|
8
|
+
module Provision
|
9
|
+
class User < Thor
|
10
|
+
include Gtool::Util
|
11
|
+
Gtool::CLI.register self, "user", "user [COMMAND]", "GProv user provisioning"
|
12
|
+
namespace :user
|
13
|
+
|
14
|
+
class_option "debug", :type => :boolean, :desc => "Enable debug output", :aliases => "-d"
|
15
|
+
class_option "noop", :type => :boolean, :desc => "Enable noop mode", :aliases => "-n"
|
16
|
+
|
17
|
+
desc "list", "List users"
|
18
|
+
def list
|
19
|
+
connection = Gtool::Auth.connection(options)
|
20
|
+
users = GProv::Provision::User.all(connection)
|
21
|
+
fields = GProv::Provision::User.attribute_names
|
22
|
+
field_names = GProv::Provision::User.attribute_titles
|
23
|
+
|
24
|
+
rows = users.map do |user|
|
25
|
+
fields.map {|f| user.send f}
|
26
|
+
end
|
27
|
+
|
28
|
+
rows.unshift field_names
|
29
|
+
print_table rows
|
30
|
+
say "#{rows.length - 1} entries.", :cyan
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "get USER", "Get a user"
|
34
|
+
def get(username)
|
35
|
+
connection = Gtool::Auth.connection(options)
|
36
|
+
user = GProv::Provision::User.get(connection, username)
|
37
|
+
fields = GProv::Provision::User.attribute_names
|
38
|
+
field_names = GProv::Provision::User.attribute_titles
|
39
|
+
|
40
|
+
if user.nil?
|
41
|
+
say "User '#{username}' not found!", :red
|
42
|
+
else
|
43
|
+
properties = fields.map {|f| user.send f}
|
44
|
+
print_table field_names.zip(properties)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
desc "create USER", "Create a new user"
|
49
|
+
def create(username)
|
50
|
+
connection = Gtool::Auth.connection(options)
|
51
|
+
|
52
|
+
user = GProv::Provision::User.new(:connection => connection)
|
53
|
+
|
54
|
+
user.user_name = username
|
55
|
+
user.given_name = ask "Given Name:"
|
56
|
+
user.family_name = ask "Family Name:"
|
57
|
+
|
58
|
+
# password! wheee!
|
59
|
+
%x{stty -echo}
|
60
|
+
user.password = Digest::SHA1.hexdigest(ask "Password:")
|
61
|
+
user.hash_function_name = "SHA-1"
|
62
|
+
%x{stty echo}
|
63
|
+
|
64
|
+
user.create!
|
65
|
+
|
66
|
+
invoke "user:get", [user.user_name]
|
67
|
+
end
|
68
|
+
|
69
|
+
desc "update USER", "Update an existing user"
|
70
|
+
def update(username)
|
71
|
+
connection = Gtool::Auth.connection(options)
|
72
|
+
|
73
|
+
user = GProv::Provision::User.get(connection, username)
|
74
|
+
|
75
|
+
user.user_name = ask_default(user.user_name, "Username (#{user.user_name}):")
|
76
|
+
user.given_name = ask_default(user.given_name, "Given Name (#{user.given_name}):")
|
77
|
+
user.family_name = ask_default(user.family_name, "Family Name (#{user.family_name}):")
|
78
|
+
user.admin = ask_default(user.admin, "Administrator (#{user.admin}):")
|
79
|
+
user.agreed_to_terms = ask_default(user.agreed_to_terms, "Agreed to terms (#{user.agreed_to_terms}):")
|
80
|
+
user.suspended = ask_default(user.suspended, "Suspended (#{user.suspended}):")
|
81
|
+
user.change_password_at_next_login = ask_default(user.change_password_at_next_login, "Change password at next login (#{user.change_password_at_next_login}):")
|
82
|
+
|
83
|
+
%x{stty -echo}
|
84
|
+
password = ask "Password (blank will not change):"
|
85
|
+
unless password.empty?
|
86
|
+
user.password = Digest::SHA1.hexdigest(password)
|
87
|
+
user.hash_function_name = "SHA-1"
|
88
|
+
end
|
89
|
+
%x{stty echo}
|
90
|
+
|
91
|
+
user.update!
|
92
|
+
|
93
|
+
invoke "user:get", [user.user_name]
|
94
|
+
end
|
95
|
+
|
96
|
+
desc "delete USER", "Delete a user"
|
97
|
+
def delete(username)
|
98
|
+
connection = Gtool::Auth.connection(options)
|
99
|
+
invoke "user:get", [username]
|
100
|
+
user = GProv::Provision::User.get(connection, username)
|
101
|
+
|
102
|
+
if user and (yes? "Permanently delete this user?") and (username == ask("Type in #{username} to confirm:"))
|
103
|
+
user.delete!
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
desc "groups USER", "Retrieve groups for a user"
|
108
|
+
def groups(username)
|
109
|
+
connection = Gtool::Auth.connection(options)
|
110
|
+
groups = GProv::Provision::Group.all(connection, :member => username)
|
111
|
+
fields = GProv::Provision::Group.attribute_names
|
112
|
+
field_names = GProv::Provision::Group.attribute_titles
|
113
|
+
|
114
|
+
rows = groups.map do |group|
|
115
|
+
fields.map {|f| group.send f}
|
116
|
+
end
|
117
|
+
|
118
|
+
rows.unshift field_names
|
119
|
+
print_table rows
|
120
|
+
say "#{rows.length - 1} entries.", :cyan
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.banner(task, namespace = true, subcommand = false)
|
124
|
+
"#{basename} #{task.formatted_usage(self, true, subcommand)}"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gtool
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Adrien Thebo
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-02-02 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: gprov
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 27
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
- 0
|
32
|
+
- 2
|
33
|
+
version: 0.0.2
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
description: All the fun of Google Provisioning, none of the HTML
|
37
|
+
email: adrien@puppetlabs.com
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files: []
|
43
|
+
|
44
|
+
files:
|
45
|
+
- bin/gtool
|
46
|
+
- lib/gtool/auth.rb
|
47
|
+
- lib/gtool/cli.rb
|
48
|
+
- lib/gtool/provision/customerid.rb
|
49
|
+
- lib/gtool/provision/group.rb
|
50
|
+
- lib/gtool/provision/orgmember.rb
|
51
|
+
- lib/gtool/provision/orgunit.rb
|
52
|
+
- lib/gtool/provision/user.rb
|
53
|
+
- lib/gtool/util/ask_default.rb
|
54
|
+
- lib/gtool/version.rb
|
55
|
+
- lib/gtool.rb
|
56
|
+
- LICENSE
|
57
|
+
- Rakefile
|
58
|
+
- README.markdown
|
59
|
+
homepage: http://github.com/adrienthebo/gtool
|
60
|
+
licenses: []
|
61
|
+
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
hash: 3
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
version: "0"
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
hash: 3
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
version: "0"
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 1.8.10
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: Command line interface to the Google Provisioning API
|
92
|
+
test_files: []
|
93
|
+
|