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.
@@ -0,0 +1,5 @@
1
+ config.yaml
2
+ log/*
3
+ /.yardoc
4
+ /Gemfile.local*
5
+ /coverage
@@ -0,0 +1,2 @@
1
+ --markup-provider=redcarpet
2
+ --markup=markdown
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
@@ -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.
@@ -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.
@@ -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
@@ -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
@@ -0,0 +1 @@
1
+ require_relative 'razor/cli'
@@ -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
@@ -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
@@ -0,0 +1,8 @@
1
+ # Useful things about our VCR tapes that needto be used by both the
2
+ # Rakefile and the spec_helper.
3
+
4
+ VCR_LIBRARY=File::join(File::dirname(__FILE__), 'fixtures', 'vcr')
5
+
6
+ def erase_vcr_library
7
+ FileUtils.rm_rf VCR_LIBRARY
8
+ end
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: