pe-razor-client 0.14.0 → 0.15.2

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/NEWS.md +25 -0
  3. data/bin/razor +9 -4
  4. data/lib/razor/cli.rb +10 -0
  5. data/lib/razor/cli/document.rb +59 -0
  6. data/lib/razor/cli/format.rb +81 -20
  7. data/lib/razor/cli/navigate.rb +121 -27
  8. data/lib/razor/cli/parse.rb +83 -10
  9. data/lib/razor/cli/transforms.rb +42 -0
  10. data/lib/razor/cli/version.rb +46 -0
  11. data/lib/razor/cli/views.rb +25 -0
  12. data/lib/razor/cli/views.yaml +196 -0
  13. data/spec/cli/format_spec.rb +99 -0
  14. data/spec/cli/navigate_spec.rb +111 -2
  15. data/spec/cli/parse_spec.rb +20 -0
  16. data/spec/fixtures/vcr/Razor_CLI_Navigate/argument_formatting/should_allow_spaces.yml +966 -0
  17. data/spec/fixtures/vcr/Razor_CLI_Navigate/for_command_help/should_provide_command_help_for_razor_--help_command_.yml +99 -0
  18. data/spec/fixtures/vcr/Razor_CLI_Navigate/for_command_help/should_provide_command_help_for_razor_-h_command_.yml +99 -0
  19. data/spec/fixtures/vcr/Razor_CLI_Navigate/for_command_help/should_provide_command_help_for_razor_command_--help_.yml +99 -0
  20. data/spec/fixtures/vcr/Razor_CLI_Navigate/for_command_help/should_provide_command_help_for_razor_command_-h_.yml +99 -0
  21. data/spec/fixtures/vcr/Razor_CLI_Navigate/for_command_help/should_provide_command_help_for_razor_command_help_.yml +99 -0
  22. data/spec/fixtures/vcr/Razor_CLI_Navigate/for_command_help/should_provide_command_help_for_razor_help_command_.yml +99 -0
  23. data/spec/fixtures/vcr/Razor_CLI_Navigate/with_authentication/should_preserve_that_across_navigation.yml +9 -42
  24. data/spec/fixtures/vcr/Razor_CLI_Navigate/with_authentication/should_supply_that_to_the_API_service.yml +5 -5
  25. data/spec/fixtures/vcr/Razor_CLI_Navigate/with_invalid_parameter/should_fail_with_bad_JSON.yml +228 -0
  26. data/spec/fixtures/vcr/Razor_CLI_Navigate/with_invalid_parameter/should_fail_with_malformed_argument.yml +120 -0
  27. data/spec/fixtures/vcr/Razor_CLI_Navigate/with_multiple_arguments_with_same_name/combining_as_an_array/should_merge_an_array_into_an_existing_array.yml +2006 -0
  28. data/spec/fixtures/vcr/Razor_CLI_Navigate/with_multiple_arguments_with_same_name/combining_as_an_array/should_merge_the_arguments_as_an_array.yml +2006 -0
  29. data/spec/fixtures/vcr/Razor_CLI_Navigate/with_multiple_arguments_with_same_name/combining_as_an_array/should_merge_the_arguments_into_an_existing_array.yml +2006 -0
  30. data/spec/fixtures/vcr/Razor_CLI_Navigate/with_multiple_arguments_with_same_name/combining_as_an_object/should_construct_a_json_object.yml +234 -0
  31. data/spec/fixtures/vcr/Razor_CLI_Navigate/with_multiple_arguments_with_same_name/combining_as_an_object/should_construct_a_json_object_with_unicode.yml +412 -0
  32. data/spec/fixtures/vcr/Razor_CLI_Navigate/with_multiple_arguments_with_same_name/combining_as_an_object/should_fail_with_mixed_types_array_then_hash_.yml +228 -0
  33. data/spec/fixtures/vcr/Razor_CLI_Navigate/with_multiple_arguments_with_same_name/combining_as_an_object/should_fail_with_mixed_types_hash_then_array_.yml +164 -0
  34. data/spec/fixtures/vcr/Razor_CLI_Navigate/with_no_parameters/should_fail_with_bad_JSON.yml +36 -0
  35. data/spec/fixtures/vcr/Razor_CLI_Parse/_new/_help/should_print_a_list_of_known_endpoints.yml +5 -5
  36. data/spec/spec_helper.rb +12 -1
  37. data/spec/testing.md +16 -0
  38. data/spec/version_spec.rb +8 -0
  39. metadata +67 -60
  40. data/.gitignore +0 -7
  41. data/.yardopts +0 -2
  42. data/Gemfile +0 -35
  43. data/Gemfile.lock +0 -53
  44. data/Rakefile +0 -37
  45. data/lib/razor/cli/navigate.yaml +0 -28
  46. data/pe-razor-client.gemspec +0 -32
  47. data/spec/fixtures/vcr/Razor_CLI_Navigate/with_a_single_item_path/.yml +0 -69
  48. data/spec/fixtures/vcr/Razor_CLI_Navigate/with_an_invalid_path/.yml +0 -36
  49. data/spec/fixtures/vcr/Razor_CLI_Navigate/with_no_path/.yml +0 -36
  50. data/spec/fixtures/vcr/Razor_CLI_Parse/_new/_help/.yml +0 -36
@@ -1,11 +1,15 @@
1
1
  require 'uri'
2
2
  require 'optparse'
3
+ require 'forwardable'
3
4
 
4
5
  module Razor::CLI
5
6
 
6
7
  class Parse
8
+ extend Forwardable
7
9
  DEFAULT_RAZOR_API = "http://localhost:8080/api"
8
10
 
11
+ def_delegator 'navigate', 'query?'
12
+
9
13
  def get_optparse
10
14
  @optparse ||= OptionParser.new do |opts|
11
15
  opts.banner = "Usage: razor [FLAGS] NAVIGATION\n"
@@ -14,6 +18,14 @@ module Razor::CLI
14
18
  @dump = true
15
19
  end
16
20
 
21
+ opts.on "-f", "--full", "Show full details when viewing entities" do
22
+ @format = 'full'
23
+ end
24
+
25
+ opts.on "-s", "--short", "Show shortened details when viewing entities" do
26
+ @format = 'short'
27
+ end
28
+
17
29
  opts.on "-u", "--url URL",
18
30
  "The full Razor API URL, can also be set\n" + " "*37 +
19
31
  "with the RAZOR_API environment variable\n" + " "*37 +
@@ -21,7 +33,12 @@ module Razor::CLI
21
33
  parse_and_set_api_url(url, :opts)
22
34
  end
23
35
 
36
+ opts.on "-v", "--version", "Show the version of Razor" do
37
+ @show_version = true
38
+ end
39
+
24
40
  opts.on "-h", "--help", "Show this screen" do
41
+ # If searching for a command's help, leave the argument for navigation.
25
42
  @option_help = true
26
43
  end
27
44
 
@@ -35,41 +52,97 @@ module Razor::CLI
35
52
  end.join("\n")
36
53
  end
37
54
 
55
+ def version
56
+ <<-VERSION
57
+ Razor Server version: #{navigate.server_version}
58
+ Razor Client version: #{Razor::CLI::VERSION}
59
+ VERSION
60
+ end
61
+
38
62
  def help
39
63
  output = get_optparse.to_s
40
64
  begin
41
- output << list_things("Collections", navigate.collections)
42
- output << "\n\n Navigate to entries of a collection using COLLECTION NAME, for example,\n 'nodes node15' for the details of a node or 'nodes node15 log' to see\n the log for node15\n"
43
- output << list_things("Commands", navigate.commands)
44
- output << "\n\n Pass arguments to commands either directly by name ('--name=NAME')\n or save the JSON body for the command in a file and pass it with\n '--json FILE'. Using --json is the only way to pass arguments in\n nested structures such as the configuration for a broker.\n"
65
+ output << <<-HELP
66
+ #{list_things("Collections", navigate.collections)}
67
+
68
+ Navigate to entries of a collection using COLLECTION NAME, for example,
69
+ 'nodes node15' for the details of a node or 'nodes node15 log' to see
70
+ the log for node15
71
+ #{list_things("Commands", navigate.commands)}
72
+
73
+ Pass arguments to commands either directly by name ('--name=NAME')
74
+ or save the JSON body for the command in a file and pass it with
75
+ '--json FILE'. Using --json is the only way to pass arguments in
76
+ nested structures such as the configuration for a broker.
77
+
78
+ HELP
79
+ rescue RestClient::Unauthorized
80
+ output << <<-UNAUTH
81
+ Error: Credentials are required to connect to the server at #{@api_url}"
82
+ UNAUTH
45
83
  rescue
46
- output << "\nCould not connect to the server at #{@api_url}. More help is available after "
47
- output << "pointing\nthe client to a Razor server"
84
+ output << <<-ERR
85
+ Error: Could not connect to the server at #{@api_url}. More help is available after pointing
86
+ the client to a Razor server
87
+ ERR
48
88
  end
49
89
  output
50
90
  end
51
91
 
92
+ def show_version?
93
+ !!@show_version
94
+ end
95
+
52
96
  def show_help?
53
97
  !!@option_help
54
98
  end
55
99
 
100
+ def show_command_help?
101
+ !!@command_help
102
+ end
103
+
56
104
  def dump_response?
57
105
  !!@dump
58
106
  end
59
107
 
60
- attr_reader :api_url
108
+ attr_reader :api_url, :format, :args
61
109
 
62
110
  def initialize(args)
63
111
  parse_and_set_api_url(ENV["RAZOR_API"] || DEFAULT_RAZOR_API, :env)
64
112
  @args = args.dup
65
- rest = get_optparse.order(args)
66
- if rest.any?
67
- @navigation = rest
113
+ @format = 'short'
114
+ @args = get_optparse.order(@args)
115
+ @args = set_help_vars(@args)
116
+ if @args == ['version'] or @show_version
117
+ @show_version = true
118
+ elsif @args.any?
119
+ @navigation = @args.dup
68
120
  else
121
+ # Called with no remaining arguments to parse.
69
122
  @option_help = true
70
123
  end
71
124
  end
72
125
 
126
+ # This method sets the appropriate help flags `@command_help` and `@option_help`,
127
+ # then returns a new set of arguments.
128
+ def set_help_vars(rest)
129
+ # Find and remove 'help' variations anywhere in the command.
130
+ if rest.any? { |arg| ['-h', '--help'].include? arg } or
131
+ rest.first == 'help' or rest.drop(1).first == 'help'
132
+ rest = rest.reject { |arg| ['-h', '--help', 'help'].include? arg }
133
+ # If anything is left, assume it is a command.
134
+ if rest.any?
135
+ @command_help = true
136
+ else
137
+ @option_help = true
138
+ end
139
+ end
140
+ if @option_help && rest.any?
141
+ @command_help = true
142
+ end
143
+ rest
144
+ end
145
+
73
146
  def navigate
74
147
  @navigate ||=Navigate.new(self, @navigation)
75
148
  end
@@ -0,0 +1,42 @@
1
+ module Razor::CLI
2
+ module Transforms
3
+ module_function
4
+ def identity(any)
5
+ any
6
+ end
7
+ def if_present(obj)
8
+ obj.nil? ? "---" : obj
9
+ end
10
+ def join_names(arr)
11
+ (arr.nil? or arr.empty?) ? '(none)' : arr.map { |item| item['name'] }.join(", ")
12
+ end
13
+ def nested(nested_obj)
14
+ (nested_obj.nil? or nested_obj.empty?) ? '(none)' : nested_obj.to_s
15
+ end
16
+ def shallow_hash(hash)
17
+ (hash.nil? or hash.empty?) ? '(none)' :
18
+ hash.map {|key, val| "#{key}: #{val}"}.join(', ')
19
+ end
20
+ def select_name(item)
21
+ item and item['name'] or "---"
22
+ end
23
+ def mac(mac)
24
+ mac ? mac.gsub(/-/, ":") : "---"
25
+ end
26
+ def name(obj)
27
+ obj ? obj['name'] : "---"
28
+ end
29
+ def name_if_present(obj)
30
+ obj ? obj['name'] : "---"
31
+ end
32
+ def count_column(hash)
33
+ hash['count']
34
+ end
35
+ def count(arr)
36
+ arr.size
37
+ end
38
+ def count_hash(hash)
39
+ hash.is_a?(Hash) ? hash.keys.size : 0
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,46 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module Razor
3
+ module CLI
4
+ # Define the Razor version, and stash it in a constant. When we build a
5
+ # package for shipping we burn the version directly into this file, by
6
+ # modifying the text on the fly during package building.
7
+ #
8
+ # That "burns in" the value, but if that hasn't happened we do our best to
9
+ # work out a reasonable version number: If we are running from a git
10
+ # checkout, and we have git installed, determine this with `git describe`,
11
+ #
12
+ # If we don't have git, or it fails, but have the metadata, parse out some
13
+ # useful information directly from the checkout; this isn't great, but does
14
+ # give some guidance as to where the user was working.
15
+ #
16
+ # Finally, fall back to a default version placeholder.
17
+ #
18
+ #
19
+ # The next line is the one that our packaging tools modify, so please make
20
+ # sure that any change to it is discussed and agreed first.
21
+ version = '0.15.2'
22
+
23
+ if version == "DEVELOPMENT"
24
+ root = File.expand_path("../../..", File.dirname(__FILE__))
25
+ if File.directory? File.join(root, ".git")
26
+ git_version = %x{cd '#{root}' && git describe --tags --dirty --always 2>&1}
27
+ if $?.success?
28
+ version = 'v' + git_version
29
+ else # try to read manually...
30
+ head = File.read(File.join(root, ".git", "HEAD")) rescue nil
31
+ if head and match = %r{^ref: (refs/heads/(.[^\n]+))$}.match(head.lines.first)
32
+ version = 'git-' + match[2]
33
+ if sha = File.read(File.join(root, ".git", match[1]))[0,8] rescue nil
34
+ version += '-' + sha
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ # The running version of Razor. Razor follows the tenets of [semantic
42
+ # versioning](http://semver.org), and this version number reflects the rules
43
+ # as of SemVer 2.0.0
44
+ VERSION = version.chomp
45
+ end
46
+ end
@@ -0,0 +1,25 @@
1
+ module Razor::CLI
2
+ module Views
3
+ module_function
4
+ def views
5
+ @views ||= YAML::load_file(File::join(File::dirname(__FILE__), "views.yaml"))
6
+ end
7
+
8
+ def transform(item, transform_name)
9
+ Razor::CLI::Transforms.send(transform_name || 'identity', item)
10
+ end
11
+
12
+ def find_formatting(spec, format, remaining_navigation)
13
+ remaining_navigation ||= ''
14
+ # Scope will narrow by traversing the spec.
15
+ scope = views
16
+ spec = spec ? spec.split('/').drop_while { |i| i != 'collections'} : []
17
+ spec = spec + remaining_navigation.split(' ')
18
+ while spec.any?
19
+ val = spec.shift
20
+ scope = (scope[val] or {})
21
+ end
22
+ scope["+#{format}"] or {}
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,196 @@
1
+ ---
2
+
3
+ # This file contains instructions for how the client should format various
4
+ # objects based on the object's 'spec' path. The structure uses a `+` prefix
5
+ # to denote metadata. `member` is used to describe a member of a group.
6
+ #
7
+ # Accepted metadata annotations are:
8
+ # `+short`: This section configures what the output for the object looks like in short format.
9
+ # `+show`: This section configures which attributes are shown in the output.
10
+ # `+layout`: This configures whether to use 'list' or 'table' output.
11
+ # `+column`: This changes which column is used in the field formatting.
12
+ collections:
13
+ brokers:
14
+ +short:
15
+ +layout: table
16
+ +show:
17
+ name:
18
+ broker-type:
19
+ configuration:
20
+ +format: nested
21
+ policies:
22
+ +format: count_column
23
+ member:
24
+ +short:
25
+ +layout: list
26
+ +show:
27
+ name:
28
+ broker-type:
29
+ configuration:
30
+ policies:
31
+ +format: count_column
32
+ nodes:
33
+ +short:
34
+ +layout: table
35
+ +show:
36
+ name:
37
+ dhcp_mac:
38
+ +format: mac
39
+ tags:
40
+ +format: join_names
41
+ policy:
42
+ +format: select_name
43
+ metadata count:
44
+ +column: metadata
45
+ +format: count_hash
46
+ member:
47
+ +short:
48
+ +layout: list
49
+ +show:
50
+ name:
51
+ dhcp_mac:
52
+ +format: mac
53
+ state:
54
+ last_checkin:
55
+ +format: if_present
56
+ metadata:
57
+ +format: if_present
58
+ tags:
59
+ +format: join_names
60
+ tags:
61
+ +short:
62
+ +layout: table
63
+ +show:
64
+ name:
65
+ rule:
66
+ +format: nested
67
+ nodes:
68
+ +format: count_column
69
+ policies:
70
+ +format: count_column
71
+ hw_info:
72
+ +short:
73
+ +layout: list
74
+ log:
75
+ +short:
76
+ +layout: table
77
+ # +show:
78
+ # event:
79
+ # task:
80
+ # timestamp:
81
+ policies:
82
+ +short:
83
+ +layout: table
84
+ +show:
85
+ name:
86
+ repo:
87
+ +format: name
88
+ task:
89
+ +format: name
90
+ broker:
91
+ +format: name
92
+ enabled:
93
+ max_count:
94
+ tags:
95
+ +format: join_names
96
+ nodes:
97
+ +format: count_column
98
+ member:
99
+ +short:
100
+ +show:
101
+ name:
102
+ repo:
103
+ +format: name
104
+ task:
105
+ +format: name
106
+ broker:
107
+ +format: name
108
+ enabled:
109
+ max_count:
110
+ tags:
111
+ +format: join_names
112
+ nodes:
113
+ +format: count_column
114
+ tasks:
115
+ +short:
116
+ +layout: table
117
+ +show:
118
+ name:
119
+ description:
120
+ base:
121
+ +format: name_if_present
122
+ boot_seq:
123
+ +format: shallow_hash
124
+ member:
125
+ +short:
126
+ +show:
127
+ name:
128
+ description:
129
+ os:
130
+ boot_seq:
131
+ repos:
132
+ +short:
133
+ +layout: table
134
+ +show:
135
+ name:
136
+ iso_url:
137
+ +format: if_present
138
+ url:
139
+ +format: if_present
140
+ task:
141
+ +format: name
142
+ member:
143
+ +short:
144
+ +layout: list
145
+ +show:
146
+ name:
147
+ iso_url:
148
+ +format: if_present
149
+ url:
150
+ +format: if_present
151
+ task:
152
+ +format: name
153
+ tags:
154
+ +short:
155
+ +layout: table
156
+ +show:
157
+ name:
158
+ rule:
159
+ +format: nested
160
+ nodes:
161
+ +format: count_column
162
+ policies:
163
+ +format: count_column
164
+ member:
165
+ +short:
166
+ +layout: list
167
+ +show:
168
+ name:
169
+ rule:
170
+ +format: nested
171
+ nodes:
172
+ +format: count_column
173
+ policies:
174
+ +format: count_column
175
+ commands:
176
+ +short:
177
+ +layout: table
178
+ +show:
179
+ name:
180
+ command:
181
+ name parameter:
182
+ +format: name
183
+ +column: params
184
+ errors:
185
+ +format: count
186
+ status:
187
+ member:
188
+ +short:
189
+ +show:
190
+ name:
191
+ command:
192
+ params:
193
+ errors:
194
+ +format: count
195
+ status:
196
+ submitted_at: