razor-client 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: