Class: Smash::CloudPowers::Context

Inherits:
Object
  • Object
show all
Includes:
Helper
Defined in:
lib/cloud_powers/context.rb

Overview

The Context class is the class that handles serializing the Context so that it can be passed from node to node and rebuilt. This provides a way for nodes in the same Brain to have an awareness of required communication modes, for example. Because resources generally require some sort of information to connect with or create and a Brain operates in the same Context, it can use the Context to decouple the creation and usage from the coordination.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helper

#attr_map!, #available_resources, #called_from, #create_logger, #deep_modify_keys_with, #format_error_message, #log_file, #logger, #modify_keys_with, #smart_retry, #task_path, #task_require_path, #to_camel, #to_hyph, #to_i_var, #to_pascal, #to_ruby_file_name, #to_snake, #update_message_body, #valid_json?, #valid_url?

Constructor Details

#initialize(args) ⇒ Context

Attempts to create a Context out of the argument(s) you've passed.

Parameters

  • args +Hash+|+JSON+|+Array+|+enumerable list+
    • expample Hash:
      • each key is a module or class that is in CloudPowers and each value is either an array of configurations information or a single configuration. { task: 'demo', queue: [:backlog, :sned], pipe: :status_stream }
    • expample Array
      • each key is followed by 0..n valid configurations information [:task, 'demo', :queue, :backlog, :sned, :pipe, :status_stream]

Returns Smash::Context



33
34
35
36
37
38
39
40
# File 'lib/cloud_powers/context.rb', line 33

def initialize(args)
  unless valid_args?(args)
    raise ArgumentError.new 'Can be either a Hash, JSON, or an Enumerable ' +
      "arguments: #{args}"
  end
  @package = args
  @structure = decipher(args)
end

Instance Attribute Details

#package ⇒ Object

The given data structure that is used to build @structure



15
16
17
# File 'lib/cloud_powers/context.rb', line 15

def package
  @package
end

#structure ⇒ Object

A Hash that represents the resources and some configuration for them

Returns Hash



16
17
18
# File 'lib/cloud_powers/context.rb', line 16

def structure
  @structure
end

Instance Method Details

#decipher(args) ⇒ Object

Decipher figures out which translation method to use by making some simple type checks, etc. and then routing the args to the correct method.

Notes

  • See #translate_json()
  • See #translate_list()


48
49
50
51
52
53
54
55
56
57
# File 'lib/cloud_powers/context.rb', line 48

def decipher(args)
  case args
  when Hash
    args
  when String
    translate_json(args)
  when Enumerable
    translate_list(args)
  end
end

#flatten ⇒ Object

Creates a flat Array of the 2-D Array that gets returned from #simplify()

Returns Array

Example example_context.structure

=> { task: 'demo', queue: [:backlog, :sned], pipe: [:status_stream] }

example.flatten

=> [:task, 'demo', :queue, :backlog, :sned, :pipe, :status_stream]

Notes

  • See +#simplify()
  • See #Array::flatten()


72
73
74
# File 'lib/cloud_powers/context.rb', line 72

def flatten
  simplify.flatten
end

#simplify ⇒ Object

Create an array version of @sructure by calling #to_a() on it

Returns Array

Example example_context.structure

=> { task: 'demo', queue: [:backlog, :sned], pipe: [:status_stream] }

example.simplify

=> [:task, 'demo', :queue, [:backlog, :sned], :pipe, [:status_stream]]

Notes

  • This uses the different Constants, like Smash, Synapse and anything it can find to decide what should be used as a key and what its following values array should contain. It basically says:
    1. if the nth item is a known key (from the above search), add it as an object in the Array.
    2. else, add it to the last sub-Array
    3. move to n+1 in the structure Hash
  • TODO: Check if this has a limit to n-layers


95
96
97
# File 'lib/cloud_powers/context.rb', line 95

def simplify
  @structure.to_a
end

#to_json ⇒ Object

Uses #to_json() on the @structure Returns Hash



220
221
222
# File 'lib/cloud_powers/context.rb', line 220

def to_json
  structure.to_json
end

#translate_flattened(list) ⇒ Object

Translates an Array into a valid @structure Hash Parameters arr e.g.

[:task, 'demo', :queue, 'name1', {other config hash},...,:pipe, 'name1']

Returns Hash calling #valid_hash_format?() on returned Hash will return true



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/cloud_powers/context.rb', line 176

def translate_flattened(list)
  arr = list.to_a
  results = []
  # get the indexes of CloudPowers resources in arr
  key_locations = arr.each_with_index.collect do |key, i, _|
    i if available_resources.include?(to_pascal(key).to_sym)
  end.reject(&:nil?)
  key_locations << arr.size # add the last index into the ranges
  # use each pair as ranges to slice up the Array
  key_locations.each_cons(2) do |current_i, next_i|
    results << [arr[current_i], arr[(current_i+1)..(next_i-1)]]
  end

  translate_simplified(results)
end

#translate_json(json_string) ⇒ Object

Parse the given JSON Parameters: json_string String::Json Returns



115
116
117
118
119
120
121
# File 'lib/cloud_powers/context.rb', line 115

def translate_json(json_string)
  begin
    JSON.parse(json_string)
  rescue JSON::ParserError
    raise ArgumentError "Incorrectly formatted JSON"
  end
end

#translate_list(list) ⇒ Object

Re-layer this flattened Array or enumerable list so that it looks like the Hash that it used to be before the Smash::Context#flatten() method was called

@param list

<Array|List <Enumerable> e.g. flat Ruby [ object_name_1, config_1a, config_2a, ..., object_2, config_1b, etc, ... ] grouped or Ruby [ [object_name_1, config_1a, config_2a, ...], [object_2, config_1b, etc], ... ] or structured Ruby [ [object_name_1, [config_1a, config_2a, ...]], [object_2, [config_1b, etc]], ... ] returns Ruby { object_1: [config_1a, config_2a, ...], object_2: [config_1b, ...], ... } Returns Hash If #valid_package_hash?() is called on this Hash, it will return true



164
165
166
# File 'lib/cloud_powers/context.rb', line 164

def translate_list(list)
  list.first.kind_of?(Enumerable) ? translate_simplified(list) : translate_flattened(list)
end

#translate_simplified(arr) ⇒ Object

Translates a 2D Array into a valid @structure Hash Parameters arr e.g.

  [
    [:task, 'demo'],
    [:queue, 'name1', {other config hash},...],
    [:pipe, 'name1']
    ...
  ]
  • Needs to be a 2D Array
  • First object of each inner-Array is the key
  • All following values in that inner Array are separate configuration information pieces that can be used in the #create!() method for that particular resource Returns Hash well formatted for the @structure


209
210
211
212
213
214
215
216
# File 'lib/cloud_powers/context.rb', line 209

def translate_simplified(arr)
  arr.inject({}) do |hash, key_config_map|
    hash.tap do |h|
      key = key_config_map.shift
      h[key.to_sym] = *key_config_map.flatten
    end
  end
end

#valid_args?(args) ⇒ Boolean

The Context class can be initialized in any of the formats that a Context class should exist in. It can be a vanilla version, where the @structure is a Hash, structured correctly or it can be serialized into JSON or it can be an Array Parameters args String Returns Boolean

Returns:

  • (Boolean)


230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/cloud_powers/context.rb', line 230

def valid_args?(args)
  case args
  when Hash
    valid_hash_format?(args)
  when String
    valid_json_format?(args)
  when Enumerable
    valid_array_format?(args)
  else
    false
  end
end

#valid_array_format?(list) ⇒ Boolean

Makes sure that the list is enumerable and that at least the first term is a resource name from Smash::CloudPowers. All other objects can potentially be configurations. Parameters list <Array|Enumerable> Returns Boolean

Returns:

  • (Boolean)


248
249
250
251
# File 'lib/cloud_powers/context.rb', line 248

def valid_array_format?(list)
  use = list.first.kind_of?(Enumerable) ? list.first.first : list.first
  ((list.kind_of? Enumerable) && (available_resources.include?(to_pascal(use).to_sym)))
end

#valid_hash_format?(hash) ⇒ Boolean

Makes sure that each key is the name of something CloudPowers can interact with Parameters hash Returns Boolean

Returns:

  • (Boolean)


256
257
258
259
# File 'lib/cloud_powers/context.rb', line 256

def valid_hash_format?(hash)
  keys_arr = hash.keys.map { |key| to_pascal(key).to_sym }
  (keys_arr - available_resources).empty?
end

#valid_json_format?(json_string) ⇒ Boolean

Parses the json_string which yields a Hash or an exception. From there, use the #valid_hash_format?() method

Returns:

  • (Boolean)


263
264
265
266
267
268
269
# File 'lib/cloud_powers/context.rb', line 263

def valid_json_format?(json_string)
  begin
    valid_hash_format?(JSON.parse(json_string))
  rescue JSON::ParserError
    false
  end
end