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.
@@ -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
@@ -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
@@ -0,0 +1,7 @@
1
+ $:.unshift File.join File.dirname(__FILE__)
2
+ require 'collins/util'
3
+ require 'collins/option'
4
+ require 'collins/simple_callback'
5
+ require 'collins/asset'
6
+ require 'collins/client'
7
+ require 'collins/errors'
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: []