Class: Cisco::Yang
- Inherits:
-
Object
- Object
- Cisco::Yang
- Defined in:
- lib/util/yang.rb
Overview
The Yang class is a container for the needs_something? logic, which attempts to determine if a given operation and data structures will require setting the configuration of the remote device.
Class Method Summary collapse
- .array_equiv?(op, target, run) ⇒ Boolean
-
.empty?(yang) ⇒ Boolean
Is the specified yang string empty?.
- .hash_equiv?(op, target, run) ⇒ Boolean
-
.insync_for_merge?(target, current) ⇒ Boolean
Given a current and target YANG configuration, returns true if the configurations are in-sync, relative to a “merge_config” action.
-
.insync_for_replace?(target, current) ⇒ Boolean
Given a current and target YANG configuration, returns true if the configuration are in-sync, relative to a “replace_config” action.
-
.needs_something?(op, target, run) ⇒ Boolean
usage: needs_something?(op, target, run).
- .nil_array(elt) ⇒ Object
- .sub_elt(op, target, run) ⇒ Object
Class Method Details
.array_equiv?(op, target, run) ⇒ Boolean
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/util/yang.rb', line 106 def self.array_equiv?(op, target, run) n = target.length # We need to count the number of times that we've had a miss because # the target element was marked delete no_op_delete_count = 0 loop = lambda do |i| if i == n if op == :replace # NB: We could end up with arrays that have only nil in them # sometimes, so correct for that, then normalize for the # number of elements that are no-ops because they are marked # delete rl = run.clone.delete_if(&:nil?).length tl = target.clone.delete_if(&:nil?).length - no_op_delete_count rl == tl else true end else target_elt = target[i] if target_elt.is_a?(Hash) && (target_elt[:delete] == :delete) target_elt = target_elt.clone target_elt.delete(:delete) delete = true end run_elt = run.find { |re| sub_elt(op, target_elt, re) } if run_elt.nil? && !nil_array(target_elt) if delete no_op_delete_count += 1 loop.call(i + 1) else target_elt.nil? end else if delete false else loop.call(i + 1) end end end end loop.call(0) end |
.empty?(yang) ⇒ Boolean
Is the specified yang string empty?
23 24 25 |
# File 'lib/util/yang.rb', line 23 def self.empty?(yang) !yang || yang.empty? end |
.hash_equiv?(op, target, run) ⇒ Boolean
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/util/yang.rb', line 152 def self.hash_equiv?(op, target, run) keys = target.keys n = keys.length loop = lambda do |i| if i == n if op == :replace run.keys.length == target.keys.length else true end else k = keys[i] run_v = run[k] target_v = target[k] if run_v.nil? && !nil_array(target_v) false else sub_elt(op, target_v, run_v) && loop.call(i + 1) end end end loop.call(0) end |
.insync_for_merge?(target, current) ⇒ Boolean
Given a current and target YANG configuration, returns true if the configurations are in-sync, relative to a “merge_config” action
29 30 31 32 33 34 |
# File 'lib/util/yang.rb', line 29 def self.insync_for_merge?(target, current) target_hash = self.empty?(target) ? {} : JSON.parse(target) current_hash = self.empty?(current) ? {} : JSON.parse(current) !needs_something?(:merge, target_hash, current_hash) end |
.insync_for_replace?(target, current) ⇒ Boolean
Given a current and target YANG configuration, returns true if the configuration are in-sync, relative to a “replace_config” action
38 39 40 41 42 43 |
# File 'lib/util/yang.rb', line 38 def self.insync_for_replace?(target, current) target_hash = self.empty?(target) ? {} : JSON.parse(target) current_hash = self.empty?(current) ? {} : JSON.parse(current) !needs_something?(:replace, target_hash, current_hash) end |
.needs_something?(op, target, run) ⇒ Boolean
usage:
needs_something?(op, target, run)
op - symbol - If value is not :replace, it's assumed to be :merge.
Indicates to the function whether to check for a
possible merge vs. replace
target - JSON - JSON tree representing target configuration
run - JSON - JSON tree representing target configuration
Needs merge will determine if target and run differ sufficiently to necessitate running the merge command.
The logic here amounts to determining if target is a subtree of run, with a tiny bit of domain trickiness surrounding elements that are arrays that contain a single nil element that is required for “creating” certain configuration elements.
There are ultimately 3 different types of elements in a json tree. Hashes, Arrays, and leaves. While hashes and array values are organized with an order, the logic here ignores the order. In fact, it specifically attempts to match assuming order doesn’t matter. This is largely to allow users some freedom in specifying the config in the manifest. The gRPC interface doesn’t seem to care about order. If that changes, then so should this code.
Arrays and Hashes are compared by iterating over every element in target, and ensuring it is within run.
Leaves are directly compared for equality, excepting the condition that the target leaf is in fact an array with one element that is nil.
Needs replace will determine if target and run differ sufficiently to necessitate running the replace command.
The logic is the same as merge, except when comparing hashes, if the run hash table has elements that are not in target, we ultimately indicate that replace is needed
87 88 89 |
# File 'lib/util/yang.rb', line 87 def self.needs_something?(op, target, run) !hash_equiv?(op, target, run) end |
.nil_array(elt) ⇒ Object
91 92 93 |
# File 'lib/util/yang.rb', line 91 def self.nil_array(elt) elt.nil? || (elt.is_a?(Array) && elt.length == 1 && elt[0].nil?) end |
.sub_elt(op, target, run) ⇒ Object
95 96 97 98 99 100 101 102 103 104 |
# File 'lib/util/yang.rb', line 95 def self.sub_elt(op, target, run) if target.is_a?(Hash) && run.is_a?(Hash) hash_equiv?(op, target, run) elsif target.is_a?(Array) && run.is_a?(Array) array_equiv?(op, target, run) else delete = target.is_a?(Hash) && (target[:delete] == :delete) delete || target == run || nil_array(target) end end |