Skip to content

Commit

Permalink
Merge "scriptability improvements for uaac" into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
daleolds authored and Gerrit Code Review committed Sep 21, 2012
2 parents 15c97f3 + be80fd8 commit 4e964cb
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 173 deletions.
4 changes: 1 addition & 3 deletions gem/bin/uaac
@@ -1,7 +1,5 @@
#!/usr/bin/env ruby

$:.unshift File.expand_path File.join __FILE__, '..', '..', 'lib'

require 'cli'

CF::UAA::Cli.configure("#{ENV['HOME']}/.uaac.yml").run
exit CF::UAA::Cli.configure("#{ENV['HOME']}/.uaac.yml").run ? 0 : 1
33 changes: 20 additions & 13 deletions gem/lib/cli/base.rb
Expand Up @@ -20,9 +20,7 @@ module CF::UAA

class Topic

class << self
attr_reader :synonyms
end
class << self; attr_reader :synonyms end

def self.option_defs ; @option_defs || {} end
def self.commands; @commands || {} end
Expand Down Expand Up @@ -60,7 +58,8 @@ def initialize(cli_class, options = {}, input = $stdin, output = $stdout)

def ask(prompt); @highline.ask("#{prompt}: ") end
def ask_pwd(prompt); @highline.ask("#{prompt}: ") { |q| q.echo = '*' } end
def say(*args); @output.puts args end
def say(msg); @output.puts(msg); msg end
def gripe(msg); @output.puts(msg) end
def opts; @options end

def terminal_columns
Expand All @@ -75,7 +74,6 @@ def help_col_start
end

def pp(obj, indent = 0, wrap = terminal_columns, label = nil)
#line = indent_count == 0 ? "#{label}": sprintf("%*c%s", indent_count * indent_size, ' ', label)
case obj
when Array
if obj.empty? || !obj[0].is_a?(Hash) && !obj[0].is_a?(Array)
Expand All @@ -87,8 +85,10 @@ def pp(obj, indent = 0, wrap = terminal_columns, label = nil)
when Hash
say_definition(indent, label, nil, nil, wrap) if label
obj.each { |k, v| pp v, indent + 2, wrap, "#{k}: " }
when nil
else say_definition(indent, label, obj.to_s, nil, wrap)
end
obj
end

def say_definition(indent, term, text = nil, start = help_col_start, wrap = terminal_columns)
Expand Down Expand Up @@ -119,6 +119,7 @@ def say_definition(indent, term, text = nil, start = help_col_start, wrap = term
@output.printf("%s\n", line)
cur = start
end
nil
end

def opt_help(key, args)
Expand Down Expand Up @@ -160,12 +161,15 @@ def say_command_help(args)
say ""
@cli_class.topics.each do |tpc|
tpc.commands.each do |k, v|
return say_cmd_helper(v, "\n") if args[0..v[:parts].length - 1] == v[:parts]
if args[0..v[:parts].length - 1] == v[:parts]
say_cmd_helper(v, "\n")
return "help command"
end
end
end
args = args.map(&:downcase)
@cli_class.topics.each { |tpc| return say_help(tpc) unless (args & tpc.synonyms).empty? }
say "No command or topic found to match: #{args.join(' ')}", ""
gripe "No command or topic found to match: #{args.join(' ')}\n"
end

def say_help(topic = nil)
Expand All @@ -175,13 +179,17 @@ def say_help(topic = nil)
@output.print "\n#{tpc.topic}\n"
tpc.commands.each { |k, v| say_cmd_helper v }
end
return @output.print("\n") if topic || !@cli_class.global_options
if topic || !@cli_class.global_options
@output.print("\n")
return topic ? "help topic" : "help"
end
@output.print "\nGlobal options:\n"
@cli_class.global_options.each do |o|
odef, desc = opt_help(o, @cli_class.option_defs[o])
say_definition 2, odef, desc
end
@output.print("\n")
"help"
end

def add_command(branches, parts, opts = nil)
Expand Down Expand Up @@ -213,6 +221,7 @@ def say_commands
add_command(tree[:sub], [], @cli_class.global_options)
@output.puts tree[:label]
print_tree(tree[:sub], 1)
"help commands"
end

end
Expand Down Expand Up @@ -249,18 +258,16 @@ def self.run(args = ARGV)
# variable args, leave args alone
elsif args.length > v[:argc]
too_many_args(v[:parts].dup)
return self
return nil
elsif args.length < v[:argc]
(v[:argc] - args.length).times { args << nil }
end
tpc.new(self, opts, @input, @output).send(k, *args)
return self
return tpc.new(self, opts, @input, @output).send(k, *args)
end
end
@output.puts "#{File.basename($0)}: subcommand not found"
self
rescue Exception => e
$stderr.puts "", "#{e.class}: #{e.message}", (e.backtrace if opts[:trace])
@output.puts "#{File.basename($0)} error", "#{e.class}: #{e.message}", (e.backtrace if opts[:trace])
end

end
Expand Down
59 changes: 25 additions & 34 deletions gem/lib/cli/client_reg.rb
Expand Up @@ -20,15 +20,31 @@ class ClientCli < CommonCli

topic "Client Application Registrations", "reg"

CLIENT_SCHEMA =
{
scope: "list",
authorized_grant_types: "list",
authorities: "list",
access_token_validity: "seconds",
refresh_token_validity: "seconds",
redirect_uri: "list"
}
def client_reg_request
(yield ClientReg.new(Config.target, auth_header)) || "success" # no exception means success
rescue TargetError => e
complain e
end

def client_info(defaults, interact)
del_op = "<delete>"
info = {client_id: opts[:client_id]}
info[:client_secret] = opts[:secret] if opts[:secret]
CLIENT_SCHEMA.each_with_object(info) do |(k, p), info|
v = nil
if !opts.key?(k)
info[k] = (v unless v == del_op) if interact ?
!p.empty? && (v = askd("#{k.to_s.gsub('_', ' ')} (#{p})", defaults[k])) : (v = defaults[k])
elsif opts[k] == del_op
info[k] = nil
else
info[k] = v if (v = (opts[k].nil? || opts[k].empty? ? defaults[k]: opts[k]))
end
end
end

CLIENT_SCHEMA = { scope: "list", authorized_grant_types: "list", authorities: "list",
access_token_validity: "seconds", refresh_token_validity: "seconds", redirect_uri: "list" }

CLIENT_SCHEMA.each { |k, v| define_option(k, "--#{k} <#{v}>") }

Expand Down Expand Up @@ -83,31 +99,6 @@ class ClientCli < CommonCli
end
end

def client_reg_request
return yield ClientReg.new(Config.target, auth_header)
rescue TargetError => e
say "\n#{e.message}:\n#{JSON.pretty_generate(e.info)}"
rescue Exception => e
say "\n#{e.class}: #{e.message}", (e.backtrace if trace?)
end

def client_info(defaults, interact)
del_op = "<delete>"
info = {client_id: opts[:client_id]}
info[:client_secret] = opts[:secret] if opts[:secret]
CLIENT_SCHEMA.each_with_object(info) do |(k, p), info|
v = nil
if !opts.key?(k)
info[k] = (v unless v == del_op) if interact ?
!p.empty? && (v = askd("#{k.to_s.gsub('_', ' ')} (#{p})", defaults[k])) : (v = defaults[k])
elsif opts[k] == del_op
info[k] = nil
else
info[k] = v if (v = (opts[k].nil? || opts[k].empty? ? defaults[k]: opts[k]))
end
end
end

end

end
62 changes: 36 additions & 26 deletions gem/lib/cli/common.rb
Expand Up @@ -48,12 +48,21 @@ def askd(prompt, defary)
result.nil? || result.empty? ? defary : result
end

def complain(e)
case e
when TargetError then gripe "\n#{e.message}:\n#{JSON.pretty_generate(e.info)}"
when Exception
gripe "\n#{e.class}: #{e.message}"
gripe e.backtrace if trace?
when String then gripe e
else gripe "unknown type of gripe: #{e.class}, #{e}"
end
end

def handle_request
yield
rescue TargetError => e
say "\n#{e.message}:\n#{JSON.pretty_generate(e.info)}"
rescue Exception => e
say "\n#{e.class}: #{e.message}", (e.backtrace if trace?)
complain e
end

def update_target_info(info = nil)
Expand All @@ -78,31 +87,51 @@ class MiscCli < CommonCli
define_option :debug, "--[no-]debug", "-d", "display debug information"
define_option :help, "--[no-]help", "-h", "display helpful information"
define_option :version, "--[no-]version", "-v", "show version"
define_option :config, "--config [string|file]", "file to get/save configuration information or yaml string"

desc "help [topic|command...]", "Display summary or details of command or topic" do |*args|
# handle hidden command, output commands in form for bash completion
return say_commands if args.length == 1 && args[0] == "commands"
args.empty? ? say_help : say_command_help(args)
end

def normalize_url(url, scheme = nil)
url = url.strip.gsub(/\/*$/, "")
raise ArgumentError, "invalid whitespace in target url" if url =~ /\s/
unless url =~ /^https?:\/\//
return unless scheme
url = "#{scheme}://#{url}"
end
url = URI.parse(url)
url.host.downcase!
url.to_s.to_sym
end

def bad_uaa_url(url, info)
info.replace(Misc.server(url.to_s))
nil
rescue Exception => e
"failed to access #{url}: #{e.message}"
end

define_option :force, "--[no-]force", "-f", "set context even if target UAA is not available"
desc "target [uaa_url]", "Display current or set new target" do |uaa_url|
msg, info = nil, {}
if uaa_url
if uaa_url.to_i.to_s == uaa_url
return say "invalid target index" unless url = Config.target?(uaa_url.to_i)
return gripe "invalid target index" unless url = Config.target?(uaa_url.to_i)
elsif url = normalize_url(uaa_url)
return say msg if (msg = bad_uaa_url(url, info)) unless opts[:force] || Config.target?(url)
return gripe msg if (msg = bad_uaa_url(url, info)) unless opts[:force] || Config.target?(url)
elsif !Config.target?(url = normalize_url(uaa_url, "https")) &&
!Config.target?(url = normalize_url(uaa_url, "http"))
if opts[:force]
url = normalize_url(uaa_url, "https")
elsif bad_uaa_url((url = normalize_url(uaa_url, "https")), info)
return say msg if msg = bad_uaa_url((url = normalize_url(uaa_url, "http")), info)
return gripe msg if msg = bad_uaa_url((url = normalize_url(uaa_url, "http")), info)
end
end
Config.target = url # we now have a canonical url set to https if possible
update_target_info(info)
update_target_info(info) if info[:prompts]
end
return say "no target set" unless Config.target
return say "target set to #{Config.target}" unless Config.context
Expand Down Expand Up @@ -146,25 +175,6 @@ def config_pp(tgt = nil, ctx = nil)

desc "contexts", "Display all contexts" do config_pp end

def normalize_url(url, scheme = nil)
url = url.strip.gsub(/\/*$/, "")
raise ArgumentError, "invalid whitespace in target url" if url =~ /\s/
unless url =~ /^https?:\/\//
return unless scheme
url = "#{scheme}://#{url}"
end
url = URI.parse(url)
url.host.downcase!
url.to_s.to_sym
end

def bad_uaa_url(url, info)
info.merge! Misc.server(url.to_s)
nil
rescue Exception => e
"failed to access #{url}: #{e.message}"
end

end

end
11 changes: 6 additions & 5 deletions gem/lib/cli/config.rb
Expand Up @@ -18,19 +18,18 @@ module CF::UAA

class Config

class << self
attr_reader :target, :context
end
class << self; attr_reader :target, :context end

def self.config; @config ? @config.dup : {} end
def self.loaded?; !!@config end
def self.yaml; YAML.dump(Util.hash_keys(@config, :tostr)) end
def self.target?(tgt) tgt if @config[tgt = subhash_key(@config, tgt)] end

# if a yaml string is provided, config is loaded from the string, otherwise
# config is assumed to be a file name to read and store config.
# config can be retrieved in yaml form from Config.yaml
def self.load(config = nil)
@config ||= {}
@config = {}
return unless config
if config =~ /^---/ || config == ""
@config = config == "" ? {} : YAML.load(config)
Expand All @@ -45,14 +44,16 @@ def self.load(config = nil)
"Please review the new commands with 'uaac help'", ""
exit 1
}
else # file doesn't exist, make sure we can write it now
File.open(@config_file, 'w') { |f| f.write(" ") }
end
@config = Util.hash_keys(@config, :tosym)
@context = current_subhash(@config[@target][:contexts]) if @target = current_subhash(@config)
end

def self.save
File.open(@config_file, 'w') { |f| YAML.dump(Util.hash_keys(@config, :tostr), f) } if @config_file
nil
true
end

def self.target=(tgt)
Expand Down
6 changes: 2 additions & 4 deletions gem/lib/cli/group.rb
Expand Up @@ -21,11 +21,9 @@ class GroupCli < CommonCli
topic "Groups", "group"

def acct_request
return yield UserAccount.new(Config.target, auth_header)
(yield UserAccount.new(Config.target, auth_header)) || "success"
rescue TargetError => e
"\n#{e.message}:\n#{JSON.pretty_generate(e.info)}\n"
rescue Exception => e
"\n#{e.class}: #{e.message}\n#{e.backtrace if trace?}\n"
complain e
end

def gname(name) name || ask("Group name") end
Expand Down

0 comments on commit 4e964cb

Please sign in to comment.