pe-razor-client 1.1.0 → 1.2.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 +4 -4
- data/NEWS.md +16 -2
- data/bin/razor +3 -2
- data/lib/razor/cli/command.rb +41 -36
- data/lib/razor/cli/format.rb +28 -13
- data/lib/razor/cli/navigate.rb +45 -1
- data/lib/razor/cli/parse.rb +52 -21
- data/lib/razor/cli/version.rb +1 -1
- data/spec/cli/command_spec.rb +96 -0
- data/spec/cli/navigate_spec.rb +25 -0
- data/spec/cli/parse_spec.rb +11 -0
- data/spec/fixtures/vcr/Razor_CLI_Navigate/argument_formatting/should_allow_single-dash_with_single_character_flag.yml +203 -0
- data/spec/fixtures/vcr/Razor_CLI_Navigate/argument_formatting/should_not_allow_double-dash_with_single_character_flag.yml +133 -0
- data/spec/fixtures/vcr/Razor_CLI_Navigate/argument_formatting/should_not_allow_single-dash_with_multiple_character_flag.yml +133 -0
- data/spec/fixtures/vcr/Razor_CLI_Navigate/positional_arguments/should_allow_the_use_of_positional_arguments.yml +681 -0
- data/spec/fixtures/vcr/Razor_CLI_Navigate/positional_arguments/should_fail_with_too_many_positional_arguments.yml +133 -0
- metadata +17 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe070f4bc93ec0248752bc35b80c29e24df6461a
|
4
|
+
data.tar.gz: 8f0a33e1f9b6e5a29421c6e1fd52055affd1c1f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 80e55e7decd173351ffbf41a45bad53f2a2c60e3b7d75a03a974dabc100bddf6117dbaf92d7e844022027ec98f0f1e2bc9f248142254bae716b40c071b214b5c
|
7
|
+
data.tar.gz: 53be116318939b11783b775ddbb1849ea291f06d55aada79d6a7cbea64c587f240eddf09ae9a6e2af968a0bd6dfa6075d1bdfb622f8e1ac5280f931acb5afec9
|
data/NEWS.md
CHANGED
@@ -1,8 +1,22 @@
|
|
1
1
|
# Razor Client Release Notes
|
2
2
|
|
3
|
-
##
|
3
|
+
## 1.2.0 - 2016-03-08
|
4
4
|
|
5
|
-
*
|
5
|
+
* BUGFIX: Razor client version will be reported even if the Razor server is
|
6
|
+
unreachable.
|
7
|
+
* BUGFIX: Fixed insecure flag when supplied in addition to a server URL.
|
8
|
+
* NEW: Added positional argument support, when supplied by the server. See
|
9
|
+
`razor <command> --help` for details on usage.
|
10
|
+
* NEW: Added USAGE section to the command's help, which will include positional
|
11
|
+
arguments, if any exist.
|
12
|
+
* IMPROVEMENT: Proper short form argument style is now followed.
|
13
|
+
Single-character arguments now require a single dash, e.g. `-c`.
|
14
|
+
* IMPROVEMENT: Error messaging for SSL issues has been improved.
|
15
|
+
|
16
|
+
## 1.1.0 - 2015-11-12
|
17
|
+
|
18
|
+
* IMPROVEMENT: By default, `razor` will point to port 8150.
|
19
|
+
* IMPROVEMENT: Better display of several views/collections.
|
6
20
|
|
7
21
|
## 1.0.0 - 2015-06-08
|
8
22
|
|
data/bin/razor
CHANGED
data/lib/razor/cli/command.rb
CHANGED
@@ -1,54 +1,60 @@
|
|
1
1
|
class Razor::CLI::Command
|
2
|
-
def initialize(parse, navigate,
|
3
|
-
@
|
2
|
+
def initialize(parse, navigate, command, segments, cmd_url)
|
3
|
+
@dump_response = parse && parse.dump_response?
|
4
|
+
@show_command_help = parse && parse.show_command_help?
|
4
5
|
@navigate = navigate
|
5
|
-
@
|
6
|
+
@command = command
|
7
|
+
@cmd_schema = command ? command['schema'] : nil
|
8
|
+
@cmd_url = cmd_url
|
6
9
|
@segments = segments
|
7
10
|
end
|
8
11
|
|
9
12
|
def run
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
# Ensure that we copy authentication data from our previous URL.
|
14
|
-
url = URI.parse(cmd["id"])
|
15
|
-
if @doc_resource
|
16
|
-
url = URI.parse(url.to_s)
|
17
|
-
end
|
18
|
-
|
19
|
-
if @parse.show_command_help?
|
20
|
-
@navigate.json_get(url)
|
13
|
+
body = extract_command
|
14
|
+
if @show_command_help
|
15
|
+
@command
|
21
16
|
else
|
22
17
|
if body.empty?
|
23
18
|
raise Razor::CLI::Error,
|
24
19
|
"No arguments for command (did you forget --json ?)"
|
25
20
|
end
|
26
|
-
result = @navigate.json_post(
|
21
|
+
result = @navigate.json_post(@cmd_url, body)
|
27
22
|
# Get actual object from the id.
|
28
23
|
result = result.merge(@navigate.json_get(URI.parse(result['id']))) if result['id']
|
29
24
|
result
|
30
25
|
end
|
31
26
|
end
|
32
27
|
|
33
|
-
def command(name)
|
34
|
-
@command ||= @commands.find { |coll| coll["name"] == name }
|
35
|
-
end
|
36
|
-
|
37
28
|
def extract_command
|
38
|
-
cmd = command(@segments.shift)
|
39
|
-
@cmd_url = URI.parse(cmd['id'])
|
40
|
-
@cmd_schema = cmd_schema(@cmd_url)
|
41
29
|
body = {}
|
30
|
+
pos_index = 0
|
42
31
|
until @segments.empty?
|
43
32
|
argument = @segments.shift
|
44
|
-
if argument =~ /\A--([a-z-]
|
45
|
-
|
46
|
-
arg
|
33
|
+
if argument =~ /\A--([a-z-]{2,})(=(.+))?\Z/ or
|
34
|
+
argument =~ /\A-([a-z])(=(.+))?\Z/
|
35
|
+
# `--arg=value`/`--arg value`
|
36
|
+
# `-a=value`/`-a value`
|
37
|
+
arg_name, value = [$1, $3]
|
47
38
|
value = @segments.shift if value.nil? && @segments[0] !~ /^--/
|
48
|
-
|
49
|
-
body[
|
39
|
+
arg_name = self.class.resolve_alias(arg_name, @cmd_schema)
|
40
|
+
body[arg_name] = self.class.convert_arg(arg_name, value, body[arg_name], @cmd_schema)
|
41
|
+
elsif argument =~ /\A-([a-z-]{2,})(=(.+))?\Z/ and
|
42
|
+
@cmd_schema[self.class.resolve_alias($1, @cmd_schema)]
|
43
|
+
# Short form, should be long; offer suggestion
|
44
|
+
raise ArgumentError, "Unexpected argument #{argument} (did you mean --#{$1}?)"
|
45
|
+
elsif argument =~ /\A--([a-z])(=(.+))?\Z/ and
|
46
|
+
@cmd_schema[self.class.resolve_alias($1, @cmd_schema)]
|
47
|
+
# Long form, should be short; offer suggestion
|
48
|
+
raise ArgumentError, "Unexpected argument #{argument} (did you mean -#{$1}?)"
|
50
49
|
else
|
51
|
-
|
50
|
+
# This may be a positional argument.
|
51
|
+
arg_name = positional_argument(@cmd_schema, pos_index)
|
52
|
+
if arg_name
|
53
|
+
body[arg_name] = self.class.convert_arg(arg_name, argument, body[arg_name], @cmd_schema)
|
54
|
+
pos_index += 1
|
55
|
+
else
|
56
|
+
raise ArgumentError, "Unexpected argument #{argument}"
|
57
|
+
end
|
52
58
|
end
|
53
59
|
end
|
54
60
|
|
@@ -62,15 +68,14 @@ class Razor::CLI::Command
|
|
62
68
|
raise Razor::CLI::Error,
|
63
69
|
"Permission to read file #{body["json"]} denied"
|
64
70
|
end
|
65
|
-
|
71
|
+
body
|
66
72
|
end
|
67
73
|
|
68
|
-
def cmd_schema
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
74
|
+
def positional_argument(cmd_schema, pos_index)
|
75
|
+
# Find a matching position and return its argument name.
|
76
|
+
cmd_schema && cmd_schema.select do |_, schema|
|
77
|
+
schema['position'] == pos_index
|
78
|
+
end.keys.first
|
74
79
|
end
|
75
80
|
|
76
81
|
def self.arg_type(arg_name, cmd_schema)
|
@@ -94,7 +99,7 @@ class Razor::CLI::Command
|
|
94
99
|
argument_type = arg_type(arg_name, cmd_schema)
|
95
100
|
|
96
101
|
# This might be helpful, since there's no other method for debug-level logging on the client.
|
97
|
-
puts "Formatting argument #{arg_name} with value #{value} as #{argument_type}\n" if @
|
102
|
+
puts "Formatting argument #{arg_name} with value #{value} as #{argument_type}\n" if @dump_response
|
98
103
|
|
99
104
|
case argument_type
|
100
105
|
when "array"
|
data/lib/razor/cli/format.rb
CHANGED
@@ -65,33 +65,48 @@ module Razor::CLI
|
|
65
65
|
def format_command_help(doc, show_api_help)
|
66
66
|
item = doc.items.first
|
67
67
|
raise Razor::CLI::Error, 'Could not find help for that entry' unless item.has_key?('help')
|
68
|
-
if
|
69
|
-
|
70
|
-
|
71
|
-
|
68
|
+
if item['help'].has_key?('examples')
|
69
|
+
if show_api_help && item['help']['examples'].has_key?('api')
|
70
|
+
format_composed_help(item, item['help']['examples']['api']).chomp
|
71
|
+
else
|
72
|
+
format_composed_help(item).chomp
|
73
|
+
end
|
72
74
|
else
|
73
75
|
format_full_help(item['help']).chomp
|
74
76
|
end
|
75
77
|
end
|
76
78
|
|
77
|
-
def
|
79
|
+
def positional_args_usage(object)
|
80
|
+
object['schema'].map do |k, v|
|
81
|
+
[v['position'], k] if v.has_key?('position')
|
82
|
+
end.compact.sort.map(&:last).
|
83
|
+
map {|attr| "[#{attr.gsub('_', '-')}] " }.join.strip
|
84
|
+
end
|
85
|
+
def format_composed_help(object, examples = object['help']['examples']['cli'])
|
86
|
+
help_obj = object['help']
|
78
87
|
ret = ''
|
79
|
-
ret = ret + <<-
|
88
|
+
ret = ret + <<-USAGE
|
89
|
+
# USAGE
|
90
|
+
|
91
|
+
razor #{object['name']} #{positional_args_usage(object)} <flags>
|
92
|
+
|
93
|
+
USAGE
|
94
|
+
ret = ret + <<-SYNOPSIS if help_obj.has_key?('summary')
|
80
95
|
# SYNOPSIS
|
81
|
-
#{
|
96
|
+
#{help_obj['summary']}
|
82
97
|
|
83
98
|
SYNOPSIS
|
84
|
-
ret = ret + <<-DESCRIPTION if
|
99
|
+
ret = ret + <<-DESCRIPTION if help_obj.has_key?('description')
|
85
100
|
# DESCRIPTION
|
86
|
-
#{
|
101
|
+
#{help_obj['description']}
|
87
102
|
|
88
|
-
#{
|
103
|
+
#{help_obj['schema']}
|
89
104
|
DESCRIPTION
|
90
|
-
ret = ret + <<-RETURNS if
|
105
|
+
ret = ret + <<-RETURNS if help_obj.has_key?('returns')
|
91
106
|
# RETURNS
|
92
|
-
#{
|
107
|
+
#{help_obj['returns'].gsub(/^/, ' ')}
|
93
108
|
RETURNS
|
94
|
-
ret = ret + <<-EXAMPLES if
|
109
|
+
ret = ret + <<-EXAMPLES if examples
|
95
110
|
# EXAMPLES
|
96
111
|
|
97
112
|
#{examples.gsub(/^/, ' ')}
|
data/lib/razor/cli/navigate.rb
CHANGED
@@ -3,6 +3,42 @@ require 'multi_json'
|
|
3
3
|
require 'yaml'
|
4
4
|
require 'forwardable'
|
5
5
|
|
6
|
+
# Needed to make the client work on Ruby 1.8.7
|
7
|
+
unless URI.respond_to?(:encode_www_form)
|
8
|
+
module URI
|
9
|
+
def self.encode_www_form_component(str)
|
10
|
+
str = str.to_s
|
11
|
+
if HTML5ASCIIINCOMPAT.include?(str.encoding)
|
12
|
+
str = str.encode(Encoding::UTF_8)
|
13
|
+
else
|
14
|
+
str = str.dup
|
15
|
+
end
|
16
|
+
str.force_encoding(Encoding::ASCII_8BIT)
|
17
|
+
str.gsub!(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_)
|
18
|
+
str.force_encoding(Encoding::US_ASCII)
|
19
|
+
end
|
20
|
+
def self.encode_www_form(enum)
|
21
|
+
enum.map do |k,v|
|
22
|
+
if v.nil?
|
23
|
+
encode_www_form_component(k)
|
24
|
+
elsif v.respond_to?(:to_ary)
|
25
|
+
v.to_ary.map do |w|
|
26
|
+
str = encode_www_form_component(k)
|
27
|
+
unless w.nil?
|
28
|
+
str << '='
|
29
|
+
str << encode_www_form_component(w)
|
30
|
+
end
|
31
|
+
end.join('&')
|
32
|
+
else
|
33
|
+
str = encode_www_form_component(k)
|
34
|
+
str << '='
|
35
|
+
str << encode_www_form_component(v)
|
36
|
+
end
|
37
|
+
end.join('&')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
6
42
|
module Razor::CLI
|
7
43
|
class Navigate
|
8
44
|
extend Forwardable
|
@@ -57,7 +93,15 @@ module Razor::CLI
|
|
57
93
|
elsif query?
|
58
94
|
Razor::CLI::Query.new(@parse, self, collections, @segments).run
|
59
95
|
elsif command?
|
60
|
-
|
96
|
+
cmd = @segments.shift
|
97
|
+
command = commands.find { |coll| coll["name"] == cmd }
|
98
|
+
cmd_url = URI.parse(command['id'])
|
99
|
+
# Ensure that we copy authentication data from our previous URL.
|
100
|
+
if @doc_resource
|
101
|
+
cmd_url = URI.parse(cmd_url.to_s)
|
102
|
+
end
|
103
|
+
command = json_get(cmd_url)
|
104
|
+
Razor::CLI::Command.new(@parse, self, command, @segments, cmd_url).run
|
61
105
|
else
|
62
106
|
raise NavigationError.new(@doc_resource, @segments, @doc)
|
63
107
|
end
|
data/lib/razor/cli/parse.rb
CHANGED
@@ -2,6 +2,16 @@ require 'uri'
|
|
2
2
|
require 'optparse'
|
3
3
|
require 'forwardable'
|
4
4
|
|
5
|
+
# Needed to make the client work on Ruby 1.8.7
|
6
|
+
unless URI::Generic.method_defined?(:hostname)
|
7
|
+
module URI
|
8
|
+
def hostname
|
9
|
+
v = self.host
|
10
|
+
/\A\[(.*)\]\z/ =~ v ? $1 : v
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
5
15
|
module Razor::CLI
|
6
16
|
|
7
17
|
class Parse
|
@@ -53,22 +63,19 @@ module Razor::CLI
|
|
53
63
|
end
|
54
64
|
|
55
65
|
def version
|
66
|
+
server_version = '(unknown)'
|
67
|
+
error = ''
|
56
68
|
begin
|
57
|
-
|
58
|
-
Razor Server version: #{navigate.server_version}
|
59
|
-
Razor Client version: #{Razor::CLI::VERSION}
|
60
|
-
VERSION
|
69
|
+
server_version = navigate.server_version
|
61
70
|
rescue RestClient::Unauthorized
|
62
|
-
|
63
|
-
Error: Credentials are required to connect to the server at #{@api_url}"
|
64
|
-
UNAUTH
|
65
|
-
exit 1
|
71
|
+
error = "Error: Credentials are required to connect to the server at #{@api_url}."
|
66
72
|
rescue
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
73
|
+
error = "Error: Could not connect to the server at #{@api_url}."
|
74
|
+
ensure
|
75
|
+
return [(<<-OUTPUT + "\n" + error).rstrip, error != '' ? 1 : 0]
|
76
|
+
Razor Server version: #{server_version}
|
77
|
+
Razor Client version: #{Razor::CLI::VERSION}
|
78
|
+
OUTPUT
|
72
79
|
end
|
73
80
|
end
|
74
81
|
|
@@ -95,10 +102,23 @@ HELP
|
|
95
102
|
Error: Credentials are required to connect to the server at #{@api_url}"
|
96
103
|
UNAUTH
|
97
104
|
exit = 1
|
98
|
-
rescue
|
105
|
+
rescue SocketError, Errno::ECONNREFUSED => e
|
106
|
+
puts "Error: Could not connect to the server at #{@api_url}"
|
107
|
+
puts " #{e}\n"
|
108
|
+
die
|
109
|
+
rescue RestClient::SSLCertificateNotVerified
|
110
|
+
puts "Error: SSL certificate could not be verified against known CA certificates."
|
111
|
+
puts " To turn off verification, use the -k or --insecure option."
|
112
|
+
die
|
113
|
+
rescue OpenSSL::SSL::SSLError => e
|
114
|
+
# Occurs in case of e.g. certificate mismatch (FQDN vs. hostname)
|
115
|
+
puts "Error: SSL certificate error from server at #{@api_url}"
|
116
|
+
puts " #{e}"
|
117
|
+
die
|
118
|
+
rescue => e
|
99
119
|
output << <<-ERR
|
100
|
-
Error:
|
101
|
-
|
120
|
+
Error: Unknown error occurred while connecting to server at #{@api_url}:
|
121
|
+
#{e}
|
102
122
|
ERR
|
103
123
|
exit = 1
|
104
124
|
end
|
@@ -133,23 +153,34 @@ ERR
|
|
133
153
|
# The format can be determined from later segments.
|
134
154
|
attr_accessor :format, :stripped_args, :ssl_ca_file
|
135
155
|
|
156
|
+
LINUX_PEM_FILE = '/etc/puppetlabs/puppet/ssl/certs/ca.pem'
|
157
|
+
WIN_PEM_FILE = 'C:\ProgramData\PuppetLabs\puppet\etc\ssl\certs\ca.pem'
|
136
158
|
def initialize(args)
|
137
159
|
parse_and_set_api_url(ENV["RAZOR_API"] || DEFAULT_RAZOR_API, :env)
|
138
160
|
@args = args.dup
|
139
161
|
# To be populated externally.
|
140
162
|
@stripped_args = []
|
141
163
|
@format = 'short'
|
164
|
+
@verify_ssl = true
|
165
|
+
env_pem_file = ENV['RAZOR_CA_FILE']
|
142
166
|
# If this is set, it should actually exist.
|
143
|
-
if
|
144
|
-
raise Razor::CLI::InvalidCAFileError.new(
|
167
|
+
if env_pem_file && !File.exists?(env_pem_file)
|
168
|
+
raise Razor::CLI::InvalidCAFileError.new(env_pem_file)
|
169
|
+
end
|
170
|
+
pem_file_locations = [env_pem_file, LINUX_PEM_FILE, WIN_PEM_FILE]
|
171
|
+
pem_file_locations.each do |file|
|
172
|
+
if file && File.exists?(file)
|
173
|
+
@ssl_ca_file = file
|
174
|
+
break
|
175
|
+
end
|
145
176
|
end
|
146
|
-
ca_file = ENV["RAZOR_CA_FILE"] || '/etc/puppetlabs/puppet/ssl/certs/ca.pem'
|
147
|
-
@ssl_ca_file = ca_file if ca_file && File.exists?(ca_file)
|
148
177
|
@args = get_optparse.order(@args)
|
149
178
|
|
150
179
|
# Localhost won't match the server's certificate; no verification required.
|
151
180
|
# This needs to happen after get_optparse so `-k` and `-u` can take effect.
|
152
|
-
|
181
|
+
if @api_url.hostname == 'localhost'
|
182
|
+
@verify_ssl = false
|
183
|
+
end
|
153
184
|
|
154
185
|
@args = set_help_vars(@args)
|
155
186
|
if @args == ['version'] or @show_version
|
data/lib/razor/cli/version.rb
CHANGED
@@ -18,7 +18,7 @@ module Razor
|
|
18
18
|
#
|
19
19
|
# The next line is the one that our packaging tools modify, so please make
|
20
20
|
# sure that any change to it is discussed and agreed first.
|
21
|
-
version = '1.
|
21
|
+
version = '1.2.0'
|
22
22
|
|
23
23
|
if version == "DEVELOPMENT"
|
24
24
|
root = File.expand_path("../../..", File.dirname(__FILE__))
|
data/spec/cli/command_spec.rb
CHANGED
@@ -63,4 +63,100 @@ describe Razor::CLI::Command do
|
|
63
63
|
result.should == 'abc'
|
64
64
|
end
|
65
65
|
end
|
66
|
+
|
67
|
+
context "extract_command" do
|
68
|
+
|
69
|
+
def extract(schema, run_array)
|
70
|
+
c = Razor::CLI::Command.new(nil, nil, schema, run_array, nil)
|
71
|
+
c.extract_command
|
72
|
+
end
|
73
|
+
context "flag length" do
|
74
|
+
|
75
|
+
it "fails with a single dash for long flags" do
|
76
|
+
expect{extract({'schema' => {'name' => {'type' => 'array'}}}, ['-name', 'abc'])}.
|
77
|
+
to raise_error(ArgumentError, 'Unexpected argument -name (did you mean --name?)')
|
78
|
+
end
|
79
|
+
it "fails with a double dash for short flags" do
|
80
|
+
expect{extract({'schema' => {'n' => {'type' => 'array'}}}, ['--n', 'abc'])}.
|
81
|
+
to raise_error(ArgumentError, 'Unexpected argument --n (did you mean -n?)')
|
82
|
+
end
|
83
|
+
it "fails with a double dash for short flags if argument does not exist" do
|
84
|
+
c = Razor::CLI::Command.new(nil, nil, {'schema' => {}},
|
85
|
+
['--n', 'abc'], '/foobar')
|
86
|
+
expect{extract({'schema' => {}}, ['--n', 'abc'])}.
|
87
|
+
to raise_error(ArgumentError, 'Unexpected argument --n')
|
88
|
+
end
|
89
|
+
it "succeeds with a double dash for long flags" do
|
90
|
+
extract({'schema' => {'name' => {'type' => 'array'}}},
|
91
|
+
['--name', 'abc'])['name'].should == ['abc']
|
92
|
+
end
|
93
|
+
it "succeeds with a single dash for short flags" do
|
94
|
+
c = Razor::CLI::Command.new(nil, nil, {'schema' => {'n' => {'type' => 'array'}}},
|
95
|
+
['-n', 'abc'], nil)
|
96
|
+
extract({'schema' => {'n' => {'type' => 'array'}}}, ['-n', 'abc'])['n'].should == ['abc']
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "positional arguments" do
|
101
|
+
let(:schema) do
|
102
|
+
{'schema' => {'n' => {'position' => 1},
|
103
|
+
'o' => {'position' => 0}}}
|
104
|
+
end
|
105
|
+
it "fails without a command schema" do
|
106
|
+
expect{extract(nil, ['123'])}.
|
107
|
+
to raise_error(ArgumentError, 'Unexpected argument 123')
|
108
|
+
end
|
109
|
+
it "fails if no positional arguments exist for a command" do
|
110
|
+
expect{extract({'schema' => {'n' => {}}}, ['abc'])}.
|
111
|
+
to raise_error(ArgumentError, 'Unexpected argument abc')
|
112
|
+
end
|
113
|
+
it "succeeds if no position is supplied" do
|
114
|
+
extract({'schema' => {'n' => {'position' => 0}}}, ['-n', '123'])['n'].
|
115
|
+
should == '123'
|
116
|
+
end
|
117
|
+
it "succeeds if position exists and is supplied" do
|
118
|
+
extract({'schema' => {'n' => {'position' => 0}}}, ['123'])['n'].
|
119
|
+
should == '123'
|
120
|
+
end
|
121
|
+
it "succeeds if multiple positions exist and are supplied" do
|
122
|
+
body = extract(schema, ['123', '456'])
|
123
|
+
body['o'].should == '123'
|
124
|
+
body['n'].should == '456'
|
125
|
+
end
|
126
|
+
it "fails if too many positions are supplied" do
|
127
|
+
expect{extract(schema, ['123', '456', '789'])}.
|
128
|
+
to raise_error(ArgumentError, 'Unexpected argument 789')
|
129
|
+
end
|
130
|
+
it "succeeds if multiple positions exist and one is supplied" do
|
131
|
+
body = extract(schema, ['123'])
|
132
|
+
body['o'].should == '123'
|
133
|
+
body['n'].should == nil
|
134
|
+
end
|
135
|
+
it "succeeds with a combination of positional and flags" do
|
136
|
+
body = extract(schema, ['123', '-n', '456'])
|
137
|
+
body['o'].should == '123'
|
138
|
+
body['n'].should == '456'
|
139
|
+
end
|
140
|
+
it "prefers the later between positional and flags" do
|
141
|
+
body = extract(schema, ['123', '-o', '456'])
|
142
|
+
body['o'].should == '456'
|
143
|
+
body = extract(schema, ['-o', '456', '123'])
|
144
|
+
body['o'].should == '123'
|
145
|
+
end
|
146
|
+
it "correctly sets datatypes" do
|
147
|
+
schema =
|
148
|
+
{'schema' => {'n' => {'type' => 'array', 'position' => 0},
|
149
|
+
'o' => {'type' => 'number', 'position' => 1},
|
150
|
+
'w' => {'type' => 'boolean', 'position' => 2},
|
151
|
+
'a' => {'type' => 'object', 'position' => 3},
|
152
|
+
'i' => {'type' => 'object', 'position' => 4}}}
|
153
|
+
body = extract(schema, ['arr', '123', 'true', '{}', 'abc=123'])
|
154
|
+
body['n'].should == ['arr']
|
155
|
+
body['o'].should == 123
|
156
|
+
body['w'].should == true
|
157
|
+
body['a'].should == {}
|
158
|
+
body['i'].should == {'abc' => '123'}
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
66
162
|
end
|