Class: Docker::Template::Metadata

Inherits:
Object
  • Object
show all
Extended by:
Forwardable::Extended
Defined in:
lib/docker/template/metadata.rb

Constant Summary collapse

OPTS_FILE =

rubocop:disable Style/MultilineBlockLayout


"opts.yml"
DEFAULTS =

rubocop:enable Style/MultilineBlockLayout


HashWithIndifferentAccess.new({
  "log_filters" => [],
  "push" => false,
  "cache" => false,
  "type" => "normal",
  "user" => "random_user",
  "local_prefix" => "local",
  "rootfs_base_img" => "envygeeks/ubuntu",
  "maintainer" => "Random User <[email protected]>",
  "name" => Template.root.basename.to_s,
  "rootfs_template" => "alpine",
  "cache_dir" => "cache",
  "repos_dir" => "repos",
  "copy_dir" => "copy",
  "tag" => "latest",
  "clean" => true,
  "tty" => false,
  "tags" => {}
}).freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(overrides, root: nil) ⇒ Metadata


Create a new instance of self.class.

“‘


Examples:

“‘

self.class.new({
  :hello => :world
})

Parameters:

  • data (Hash, self.class)
    • the main data.

  • root (Hash, self.class) (defaults to: nil)
    • the root data.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/docker/template/metadata.rb', line 64

def initialize(overrides, root: nil)
  if root.is_a?(self.class)
    then root = root.to_h({
      :raw => true
    })
  end

  if overrides.is_a?(self.class)
    then overrides = overrides.to_h({
      :raw => true
    })
  end

  if root.nil?
    overrides = overrides.stringify
    gdata = Template.root.join(OPTS_FILE).read_yaml
    @data = DEFAULTS.deep_merge(gdata.stringify).deep_merge(overrides)
    tdata = Template.root.join(@data[:repos_dir], @data[:name], OPTS_FILE).read_yaml
    @data = @data.deep_merge(tdata.stringify).deep_merge(overrides)
    @data = @data.stringify.with_indifferent_access

  else
    @data = overrides.stringify.with_indifferent_access
    @root_data = root.stringify \
      .with_indifferent_access
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, shell: false, &block) ⇒ Object (private)



577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
# File 'lib/docker/template/metadata.rb', line 577

def method_missing(method, *args, shell: false, &block)
  key = method.to_s.gsub(/\?$/, "")
  val = self[key] || self[key.singularize] \
     || self[key.pluralize]

  if !args.empty? || block_given?
    super

  elsif method !~ /\?$/
    string_wrapper(
      val, :shell => shell
    )

  else
    val != false && !val.nil? && \
      !val.empty?
  end
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



14
15
16
# File 'lib/docker/template/metadata.rb', line 14

def data
  @data
end

Instance Method Details

#[](key) ⇒ Object

Note:

we make the getter slightly more indifferent because of tags.


Pull an indifferent key from the hash.


Parameters:

  • key (Anything())

    the key you wish to pull.



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/docker/template/metadata.rb', line 145

def [](key)
  val = begin
    if key =~ /^\d+\.\d+$/
      @data[key] || @data[
        key.to_f
      ]

    elsif key =~ /^\d+$/
      @data[key] || @data[
        key.to_i
      ]

    else
      @data[key]
    end
  end

  if val.is_a?(Hash)
    return self.class.new(val, {
      :root => root_data
    })
  end

  val
end

#[]=(key, val) ⇒ Object




173
174
175
176
177
178
# File 'lib/docker/template/metadata.rb', line 173

def []=(key, val)
  hash = { key => val }.stringify
  @data.update(
    hash
  )
end

#_shasObject




94
95
96
97
98
99
100
# File 'lib/docker/template/metadata.rb', line 94

def _shas
  return @_shas ||= begin
    self.class.new(Template.gem_root.join("shas.yml").read_yaml, {
      :root => root_data
    })
  end
end

#alias?Boolean


Checks to see if the current metadata is an alias of another. This happens when the user has the tag in aliases but it’s not complex.


Returns:

  • (Boolean)


369
370
371
# File 'lib/docker/template/metadata.rb', line 369

def alias?
  !!(aliased_tag && aliased_tag != tag)
end

#aliased_group(tag: current_tag) ⇒ Object




408
409
410
411
412
# File 'lib/docker/template/metadata.rb', line 408

def aliased_group(tag: current_tag)
  root_data[:tags][aliased_tag({
    :tag => tag
  })]
end

#aliased_tag(tag: current_tag) ⇒ Object




394
395
396
397
398
399
400
401
402
403
404
# File 'lib/docker/template/metadata.rb', line 394

def aliased_tag(tag: current_tag)
  aliases = root_data[:aliases]
  if aliases.nil? || !aliases.key?(tag)
    tag

  else
    aliases[
      tag
    ]
  end
end

#by_group(group: current_group, query_data: @data) ⇒ Object




332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/docker/template/metadata.rb', line 332

def by_group(group: current_group, query_data: @data)
  if query_data.is_a?(self.class)
    then query_data.by_group({
      :group => group
    })

  elsif !query_data || !query_data.is_a?(Hash)
    return nil

  else
    query_data.fetch("group", {}).fetch(
      group, nil
    )
  end
end

#by_parent_group(tag: current_tag, query_data: @data) ⇒ Object




350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'lib/docker/template/metadata.rb', line 350

def by_parent_group(tag: current_tag, query_data: @data)
  if aliased_tag == current_tag || !complex_alias?
    return nil

  else
    by_group({
      :query_data => query_data,
      :group => aliased_group({
        :tag => tag
      })
    })
  end
end

#by_parent_tag(tag: current_tag, query_data: @data) ⇒ Object




316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/docker/template/metadata.rb', line 316

def by_parent_tag(tag: current_tag, query_data: @data)
  if aliased_tag == current_tag || !complex_alias?
    return nil

  else
    by_tag({
      :query_data => query_data,
      :tag => aliased_tag({
        :tag => tag
      })
    })
  end
end

#by_tag(tag: current_tag, query_data: @data) ⇒ Object




298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/docker/template/metadata.rb', line 298

def by_tag(tag: current_tag, query_data: @data)
  if query_data.is_a?(self.class)
    then query_data.by_tag({
      :tag => tag
    })

  elsif !query_data || !query_data.is_a?(Hash)
    return nil

  else
    query_data.fetch("tag", {}).fetch(
      tag, nil
    )
  end
end

#complex_alias?Boolean


A complex alias happens when the user has an alias but also tries to add extra data, this allows them to use data from all parties. This allows them to reap the benefits of having shared data but sometimes independent data that diverges into it’s own.


Returns:

  • (Boolean)


380
381
382
383
384
385
386
387
388
389
390
# File 'lib/docker/template/metadata.rb', line 380

def complex_alias?
  if !alias?
    return false

  else
    !!root_data.find do |_, v|
      (v.is_a?(self.class) || v.is_a?(Hash)) && queryable?(:query_data => v) \
        && by_tag(:query_data => v)
    end
  end
end

#current_groupObject Also known as: group




532
533
534
535
# File 'lib/docker/template/metadata.rb', line 532

def current_group
  root_data[:tags][current_tag] ||
    "normal"
end

#fallback(group: current_group, tag: current_tag, query_data: @data) ⇒ Object


Fallback, determining which route is the best. Tag > Group > All.




261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/docker/template/metadata.rb', line 261

def fallback(group: current_group, tag: current_tag, query_data: @data)
  if query_data.is_a?(self.class)
    then query_data.fallback({
      :group => group, :tag => tag
    })

  elsif !query_data || !query_data.is_a?(Hash) || query_data.empty?
    return nil

  else
    by_tag(:tag => tag, :query_data => query_data) || \
      by_parent_tag(:tag => tag, :query_data => query_data) || \
      by_group(:group => group, :query_data => query_data) || \
      by_parent_group(:tag => tag, :query_data => query_data) || \
      for_all(:query_data => query_data)
  end
end

#for_all(query_data: @data) ⇒ Object




281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'lib/docker/template/metadata.rb', line 281

def for_all(query_data: @data)
  if query_data.is_a?(self.class)
    then query_data \
      .for_all

  elsif !query_data || !query_data.is_a?(Hash)
    return nil

  else
    query_data.fetch(
      "all", nil
    )
  end
end

#groupsObject


HELPER: Get a list of all the groups.




549
550
551
# File 'lib/docker/template/metadata.rb', line 549

def groups
  root_data["tags"].values.uniq
end

#include?(val) ⇒ Boolean


Check if a part of the hash or a value is inside.


Examples:

metadata.include?(:key => :val) => true|false


metadata.include?(:key) => true|false


Parameters:

  • val (Anytning(), Hash)
    • The key or key => val you wish check.

Returns:

  • (Boolean)


123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/docker/template/metadata.rb', line 123

def include?(val)
  if val.is_a?(Hash)
    then val.stringify.each do |k, v|
      unless @data.key?(k) && @data[k] == v
        return false
      end
    end

    true
  else
    @data.include?(
      val
    )
  end
end

#merge(new_) ⇒ Object Also known as: deep_merge


Merge a hash into the metadata. If you merge non-queryable data it will then get merged into the queryable data.




207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/docker/template/metadata.rb', line 207

def merge(new_)
  if !queryable?(:query_data => new_) && queryable?
    new_ = {
      :all => new_
    }
  end

  new_ = new_.stringify
  self.class.new(@data.deep_merge(new_), {
    :root => root_data
  })
end

#merge!(new_) ⇒ Object


Destructive merging (@see self#merge)




224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/docker/template/metadata.rb', line 224

def merge!(new_)
  if !queryable?(:query_data => new_) && queryable?
    new_ = {
      :all => new_
    }
  end

  @data = @data.deep_merge(
    new_.stringify
  )

  self
end

#mergeable_array?(key = nil) ⇒ Boolean


Returns:

  • (Boolean)


512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
# File 'lib/docker/template/metadata.rb', line 512

def mergeable_array?(key = nil)
  return false unless queryable?
  vals = [by_parent_tag, by_parent_group, \
    by_tag, for_all, by_group].compact

  if key
    vals = vals.map do |val|
      val[key]
    end
  end

  !vals.empty? && !vals.any? do |val|
    !val.is_a?(
      Array
    )
  end
end

#mergeable_hash?(key = nil) ⇒ Boolean


Returns:

  • (Boolean)


492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
# File 'lib/docker/template/metadata.rb', line 492

def mergeable_hash?(key = nil)
  return false unless queryable?
  vals = [by_parent_tag, by_parent_group, \
    by_tag, for_all, by_group].compact

  if key
    vals = vals.map do |val|
      val[key]
    end
  end

  !vals.empty? && !vals.any? do |val|
    !val.is_a?(Hash) && !val.is_a?(
      self.class
    )
  end
end

#queryable?(query_data: @data) ⇒ Boolean


Check if a hash is queryable. AKA has “all”, “group”, “tag”.


Returns:

  • (Boolean)


242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/docker/template/metadata.rb', line 242

def queryable?(query_data: @data)
  if query_data.is_a?(self.class)
    then query_data \
      .queryable?

  elsif !query_data || !query_data.is_a?(Hash) || query_data.empty?
    return false

  else
    (query_data.keys - %w(
      group tag all
    )).empty?
  end
end

#rootObject




110
111
112
113
114
# File 'lib/docker/template/metadata.rb', line 110

def root
  Template.root.join(
    root_data[:repos_dir], root_data[:name]
  )
end

#root_dataObject




104
105
106
# File 'lib/docker/template/metadata.rb', line 104

def root_data
  return @root_data || @data
end

#tagsObject


HELPER: Get a list of all the tags.




541
542
543
# File 'lib/docker/template/metadata.rb', line 541

def tags
  (root_data[:tags] || {}).keys | (root_data[:aliases] || {}).keys
end

#to_a(raw: false, shell: false) ⇒ Object




435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
# File 'lib/docker/template/metadata.rb', line 435

def to_a(raw: false, shell: false)
  if raw
    return to_h({
      :raw => true
    }).to_a

  elsif !mergeable_array?
    to_h.each_with_object([]) do |(k, v), a|
      a << "#{k}=#{
        shell ? v.to_s.shellescape : v
      }"
    end
  else
    (for_all || []) | (by_parent_group || []) | (by_group || []) | \
      (by_parent_tag || []) | (by_tag || [])
  end
end

#to_enumObject




190
191
192
193
194
195
196
197
198
199
200
# File 'lib/docker/template/metadata.rb', line 190

def to_enum
  @data.each_with_object({}) do |(k, v), h|
    if v.is_a?(Hash)
      then v = self.class.new(v, {
        :root => root_data
      })
    end

    h[k] = v
  end.to_enum
end

#to_h(raw: false) ⇒ Object


Convert a ‘Metadata’ into a normal hash. If ‘self’ is queryable then we go and start merging values smartly. This means that we will merge all the arrays into one another and we will merge hashes into hashes.




459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
# File 'lib/docker/template/metadata.rb', line 459

def to_h(raw: false)
  return @data.to_h if raw || !queryable? || !mergeable_hash?
  keys = [for_all, by_group, by_parent_group, by_tag, \
    by_parent_tag].compact.map(&:keys)

  keys.reduce(:+).each_with_object({}) do |k, h|
    vals = [for_all, by_group, by_parent_group, by_tag, \
      by_parent_tag].compact

    h[k] = \
      if mergeable_array?(k)
        vals.map { |v| v[k].to_a } \
          .compact.reduce(
            :+
          )

      elsif mergeable_hash?(k)
        vals.map { |v| v[k].to_h } \
          .compact.reduce(
            :deep_merge
          )

      else
        vals.find do |v|
          v[k]
        end \
        [k]
      end
  end
end

#to_s(raw: false, shell: false) ⇒ Object


Converts the current meta into a string.




418
419
420
421
422
423
424
425
426
427
428
429
430
431
# File 'lib/docker/template/metadata.rb', line 418

def to_s(raw: false, shell: false)
  if !raw && (mergeable_hash? || mergeable_array?)
    to_a(:shell => shell).join(" #{
      "\n" if shell
    }")

  elsif !raw && queryable?
    then fallback \
      .to_s

  else
    @data.to_s
  end
end

#update(hash) ⇒ Object




182
183
184
185
186
# File 'lib/docker/template/metadata.rb', line 182

def update(hash)
  @data.update(
    hash.stringify
  )
end