Class: SparkleFormation::Translation

Inherits:
Object
  • Object
show all
Includes:
SparkleAttribute, Utils::AnimalStrings
Defined in:
lib/sparkle_formation/translation.rb,
lib/sparkle_formation/translation/heat.rb,
lib/sparkle_formation/translation/rackspace.rb

Overview

Translator

Direct Known Subclasses

Heat

Defined Under Namespace

Classes: Heat, Rackspace

Constant Summary collapse

REF_MAPPING =

Returns mapping for pseudo-parameters.

Returns:

  • (Hash)

    mapping for pseudo-parameters

{}
FN_MAPPING =

Returns mapping for intrinsic functions.

Returns:

  • (Hash)

    mapping for intrinsic functions

{}

Constants included from SparkleAttribute

SparkleAttribute::OpenStack

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from SparkleAttribute

#__attribute_key, #_dynamic, #_method, #_nest, #_puts, #_raise, #_registry, #_resource_name, #_system

Methods included from Utils::AnimalStrings

#camel, #snake

Constructor Details

#initialize(template_hash, args = {}) ⇒ Translation

Create new instance

Parameters:

  • template_hash (Hash)

    stack template

  • args (Hash) (defaults to: {})

Options Hash (args):

  • :logger (Logger)

    custom logger

  • :parameters (Hash)

    parameters for stack creation

  • :options (Hash)

    options for translation



32
33
34
35
36
37
38
39
# File 'lib/sparkle_formation/translation.rb', line 32

def initialize(template_hash, args = {})
  @original = template_hash.dup
  @template = template_hash.to_smash
  @translated = {}
  @logger = args.fetch(:logger, Logger.new($stdout))
  @parameters = args[:parameters] || {}
  @options = args[:options] || {}
end

Instance Attribute Details

#loggerLogger (readonly)

Returns current logger.

Returns:

  • (Logger)

    current logger



21
22
23
# File 'lib/sparkle_formation/translation.rb', line 21

def logger
  @logger
end

#optionsHash (readonly)

Returns extra options (generally used by translation implementations).

Returns:

  • (Hash)

    extra options (generally used by translation implementations)



23
24
25
# File 'lib/sparkle_formation/translation.rb', line 23

def options
  @options
end

#originalHash (readonly)

Returns original template.

Returns:

  • (Hash)

    original template



15
16
17
# File 'lib/sparkle_formation/translation.rb', line 15

def original
  @original
end

#templateHash (readonly)

Returns duplicated template (full deep copy).

Returns:

  • (Hash)

    duplicated template (full deep copy)



19
20
21
# File 'lib/sparkle_formation/translation.rb', line 19

def template
  @template
end

#translatedHash (readonly)

Returns current translation.

Returns:

  • (Hash)

    current translation



17
18
19
# File 'lib/sparkle_formation/translation.rb', line 17

def translated
  @translated
end

Instance Method Details

#apply_function(hash, funcs = []) ⇒ Hash

Note:

also allows ‘Ref’ within funcs to provide mapping replacements using the REF_MAPPING constant

Apply function if possible

Parameters:

  • hash (Hash)
  • funcs (Array) (defaults to: [])

    allowed functions

Returns:

  • (Hash)


300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/sparkle_formation/translation.rb', line 300

def apply_function(hash, funcs = [])
  k, v = hash.first
  if hash.size == 1 && (k.start_with?("Fn") || k == "Ref") && (funcs.empty? || funcs.include?(k))
    case k
    when "Fn::Join"
      v.last.join(v.first)
    when "Fn::FindInMap"
      map_holder = mappings[v[0]]
      if map_holder
        map_item = map_holder[dereference(v[1])]
        if map_item
          map_item[v[2]]
        else
          raise "Failed to find mapping item! (#{v[0]} -> #{v[1]})"
        end
      else
        raise "Failed to find mapping! (#{v[0]})"
      end
    when "Ref"
      {"Ref" => self.class.const_get(:REF_MAPPING).fetch(v, v)}
    else
      hash
    end
  else
    hash
  end
end

#apply_rename(hash, names = []) ⇒ Hash

Note:

remapping references to constants: REF_MAPPING for Ref maps FN_MAPPING for Fn maps

Apply function if possible

Parameters:

  • hash (Hash)
  • names (Array<Symbol>) (defaults to: [])

    enable renaming (:ref, :fn)

Returns:

  • (Hash)


258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/sparkle_formation/translation.rb', line 258

def apply_rename(hash, names = [])
  k, v = hash.first
  if hash.size == 1
    if k.start_with?("Fn::")
      {self.class.const_get(:FN_MAPPING).fetch(k, k) => attr_mapping(*v)}
    elsif k == "Ref"
      if resources.key?(v)
        {"get_resource" => v}
      else
        {"get_param" => self.class.const_get(:REF_MAPPING).fetch(v, v)}
      end
    else
      hash
    end
  else
    hash
  end
end

#attr_mapping(resource_name, value) ⇒ Array

Apply ‘GetAttr` mapping if available

Parameters:

  • resource_name (String)
  • value (String)

Returns:

  • (Array)


282
283
284
285
286
287
288
289
290
291
# File 'lib/sparkle_formation/translation.rb', line 282

def attr_mapping(resource_name, value)
  result = [resource_name, value]
  if r = resources[resource_name]
    attr_map = self.class.const_get(:FN_ATT_MAPPING)
    if attr_map[r["Type"]] && replacement = attr_map[r["Type"]][value]
      result = [resource_name, *[replacement].flatten.compact]
    end
  end
  result
end

#default_key_format(key) ⇒ String, Symbol

Default formatting for keys

Parameters:

  • key (String, Symbol)

Returns:

  • (String, Symbol)


177
178
179
# File 'lib/sparkle_formation/translation.rb', line 177

def default_key_format(key)
  key
end

#dereference(obj) ⇒ Object

Attempt to dereference name

Parameters:

  • obj (Object)

Returns:

  • (Object)


185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/sparkle_formation/translation.rb', line 185

def dereference(obj)
  result = obj
  if obj.is_a?(Hash)
    name = obj["Ref"] || obj["get_param"]
    if name
      p_val = parameters[name.to_s]
      if p_val
        result = p_val
      end
    end
  end
  result
end

#dereference_processor(obj, funcs = []) ⇒ Object

Process object through dereferencer. This will dereference names and apply functions if possible.

Parameters:

  • obj (Object)

Returns:

  • (Object)


217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/sparkle_formation/translation.rb', line 217

def dereference_processor(obj, funcs = [])
  case obj
  when Array
    obj = obj.map { |v| dereference_processor(v, funcs) }
  when Hash
    new_hash = {}
    obj.each do |k, v|
      new_hash[k] = dereference_processor(v, funcs)
    end
    obj = apply_function(new_hash, funcs)
  end
  obj
end

#format_properties(args) ⇒ Hash

Format the properties of the new resource

Parameters:

  • args (Hash)

Options Hash (args):

  • :original_properties (Hash)
  • :property_map (Hash)
  • :new_resource (Hash)
  • :original_resource (Hash)

Returns:

  • (Hash)


132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/sparkle_formation/translation.rb', line 132

def format_properties(args)
  args[:new_resource]["Properties"] = {}.tap do |new_properties|
    args[:original_properties].each do |property_name, property_value|
      new_key = args[:property_map][property_name]
      if new_key
        if new_key.is_a?(Symbol)
          unless new_key == :delete
            new_key, new_value = send(new_key, property_value,
                                      :new_resource => args[:new_resource],
                                      :new_properties => new_properties,
                                      :original_resource => args[:original_resource])
            new_properties[new_key] = new_value
          end
        else
          new_properties[new_key] = property_value
        end
      else
        logger.warn "Failed to locate property conversion for `#{property_name}` on " \
                    "resource type `#{args[:new_resource]["Type"]}`. Passing directly."
        new_properties[default_key_format(property_name)] = property_value
      end
    end
  end
end

#mapHash

Returns resource mapping.

Returns:

  • (Hash)

    resource mapping



66
67
68
# File 'lib/sparkle_formation/translation.rb', line 66

def map
  self.class.const_get(:MAP)
end

#mappingsHash

Returns mappings for template.

Returns:

  • (Hash)

    mappings for template



51
52
53
# File 'lib/sparkle_formation/translation.rb', line 51

def mappings
  @original.fetch("Mappings", {})
end

#outputsHash

Returns outputs for template.

Returns:

  • (Hash)

    outputs for template



61
62
63
# File 'lib/sparkle_formation/translation.rb', line 61

def outputs
  @original.fetch("Outputs", {})
end

#parametersHash

Returns parameters for template.

Returns:

  • (Hash)

    parameters for template



42
43
44
45
46
47
48
# File 'lib/sparkle_formation/translation.rb', line 42

def parameters
  Hash[
    @original.fetch("Parameters", {}).map do |k, v|
      [k, v.fetch("Default", "")]
    end
  ].merge(@parameters)
end

#rename_processor(obj, names = []) ⇒ Object

Process object through name mapping

Parameters:

  • obj (Object)
  • names (Array<Symbol>) (defaults to: [])

    enable renaming (:ref, :fn)

Returns:

  • (Object)


236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/sparkle_formation/translation.rb', line 236

def rename_processor(obj, names = [])
  case obj
  when Array
    obj = obj.map { |v| rename_processor(v, names) }
  when Hash
    new_hash = {}
    obj.each do |k, v|
      new_hash[k] = rename_processor(v, names)
    end
    obj = apply_rename(new_hash, names)
  end
  obj
end

#resource_name(obj) ⇒ String

Provide name of resource

Parameters:

  • obj (Object)

Returns:

  • (String)

    name



203
204
205
206
207
208
209
210
# File 'lib/sparkle_formation/translation.rb', line 203

def resource_name(obj)
  case obj
  when Hash
    obj["Ref"] || obj["get_resource"]
  else
    obj.to_s
  end
end

#resource_translation(resource_name, resource_args) ⇒ Hash, NilClass

Translate resource

Parameters:

  • resource_name (String)
  • resource_args (Hash)

Returns:

  • (Hash, NilClass)

    new resource Hash or nil



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/sparkle_formation/translation.rb', line 97

def resource_translation(resource_name, resource_args)
  new_resource = {}
  lookup = map[:resources][resource_args["Type"]]
  if lookup.nil?
    logger.warn "Failed to locate resource type: #{resource_args["Type"]}"
    nil
  elsif lookup == :delete
    logger.warn "Deleting resource #{resource_name} due to configuration"
    nil
  else
    new_resource["Type"] = lookup[:name]
    if resource_args["Properties"]
      new_resource["Properties"] = format_properties(
        :original_properties => resource_args["Properties"],
        :property_map => lookup[:properties],
        :new_resource => new_resource,
        :original_resource => resource_args,
      )
    end
    if lookup[:finalizer]
      send(lookup[:finalizer], resource_name, new_resource, resource_args)
    end
    resource_finalizer(resource_name, new_resource, resource_args)
    new_resource
  end
end

#resourcesHash

Returns resources for template.

Returns:

  • (Hash)

    resources for template



56
57
58
# File 'lib/sparkle_formation/translation.rb', line 56

def resources
  @original.fetch("Resources", {})
end

#translate!TrueClass

Translate stack definition

Returns:

  • (TrueClass)


73
74
75
76
77
78
79
80
81
82
83
# File 'lib/sparkle_formation/translation.rb', line 73

def translate!
  template.each do |key, value|
    translate_method = "translate_#{snake(key.to_s)}".to_sym
    if respond_to?(translate_method)
      send(translate_method, value)
    else
      translate_default(key, value)
    end
  end
  true
end

#translate_default(key, value) ⇒ Object

Default translation action if no mapping is provided

Returns:

  • (Object)

    value



88
89
90
# File 'lib/sparkle_formation/translation.rb', line 88

def translate_default(key, value)
  translated[key] = value
end

#translate_resources(value) ⇒ Hash

Translate provided resources

Parameters:

  • value (Hash)

    resources hash

Returns:

  • (Hash)


161
162
163
164
165
166
167
168
169
170
171
# File 'lib/sparkle_formation/translation.rb', line 161

def translate_resources(value)
  translated["Resources"] = {}
  translated["Resources"].tap do |modified_resources|
    value.each do |resource_name, resource_args|
      new_resource = resource_translation(resource_name, resource_args)
      if new_resource
        modified_resources[resource_name] = new_resource
      end
    end
  end
end