Class: LeapCli::Config::ObjectList

Inherits:
Hash show all
Includes:
TSort
Defined in:
lib/leap_cli/config/object_list.rb

Overview

A list of Config::Object instances (internally stored as a hash)

Instance Method Summary collapse

Methods inherited from Hash

#deep_dup, #deep_merge, #deep_merge!, #pick

Constructor Details

#initialize(config = nil) ⇒ ObjectList

Returns a new instance of ObjectList.



11
12
13
14
15
# File 'lib/leap_cli/config/object_list.rb', line 11

def initialize(config=nil)
  if config
    self.add(config['name'], config)
  end
end

Instance Method Details

#[](key) ⇒ Object

If the key is a string, the Config::Object it references is returned.

If the key is a hash, we treat it as a condition and filter all the Config::Objects using the condition. A new ObjectList is returned.

Examples:

nodes

node named 'vpn1'

nodes[:public_dns => true]

all nodes with public dns

nodes[:services => ‘openvpn’, ‘location.country_code’ => ‘US’]

all nodes with services containing 'openvpn' OR country code of US

Sometimes, you want to do an OR condition with multiple conditions for the same field. Since hash keys must be unique, you can use an array representation instead:

nodes[[:services, ‘openvpn’], [:services, ‘tor’]]

nodes with openvpn OR tor service

nodes[:services => ‘openvpn’][:tags => ‘production’]

nodes with openvpn AND are production


44
45
46
47
48
49
50
# File 'lib/leap_cli/config/object_list.rb', line 44

def [](key)
  if key.is_a?(Hash) || key.is_a?(Array)
    filter(key)
  else
    super key.to_s
  end
end

#add(name, object) ⇒ Object



99
100
101
# File 'lib/leap_cli/config/object_list.rb', line 99

def add(name, object)
  self[name] = object
end

#each_node(&block) ⇒ Object



58
59
60
61
62
# File 'lib/leap_cli/config/object_list.rb', line 58

def each_node(&block)
  self.keys.sort.each do |node_name|
    yield self[node_name]
  end
end

#exclude(node) ⇒ Object



52
53
54
55
56
# File 'lib/leap_cli/config/object_list.rb', line 52

def exclude(node)
  list = self.dup
  list.delete(node.name)
  return list
end

#field(field) ⇒ Object

like fields(), but returns an array of values instead of an array of hashes.



117
118
119
120
121
122
123
124
# File 'lib/leap_cli/config/object_list.rb', line 117

def field(field)
  field = field.to_s
  result = []
  keys.sort.each do |name|
    result << self[name].get(field)
  end
  result
end

#fields(*fields) ⇒ Object

converts the hash of configs into an array of hashes, with ONLY the specified fields



106
107
108
109
110
111
112
# File 'lib/leap_cli/config/object_list.rb', line 106

def fields(*fields)
  result = []
  keys.sort.each do |name|
    result << self[name].pick(*fields)
  end
  result
end

#filter(filter) ⇒ Object

filters this object list, producing a new list. filter is an array or a hash. see []



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/leap_cli/config/object_list.rb', line 68

def filter(filter)
  results = Config::ObjectList.new
  filter.each do |field, match_value|
    field = field.is_a?(Symbol) ? field.to_s : field
    match_value = match_value.is_a?(Symbol) ? match_value.to_s : match_value
    if match_value.is_a?(String) && match_value =~ /^!/
      operator = :not_equal
      match_value = match_value.sub(/^!/, '')
    else
      operator = :equal
    end
    each do |name, config|
      value = config[field]
      if value.is_a? Array
        if operator == :equal && value.include?(match_value)
          results[name] = config
        elsif operator == :not_equal && !value.include?(match_value)
          results[name] = config
        end
      else
        if operator == :equal && value == match_value
          results[name] = config
        elsif operator == :not_equal && value != match_value
          results[name] = config
        end
      end
    end
  end
  results
end

#inherit_from!(object_list) ⇒ Object

applies inherit_from! to all objects.



172
173
174
175
176
177
178
179
180
# File 'lib/leap_cli/config/object_list.rb', line 172

def inherit_from!(object_list)
  object_list.each do |name, object|
    if self[name]
      self[name].inherit_from!(object)
    else
      self[name] = object.deep_dup
    end
  end
end

#names_in_test_dependency_orderObject



200
201
202
# File 'lib/leap_cli/config/object_list.rb', line 200

def names_in_test_dependency_order
  self.tsort
end

#pick_fields(*fields) ⇒ Object

pick_fields(field1, field2, …)

generates a Hash from the object list, but with only the fields that are picked.

If there are more than one field, then the result is a Hash of Hashes. If there is just one field, it is a simple map to the value.

For example:

"neighbors" = "= nodes_like_me[:services => :couchdb].pick_fields('domain.full', 'ip_address')"

generates this:

neighbors:
  couch1:
    domain_full: couch1.bitmask.net
    ip_address: "10.5.5.44"
  couch2:
    domain_full: couch2.bitmask.net
    ip_address: "10.5.5.52"

But this:

"neighbors": "= nodes_like_me[:services => :couchdb].pick_fields('domain.full')"

will generate this:

neighbors:
  couch1: couch1.bitmask.net
  couch2: couch2.bitmask.net


158
159
160
161
162
163
164
165
166
167
# File 'lib/leap_cli/config/object_list.rb', line 158

def pick_fields(*fields)
  self.values.inject({}) do |hsh, node|
    value = self[node.name].pick(*fields)
    if fields.size == 1
      value = value.values.first
    end
    hsh[node.name] = value
    hsh
  end
end

#tsort_each_child(node_name, &block) ⇒ Object



189
190
191
192
193
194
195
196
197
198
# File 'lib/leap_cli/config/object_list.rb', line 189

def tsort_each_child(node_name, &block)
  if self[node_name]
    self[node_name].test_dependencies.each do |test_me_first|
      if self[test_me_first] # TODO: in the future, allow for ability to optionally pull in all dependencies.
                             # not just the ones that pass the node filter.
        yield(test_me_first)
      end
    end
  end
end

#tsort_each_node(&block) ⇒ Object

topographical sort based on test dependency



185
186
187
# File 'lib/leap_cli/config/object_list.rb', line 185

def tsort_each_node(&block)
  self.each_key(&block)
end