Class: Cisco::Yang
- Inherits:
-
Object
- Object
- Cisco::Yang
- Defined in:
- lib/cisco_node_utils/yang.rb
Overview
class Cisco::Yang Utility class mainly containing methods to compare YANG configurations in order to determine if the running config is in-sync with the desired config.
Class Method Summary collapse
- .array_equiv?(op, should, is) ⇒ Boolean
-
.empty?(yang) ⇒ Boolean
Is the specified yang string empty?.
- .hash_equiv?(op, should, is) ⇒ Boolean
-
.insync_for_merge?(should, is) ⇒ Boolean
Given target and current YANG configurations, returns true if the configurations are in-sync, relative to a “merge_config” action.
-
.insync_for_replace?(should, is) ⇒ Boolean
Given a is and should YANG configuration, returns true if the configuration are in-sync, relative to a “replace_config” action.
-
.needs_something?(op, should, is) ⇒ Boolean
usage: needs_something?(op, should, run).
- .nil_array(elt) ⇒ Object
- .sub_elt(op, should, is) ⇒ Object
Class Method Details
.array_equiv?(op, should, is) ⇒ Boolean
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/cisco_node_utils/yang.rb', line 112 def self.array_equiv?(op, should, is) n = should.length loop = lambda do|i| if i == n if op == :replace is.length == should.length else true end else should_elt = should[i] is_elt = is.find do |elt| sub_elt(op, should_elt, elt) end if is_elt.nil? && !nil_array(should_elt) should_elt.nil? else loop.call(i + 1) end end end loop.call(0) end |
.empty?(yang) ⇒ Boolean
Is the specified yang string empty?
26 27 28 |
# File 'lib/cisco_node_utils/yang.rb', line 26 def self.empty?(yang) !yang || yang.empty? end |
.hash_equiv?(op, should, is) ⇒ Boolean
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/cisco_node_utils/yang.rb', line 136 def self.hash_equiv?(op, should, is) keys = should.keys n = keys.length loop = lambda do|i| if i == n if op == :replace is.keys.length == should.keys.length else true end else k = keys[i] is_v = is[k] should_v = should[k] if is_v.nil? && !nil_array(should_v) false else sub_elt(op, should_v, is_v) && loop.call(i + 1) end end end loop.call(0) end |
.insync_for_merge?(should, is) ⇒ Boolean
Given target and current YANG configurations, returns true if the configurations are in-sync, relative to a “merge_config” action
34 35 36 37 38 39 |
# File 'lib/cisco_node_utils/yang.rb', line 34 def self.insync_for_merge?(should, is) should_hash = self.empty?(should) ? {} : JSON.parse(should) is_hash = self.empty?(is) ? {} : JSON.parse(is) !needs_something?(:merge, should_hash, is_hash) end |
.insync_for_replace?(should, is) ⇒ Boolean
Given a is and should YANG configuration, returns true if the configuration are in-sync, relative to a “replace_config” action
45 46 47 48 49 50 |
# File 'lib/cisco_node_utils/yang.rb', line 45 def self.insync_for_replace?(should, is) should_hash = self.empty?(should) ? {} : JSON.parse(should) is_hash = self.empty?(is) ? {} : JSON.parse(is) !needs_something?(:replace, should_hash, is_hash) end |
.needs_something?(op, should, is) ⇒ Boolean
usage:
needs_something?(op, should, 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
should - JSON - JSON tree representing target configuration
is - JSON - JSON tree representing current configuration
Needs merge will determine if should and is differ sufficiently to necessitate running the merge command.
The logic here amounts to determining if should is a subtree of is, 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 target configuration. 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 should, and ensuring it is within is.
Leaves are directly compared for equality, excepting the condition that the should leaf is in fact an array with one element that is nil.
Needs replace will determine if should and is differ sufficiently to necessitate running the replace command.
The logic is the same as merge, except when comparing hashes, if the is hash table has elements that are not in should, we ultimately indicate that replace is needed
94 95 96 |
# File 'lib/cisco_node_utils/yang.rb', line 94 def self.needs_something?(op, should, is) !hash_equiv?(op, should, is) end |
.nil_array(elt) ⇒ Object
98 99 100 |
# File 'lib/cisco_node_utils/yang.rb', line 98 def self.nil_array(elt) elt.nil? || (elt.is_a?(Array) && elt.length == 1 && elt[0].nil?) end |
.sub_elt(op, should, is) ⇒ Object
102 103 104 105 106 107 108 109 110 |
# File 'lib/cisco_node_utils/yang.rb', line 102 def self.sub_elt(op, should, is) if should.is_a?(Hash) && is.is_a?(Hash) return self.hash_equiv?(op, should, is) elsif should.is_a?(Array) && is.is_a?(Array) return self.array_equiv?(op, should, is) else return !(should != is && !nil_array(should)) end end |