shopify-junos-ez-stdlib 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +91 -0
  3. data/LICENSE +26 -0
  4. data/README.md +199 -0
  5. data/docs/Facts.md +192 -0
  6. data/docs/Providers/Group.md +61 -0
  7. data/docs/Providers/IPports.md +61 -0
  8. data/docs/Providers/L1ports.md +29 -0
  9. data/docs/Providers/L2ports.md +43 -0
  10. data/docs/Providers/LAGports.md +57 -0
  11. data/docs/Providers/StaticHosts.md +26 -0
  12. data/docs/Providers/StaticRoutes.md +37 -0
  13. data/docs/Providers/UserAuths.md +32 -0
  14. data/docs/Providers/Users.md +122 -0
  15. data/docs/Providers/Vlans.md +43 -0
  16. data/docs/Providers_Resources.md +353 -0
  17. data/docs/README_FIRST.md +27 -0
  18. data/docs/Utils/Config.md +160 -0
  19. data/docs/Utils/Filesystem.md +360 -0
  20. data/docs/Utils/Routing-Engine.md +379 -0
  21. data/docs/Utils/SCP.md +24 -0
  22. data/examples/config/config_file.rb +72 -0
  23. data/examples/config/config_template_object.rb +81 -0
  24. data/examples/config/config_template_simple.rb +76 -0
  25. data/examples/config/multi_config.rb +60 -0
  26. data/examples/fs_utils.rb +31 -0
  27. data/examples/lag_port.rb +27 -0
  28. data/examples/re_upgrade.rb +99 -0
  29. data/examples/re_utils.rb +33 -0
  30. data/examples/simple.rb +46 -0
  31. data/examples/st_hosts.rb +33 -0
  32. data/examples/user.rb +32 -0
  33. data/examples/vlans.rb +31 -0
  34. data/junos-ez-stdlib.gemspec +15 -0
  35. data/lib/junos-ez/exceptions.rb +3 -0
  36. data/lib/junos-ez/facts.rb +83 -0
  37. data/lib/junos-ez/facts/chassis.rb +51 -0
  38. data/lib/junos-ez/facts/ifd_style.rb +17 -0
  39. data/lib/junos-ez/facts/personality.rb +25 -0
  40. data/lib/junos-ez/facts/switch_style.rb +31 -0
  41. data/lib/junos-ez/facts/version.rb +58 -0
  42. data/lib/junos-ez/group.rb +206 -0
  43. data/lib/junos-ez/ip_ports.rb +30 -0
  44. data/lib/junos-ez/ip_ports/classic.rb +188 -0
  45. data/lib/junos-ez/l1_ports.rb +121 -0
  46. data/lib/junos-ez/l1_ports/classic.rb +87 -0
  47. data/lib/junos-ez/l1_ports/switch.rb +134 -0
  48. data/lib/junos-ez/l2_ports.rb +66 -0
  49. data/lib/junos-ez/l2_ports/bridge_domain.rb +499 -0
  50. data/lib/junos-ez/l2_ports/vlan.rb +433 -0
  51. data/lib/junos-ez/l2_ports/vlan_l2ng.rb +502 -0
  52. data/lib/junos-ez/lag_ports.rb +268 -0
  53. data/lib/junos-ez/provider.rb +619 -0
  54. data/lib/junos-ez/stdlib.rb +18 -0
  55. data/lib/junos-ez/system.rb +48 -0
  56. data/lib/junos-ez/system/st_hosts.rb +92 -0
  57. data/lib/junos-ez/system/st_routes.rb +159 -0
  58. data/lib/junos-ez/system/syscfg.rb +103 -0
  59. data/lib/junos-ez/system/userauths.rb +84 -0
  60. data/lib/junos-ez/system/users.rb +217 -0
  61. data/lib/junos-ez/utils/config.rb +236 -0
  62. data/lib/junos-ez/utils/fs.rb +385 -0
  63. data/lib/junos-ez/utils/re.rb +558 -0
  64. data/lib/junos-ez/version.rb +6 -0
  65. data/lib/junos-ez/vlans.rb +38 -0
  66. data/lib/junos-ez/vlans/bridge_domain.rb +89 -0
  67. data/lib/junos-ez/vlans/vlan.rb +119 -0
  68. data/lib/junos-ez/vlans/vlan_l2ng.rb +126 -0
  69. data/shipit.yml +4 -0
  70. data/tmp +7 -0
  71. metadata +129 -0
@@ -0,0 +1,43 @@
1
+ # Junos::Ez::Vlans::Provider
2
+
3
+ Manages Ethernet VLANs.
4
+
5
+ If you are looking for associating ethernet-ports to VLANs, please refer to the `Junos::Ez::L2ports::Provider` documentation.
6
+
7
+ # USAGE
8
+
9
+ The provider *name* selector is the vlan-name, String.
10
+
11
+ ```ruby
12
+ Junos::Ez::Vlans::Provider( ndev, :vlans )
13
+
14
+ vlan = ndev.vlans["Blue"]
15
+
16
+ puts "VLAN: #{vlan.name} does not exists!" unless vlan.exists?
17
+ ```
18
+
19
+ # PROPERTIES
20
+
21
+ - `:vlan_id` - The VLAN tag-id, Fixnum [ 1 .. 4094]
22
+ - `:description` - String description for this VLAN
23
+ - `:no_mac_learning` - [`:enable`, `:disable`]. If `:enable` this VLAN will not learn MAC addresses
24
+
25
+ # RESOURCE METHODS
26
+
27
+ ## interfaces
28
+
29
+ This method will return a Hash structure of interfaces bound to this VLAN.
30
+ ```ruby
31
+ ndev.vlans["Green"].interfaces
32
+ ->
33
+ {"ge-0/0/22"=>{:mode=>:trunk},
34
+ "ge-0/0/0"=>{:mode=>:trunk, :native=>true},
35
+ "ge-0/0/1"=>{:mode=>:trunk, :native=>true},
36
+ "ge-0/0/2"=>{:mode=>:trunk, :native=>true},
37
+ "ge-0/0/3"=>{:mode=>:trunk, :native=>true},
38
+ "ge-0/0/5"=>{:mode=>:trunk, :native=>true},
39
+ "ge-0/0/6"=>{:mode=>:trunk, :native=>true},
40
+ "ge-0/0/7"=>{:mode=>:trunk, :native=>true},
41
+ "ge-0/0/20"=>{:mode=>:access},
42
+ "ge-0/0/21"=>{:mode=>:access}}
43
+ ```
@@ -0,0 +1,353 @@
1
+ # RESOURCES
2
+
3
+ Let's start with Resources before we get to Providers. Resources are generally where all "the action" happens.
4
+ The primary purpose of a resource is to allow you to make configuration changes without having to know
5
+ the underlying Junos XML configuration. When you have a resource, you can always get a list of the properties
6
+ available to you.
7
+
8
+ Here's an example of looking at a an ethernet switching port using the L2ports provider.
9
+ This is just a snippet of code, and they use the (->) notation to indicate standard output results.
10
+
11
+ For the following example assume that `l2_ports` is the provider assigned to the `ndev` object. The `ndev` object is of class `Netconf::SSH` (or has this as a parent class)
12
+
13
+ ```ruby
14
+
15
+ # select a port by name from the provider
16
+
17
+ port = ndev.l2_ports['ge-0/0/0']
18
+
19
+ # check to see if this actually exists in the config
20
+
21
+ unless port.exists?
22
+ puts "This port #{port.name} does not exist!"
23
+ exit 1
24
+ end
25
+
26
+ # now pretty-print the properties associated with this resource (which would be the same list for
27
+ # any L2port resource
28
+
29
+ pp port.properties
30
+ ->
31
+ [:_exist, :_active, :description, :untagged_vlan, :tagged_vlans, :vlan_tagging]
32
+
33
+ # now look at the specific values for this resource by pp the assocaite hash
34
+
35
+ pp port.to_h
36
+ ->
37
+ {"ge-0/0/0"=>
38
+ {:_active=>true,
39
+ :_exist=>true,
40
+ :vlan_tagging=>true,
41
+ :tagged_vlans=>["Red", "Green", "Blue"],
42
+ :untagged_vlan=>nil}}
43
+ ```
44
+
45
+ ## Resource Methods
46
+
47
+ - `read!` - reads the contents into the resource read-hash (@has)
48
+ - `write!` - writes the contents from the resource write-hash (@should) to the device
49
+ - `delete!` - delete the resource from the configuration
50
+ - `activate!` - activates the configuration for this resource
51
+ - `deactivate!` - deactivates the configuration for this resource
52
+ - `rename!` - renames the resource in the configuration
53
+ - `reorder!` - reorders (Junos `insert`) the resource in the configuration
54
+ - `exists?` - indicates if this resource exists in the configuration
55
+ - `active?` - indicates if this resource is active in the configuration
56
+ - `to_h` - return the read-from and write-to hash values
57
+
58
+ ## Instance Variables
59
+
60
+ Each resource include a hash structure containing the values read-from the device. This is
61
+ the `@has` variable. When modifying properties, the changed values are stored in the
62
+ write-to hash `@should` variable. These instance variable are made accessible, but you
63
+ should not access them directly. See next section for changing the property values.
64
+
65
+ ## Reading Properties
66
+
67
+ You can obtain the entire `@has` property hash has using the `to_h` method. This example selects the "ge-0/0/0" physical port and dumps the property hash:
68
+
69
+ ```ruby
70
+ port = ndev.l1_ports["ge-0/0/1"]
71
+
72
+ pp port.to_h
73
+ ->
74
+ {"ge-0/0/1"=>
75
+ {:_active=>true,
76
+ :_exist=>true,
77
+ :admin=>:up,
78
+ :duplex=>:auto,
79
+ :speed=>:auto,
80
+ :unit_count=>26}}
81
+
82
+ ```
83
+
84
+ You can also obtain just a specific property using the `[]` operator:
85
+
86
+ ```ruby
87
+ pp port[:admin]
88
+ ->
89
+ :up
90
+ ```
91
+
92
+ ## Modifying Properties
93
+
94
+ Modifying the resource property is simply making use of the `[]=` operator. For example,
95
+ setting the `:untagged_vlan` to "Black" and writing that back to the device would
96
+ look something like this:
97
+
98
+ ```ruby
99
+ port[:untagged_vlan] = "Black"
100
+ port.write!
101
+ ```
102
+
103
+ You can also obtain the `@should` property hash using the `to_h` method and providing the optional `:write` argument:
104
+
105
+ ```ruby
106
+ port[:admin] = :down
107
+
108
+ pp port.to_h( :write )
109
+ ->
110
+ {"ge-0/0/1"=>{:admin=>:down}}
111
+ ```
112
+
113
+ _NOTE: The `@should` property hash only contains the changes that will be applied, not every property value._
114
+
115
+ When you execute the `write!` method, the framework will examine the contents of
116
+ the `@should` hash to determine what changes need to be made. On success the
117
+ values are then transfered into the `@has` hash.
118
+
119
+ If you're going to make changes to an array property, you would need to do something like this:
120
+
121
+ ```ruby
122
+ port[:tagged_vlans] += ["Purple"]
123
+ port[:tagged_vlans] -= ["Red", "Green"]
124
+ port.write!
125
+ ```
126
+
127
+ _NOTE: for Array values, do not use array methods like `delete` as they will operate
128
+ on the `@has` hash._
129
+
130
+ ## Special Properties
131
+
132
+ All resources include two special properties `_exist` and `_active`. These control whether or
133
+ not a resource exists (or should) and whether or not the resource is active (or deactive).
134
+ Generally speaking you should not modify these properties directly. Rather you should use the
135
+ `delete!` method to remove the resource and the `activate!` and `deactivate!` methods respectively.
136
+ That being said, if you have a Hash/YAML dataset that explicity has `:_exist => false` when that
137
+ resource is applied to the device, the resource is deleted. This is handy to ensure a specific
138
+ resource does not exist, for example.
139
+
140
+ # PROVIDERS
141
+
142
+ Providers enable access to, and information about resources. So how to you bind a provider to a
143
+ Netconf::SSH (netconf) object? This is done by the provider's `Provider` method. There are
144
+ two techniques for *bindng* a provider to a netconf object.
145
+
146
+ One method is to bind the provider after the call to `Netconf::SSH#open`. For example, if you want
147
+ to use the L2port provider, you bind it to the netconf object like so:
148
+
149
+ ```ruby
150
+
151
+ # creating a netconf object, here login is a hash defining login info
152
+
153
+ ndev = Netconf::SSH.new( login )
154
+
155
+ # connect to the target
156
+
157
+ ndev.open
158
+
159
+ # bind providers to this object
160
+
161
+ Junos::Ez::Provider( ndev )
162
+ Junos::Ez::L2ports::Provider( ndev, :l2_ports )
163
+ ```
164
+
165
+ But let's say that you want to create multiple `Netconf::SSH` objects and you don't want to
166
+ programmatically do the binding each time? You can define a new class inheriting `Netconf::SSH` and
167
+ overload the `open` method, for example:
168
+
169
+ ```ruby
170
+ class MyJunosSwitch < Netconf::SSH
171
+ def open
172
+ # must be first to open the connection to the target
173
+ super
174
+
175
+ # bind init provider, this will retrieve facts
176
+ Junos::Ez::Provider( self )
177
+
178
+ # bind other providers you want this object to have
179
+ Junos::Ez::L2ports::Provider( self, :l2_ports )
180
+ Junos::Ez::Vlans::Provider( self, :vlans )
181
+ end
182
+ end
183
+
184
+ # now open a few devices ...
185
+
186
+ dev1 = MyJunosSwitch.new( login )
187
+ dev2 = MyJunosSwitch.new( login )
188
+
189
+ dev1.open
190
+ dev2.open
191
+
192
+ pp dev1.vlans.list
193
+ pp dev2.vlans.list
194
+
195
+ dev1.close
196
+ dev2.close
197
+ ```
198
+
199
+ There are a few things to note on these example:
200
+
201
+ 1. This framework is built around the NETCONF gem as all of the underlying code access the Junos XML
202
+ API via the NETCONF protocol
203
+
204
+ 2. You **MUST** use the `Junos::Ez::Provider` before any other providers as this sets up the `Netconf::SSH`
205
+ object for future bindings and reads the `facts` from the target. These facts can then be
206
+ used by other provider libraries to abstract target specific differences
207
+
208
+ 3. **You** get to chose the provider instance variable name (in this case `l2_ports`, there are is no
209
+ hard-coding going on in this framework, yo! (except for the `facts` variable)
210
+
211
+ ## Listing Providers
212
+
213
+ When you bind providers to a netconf object, you can always get a list of what exists:
214
+
215
+ ```ruby
216
+ pp ndev.providers
217
+ ->
218
+ [:l1_ports, :ip_ports, :l2_ports]
219
+ ```
220
+
221
+ ## Resource List
222
+
223
+ You can obtain a list of managed resources using the `list` or `list!` method. This method
224
+ will return an Array of names. Again these names could be simple strings or complex values.
225
+ The `list!` method causes the framework to re-read from the device. The `list` method uses the cached value.
226
+ If there is no-cached value, the framework will read from the device, so you don't need to explicity
227
+ use `list!` unless you need to force the cache update.
228
+
229
+ ```ruby
230
+ pp ndev.l2_ports.list
231
+ ->
232
+ ["fe-0/0/2", "fe-0/0/3", "fe-0/0/6"]
233
+ ```
234
+
235
+ ## Resource Catalog
236
+
237
+ You can also obtain the provider's catalog, which is a Hash of resources keyed by name and
238
+ each value is the Hash of the associated properties. The `catalog` and `catalog!` methods
239
+ work the same as described in the list section above.
240
+
241
+ ```ruby
242
+ pp ndev.l2_ports.catalog
243
+ ->
244
+ {"fe-0/0/2"=>
245
+ {:_active=>true,
246
+ :_exist=>true,
247
+ :vlan_tagging=>true,
248
+ :tagged_vlans=>["Red", "Green", "Blue"]},
249
+ "fe-0/0/3"=>{:_active=>true, :_exist=>true, :vlan_tagging=>false},
250
+ "fe-0/0/6"=>
251
+ {:_active=>true,
252
+ :_exist=>true,
253
+ :vlan_tagging=>false,
254
+ :untagged_vlan=>"Blue"}}
255
+ ```
256
+
257
+ ## Selecting a Resource from a Provider
258
+
259
+ You select a resource from a provider using the `[]` operator and identifying the resource by *name*. The
260
+ name could be a simple string as shown in the previous example, or could be a complex name
261
+ like an Array. If you take a look a the SRX library (separate repo), you can see that
262
+ the `Junos::Ez::SRX::Policies::Provider` name is an Array of [ from_zone_name, to_zone_name ].
263
+
264
+ Here is an example of selecting an ethernet switching port, "ge-0/0/0":
265
+
266
+ ```ruby
267
+ port = ndev.l2_ports['ge-0/0/0']
268
+ ```
269
+
270
+ When a resource is selected, the framework will automatically `read!` retrieve the configuration.
271
+
272
+ ## Creating a new Resource
273
+
274
+ There are two ways to create a resource. One is using the `create` or `create!` methods.
275
+ The `create` method is used to create the new resource but not write it do the device. The
276
+ `create!` method does both the creation and the write to the device. The `create` method
277
+ can also be given a block, so you can setup the contents of the new resource. Here's an
278
+ example that creates some config and then deactivates it.
279
+
280
+ ```ruby
281
+ ndev.l2_ports.create('ge-0/0/20') do |port|
282
+ port[:description] = "I am port 20"
283
+ port[:untagged_vlan] = "Blue"
284
+ port.write!
285
+ port.deactivate!
286
+ end
287
+ ```
288
+ The above example will also return the new resource object. So you could use the Ruby
289
+ block as a default initializer, and then continue to make changes to the resource.
290
+
291
+ The `create` method takes an optional 2nd argument, a Hash of the resource properties. So you could do the following equivalent:
292
+
293
+ ```ruby
294
+ data = {:description => "I am port 20", :untagged_vlan => "Blue" }
295
+
296
+ ndev.l2_ports.create('ge-0/0/20', data) do |port|
297
+ port.write!
298
+ port.deactivate!
299
+ end
300
+ ```
301
+
302
+ The second way is to simply select a resource by name that doesn't exist. So let's
303
+ say you want to create a new L2port for `ge-0/0/20`. It would look something like this:
304
+
305
+ ```ruby
306
+ port = ndev.l2_ports['ge-0/0/20']
307
+
308
+ puts "I don't exist" unless port.exists?
309
+
310
+ port[:description] = "I am port 20"
311
+ port[:untagged_vlan] = "Storage"
312
+ port.write!
313
+ ```
314
+
315
+ ### Interating Resources
316
+
317
+ You can use the `each` method to iterate through each managed resource, as provided by the `list` provider instance variable. For example:
318
+
319
+ ```ruby
320
+ ndev.l1_ports.each do |port|
321
+ status = port.status
322
+ if (port[:admin] == :up) and (status[:oper_status] != :up)
323
+ puts "Port #{port.name} should be up, and isn't!
324
+ end
325
+ end
326
+ ```
327
+
328
+ You can use the `with` method to iterate through a given list of managed resources. For example:
329
+
330
+ ```ruby
331
+ # dump the status for just these two IP ports ...
332
+
333
+ ip_list = ["ge-0/0/1.719","ge-0/0/1.335"]
334
+
335
+ ndev.ip_ports.with(ip_list) do |ip|
336
+ pp ip.name
337
+ pp ip.status
338
+ end
339
+
340
+ ->
341
+ "ge-0/0/1.719"
342
+ {:l1_oper_status=>:up,
343
+ :oper_status=>:down,
344
+ :snmp_index=>616,
345
+ :packets_rx=>0,
346
+ :packets_tx=>0}
347
+ "ge-0/0/1.335"
348
+ {:l1_oper_status=>:up,
349
+ :oper_status=>:up,
350
+ :snmp_index=>613,
351
+ :packets_rx=>0,
352
+ :packets_tx=>0}
353
+ ```
@@ -0,0 +1,27 @@
1
+ # CODE EXAMPLES
2
+
3
+ Much of the documentation include small code "snippets". These are not complete programs, but rather meant to show specific functionality.
4
+
5
+ The following libraries are assumed to be in scope:
6
+
7
+ - `require 'pp'` : for pretty-printing Ruby objects
8
+ - `require 'pry'` : for setting code break-points
9
+
10
+ These examples use the `->` symbol to indicate screen output. For example:
11
+
12
+ ```ruby
13
+
14
+ port = ndev.l2_ports["ge-0/0/8"]
15
+ pp port.to_h
16
+ ->
17
+ {"ge-0/0/0"=>
18
+ {:_active=>true,
19
+ :_exist=>true,
20
+ :description=>"Jeremy port for testing",
21
+ :vlan_tagging=>true,
22
+ :untagged_vlan=>"Green",
23
+ :tagged_vlans=>["Red"]}}
24
+
25
+ ```
26
+
27
+ Here the Hash structure following the `->` is the output of the prior "pretty-print", `pp port.to_h`, instruction.
@@ -0,0 +1,160 @@
1
+ # `Junos::Ez::Config::Utils`
2
+
3
+ A collection of methods to perform file / template based configuration, and configuration control functions, like "commit", "show | compare", "rollback", etc. These methods return data in Hash / Array structures so the information can be programmatically accessible.
4
+
5
+ # METHODS
6
+
7
+ - [`lock!`](#lock) - attempt exclusive config, returns true or raises Netconf::LockError
8
+ - [`load!`](#load) - loads configuration snippets or templates (ERB)
9
+ - [`diff?`](#diff) - returns String of "show | compare" as String
10
+ - [`commit?`](#commit_check) - checks the candidate config for validation, returns true or Hash of errors
11
+ - [`commit!`](#commit) - performs commit, returns true or raises Netconf::CommitError
12
+ - [`unlock!`](#unlock) - releases exclusive lock on config
13
+ - [`rollback!`](#rollback) - performs rollback of config
14
+ - [`get_config`](#get_config) - returns text-format of configuration
15
+
16
+ # USAGE
17
+
18
+ ```ruby
19
+ # bind :cu to give us access to the config utilities
20
+ Junos::Ez::Config::Utils( ndev, :cu )
21
+
22
+ # load a Junos configuration file on our local filesys
23
+
24
+ ndev.cu.load! :filename => 'basic-setup.conf'
25
+
26
+ # check to see if these changes will commit ok. if not, display the errors, rollback the config,
27
+ # close the netconf session, and exit the program.
28
+
29
+ unless (result = ndev.cu.commit?) == true
30
+ puts "There are commit errors, dumping result ..."
31
+ pp result
32
+ ndev.cu.rollback!
33
+ ndev.close
34
+ exit 1
35
+ end
36
+
37
+ # commit the confguration and close the netconf session
38
+
39
+ ndev.cu.commit!
40
+ ndev.close
41
+ ```
42
+
43
+
44
+
45
+ # GORY DETAILS
46
+
47
+ ## lock! <a name="lock">
48
+ Attempt exclusive config, returns `true` if you now have the lock, or raises `Netconf::LockError` exception if the lock is not available
49
+
50
+ ## load!( opts = {} ) <a name="load">
51
+
52
+ Loads configuration snippets or templates (ERB). This method does **not** commit the change, only loads the contents into the candidate configuration. If the load was successful, this method will return `true`. Otherwise it will raise a `Netconf::EditError` exception.
53
+
54
+ The options Hash enables the following controls:
55
+
56
+ ```
57
+ :filename => String
58
+ ```
59
+ Identifies filename on local-system. File can contain either static config or template in ERB format. The framework will identify the format-style of the content by the filename extension. You can override this behavior using the `:format` option. By default, the framework will map extensions to `:format` as follow:
60
+
61
+ - `:text` when *.{conf,text,txt}
62
+ - `:set` when *.set
63
+ - `:xml` when *.xml
64
+
65
+ ```
66
+ :content => String
67
+ ```
68
+ Ccontent of configuration, rather than loading it from a file. Handy if you are loading the same content on many devices, and you don't want to keep re-reading it from a file
69
+
70
+ ```
71
+ :format => Symbol
72
+ ```
73
+
74
+ Identifies the format-style of the configuration. The default is `:text`. Setting this option will override the `:filename` extension style mapping.
75
+
76
+ `:text` - indcates "text" or "curly-brace" style
77
+
78
+ `:set` - "set" commands, one per line
79
+
80
+ `:xml` - native Junos XML
81
+
82
+ ```
83
+ :binding => Object | Binding
84
+ ```
85
+ Required when the configuration content is a Ruby ERB template. If `:binding` is an Object, then that object becomes the scope of the variables available to the template. If you want to use the *current scope*, then using the `binding` variable that is availble (it is always there)
86
+
87
+ ```
88
+ :overwrite!
89
+ ```
90
+ When `true` the provided configuraiton will **COMPLETELY OVERWRITE** any existing configuration. This is useful when writing an entire configuration from scratch.
91
+
92
+ ```
93
+ :replace!
94
+ ```
95
+ When `true` enables the Junos *replace* option. This is required if your configuration changes utilize either the `replace:` statement in text-format style or the `replace="replace"` attribute in XML-format style. You do not need to set this option if you are using the set-format style.
96
+
97
+ ## diff? <a name="diff">
98
+ Returns String of "show | compare" as String. If there is no diff, then this method returns `nil`.
99
+
100
+ ## commit? <a name="commit_check">
101
+
102
+ Checks the candidate config for validation, returns `true` or Array of errors.
103
+
104
+ The following is an example errors:
105
+ ```ruby
106
+ ndev.cu.commit?
107
+ ->
108
+ [{:severity=>"error",
109
+ :message=>"Referenced filter 'foo' is not defined",
110
+ :edit_path=>"[edit interfaces ge-0/0/8 unit 0 family inet]",
111
+ :bad_identifier=>"filter"},
112
+ {:severity=>"error", :message=>"configuration check-out failed"}]
113
+ ```
114
+
115
+ ## commit!( opts = {} ) <a name="commit">
116
+
117
+ Performs commit, returns `true` or raises `Netconf::CommitError`. Available options are:
118
+
119
+ :comment => String
120
+ A commit log comment that is available when retrieving the commit log.
121
+
122
+ :confirm => Fixnum-Minutes
123
+ Identifies a timeout in minutes to automatically rollback the configuration unless you explicitly issue another commit action. This is very useful if you think your configuration changes may lock you out of the device.
124
+
125
+ ## unlock! <a name="unlock">
126
+
127
+ Releases exclusive lock on config. If you do not posses the lock, this method will raise an `Netconf::RpcError` exception.
128
+
129
+ ## rollback!( rollback_id = 0 ) <a name="rollback">
130
+
131
+ Loads a rollback of config, does not commit.
132
+
133
+ ## get_config( scope = nil ) <a name="get_config">
134
+
135
+ Returns the text-style format of the request config. If `scope` is `nil` then the entire configuration is returned. If the `scope` is invalid (asking for the "foo" stanza for example), then a string with "ERROR!" is returned. If the requested config is non-existant (asking for non-existant interface), then `nil` is returned.
136
+
137
+ Successful request:
138
+ ```ruby
139
+ puts ndev.cu.get_config "interfaces ge-0/0/0"
140
+ ->
141
+ unit 0 {
142
+ family inet {
143
+ address 192.168.56.2/24;
144
+ }
145
+ }
146
+ ```
147
+
148
+ Valid request, but not config:
149
+ ```ruby
150
+ puts ndev.cu.get_config "interfaces ge-0/0/3"
151
+ ->
152
+ nil
153
+ ```
154
+
155
+ Invalid request:
156
+ ```ruby
157
+ puts ndev.cu.get_config "foober jazzbot"
158
+ ->
159
+ ERROR! syntax error: foober
160
+ ```