collins_client 0.2.7
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/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: []
|