collins_client 0.2.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +15 -0
- data/Gemfile.lock +50 -0
- data/README.md +46 -0
- data/Rakefile +66 -0
- data/VERSION +1 -0
- data/collins_client.gemspec +73 -0
- data/lib/collins/address.rb +74 -0
- data/lib/collins/api.rb +119 -0
- data/lib/collins/api/admin.rb +19 -0
- data/lib/collins/api/asset.rb +184 -0
- data/lib/collins/api/asset_state.rb +85 -0
- data/lib/collins/api/attributes.rb +76 -0
- data/lib/collins/api/ip_address.rb +87 -0
- data/lib/collins/api/logging.rb +137 -0
- data/lib/collins/api/management.rb +84 -0
- data/lib/collins/api/tag.rb +46 -0
- data/lib/collins/api/util.rb +28 -0
- data/lib/collins/api/util/errors.rb +45 -0
- data/lib/collins/api/util/parameters.rb +44 -0
- data/lib/collins/api/util/requests.rb +136 -0
- data/lib/collins/api/util/responses.rb +46 -0
- data/lib/collins/asset.rb +311 -0
- data/lib/collins/asset_client.rb +57 -0
- data/lib/collins/client.rb +100 -0
- data/lib/collins/errors.rb +56 -0
- data/lib/collins/ipmi.rb +41 -0
- data/lib/collins/logging.rb +33 -0
- data/lib/collins/monkeypatch.rb +24 -0
- data/lib/collins/option.rb +220 -0
- data/lib/collins/power.rb +99 -0
- data/lib/collins/profile.rb +73 -0
- data/lib/collins/simple_callback.rb +141 -0
- data/lib/collins/state.rb +50 -0
- data/lib/collins/util.rb +145 -0
- data/lib/collins_client.rb +7 -0
- metadata +100 -0
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'collins/util'
|
2
|
+
|
3
|
+
module Collins
|
4
|
+
|
5
|
+
class Profile
|
6
|
+
|
7
|
+
include Collins::Util
|
8
|
+
|
9
|
+
attr_accessor :options
|
10
|
+
|
11
|
+
def initialize options = {}
|
12
|
+
@options = symbolize_hash options, :downcase => true
|
13
|
+
end
|
14
|
+
|
15
|
+
def profile
|
16
|
+
@options[:profile]
|
17
|
+
end
|
18
|
+
def profile?
|
19
|
+
not profile.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
def label
|
23
|
+
@options[:label]
|
24
|
+
end
|
25
|
+
def label?
|
26
|
+
not label.nil?
|
27
|
+
end
|
28
|
+
|
29
|
+
def prefix
|
30
|
+
@options[:prefix]
|
31
|
+
end
|
32
|
+
def prefix?
|
33
|
+
not prefix.nil?
|
34
|
+
end
|
35
|
+
|
36
|
+
def suffix_allowed?
|
37
|
+
@options[:suffix_allowed]
|
38
|
+
end
|
39
|
+
|
40
|
+
def primary_role
|
41
|
+
@options[:primary_role]
|
42
|
+
end
|
43
|
+
def primary_role?
|
44
|
+
not primary_role.nil?
|
45
|
+
end
|
46
|
+
|
47
|
+
def pool
|
48
|
+
@options[:pool]
|
49
|
+
end
|
50
|
+
def pool?
|
51
|
+
not pool.nil?
|
52
|
+
end
|
53
|
+
|
54
|
+
def secondary_role
|
55
|
+
@options[:secondary_role]
|
56
|
+
end
|
57
|
+
def secondary_role?
|
58
|
+
not secondary_role.nil?
|
59
|
+
end
|
60
|
+
|
61
|
+
def requires_primary_role?
|
62
|
+
@options[:requires_primary_role]
|
63
|
+
end
|
64
|
+
def requires_pool?
|
65
|
+
@options[:requires_pool]
|
66
|
+
end
|
67
|
+
def requires_secondary_role?
|
68
|
+
@options[:requires_secondary_role]
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'collins/util'
|
2
|
+
require 'collins/option'
|
3
|
+
|
4
|
+
module Collins
|
5
|
+
|
6
|
+
# Represents a simple callback, e.g. something with a name, options and an exec block
|
7
|
+
# This is designed to be a building block for other callback implementations as opposed to a
|
8
|
+
# complete implementation. Note that we duck-type Proc. We can't extend it without running into
|
9
|
+
# some initialize issues. We do this so people can feel free to tread the class like a proc.
|
10
|
+
class SimpleCallback
|
11
|
+
include ::Collins::Util
|
12
|
+
|
13
|
+
EMPTY_NAME = :None
|
14
|
+
|
15
|
+
# @return [Symbol] Name of the callback
|
16
|
+
attr_reader :name
|
17
|
+
|
18
|
+
# @return [Hash] Options specified with the callback, after normalizing
|
19
|
+
attr_reader :options
|
20
|
+
|
21
|
+
# @return [Collins::SimpleCallback] {#empty?} will return true
|
22
|
+
def self.empty
|
23
|
+
Collins::SimpleCallback.new(:none => true) {}
|
24
|
+
end
|
25
|
+
|
26
|
+
# Instantiate a new SimpleCallback
|
27
|
+
#
|
28
|
+
# @param [Array,Hash] args Arguments for instantiation
|
29
|
+
# @yieldparam [Array<Object>] block Callback to execute, can also be specified via :block option
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# SimpleCallback.new(:my_callback, Proc.new {|arg1| puts(arg1)})
|
33
|
+
# SimpleCallback.new(:my_callback, :block => Proc.new{|arg1| puts(arg1)})
|
34
|
+
# SimpleCallback.new :my_callback, :opt1 => "val" do |arg1|
|
35
|
+
# puts(arg1)
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# @raise [ArgumentError] when name not set, and not created via #{SimpleCallback.empty}
|
39
|
+
def initialize *args, &block
|
40
|
+
opts = {}
|
41
|
+
while arg = args.shift do
|
42
|
+
if arg.is_a?(Hash) then
|
43
|
+
opts.update(arg)
|
44
|
+
elsif arg.respond_to?(:call) then
|
45
|
+
opts.update(:block => arg)
|
46
|
+
else
|
47
|
+
key = [:name, :options].select{|k| !opts.key?(k)}.first
|
48
|
+
opts.update(key => arg) unless key.nil?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
if block && block.respond_to?(:call) then
|
52
|
+
opts.update(:block => block)
|
53
|
+
end
|
54
|
+
opts = symbolize_hash(opts)
|
55
|
+
if opts.fetch(:none, false) then
|
56
|
+
@name = EMPTY_NAME
|
57
|
+
@block = ::Collins::None.new
|
58
|
+
@options = {}
|
59
|
+
else
|
60
|
+
@name = ::Collins::Option(opts.delete(:name)).get_or_else {
|
61
|
+
raise ArgumentError.new("SimpleCallback requires a name")
|
62
|
+
}.to_sym
|
63
|
+
@block = ::Collins::Option(opts.delete(:block))
|
64
|
+
@options = opts
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# @see Hash
|
69
|
+
# @param [String,Symbol] key
|
70
|
+
# @return [Object] value associated with key
|
71
|
+
def [](key)
|
72
|
+
options[key.to_sym]
|
73
|
+
end
|
74
|
+
|
75
|
+
# @see Proc
|
76
|
+
# @return [Fixnum] number of arguments that would not be ignored
|
77
|
+
def arity
|
78
|
+
block.map {|b| b.arity}.get_or_else(0)
|
79
|
+
end
|
80
|
+
# @see Proc
|
81
|
+
# @return [Binding] binding associated with the proc
|
82
|
+
def binding
|
83
|
+
to_proc.binding
|
84
|
+
end
|
85
|
+
# @see Proc
|
86
|
+
# @return [Boolean] lambda or not
|
87
|
+
def lambda?
|
88
|
+
block.map {|b| b.lambda?}.get_or_else(false)
|
89
|
+
end
|
90
|
+
# @see Proc
|
91
|
+
# @return [Array<Array<Symbol>>] array of parameters accepted by proc
|
92
|
+
def parameters
|
93
|
+
block.map {|b| b.parameters}.get_or_else([])
|
94
|
+
end
|
95
|
+
# @see Proc
|
96
|
+
# @return [Proc] proc or noop proc
|
97
|
+
def to_proc
|
98
|
+
block.map{|b| b.to_proc}.get_or_else(Proc.new{})
|
99
|
+
end
|
100
|
+
|
101
|
+
# @return [Collins::Option] Self as option
|
102
|
+
def to_option
|
103
|
+
if self.defined? then
|
104
|
+
::Collins::Some.new(self)
|
105
|
+
else
|
106
|
+
::Collins::None.new
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# @return [Boolean] True if block was given to constructor
|
111
|
+
def defined?
|
112
|
+
name != EMPTY_NAME || block.defined?
|
113
|
+
end
|
114
|
+
# @return [Boolean] False if block was given to constructor
|
115
|
+
def empty?
|
116
|
+
name == EMPTY_NAME && block.empty?
|
117
|
+
end
|
118
|
+
|
119
|
+
# Call the callback block with the specified arguments
|
120
|
+
#
|
121
|
+
# @see Proc
|
122
|
+
# @param [Array<Object>] args - Arguments for callback
|
123
|
+
# @return [Object] Value from callback
|
124
|
+
# @raise [NameError] if block wasn't specified but call was executed
|
125
|
+
def call *args
|
126
|
+
block.map do |b|
|
127
|
+
b.call(*args)
|
128
|
+
end.get
|
129
|
+
end
|
130
|
+
|
131
|
+
# @return [String] representation of callback
|
132
|
+
def to_s
|
133
|
+
"Collins::SimpleCallback(name = #{name}, options = #{options.inspect})"
|
134
|
+
end
|
135
|
+
|
136
|
+
protected
|
137
|
+
# The code block associated with the simple callback
|
138
|
+
attr_reader :block
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Collins
|
4
|
+
class AssetState
|
5
|
+
include Collins::Util
|
6
|
+
|
7
|
+
attr_accessor :description, :id, :label, :name, :status
|
8
|
+
|
9
|
+
def self.from_json json
|
10
|
+
Collins::AssetState.new json
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize opts = {}
|
14
|
+
hash = symbolize_hash(opts).inject({}) do |result, (k,v)|
|
15
|
+
key = k.to_s.downcase.to_sym
|
16
|
+
result[key] = v
|
17
|
+
result
|
18
|
+
end
|
19
|
+
@description = hash[:description].to_s
|
20
|
+
@id = hash[:id].to_s.to_i
|
21
|
+
@label = hash[:label].to_s
|
22
|
+
@name = hash[:name].to_s
|
23
|
+
@status = get_status hash[:status]
|
24
|
+
end
|
25
|
+
|
26
|
+
def empty?
|
27
|
+
@id == 0
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
if empty? then
|
32
|
+
"State(None)"
|
33
|
+
else
|
34
|
+
"State(id = #{id}, name = '#{name}', label = '#{label}', description = '#{description}')"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
def get_status opt
|
40
|
+
opts = opt || {}
|
41
|
+
hash = symbolize_hash(opts).inject({}) do |result, (k,v)|
|
42
|
+
key = k.to_s.downcase.to_sym
|
43
|
+
result[key] = v
|
44
|
+
result
|
45
|
+
end
|
46
|
+
OpenStruct.new(hash)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
data/lib/collins/util.rb
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'collins/logging'
|
2
|
+
|
3
|
+
module Collins
|
4
|
+
|
5
|
+
# General purpose util methods
|
6
|
+
#
|
7
|
+
# Methods in {Collins::Util} can be accessed by....
|
8
|
+
#
|
9
|
+
# * `Collins::Util.method_name`
|
10
|
+
# * `ClassIncludingCollinsUtil.method_name`
|
11
|
+
# * `instance_of_class_including_collins_util.method_name`
|
12
|
+
#
|
13
|
+
# Other than {Util#get\_asset\_or\_tag} most of these methods are not collins specific
|
14
|
+
module Util
|
15
|
+
|
16
|
+
include Collins::Util::Logging
|
17
|
+
|
18
|
+
def self.included base
|
19
|
+
base.extend(Collins::Util)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Create a deep copy of a hash
|
23
|
+
#
|
24
|
+
# This is useful for copying a hash that will be mutated
|
25
|
+
# @note All keys and values must be serializable, Proc for instance will fail
|
26
|
+
# @param [Hash] hash the hash to copy
|
27
|
+
# @return [Hash]
|
28
|
+
def deep_copy_hash hash
|
29
|
+
require_that(hash.is_a?(Hash), "deep_copy_hash requires a hash be specified, got #{hash.class}")
|
30
|
+
Marshal.load Marshal.dump(hash)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Require that a value not be empty
|
34
|
+
#
|
35
|
+
# If the value is a string, ensure that once stripped it's not empty. If the value responds to
|
36
|
+
# `:empty?`, ensure that it's not. Otherwise ensure the value isn't nil.
|
37
|
+
#
|
38
|
+
# @param [Object] value the value to check
|
39
|
+
# @param [String] message the exception message to use if the value is empty
|
40
|
+
# @param [Boolean,Object] return_value If true, returns value. If not false, returns the object
|
41
|
+
# @raise [ExpectationFailedError] if the value is empty
|
42
|
+
# @return [NilClass,Object] NilClass, or respecting return_value
|
43
|
+
def require_non_empty value, message, return_value = false
|
44
|
+
guard_value = if return_value == true then
|
45
|
+
value
|
46
|
+
elsif return_value != false then
|
47
|
+
return_value
|
48
|
+
else
|
49
|
+
false
|
50
|
+
end
|
51
|
+
if value.is_a?(String) then
|
52
|
+
require_that(!value.strip.empty?, message, guard_value)
|
53
|
+
elsif value.respond_to?(:empty?) then
|
54
|
+
require_that(!value.empty?, message, guard_value)
|
55
|
+
else
|
56
|
+
require_that(!value.nil?, message, guard_value)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Require that a guard condition passes
|
61
|
+
#
|
62
|
+
# Simply checks that the guard is truthy, and throws an error otherwise
|
63
|
+
# @see #require_non_empty
|
64
|
+
def require_that guard, message, return_guard = false
|
65
|
+
if not guard then
|
66
|
+
raise ExpectationFailedError.new(message)
|
67
|
+
end
|
68
|
+
if return_guard == true then
|
69
|
+
guard
|
70
|
+
elsif return_guard != false then
|
71
|
+
return_guard
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Resolve an asset from a string tag or collins asset
|
76
|
+
# @note This is perhaps the only collins specific method in Util
|
77
|
+
# @param [Collins::Asset,String,Symbol] asset_or_tag
|
78
|
+
# @return [Collins::Asset] a collins asset
|
79
|
+
# @raise [ExpectationFailedError] if asset\_or\_tag isn't valid
|
80
|
+
def get_asset_or_tag asset_or_tag
|
81
|
+
asset =
|
82
|
+
case asset_or_tag
|
83
|
+
when Collins::Asset then asset_or_tag
|
84
|
+
when String then Collins::Asset.new(asset_or_tag)
|
85
|
+
when Symbol then Collins::Asset.new(asset_or_tag.to_s)
|
86
|
+
else
|
87
|
+
error_message = "Expected Collins::Asset, String or Symbol. Got #{asset_or_tag.class}"
|
88
|
+
raise ExpectationFailedError.new(error_message)
|
89
|
+
end
|
90
|
+
if asset.nil? || asset.tag.nil? then
|
91
|
+
raise ExpectationFailedError.new("Empty asset tag, but a tag is required")
|
92
|
+
end
|
93
|
+
asset
|
94
|
+
end
|
95
|
+
|
96
|
+
# Given a hash, rewrite keys to symbols
|
97
|
+
#
|
98
|
+
# @param [Hash] hash the hash to symbolize
|
99
|
+
# @param [Hash] options specify how to process the hash
|
100
|
+
# @option options [Boolean] :rewrite_regex if the value is a regex and this is true, convert it to a string
|
101
|
+
# @option options [Boolean] :downcase if true, downcase the keys as well
|
102
|
+
# @raise [ExpectationFailedError] if hash is not a hash
|
103
|
+
def symbolize_hash hash, options = {}
|
104
|
+
return {} if (hash.nil? or hash.empty?)
|
105
|
+
(raise ExpectationFailedError.new("symbolize_hash called without a hash")) unless hash.is_a?(Hash)
|
106
|
+
hash.inject({}) do |result, (k,v)|
|
107
|
+
key = options[:downcase] ? k.to_s.downcase.to_sym : k.to_s.to_sym
|
108
|
+
if v.is_a?(Hash) then
|
109
|
+
result[key] = symbolize_hash(v)
|
110
|
+
elsif v.is_a?(Regexp) && options[:rewrite_regex] then
|
111
|
+
result[key] = v.inspect[1..-2]
|
112
|
+
else
|
113
|
+
result[key] = v
|
114
|
+
end
|
115
|
+
result
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Given a hash, convert all keys to strings
|
120
|
+
# @see #symbolize_hash
|
121
|
+
def stringify_hash hash, options = {}
|
122
|
+
(raise ExpectationFailedError.new("stringify_hash called without a hash")) unless hash.is_a?(Hash)
|
123
|
+
hash.inject({}) do |result, (k,v)|
|
124
|
+
key = options[:downcase] ? k.to_s.downcase : k.to_s
|
125
|
+
if v.is_a?(Hash) then
|
126
|
+
result[key] = stringify_hash(v)
|
127
|
+
elsif v.is_a?(Regexp) && options[:rewrite_regex] then
|
128
|
+
result[key] = v.inspect[1..-2]
|
129
|
+
else
|
130
|
+
result[key] = v
|
131
|
+
end
|
132
|
+
result
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# This provides access to these methods via a Collins::Util.method_name call
|
137
|
+
[:deep_copy_hash, :require_non_empty, :get_asset_or_tag, :require_that,
|
138
|
+
:symbolize_hash, :stringify_hash
|
139
|
+
].each do |method|
|
140
|
+
module_function method
|
141
|
+
public method # without this, module_function makes the method private
|
142
|
+
end
|
143
|
+
end # Util module
|
144
|
+
|
145
|
+
end # Collins module
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: collins_client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.7
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Blake Matheny
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-31 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: httparty
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.8.3
|
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.8.3
|
30
|
+
description: Provides ruby support for interacting with the Collins API
|
31
|
+
email: bmatheny@tumblr.com
|
32
|
+
executables: []
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files:
|
35
|
+
- README.md
|
36
|
+
files:
|
37
|
+
- Gemfile
|
38
|
+
- Gemfile.lock
|
39
|
+
- README.md
|
40
|
+
- Rakefile
|
41
|
+
- VERSION
|
42
|
+
- collins_client.gemspec
|
43
|
+
- lib/collins/address.rb
|
44
|
+
- lib/collins/api.rb
|
45
|
+
- lib/collins/api/admin.rb
|
46
|
+
- lib/collins/api/asset.rb
|
47
|
+
- lib/collins/api/asset_state.rb
|
48
|
+
- lib/collins/api/attributes.rb
|
49
|
+
- lib/collins/api/ip_address.rb
|
50
|
+
- lib/collins/api/logging.rb
|
51
|
+
- lib/collins/api/management.rb
|
52
|
+
- lib/collins/api/tag.rb
|
53
|
+
- lib/collins/api/util.rb
|
54
|
+
- lib/collins/api/util/errors.rb
|
55
|
+
- lib/collins/api/util/parameters.rb
|
56
|
+
- lib/collins/api/util/requests.rb
|
57
|
+
- lib/collins/api/util/responses.rb
|
58
|
+
- lib/collins/asset.rb
|
59
|
+
- lib/collins/asset_client.rb
|
60
|
+
- lib/collins/client.rb
|
61
|
+
- lib/collins/errors.rb
|
62
|
+
- lib/collins/ipmi.rb
|
63
|
+
- lib/collins/logging.rb
|
64
|
+
- lib/collins/monkeypatch.rb
|
65
|
+
- lib/collins/option.rb
|
66
|
+
- lib/collins/power.rb
|
67
|
+
- lib/collins/profile.rb
|
68
|
+
- lib/collins/simple_callback.rb
|
69
|
+
- lib/collins/state.rb
|
70
|
+
- lib/collins/util.rb
|
71
|
+
- lib/collins_client.rb
|
72
|
+
homepage: https://github.com/tumblr/collins/tree/master/support/ruby/collins-client
|
73
|
+
licenses:
|
74
|
+
- APL 2.0
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ! '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
hash: -1509418886285766907
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
requirements: []
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 1.8.24
|
97
|
+
signing_key:
|
98
|
+
specification_version: 3
|
99
|
+
summary: Client library for Collins API
|
100
|
+
test_files: []
|