gtool 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|