razor-client 0.10.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.
- data/.gitignore +5 -0
- data/.yardopts +2 -0
- data/Gemfile +32 -0
- data/Gemfile.lock +52 -0
- data/LICENSE +15 -0
- data/README.md +20 -0
- data/Rakefile +27 -0
- data/bin/razor +33 -0
- data/lib/razor.rb +1 -0
- data/lib/razor/cli.rb +20 -0
- data/lib/razor/cli/format.rb +72 -0
- data/lib/razor/cli/navigate.rb +118 -0
- data/lib/razor/cli/parse.rb +66 -0
- data/spec/cli/navigate_spec.rb +32 -0
- data/spec/cli/parse_spec.rb +42 -0
- data/spec/fixtures/vcr/Razor_CLI_Navigate/with_a_single_item_path/.yml +69 -0
- data/spec/fixtures/vcr/Razor_CLI_Navigate/with_an_invalid_path/.yml +36 -0
- data/spec/fixtures/vcr/Razor_CLI_Navigate/with_no_path/.yml +36 -0
- data/spec/fixtures/vcr/Razor_CLI_Parse/_new/_help/.yml +36 -0
- data/spec/fixtures/vcr/Razor_CLI_Parse/_new/_help/should_print_a_list_of_known_endpoints.yml +36 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/vcr_library.rb +8 -0
- metadata +143 -0
data/.gitignore
ADDED
data/.yardopts
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'rest-client'
|
4
|
+
gem 'terminal-table'
|
5
|
+
|
6
|
+
group :doc do
|
7
|
+
gem 'yard'
|
8
|
+
gem 'kramdown'
|
9
|
+
end
|
10
|
+
|
11
|
+
# This group will be excluded by default in `torquebox archive`
|
12
|
+
group :test do
|
13
|
+
gem 'rack-test'
|
14
|
+
gem 'rspec', '~> 2.13.0'
|
15
|
+
gem 'rspec-core', '~> 2.13.1'
|
16
|
+
gem 'rspec-expectations', '~> 2.13.0'
|
17
|
+
gem 'rspec-mocks', '~> 2.13.1'
|
18
|
+
gem 'simplecov'
|
19
|
+
gem 'webmock'
|
20
|
+
gem 'vcr'
|
21
|
+
end
|
22
|
+
|
23
|
+
group :development do
|
24
|
+
gem 'rake'
|
25
|
+
end
|
26
|
+
|
27
|
+
# This allows you to create `Gemfile.local` and have it loaded automatically;
|
28
|
+
# the purpose of this is to allow you to put additional development gems
|
29
|
+
# somewhere convenient without having to constantly mess with this file.
|
30
|
+
#
|
31
|
+
# Gemfile.local is in the .gitignore file; do not check one in!
|
32
|
+
eval(File.read(File.dirname(__FILE__) + '/Gemfile.local'), binding) rescue nil
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
addressable (2.3.3)
|
5
|
+
crack (0.3.2)
|
6
|
+
diff-lcs (1.2.4)
|
7
|
+
kramdown (1.1.0)
|
8
|
+
mime-types (1.24)
|
9
|
+
multi_json (1.7.9)
|
10
|
+
rack (1.5.2)
|
11
|
+
rack-test (0.6.2)
|
12
|
+
rack (>= 1.0)
|
13
|
+
rake (10.1.0)
|
14
|
+
rest-client (1.6.7)
|
15
|
+
mime-types (>= 1.16)
|
16
|
+
rspec (2.13.0)
|
17
|
+
rspec-core (~> 2.13.0)
|
18
|
+
rspec-expectations (~> 2.13.0)
|
19
|
+
rspec-mocks (~> 2.13.0)
|
20
|
+
rspec-core (2.13.1)
|
21
|
+
rspec-expectations (2.13.0)
|
22
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
23
|
+
rspec-mocks (2.13.1)
|
24
|
+
simplecov (0.7.1)
|
25
|
+
multi_json (~> 1.0)
|
26
|
+
simplecov-html (~> 0.7.1)
|
27
|
+
simplecov-html (0.7.1)
|
28
|
+
terminal-table (1.4.5)
|
29
|
+
vcr (2.5.0)
|
30
|
+
webmock (1.9.3)
|
31
|
+
addressable (>= 2.2.7)
|
32
|
+
crack (>= 0.3.2)
|
33
|
+
yard (0.8.7)
|
34
|
+
|
35
|
+
PLATFORMS
|
36
|
+
java
|
37
|
+
ruby
|
38
|
+
|
39
|
+
DEPENDENCIES
|
40
|
+
kramdown
|
41
|
+
rack-test
|
42
|
+
rake
|
43
|
+
rest-client
|
44
|
+
rspec (~> 2.13.0)
|
45
|
+
rspec-core (~> 2.13.1)
|
46
|
+
rspec-expectations (~> 2.13.0)
|
47
|
+
rspec-mocks (~> 2.13.1)
|
48
|
+
simplecov
|
49
|
+
terminal-table
|
50
|
+
vcr
|
51
|
+
webmock
|
52
|
+
yard
|
data/LICENSE
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Razor
|
2
|
+
|
3
|
+
Copyright 2013 Puppet Labs Inc
|
4
|
+
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
you may not use this file except in compliance with the License.
|
7
|
+
You may obtain a copy of the License at
|
8
|
+
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
See the License for the specific language governing permissions and
|
15
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Razor client
|
2
|
+
|
3
|
+
This code is still in development mode; that means that we might make
|
4
|
+
backwards incompatible changes, especially to the database schema which
|
5
|
+
would force you to rebuild all the machines that Razor is managing. Razor
|
6
|
+
will become stable RSN.
|
7
|
+
|
8
|
+
This is the command line client for the
|
9
|
+
[Razor server](https://github.com/puppetlabs/razor-server) Please have a
|
10
|
+
look at the Wiki over there for details.
|
11
|
+
|
12
|
+
## Getting in touch
|
13
|
+
|
14
|
+
* on IRC: `#puppet-razor` on [freenode](http://freenode.net/)
|
15
|
+
* mailing list: [puppet-razor@googlegroups.com](http://groups.google.com/group/puppet-razor)
|
16
|
+
|
17
|
+
## License
|
18
|
+
|
19
|
+
Razor is distributed under the Apache 2.0 license.
|
20
|
+
See [the LICENSE file](LICENSE) for full details.
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require_relative 'spec/vcr_library'
|
4
|
+
|
5
|
+
namespace :bundler do
|
6
|
+
task :setup do
|
7
|
+
require 'bundler/setup'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
namespace :spec do
|
12
|
+
require 'rspec/core'
|
13
|
+
require 'rspec/core/rake_task'
|
14
|
+
|
15
|
+
desc <<EOS
|
16
|
+
Run all specs. Set VCR_RECORD to 'all' to rerecord and to 'new_episodes'
|
17
|
+
to record new tests. Tapes are in #{VCR_LIBRARY}
|
18
|
+
EOS
|
19
|
+
RSpec::Core::RakeTask.new(:all => :"bundler:setup") do |t|
|
20
|
+
t.pattern = 'spec/**/*_spec.rb'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "Erase all VCR recordings"
|
25
|
+
task :"vcr:erase" do
|
26
|
+
erase_vcr_library
|
27
|
+
end
|
data/bin/razor
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative "../lib/razor/cli"
|
4
|
+
|
5
|
+
include Razor::CLI::Format
|
6
|
+
|
7
|
+
parse = Razor::CLI::Parse.new(ARGV)
|
8
|
+
if parse.show_help?
|
9
|
+
puts parse.help
|
10
|
+
exit 0
|
11
|
+
end
|
12
|
+
begin
|
13
|
+
document = parse.navigate.get_document
|
14
|
+
url = parse.navigate.last_url
|
15
|
+
puts "From #{url}:\n\n#{format_document document}\n\n"
|
16
|
+
rescue Razor::CLI::NavigationError => e
|
17
|
+
puts "Error: #{e}\n#{parse.help}\n\n"
|
18
|
+
rescue RestClient::Exception => e
|
19
|
+
r = e.response
|
20
|
+
puts "Error from doing #{r.args[:method].to_s.upcase} #{r.args[:url]}"
|
21
|
+
puts e.message
|
22
|
+
begin
|
23
|
+
body = JSON::parse(r.body)
|
24
|
+
puts body.delete("details") if body["details"]
|
25
|
+
unless body.empty?
|
26
|
+
puts format_document(body)
|
27
|
+
end
|
28
|
+
rescue => e
|
29
|
+
# Ignore errors here; our best efforts at telling the user more about
|
30
|
+
# what happened has failed. Just dump the response
|
31
|
+
puts r.body
|
32
|
+
end
|
33
|
+
end
|
data/lib/razor.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'razor/cli'
|
data/lib/razor/cli.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Razor
|
2
|
+
module CLI
|
3
|
+
class Error < RuntimeError; end
|
4
|
+
|
5
|
+
class NavigationError < Error
|
6
|
+
def initialize(url, key, doc)
|
7
|
+
@key = key; @doc = doc
|
8
|
+
if key.is_a?(Array)
|
9
|
+
super "Could not navigate to '#{key.join(" ")}' from #{url}"
|
10
|
+
else
|
11
|
+
super "Could not find entry '#{key}' in document at #{url}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
require_relative 'cli/navigate'
|
19
|
+
require_relative 'cli/parse'
|
20
|
+
require_relative 'cli/format'
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'terminal-table'
|
2
|
+
|
3
|
+
module Razor::CLI
|
4
|
+
module Format
|
5
|
+
PriorityKeys = %w[ id name ]
|
6
|
+
SpecNames = {
|
7
|
+
"/spec/object/policy" => "Policy",
|
8
|
+
"/spec/object/tag" => "Tag",
|
9
|
+
"/spec/object/reference" => "reference"
|
10
|
+
}
|
11
|
+
|
12
|
+
def self.spec_name(spec)
|
13
|
+
path = spec && URI.parse(spec).path
|
14
|
+
SpecNames[path] || path
|
15
|
+
rescue => e
|
16
|
+
spec
|
17
|
+
end
|
18
|
+
|
19
|
+
def format_document(doc)
|
20
|
+
case doc
|
21
|
+
when Array then format_objects(doc)
|
22
|
+
when Hash then format_object(doc)
|
23
|
+
else doc.to_s
|
24
|
+
end.chomp
|
25
|
+
end
|
26
|
+
|
27
|
+
# We assume that all collections are homogenous
|
28
|
+
def format_objects(objects, indent = 0)
|
29
|
+
objects.map do |obj|
|
30
|
+
obj.is_a?(Hash) ? format_object(obj, indent) : ' '*indent + obj.inspect
|
31
|
+
end.join "\n\n"
|
32
|
+
end
|
33
|
+
|
34
|
+
def format_reference_object(ref, indent = 0)
|
35
|
+
output = ' '* indent + "#{ref['name']} => #{ref['id'].to_s.ljust 4}"
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def format_object(object, indent = 0)
|
40
|
+
if object.keys == ["id", "name"]
|
41
|
+
format_reference_object(object, indent)
|
42
|
+
else
|
43
|
+
format_default_object(object, indent)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def format_default_object(object, indent = 0 )
|
48
|
+
fields = (PriorityKeys & object.keys) + (object.keys - PriorityKeys)
|
49
|
+
key_indent = indent + fields.map {|f| f.length}.max
|
50
|
+
output = ""
|
51
|
+
fields.map do |f|
|
52
|
+
value = object[f]
|
53
|
+
output = "#{f.rjust key_indent + 2}: "
|
54
|
+
output << case value
|
55
|
+
when Hash
|
56
|
+
"\n" + format_object(value, key_indent + 4).rstrip
|
57
|
+
when Array
|
58
|
+
if value.all? { |v| v.is_a?(String) }
|
59
|
+
"[" + value.map(&:inspect).join(",") + "]"
|
60
|
+
else
|
61
|
+
"[\n" + format_objects(value, key_indent + 6) + ("\n"+' '*(key_indent+4)+"]")
|
62
|
+
end
|
63
|
+
else
|
64
|
+
case f
|
65
|
+
when "spec" then "\"#{Format.spec_name(value)}\""
|
66
|
+
else value.inspect
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end.join "\n"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Razor::CLI
|
5
|
+
class Navigate
|
6
|
+
|
7
|
+
def initialize(parse, segments)
|
8
|
+
@parse = parse
|
9
|
+
@segments = segments||[]
|
10
|
+
@doc = entrypoint
|
11
|
+
@doc_url = parse.api_url
|
12
|
+
end
|
13
|
+
|
14
|
+
def last_url
|
15
|
+
@doc_url
|
16
|
+
end
|
17
|
+
|
18
|
+
def entrypoint
|
19
|
+
@entrypoint ||= json_get(@parse.api_url)
|
20
|
+
end
|
21
|
+
|
22
|
+
def collections
|
23
|
+
entrypoint["collections"]
|
24
|
+
end
|
25
|
+
|
26
|
+
def commands
|
27
|
+
entrypoint["commands"]
|
28
|
+
end
|
29
|
+
|
30
|
+
def query?
|
31
|
+
collections.any? { |coll| coll["name"] == @segments.first }
|
32
|
+
end
|
33
|
+
|
34
|
+
def command(name)
|
35
|
+
commands.find { |coll| coll["name"] == name }
|
36
|
+
end
|
37
|
+
|
38
|
+
def command?
|
39
|
+
!! command(@segments.first)
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_document
|
43
|
+
if @segments.empty?
|
44
|
+
entrypoint
|
45
|
+
elsif query?
|
46
|
+
@doc = collections
|
47
|
+
while @segments.any?
|
48
|
+
move_to @segments.shift
|
49
|
+
end
|
50
|
+
@doc
|
51
|
+
elsif command?
|
52
|
+
# @todo lutter 2013-08-16: None of this has any tests, and error
|
53
|
+
# handling is heinous at best
|
54
|
+
cmd, body = extract_command
|
55
|
+
json_post(cmd["id"], body)
|
56
|
+
else
|
57
|
+
raise NavigationError.new(@doc_url, @segments, @doc)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def extract_command
|
62
|
+
cmd = command(@segments.shift)
|
63
|
+
body = {}
|
64
|
+
until @segments.empty?
|
65
|
+
if @segments.shift =~ /\A--([a-z-]+)(=(\S+))?\Z/
|
66
|
+
body[$1] = ($3 || @segments.shift)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
# Special treatment for tag rules
|
70
|
+
if cmd["name"] == "create-tag" && body["rule"]
|
71
|
+
body["rule"] = JSON::parse(body["rule"])
|
72
|
+
end
|
73
|
+
body = JSON::parse(File::read(body["json"])) if body["json"]
|
74
|
+
[cmd, body]
|
75
|
+
end
|
76
|
+
|
77
|
+
def move_to(key)
|
78
|
+
key = key.to_i if key.to_i.to_s == key
|
79
|
+
if @doc.is_a? Array
|
80
|
+
obj = @doc.find {|x| x.is_a?(Hash) and x["name"] == key }
|
81
|
+
elsif @doc.is_a? Hash
|
82
|
+
obj = @doc[key]
|
83
|
+
end
|
84
|
+
|
85
|
+
raise NavigationError.new(@doc_url, key, @doc) unless obj
|
86
|
+
|
87
|
+
if obj.is_a?(Hash) && obj["id"]
|
88
|
+
@doc = json_get(obj["id"])
|
89
|
+
@doc_url = obj["id"]
|
90
|
+
elsif obj.is_a? Hash
|
91
|
+
@doc = obj
|
92
|
+
else
|
93
|
+
@doc = nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def get(url, headers={})
|
98
|
+
response = RestClient.get url.to_s, headers
|
99
|
+
puts "GET #{url.to_s}\n#{response.body}" if @parse.dump_response?
|
100
|
+
response
|
101
|
+
end
|
102
|
+
|
103
|
+
def json_get(url, headers = {})
|
104
|
+
response = get(url,headers.merge(:accept => :json))
|
105
|
+
unless response.headers[:content_type] =~ /application\/json/
|
106
|
+
raise "Received content type #{response.headers[:content_type]}"
|
107
|
+
end
|
108
|
+
JSON.parse(response.body)
|
109
|
+
end
|
110
|
+
|
111
|
+
def json_post(url, body)
|
112
|
+
headers = { :accept=>:json, "Content-Type" => :json }
|
113
|
+
response = RestClient.post url, body.to_json, headers
|
114
|
+
puts "POST #{url.to_s}\n#{body}\n-->\n#{response.body}" if @parse.dump_response?
|
115
|
+
JSON::parse(response.body)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
module Razor::CLI
|
5
|
+
|
6
|
+
class Parse
|
7
|
+
def get_optparse
|
8
|
+
@optparse ||= OptionParser.new do |opts|
|
9
|
+
opts.banner = "Usage: razor [FLAGS] NAVIGATION\n"
|
10
|
+
" or: razor shell"
|
11
|
+
|
12
|
+
opts.on "-d", "--dump", "Dumps API output to the screen" do
|
13
|
+
@dump = true
|
14
|
+
end
|
15
|
+
|
16
|
+
opts.on "-U", "--url URL", "The full Razor API URL (default #{@api_url})" do |url|
|
17
|
+
@api_url = URI.parse(url)
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on "-h", "--help", "Show this screen" do
|
21
|
+
@option_help = true
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def list_things(name, items)
|
28
|
+
"\n #{name}:\n" +
|
29
|
+
items.map {|x| x["name"]}.compact.sort.map do |name|
|
30
|
+
" #{name}"
|
31
|
+
end.join("\n")
|
32
|
+
end
|
33
|
+
|
34
|
+
def help
|
35
|
+
output = get_optparse.to_s
|
36
|
+
output << list_things("collections", navigate.collections)
|
37
|
+
output << list_things("commands", navigate.commands)
|
38
|
+
output
|
39
|
+
end
|
40
|
+
|
41
|
+
def show_help?
|
42
|
+
!!@option_help
|
43
|
+
end
|
44
|
+
|
45
|
+
def dump_response?
|
46
|
+
!!@dump
|
47
|
+
end
|
48
|
+
|
49
|
+
attr_reader :api_url
|
50
|
+
|
51
|
+
def initialize(args)
|
52
|
+
@api_url = URI.parse("http://localhost:8080/api")
|
53
|
+
@args = args.dup
|
54
|
+
rest = get_optparse.order(args)
|
55
|
+
if rest.any?
|
56
|
+
@navigation = rest
|
57
|
+
else
|
58
|
+
@option_help = true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def navigate
|
63
|
+
@navigate ||=Navigate.new(self, @navigation)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe Razor::CLI::Navigate do
|
4
|
+
context "with no path", :vcr do
|
5
|
+
subject(:nav) {Razor::CLI::Parse.new([]).navigate}
|
6
|
+
it do
|
7
|
+
nav.get_document.should_not be_nil
|
8
|
+
nav.get_document.should == nav.entrypoint
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context "with a single item path", :vcr do
|
13
|
+
subject(:nav) {Razor::CLI::Parse.new(["tags"]).navigate}
|
14
|
+
it { nav.get_document.should == []}
|
15
|
+
|
16
|
+
it do
|
17
|
+
nav.get_document;
|
18
|
+
nav.last_url.to_s.should =~ %r{/api/collections/tags$}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "with an invalid path", :vcr do
|
23
|
+
subject(:nav) {Razor::CLI::Parse.new(["going","nowhere"]).navigate}
|
24
|
+
|
25
|
+
it {expect{nav.get_document}.to raise_error Razor::CLI::NavigationError}
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "extract_command" do
|
29
|
+
it "should understand --arg=value"
|
30
|
+
it "should understand '--arg value'"
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe Razor::CLI::Parse do
|
4
|
+
|
5
|
+
def parse(*args)
|
6
|
+
Razor::CLI::Parse.new(args)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#new" do
|
10
|
+
context "with no arguments" do
|
11
|
+
it {parse.show_help?.should be true}
|
12
|
+
end
|
13
|
+
|
14
|
+
context "with a '-h'" do
|
15
|
+
it {parse("-h").show_help?.should be true}
|
16
|
+
end
|
17
|
+
|
18
|
+
context "with a '-d'" do
|
19
|
+
it {parse("-d").dump_response?.should be true}
|
20
|
+
end
|
21
|
+
|
22
|
+
context "with a '-U'" do
|
23
|
+
it "should use the given URL" do
|
24
|
+
url = 'http://razor.example.com:2150/path/to/api'
|
25
|
+
parse('-U',url).api_url.to_s.should == url
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#help", :vcr do
|
30
|
+
subject(:p) {parse}
|
31
|
+
it { should respond_to :help}
|
32
|
+
|
33
|
+
it { p.help.should be_a String}
|
34
|
+
|
35
|
+
it "should print a list of known endpoints" do
|
36
|
+
p.navigate.should_receive(:collections).and_return([])
|
37
|
+
p.navigate.should_receive(:commands).and_return([])
|
38
|
+
p.help
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://localhost:8080/api
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- application/json
|
12
|
+
Accept-Encoding:
|
13
|
+
- gzip, deflate
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
response:
|
17
|
+
status:
|
18
|
+
code: 200
|
19
|
+
message: OK
|
20
|
+
headers:
|
21
|
+
Server:
|
22
|
+
- Apache-Coyote/1.1
|
23
|
+
X-Content-Type-Options:
|
24
|
+
- nosniff
|
25
|
+
Content-Type:
|
26
|
+
- application/json;charset=utf-8
|
27
|
+
Content-Length:
|
28
|
+
- '1566'
|
29
|
+
Date:
|
30
|
+
- Wed, 28 Aug 2013 21:46:05 GMT
|
31
|
+
body:
|
32
|
+
encoding: US-ASCII
|
33
|
+
string: ! '{"commands":[{"name":"create-image","rel":"http://api.puppetlabs.com/razor/v1/commands/create-image","id":"http://localhost:8080/api/commands/create-image"},{"name":"delete-image","rel":"http://api.puppetlabs.com/razor/v1/commands/delete-image","id":"http://localhost:8080/api/commands/delete-image"},{"name":"create-installer","rel":"http://api.puppetlabs.com/razor/v1/commands/create-installer","id":"http://localhost:8080/api/commands/create-installer"},{"name":"create-tag","rel":"http://api.puppetlabs.com/razor/v1/commands/create-tag","id":"http://localhost:8080/api/commands/create-tag"},{"name":"create-broker","rel":"http://api.puppetlabs.com/razor/v1/commands/create-broker","id":"http://localhost:8080/api/commands/create-broker"},{"name":"create-policy","rel":"http://api.puppetlabs.com/razor/v1/commands/create-policy","id":"http://localhost:8080/api/commands/create-policy"}],"collections":[{"name":"brokers","rel":"http://api.puppetlabs.com/razor/v1/collections/brokers","id":"http://localhost:8080/api/collections/brokers"},{"name":"images","rel":"http://api.puppetlabs.com/razor/v1/collections/images","id":"http://localhost:8080/api/collections/images"},{"name":"tags","rel":"http://api.puppetlabs.com/razor/v1/collections/tags","id":"http://localhost:8080/api/collections/tags"},{"name":"policies","rel":"http://api.puppetlabs.com/razor/v1/collections/policies","id":"http://localhost:8080/api/collections/policies"},{"name":"nodes","rel":"http://api.puppetlabs.com/razor/v1/collections/nodes","id":"http://localhost:8080/api/collections/nodes"}]}'
|
34
|
+
http_version:
|
35
|
+
recorded_at: Wed, 28 Aug 2013 21:46:05 GMT
|
36
|
+
- request:
|
37
|
+
method: get
|
38
|
+
uri: http://localhost:8080/api/collections/tags
|
39
|
+
body:
|
40
|
+
encoding: US-ASCII
|
41
|
+
string: ''
|
42
|
+
headers:
|
43
|
+
Accept:
|
44
|
+
- application/json
|
45
|
+
Accept-Encoding:
|
46
|
+
- gzip, deflate
|
47
|
+
User-Agent:
|
48
|
+
- Ruby
|
49
|
+
response:
|
50
|
+
status:
|
51
|
+
code: 200
|
52
|
+
message: OK
|
53
|
+
headers:
|
54
|
+
Server:
|
55
|
+
- Apache-Coyote/1.1
|
56
|
+
X-Content-Type-Options:
|
57
|
+
- nosniff
|
58
|
+
Content-Type:
|
59
|
+
- application/json;charset=utf-8
|
60
|
+
Content-Length:
|
61
|
+
- '2'
|
62
|
+
Date:
|
63
|
+
- Wed, 28 Aug 2013 21:46:05 GMT
|
64
|
+
body:
|
65
|
+
encoding: US-ASCII
|
66
|
+
string: ! '[]'
|
67
|
+
http_version:
|
68
|
+
recorded_at: Wed, 28 Aug 2013 21:46:05 GMT
|
69
|
+
recorded_with: VCR 2.5.0
|
@@ -0,0 +1,36 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://localhost:8080/api
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- application/json
|
12
|
+
Accept-Encoding:
|
13
|
+
- gzip, deflate
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
response:
|
17
|
+
status:
|
18
|
+
code: 200
|
19
|
+
message: OK
|
20
|
+
headers:
|
21
|
+
Server:
|
22
|
+
- Apache-Coyote/1.1
|
23
|
+
X-Content-Type-Options:
|
24
|
+
- nosniff
|
25
|
+
Content-Type:
|
26
|
+
- application/json;charset=utf-8
|
27
|
+
Content-Length:
|
28
|
+
- '1566'
|
29
|
+
Date:
|
30
|
+
- Wed, 28 Aug 2013 21:46:05 GMT
|
31
|
+
body:
|
32
|
+
encoding: US-ASCII
|
33
|
+
string: ! '{"commands":[{"name":"create-image","rel":"http://api.puppetlabs.com/razor/v1/commands/create-image","id":"http://localhost:8080/api/commands/create-image"},{"name":"delete-image","rel":"http://api.puppetlabs.com/razor/v1/commands/delete-image","id":"http://localhost:8080/api/commands/delete-image"},{"name":"create-installer","rel":"http://api.puppetlabs.com/razor/v1/commands/create-installer","id":"http://localhost:8080/api/commands/create-installer"},{"name":"create-tag","rel":"http://api.puppetlabs.com/razor/v1/commands/create-tag","id":"http://localhost:8080/api/commands/create-tag"},{"name":"create-broker","rel":"http://api.puppetlabs.com/razor/v1/commands/create-broker","id":"http://localhost:8080/api/commands/create-broker"},{"name":"create-policy","rel":"http://api.puppetlabs.com/razor/v1/commands/create-policy","id":"http://localhost:8080/api/commands/create-policy"}],"collections":[{"name":"brokers","rel":"http://api.puppetlabs.com/razor/v1/collections/brokers","id":"http://localhost:8080/api/collections/brokers"},{"name":"images","rel":"http://api.puppetlabs.com/razor/v1/collections/images","id":"http://localhost:8080/api/collections/images"},{"name":"tags","rel":"http://api.puppetlabs.com/razor/v1/collections/tags","id":"http://localhost:8080/api/collections/tags"},{"name":"policies","rel":"http://api.puppetlabs.com/razor/v1/collections/policies","id":"http://localhost:8080/api/collections/policies"},{"name":"nodes","rel":"http://api.puppetlabs.com/razor/v1/collections/nodes","id":"http://localhost:8080/api/collections/nodes"}]}'
|
34
|
+
http_version:
|
35
|
+
recorded_at: Wed, 28 Aug 2013 21:46:05 GMT
|
36
|
+
recorded_with: VCR 2.5.0
|
@@ -0,0 +1,36 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://localhost:8080/api
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- application/json
|
12
|
+
Accept-Encoding:
|
13
|
+
- gzip, deflate
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
response:
|
17
|
+
status:
|
18
|
+
code: 200
|
19
|
+
message: OK
|
20
|
+
headers:
|
21
|
+
Server:
|
22
|
+
- Apache-Coyote/1.1
|
23
|
+
X-Content-Type-Options:
|
24
|
+
- nosniff
|
25
|
+
Content-Type:
|
26
|
+
- application/json;charset=utf-8
|
27
|
+
Content-Length:
|
28
|
+
- '1566'
|
29
|
+
Date:
|
30
|
+
- Wed, 28 Aug 2013 21:46:05 GMT
|
31
|
+
body:
|
32
|
+
encoding: US-ASCII
|
33
|
+
string: ! '{"commands":[{"name":"create-image","rel":"http://api.puppetlabs.com/razor/v1/commands/create-image","id":"http://localhost:8080/api/commands/create-image"},{"name":"delete-image","rel":"http://api.puppetlabs.com/razor/v1/commands/delete-image","id":"http://localhost:8080/api/commands/delete-image"},{"name":"create-installer","rel":"http://api.puppetlabs.com/razor/v1/commands/create-installer","id":"http://localhost:8080/api/commands/create-installer"},{"name":"create-tag","rel":"http://api.puppetlabs.com/razor/v1/commands/create-tag","id":"http://localhost:8080/api/commands/create-tag"},{"name":"create-broker","rel":"http://api.puppetlabs.com/razor/v1/commands/create-broker","id":"http://localhost:8080/api/commands/create-broker"},{"name":"create-policy","rel":"http://api.puppetlabs.com/razor/v1/commands/create-policy","id":"http://localhost:8080/api/commands/create-policy"}],"collections":[{"name":"brokers","rel":"http://api.puppetlabs.com/razor/v1/collections/brokers","id":"http://localhost:8080/api/collections/brokers"},{"name":"images","rel":"http://api.puppetlabs.com/razor/v1/collections/images","id":"http://localhost:8080/api/collections/images"},{"name":"tags","rel":"http://api.puppetlabs.com/razor/v1/collections/tags","id":"http://localhost:8080/api/collections/tags"},{"name":"policies","rel":"http://api.puppetlabs.com/razor/v1/collections/policies","id":"http://localhost:8080/api/collections/policies"},{"name":"nodes","rel":"http://api.puppetlabs.com/razor/v1/collections/nodes","id":"http://localhost:8080/api/collections/nodes"}]}'
|
34
|
+
http_version:
|
35
|
+
recorded_at: Wed, 28 Aug 2013 21:46:05 GMT
|
36
|
+
recorded_with: VCR 2.5.0
|
@@ -0,0 +1,36 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://localhost:8080/api
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- application/json
|
12
|
+
Accept-Encoding:
|
13
|
+
- gzip, deflate
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
response:
|
17
|
+
status:
|
18
|
+
code: 200
|
19
|
+
message: OK
|
20
|
+
headers:
|
21
|
+
Server:
|
22
|
+
- Apache-Coyote/1.1
|
23
|
+
X-Content-Type-Options:
|
24
|
+
- nosniff
|
25
|
+
Content-Type:
|
26
|
+
- application/json;charset=utf-8
|
27
|
+
Content-Length:
|
28
|
+
- '1566'
|
29
|
+
Date:
|
30
|
+
- Wed, 28 Aug 2013 21:46:05 GMT
|
31
|
+
body:
|
32
|
+
encoding: US-ASCII
|
33
|
+
string: ! '{"commands":[{"name":"create-image","rel":"http://api.puppetlabs.com/razor/v1/commands/create-image","id":"http://localhost:8080/api/commands/create-image"},{"name":"delete-image","rel":"http://api.puppetlabs.com/razor/v1/commands/delete-image","id":"http://localhost:8080/api/commands/delete-image"},{"name":"create-installer","rel":"http://api.puppetlabs.com/razor/v1/commands/create-installer","id":"http://localhost:8080/api/commands/create-installer"},{"name":"create-tag","rel":"http://api.puppetlabs.com/razor/v1/commands/create-tag","id":"http://localhost:8080/api/commands/create-tag"},{"name":"create-broker","rel":"http://api.puppetlabs.com/razor/v1/commands/create-broker","id":"http://localhost:8080/api/commands/create-broker"},{"name":"create-policy","rel":"http://api.puppetlabs.com/razor/v1/commands/create-policy","id":"http://localhost:8080/api/commands/create-policy"}],"collections":[{"name":"brokers","rel":"http://api.puppetlabs.com/razor/v1/collections/brokers","id":"http://localhost:8080/api/collections/brokers"},{"name":"images","rel":"http://api.puppetlabs.com/razor/v1/collections/images","id":"http://localhost:8080/api/collections/images"},{"name":"tags","rel":"http://api.puppetlabs.com/razor/v1/collections/tags","id":"http://localhost:8080/api/collections/tags"},{"name":"policies","rel":"http://api.puppetlabs.com/razor/v1/collections/policies","id":"http://localhost:8080/api/collections/policies"},{"name":"nodes","rel":"http://api.puppetlabs.com/razor/v1/collections/nodes","id":"http://localhost:8080/api/collections/nodes"}]}'
|
34
|
+
http_version:
|
35
|
+
recorded_at: Wed, 28 Aug 2013 21:46:05 GMT
|
36
|
+
recorded_with: VCR 2.5.0
|
@@ -0,0 +1,36 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://localhost:8080/api
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- application/json
|
12
|
+
Accept-Encoding:
|
13
|
+
- gzip, deflate
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
response:
|
17
|
+
status:
|
18
|
+
code: 200
|
19
|
+
message: OK
|
20
|
+
headers:
|
21
|
+
Server:
|
22
|
+
- Apache-Coyote/1.1
|
23
|
+
X-Content-Type-Options:
|
24
|
+
- nosniff
|
25
|
+
Content-Type:
|
26
|
+
- application/json;charset=utf-8
|
27
|
+
Content-Length:
|
28
|
+
- '1566'
|
29
|
+
Date:
|
30
|
+
- Wed, 28 Aug 2013 21:46:05 GMT
|
31
|
+
body:
|
32
|
+
encoding: US-ASCII
|
33
|
+
string: ! '{"commands":[{"name":"create-image","rel":"http://api.puppetlabs.com/razor/v1/commands/create-image","id":"http://localhost:8080/api/commands/create-image"},{"name":"delete-image","rel":"http://api.puppetlabs.com/razor/v1/commands/delete-image","id":"http://localhost:8080/api/commands/delete-image"},{"name":"create-installer","rel":"http://api.puppetlabs.com/razor/v1/commands/create-installer","id":"http://localhost:8080/api/commands/create-installer"},{"name":"create-tag","rel":"http://api.puppetlabs.com/razor/v1/commands/create-tag","id":"http://localhost:8080/api/commands/create-tag"},{"name":"create-broker","rel":"http://api.puppetlabs.com/razor/v1/commands/create-broker","id":"http://localhost:8080/api/commands/create-broker"},{"name":"create-policy","rel":"http://api.puppetlabs.com/razor/v1/commands/create-policy","id":"http://localhost:8080/api/commands/create-policy"}],"collections":[{"name":"brokers","rel":"http://api.puppetlabs.com/razor/v1/collections/brokers","id":"http://localhost:8080/api/collections/brokers"},{"name":"images","rel":"http://api.puppetlabs.com/razor/v1/collections/images","id":"http://localhost:8080/api/collections/images"},{"name":"tags","rel":"http://api.puppetlabs.com/razor/v1/collections/tags","id":"http://localhost:8080/api/collections/tags"},{"name":"policies","rel":"http://api.puppetlabs.com/razor/v1/collections/policies","id":"http://localhost:8080/api/collections/policies"},{"name":"nodes","rel":"http://api.puppetlabs.com/razor/v1/collections/nodes","id":"http://localhost:8080/api/collections/nodes"}]}'
|
34
|
+
http_version:
|
35
|
+
recorded_at: Wed, 28 Aug 2013 21:46:05 GMT
|
36
|
+
recorded_with: VCR 2.5.0
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start do
|
3
|
+
add_filter "/spec/"
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'json'
|
7
|
+
require 'vcr'
|
8
|
+
|
9
|
+
require_relative '../lib/razor'
|
10
|
+
require_relative 'vcr_library'
|
11
|
+
|
12
|
+
def vcr_record_mode
|
13
|
+
(ENV['VCR_RECORD'] || :none).to_sym
|
14
|
+
end
|
15
|
+
|
16
|
+
def vcr_recording?
|
17
|
+
vcr_record_mode != :none
|
18
|
+
end
|
19
|
+
|
20
|
+
VCR.configure do |c|
|
21
|
+
# NOTE: Empty this directory before re-recording
|
22
|
+
c.cassette_library_dir = VCR_LIBRARY
|
23
|
+
c.hook_into :webmock
|
24
|
+
c.configure_rspec_metadata!
|
25
|
+
c.default_cassette_options = {
|
26
|
+
:record => vcr_record_mode
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
# Record one cassette for each test
|
31
|
+
RSpec.configure do |c|
|
32
|
+
c.treat_symbols_as_metadata_keys_with_true_values = true
|
33
|
+
end
|
data/spec/vcr_library.rb
ADDED
metadata
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: razor-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.10.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- David Lutterkort
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-09-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rest-client
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: terminal-table
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: bundler
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.3'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.3'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
description: The client for the Razor server
|
79
|
+
email:
|
80
|
+
- lutter@watzmann.net
|
81
|
+
executables:
|
82
|
+
- razor
|
83
|
+
extensions: []
|
84
|
+
extra_rdoc_files: []
|
85
|
+
files:
|
86
|
+
- .gitignore
|
87
|
+
- .yardopts
|
88
|
+
- Gemfile
|
89
|
+
- Gemfile.lock
|
90
|
+
- LICENSE
|
91
|
+
- README.md
|
92
|
+
- Rakefile
|
93
|
+
- bin/razor
|
94
|
+
- lib/razor.rb
|
95
|
+
- lib/razor/cli.rb
|
96
|
+
- lib/razor/cli/format.rb
|
97
|
+
- lib/razor/cli/navigate.rb
|
98
|
+
- lib/razor/cli/parse.rb
|
99
|
+
- spec/cli/navigate_spec.rb
|
100
|
+
- spec/cli/parse_spec.rb
|
101
|
+
- spec/fixtures/vcr/Razor_CLI_Navigate/with_a_single_item_path/.yml
|
102
|
+
- spec/fixtures/vcr/Razor_CLI_Navigate/with_an_invalid_path/.yml
|
103
|
+
- spec/fixtures/vcr/Razor_CLI_Navigate/with_no_path/.yml
|
104
|
+
- spec/fixtures/vcr/Razor_CLI_Parse/_new/_help/.yml
|
105
|
+
- spec/fixtures/vcr/Razor_CLI_Parse/_new/_help/should_print_a_list_of_known_endpoints.yml
|
106
|
+
- spec/spec_helper.rb
|
107
|
+
- spec/vcr_library.rb
|
108
|
+
homepage: https://github.com/puppetlabs/razor-client
|
109
|
+
licenses:
|
110
|
+
- ASL2
|
111
|
+
post_install_message:
|
112
|
+
rdoc_options: []
|
113
|
+
require_paths:
|
114
|
+
- lib
|
115
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ! '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ! '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
requirements: []
|
128
|
+
rubyforge_project:
|
129
|
+
rubygems_version: 1.8.23
|
130
|
+
signing_key:
|
131
|
+
specification_version: 3
|
132
|
+
summary: The client for everyvody's favorite provisioning tool
|
133
|
+
test_files:
|
134
|
+
- spec/cli/navigate_spec.rb
|
135
|
+
- spec/cli/parse_spec.rb
|
136
|
+
- spec/fixtures/vcr/Razor_CLI_Navigate/with_a_single_item_path/.yml
|
137
|
+
- spec/fixtures/vcr/Razor_CLI_Navigate/with_an_invalid_path/.yml
|
138
|
+
- spec/fixtures/vcr/Razor_CLI_Navigate/with_no_path/.yml
|
139
|
+
- spec/fixtures/vcr/Razor_CLI_Parse/_new/_help/.yml
|
140
|
+
- spec/fixtures/vcr/Razor_CLI_Parse/_new/_help/should_print_a_list_of_known_endpoints.yml
|
141
|
+
- spec/spec_helper.rb
|
142
|
+
- spec/vcr_library.rb
|
143
|
+
has_rdoc:
|