cisco_node_utils 0.9.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,78 @@
1
+ # Maintainers Guide
2
+
3
+ Guidelines for the core maintainers of the cisco-network-node-utils project - above and beyond the [general developer guidelines](https://github.com/cisco/cisco-network-node-utils/blob/master/CONTRIBUTING.md).
4
+
5
+ ## Accepting Pull Requests
6
+
7
+ * Is the pull request correctly submitted against `develop`?
8
+ * Does `rubocop` pass? (TODO - this will be part of our CI integration to run automatically)
9
+ * Is `CHANGELOG.md` updated appropriately?
10
+ * Are new minitests added? Do they provide sufficient coverage and consistent results?
11
+ * Do minitests pass on both N9K and N3K?
12
+
13
+ ## Setting up git-flow
14
+
15
+ If you don't already have [`git-flow`](https://github.com/petervanderdoes/gitflow/) installed, install it.
16
+
17
+ Either run `git flow init` from the repository root directory, or manually edit your `.git/config` file. Either way, when done, you should have the following in your config:
18
+
19
+ ```ini
20
+ [gitflow "branch"]
21
+ master = master
22
+ develop = develop
23
+ [gitflow "prefix"]
24
+ feature = feature/
25
+ release = release/
26
+ hotfix = hotfix/
27
+ support = support/
28
+ versiontag = v
29
+ ```
30
+
31
+ Most of these are default for git-flow except for the `versiontag` setting.
32
+
33
+ ## Release Process
34
+
35
+ When we agree as a team that a new release should be published, the process is as follows:
36
+
37
+ 1. Create a release branch. Follow [semantic versioning](http://semver.org) - a bugfix release is a 0.0.x version bump, a new feature is a 0.x.0 bump, and a backward-incompatible change is a new x.0.0 version.
38
+
39
+ ```
40
+ git flow release start 1.0.1
41
+ ```
42
+
43
+ 2. In the newly created release branch, update `CHANGELOG.md`:
44
+
45
+ ```diff
46
+ Changelog
47
+ =========
48
+
49
+ -(unreleased)
50
+ -------------
51
+ +1.0.1
52
+ +-----
53
+ ```
54
+
55
+ and also update `version.rb`:
56
+
57
+ ```diff
58
+ - VERSION = '1.0.0'
59
+ + VERSION = '1.0.1'
60
+ ```
61
+
62
+ 3. Finish the release and push it to GitHub:
63
+
64
+ ```
65
+ git flow release finish 1.0.1
66
+ git push origin master
67
+ git push origin develop
68
+ git push --tags
69
+ ```
70
+
71
+ 4. Add release notes on GitHub, for example `https://github.com/cisco/cisco-network-node-utils/releases/new?tag=v1.0.1`. Usually this will just be a copy-and-paste of the relevant section of the `CHANGELOG.md`.
72
+
73
+ 5. Publish the new gem version to rubygems.org:
74
+
75
+ ```
76
+ gem build cisco_node_utils.gemspec
77
+ gem push cisco_node_utils-0.9.0.gem
78
+ ```
Binary file
@@ -0,0 +1,45 @@
1
+ #
2
+ # NXAPI implementation of X__CLASS_NAME__X class
3
+ #
4
+ # Copyright (c) 2014-2015 Cisco and/or its affiliates.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require File.join(File.dirname(__FILE__), 'node')
19
+ module Cisco
20
+ # Class name syntax will typically be the resource name in camelCase
21
+ # format; for example: 'tacacs server host' becomes TacacsServerHost.
22
+ class X__CLASS_NAME__X
23
+ # Establish connection to node
24
+ @@node = Cisco::Node.instance
25
+
26
+ def feature_enable
27
+ @@node.config_set('X__RESOURCE_NAME__X', 'feature', { :state => '' })
28
+ end
29
+
30
+ def feature_disable
31
+ @@node.config_set('X__RESOURCE_NAME__X', 'feature', { :state => 'no' })
32
+ end
33
+
34
+ # Check current state of the configuration
35
+ def X__CLASS_NAME__X.feature_enabled
36
+ feat = @@node.config_get('X__RESOURCE_NAME__X', 'feature')
37
+ return (!feat.nil? and !feat.empty?)
38
+ rescue Cisco::CliError => e
39
+ # This cmd will syntax reject if feature is not
40
+ # enabled. Just catch the reject and return false.
41
+ return false if e.clierror =~ /Syntax error/
42
+ raise
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,125 @@
1
+ #
2
+ # NXAPI implementation of X__CLASS_NAME__X class
3
+ #
4
+ # Copyright (c) 2014-2015 Cisco and/or its affiliates.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require File.join(File.dirname(__FILE__), 'node')
19
+
20
+ module Cisco
21
+ class X__CLASS_NAME__X
22
+ attr_reader :name
23
+
24
+ # Establish connection to node
25
+ @@node = Cisco::Node.instance
26
+
27
+ # name: name of the router instance
28
+ # instantiate: true = create router instance
29
+ def initialize(name, instantiate=true)
30
+ raise ArgumentError unless name.length > 0
31
+ @name = name
32
+ create if instantiate
33
+ end
34
+
35
+ # Create a hash of all current router instances.
36
+ def X__CLASS_NAME__X.routers
37
+ instances = @@node.config_get('X__RESOURCE_NAME__X', 'router')
38
+ return {} if instances.nil?
39
+ hash = {}
40
+ instances.each do |name|
41
+ hash[name] = X__CLASS_NAME__X.new(name, false)
42
+ end
43
+ return hash
44
+ rescue Cisco::CliError => e
45
+ # cmd will syntax reject when feature is not enabled
46
+ raise unless e.clierror =~ /Syntax error/
47
+ return {}
48
+ end
49
+
50
+ def feature_enabled
51
+ feat = @@node.config_get('X__RESOURCE_NAME__X', 'feature')
52
+ return (!feat.nil? and !feat.empty?)
53
+ rescue Cisco::CliError => e
54
+ # This cmd will syntax reject if feature is not
55
+ # enabled. Just catch the reject and return false.
56
+ return false if e.clierror =~ /Syntax error/
57
+ raise
58
+ end
59
+
60
+ def feature_enable
61
+ @@node.config_set('X__RESOURCE_NAME__X', 'feature', { :state => '' })
62
+ end
63
+
64
+ def feature_disable
65
+ @@node.config_set('X__RESOURCE_NAME__X', 'feature', { :state => 'no' })
66
+ end
67
+
68
+ # Enable feature and create router instance
69
+ def create
70
+ feature_enable unless feature_enabled
71
+ X__RESOURCE_NAME__X_router
72
+ end
73
+
74
+ # Destroy a router instance; disable feature on last instance
75
+ def destroy
76
+ ids = @@node.config_get('X__RESOURCE_NAME__X', 'router')
77
+ return if ids.nil?
78
+ if ids.size == 1
79
+ feature_disable
80
+ else
81
+ X__RESOURCE_NAME__X_router('no')
82
+ end
83
+ rescue Cisco::CliError => e
84
+ # cmd will syntax reject when feature is not enabled
85
+ raise unless e.clierror =~ /Syntax error/
86
+ end
87
+
88
+ def X__RESOURCE_NAME__X_router(state='')
89
+ @@node.config_set('X__RESOURCE_NAME__X', 'router', { :name => @name, :state => state })
90
+ end
91
+
92
+ # ----------
93
+ # PROPERTIES
94
+ # ----------
95
+
96
+ # Property methods for boolean property
97
+ def default_X__PROPERTY_BOOL__X
98
+ @@node.config_get_default('X__RESOURCE_NAME__X', 'X__PROPERTY_BOOL__X')
99
+ end
100
+
101
+ def X__PROPERTY_BOOL__X
102
+ state = @@node.config_get('X__RESOURCE_NAME__X', 'X__PROPERTY_BOOL__X', { :name => @name })
103
+ state ? true : false
104
+ end
105
+
106
+ def X__PROPERTY_BOOL__X=(state)
107
+ state = (state ? '' : 'no')
108
+ @@node.config_set('X__RESOURCE_NAME__X', 'X__PROPERTY_BOOL__X', { :name => @name, :state => state })
109
+ end
110
+
111
+ # Property methods for integer property
112
+ def default_X__PROPERTY_INT__X
113
+ @@node.config_get_default('X__RESOURCE_NAME__X', 'X__PROPERTY_INT__X')
114
+ end
115
+
116
+ def X__PROPERTY_INT__X
117
+ val = @@node.config_get('X__RESOURCE_NAME__X', 'X__PROPERTY_INT__X', { :name => @name })
118
+ val.nil? ? default_X__PROPERTY_INT__X : val.first.to_i
119
+ end
120
+
121
+ def X__PROPERTY_INT__X=(val)
122
+ @@node.config_set('X__RESOURCE_NAME__X', 'X__PROPERTY_INT__X', { :name => @name, :val => val })
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,51 @@
1
+ #
2
+ # Minitest for X__CLASS_NAME__X class
3
+ #
4
+ # Copyright (c) 2014-2015 Cisco and/or its affiliates.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require File.expand_path("../ciscotest", __FILE__)
19
+ require File.expand_path("../../lib/cisco_node_utils/X__RESOURCE_NAME__X", __FILE__)
20
+
21
+ class TestX__CLASS_NAME__X < CiscoTestCase
22
+ def setup
23
+ # setup automatically runs at the beginning of each test
24
+ super
25
+ no_feature
26
+ end
27
+
28
+ def teardown
29
+ # teardown automatically runs at the end of each test
30
+ no_feature
31
+ super
32
+ end
33
+
34
+ def no_feature
35
+ # setup/teardown helper. Turn the feature off for a clean testbed.
36
+ @device.cmd('conf t ; no feature X__CLI_NAME__X ; end')
37
+ # Flush the cache since we've modified the device outside of the node_utils APIs
38
+ node.cache_flush()
39
+ end
40
+
41
+ # TESTS
42
+
43
+ def test_feature_on_off
44
+ feat = X__CLASS_NAME__X.new()
45
+ feat.feature_enable
46
+ assert(BashShell.feature_enabled)
47
+
48
+ feat.feature_disable
49
+ refute(BashShell.feature_enabled)
50
+ end
51
+ end
@@ -0,0 +1,107 @@
1
+ #
2
+ # Minitest for __CLASS_NAME__ class
3
+ #
4
+ # Copyright (c) 2014-2015 Cisco and/or its affiliates.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require File.expand_path("../ciscotest", __FILE__)
19
+ require File.expand_path("../../lib/cisco_node_utils/router___RESOURCE_NAME__", __FILE__)
20
+
21
+ class Test__CLASS_NAME__ < CiscoTestCase
22
+ def setup
23
+ # setup runs at the beginning of each test
24
+ super
25
+ no_feature___RESOURCE_NAME__
26
+ end
27
+
28
+ def teardown
29
+ # teardown runs at the end of each test
30
+ no_feature___RESOURCE_NAME__
31
+ super
32
+ end
33
+
34
+ def no_feature___RESOURCE_NAME__
35
+ # Turn the feature off for a clean test.
36
+ @device.cmd("conf t ; no feature __RESOURCE_NAME__ ; end")
37
+ # Flush the cache since we've modified the device outside of the node_utils APIs
38
+ node.cache_flush()
39
+ end
40
+
41
+ # TESTS
42
+
43
+ def test_router_create_destroy_one
44
+ id = "blue"
45
+ rtr = __CLASS_NAME__.new(id)
46
+ s = @device.cmd("show runn | i 'router __RESOURCE_NAME__ #{id}'")
47
+ assert_match(s, /^router __RESOURCE_NAME__ #{id}$/,
48
+ "Error: failed to create router __RESOURCE_NAME__ #{id}")
49
+
50
+ rtr.destroy
51
+ s = @device.cmd("show runn | i 'router __RESOURCE_NAME__ #{id}'")
52
+ refute_match(s, /^router __RESOURCE_NAME__ #{id}$/,
53
+ "Error: failed to destroy router __RESOURCE_NAME__ #{id}")
54
+
55
+ s = @device.cmd("show runn | i 'feature __RESOURCE_NAME__'")
56
+ refute_match(s, /^feature __RESOURCE_NAME__$/,
57
+ "Error: failed to disable feature __RESOURCE_NAME__")
58
+ end
59
+
60
+ def test_router_create_destroy_multiple
61
+ id1 = "blue"
62
+ rtr1 = __CLASS_NAME__.new(id1)
63
+ id2 = "red"
64
+ rtr2 = __CLASS_NAME__.new(id2)
65
+
66
+ s = @device.cmd("show runn | i 'router __RESOURCE_NAME__'")
67
+ assert_match(s, /^router __RESOURCE_NAME__ #{id1}$/)
68
+ assert_match(s, /^router __RESOURCE_NAME__ #{id2}$/)
69
+
70
+ rtr1.destroy
71
+ s = @device.cmd("show runn | i 'router __RESOURCE_NAME__ #{id1}'")
72
+ refute_match(s, /^router __RESOURCE_NAME__ #{id1}$/,
73
+ "Error: failed to destroy router __RESOURCE_NAME__ #{id1}")
74
+
75
+ rtr2.destroy
76
+ s = @device.cmd("show runn | i 'router __RESOURCE_NAME__ #{id2}'")
77
+ refute_match(s, /^router __RESOURCE_NAME__ #{id2}$/,
78
+ "Error: failed to destroy router __RESOURCE_NAME__ #{id2}")
79
+
80
+ s = @device.cmd("show runn | i 'feature __RESOURCE_NAME__'")
81
+ refute_match(s, /^feature __RESOURCE_NAME__$/,
82
+ "Error: failed to disable feature __RESOURCE_NAME__")
83
+ end
84
+
85
+ def test_router___PROPERTY_INT__
86
+ id = "blue"
87
+ rtr = __CLASS_NAME__.new(id)
88
+ val = 5 # This value depends on property bounds
89
+ rtr.__PROPERTY_INT__ = val
90
+ assert_equal(rtr.__PROPERTY_INT__, val, "__PROPERTY_INT__ is not #{val}")
91
+
92
+ # Get default value from yaml
93
+ val = node.config_get_default("__RESOURCE_NAME__", "__PROPERTY_INT__")
94
+ rtr.__PROPERTY_INT__ = val
95
+ assert_equal(rtr.__PROPERTY_INT__, val, "__PROPERTY_INT__ is not #{val}")
96
+ end
97
+
98
+ def test_router___PROPERTY_BOOL__
99
+ id = "blue"
100
+ rtr = __CLASS_NAME__.new(id)
101
+ rtr.__PROPERTY_BOOL__ = true
102
+ assert(rtr.__PROPERTY_BOOL__, "__PROPERTY_BOOL__ state is not true")
103
+
104
+ rtr.__PROPERTY_BOOL__ = false
105
+ refute(rtr.__PROPERTY_BOOL__, "__PROPERTY_BOOL__ state is not false")
106
+ end
107
+ end
@@ -142,6 +142,17 @@ interface:
142
142
  destroy:
143
143
  config_set: "no interface %s"
144
144
 
145
+ encapsulation_dot1q:
146
+ config_get: "show running interface all"
147
+ config_get_token: ['/^interface %s$/i', '/^encapsulation dot1q (.*)/']
148
+ config_set: ["interface %s", "%s encapsulation dot1q %s"]
149
+ default_value: ""
150
+
151
+ feature_lacp:
152
+ config_get: "show running | i ^feature"
153
+ config_get_token: '/^feature lacp$/'
154
+ config_set: "%s feature lacp"
155
+
145
156
  feature_vlan:
146
157
  config_get: "show running | i ^feature"
147
158
  config_get_token: '/^feature interface-vlan$/'
@@ -196,6 +207,12 @@ interface:
196
207
  false: false
197
208
  true: true
198
209
 
210
+ mtu:
211
+ config_get: "show running interface all"
212
+ config_get_token: ['/^interface %s$/i', '/^mtu (.*)$/']
213
+ config_set: ["interface %s", "%s mtu %s"]
214
+ default_value: ""
215
+
199
216
  negotiate_auto_ethernet:
200
217
  config_get: "show running interface all"
201
218
  config_get_token: [
@@ -303,6 +320,24 @@ interface:
303
320
  test_config_result:
304
321
  false: RuntimeError
305
322
 
323
+ switchport_trunk_allowed_vlan:
324
+ config_get: "show running interface all"
325
+ config_get_token: [
326
+ '/^interface %s$/i',
327
+ '/^switchport trunk allowed vlan (.*)$/'
328
+ ]
329
+ config_set: ["interface %s", "%s switchport trunk allowed vlan %s"]
330
+ default_value: "all"
331
+
332
+ switchport_trunk_native_vlan:
333
+ config_get: "show running interface all"
334
+ config_get_token: [
335
+ '/^interface %s$/i',
336
+ '/^switchport trunk native vlan (.*)$/'
337
+ ]
338
+ config_set: ["interface %s", "%s switchport trunk native vlan %s"]
339
+ default_value: 1
340
+
306
341
  svi_autostate:
307
342
  config_get: "show running interface all"
308
343
  config_get_token: ['/^interface %s$/i', '/^autostate$/']
@@ -318,6 +353,12 @@ interface:
318
353
  config_set: ["interface %s", "%s management"]
319
354
  default_value: false
320
355
 
356
+ vrf:
357
+ config_get: "show running interface all"
358
+ config_get_token: ['/^interface %s$/i', '/^vrf member (.*)/']
359
+ config_set: ["interface %s", "%s vrf member %s"]
360
+ default_value: ""
361
+
321
362
  vtp:
322
363
  config_get: "show running interface all"
323
364
  config_get_token: ['/^interface %s$/i', '/^vtp *$/']
@@ -835,7 +876,7 @@ vtp:
835
876
 
836
877
  yum:
837
878
  install:
838
- config_set: "install add %s activate"
879
+ config_set: "install add %s %s activate"
839
880
  query:
840
881
  config_get: "show install packages"
841
882
  # pass in the pkg name, retrieve version