puppet_x_eos_eapi 0.2.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.
Files changed (123) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +24 -0
  4. data/LICENSE.txt +202 -0
  5. data/README.md +87 -0
  6. data/Rakefile +1 -0
  7. data/lib/puppet_x/eos/autoload.rb +57 -0
  8. data/lib/puppet_x/eos/eapi.rb +259 -0
  9. data/lib/puppet_x/eos/module_base.rb +37 -0
  10. data/lib/puppet_x/eos/modules/daemon.rb +109 -0
  11. data/lib/puppet_x/eos/modules/extension.rb +167 -0
  12. data/lib/puppet_x/eos/modules/interface.rb +180 -0
  13. data/lib/puppet_x/eos/modules/ipinterface.rb +133 -0
  14. data/lib/puppet_x/eos/modules/mlag.rb +268 -0
  15. data/lib/puppet_x/eos/modules/ntp.rb +129 -0
  16. data/lib/puppet_x/eos/modules/ospf.rb +129 -0
  17. data/lib/puppet_x/eos/modules/portchannel.rb +277 -0
  18. data/lib/puppet_x/eos/modules/radius.rb +367 -0
  19. data/lib/puppet_x/eos/modules/snmp.rb +177 -0
  20. data/lib/puppet_x/eos/modules/switchport.rb +255 -0
  21. data/lib/puppet_x/eos/modules/system.rb +138 -0
  22. data/lib/puppet_x/eos/modules/tacacs.rb +302 -0
  23. data/lib/puppet_x/eos/modules/vlan.rb +179 -0
  24. data/lib/puppet_x/eos/modules/vxlan.rb +132 -0
  25. data/lib/puppet_x/eos/provider.rb +71 -0
  26. data/lib/puppet_x/eos/version.rb +41 -0
  27. data/lib/puppet_x/net_dev/eos_api.rb +1011 -0
  28. data/lib/puppet_x/net_dev/eos_api/common_methods.rb +27 -0
  29. data/lib/puppet_x/net_dev/eos_api/snmp_methods.rb +647 -0
  30. data/lib/puppet_x/net_dev/eos_api/version.rb +8 -0
  31. data/lib/puppet_x_eos_eapi.rb +4 -0
  32. data/puppet_x_eos_eapi.gemspec +31 -0
  33. data/spec/fixtures/fixture_all_portchannel_modes.json +8 -0
  34. data/spec/fixtures/fixture_all_portchannels_detailed.json +15 -0
  35. data/spec/fixtures/fixture_create_vlan_error.json +17 -0
  36. data/spec/fixtures/fixture_create_vlan_success.json +12 -0
  37. data/spec/fixtures/fixture_eapi_conf.yaml +4 -0
  38. data/spec/fixtures/fixture_enable_configure_vlan_3111_name_foo.json +14 -0
  39. data/spec/fixtures/fixture_enable_configure_vlan_foo_name_bar.json +19 -0
  40. data/spec/fixtures/fixture_get_snmp_communities_non_existent_acl.yaml +2 -0
  41. data/spec/fixtures/fixture_get_snmp_location_westeros.json +5 -0
  42. data/spec/fixtures/fixture_portchannel_min_links_1.json +8 -0
  43. data/spec/fixtures/fixture_portchannel_min_links_2.json +8 -0
  44. data/spec/fixtures/fixture_running_config.yaml +1 -0
  45. data/spec/fixtures/fixture_running_configuration_radius_configured.yaml +30 -0
  46. data/spec/fixtures/fixture_running_configuration_radius_default.yaml +29 -0
  47. data/spec/fixtures/fixture_running_configuration_radius_server_groups.yaml +38 -0
  48. data/spec/fixtures/fixture_running_configuration_radius_servers.yaml +34 -0
  49. data/spec/fixtures/fixture_running_configuration_tacacs_configured.yaml +38 -0
  50. data/spec/fixtures/fixture_running_configuration_tacacs_default.yaml +38 -0
  51. data/spec/fixtures/fixture_running_configuration_tacacs_groups.yaml +1 -0
  52. data/spec/fixtures/fixture_running_configuration_tacacs_groups_3.yaml +43 -0
  53. data/spec/fixtures/fixture_running_configuration_tacacs_servers.yaml +41 -0
  54. data/spec/fixtures/fixture_s4_show_etherchannel_detailed.json +9 -0
  55. data/spec/fixtures/fixture_show_flowcontrol_et1.json +5 -0
  56. data/spec/fixtures/fixture_show_interfaces.json +297 -0
  57. data/spec/fixtures/fixture_show_interfaces_switchport_format_text.json +9 -0
  58. data/spec/fixtures/fixture_show_port_channel_summary_2_lags.json +9 -0
  59. data/spec/fixtures/fixture_show_port_channel_summary_static.json +9 -0
  60. data/spec/fixtures/fixture_show_snmp_community.yaml +2 -0
  61. data/spec/fixtures/fixture_show_snmp_contact_empty.json +5 -0
  62. data/spec/fixtures/fixture_show_snmp_contact_name.json +5 -0
  63. data/spec/fixtures/fixture_show_snmp_disabled.json +5 -0
  64. data/spec/fixtures/fixture_show_snmp_enabled.json +5 -0
  65. data/spec/fixtures/fixture_show_snmp_host.yaml +2 -0
  66. data/spec/fixtures/fixture_show_snmp_host_duplicates.yaml +2 -0
  67. data/spec/fixtures/fixture_show_snmp_host_more_duplicates.yaml +2 -0
  68. data/spec/fixtures/fixture_show_snmp_location_empty.json +5 -0
  69. data/spec/fixtures/fixture_show_snmp_trap.yaml +2 -0
  70. data/spec/fixtures/fixture_show_snmp_user.yaml +2 -0
  71. data/spec/fixtures/fixture_show_snmp_user_raw_text.yaml +1 -0
  72. data/spec/fixtures/fixture_show_vlan.json +37 -0
  73. data/spec/fixtures/fixture_show_vlan_3110.json +18 -0
  74. data/spec/fixtures/fixture_show_vlan_4000.json +18 -0
  75. data/spec/fixtures/fixture_snmp_host_opts.yaml +11 -0
  76. data/spec/spec_helper.rb +21 -0
  77. data/spec/support/fixtures.rb +104 -0
  78. data/spec/unit/puppet_x/eos/eapi_spec.rb +182 -0
  79. data/spec/unit/puppet_x/eos/module_base_spec.rb +26 -0
  80. data/spec/unit/puppet_x/eos/modules/daemon_spec.rb +110 -0
  81. data/spec/unit/puppet_x/eos/modules/extension_spec.rb +197 -0
  82. data/spec/unit/puppet_x/eos/modules/fixtures/daemon_getall.json +3 -0
  83. data/spec/unit/puppet_x/eos/modules/fixtures/extension_getall.json +28 -0
  84. data/spec/unit/puppet_x/eos/modules/fixtures/hostname.json +6 -0
  85. data/spec/unit/puppet_x/eos/modules/fixtures/interface_getall.json +509 -0
  86. data/spec/unit/puppet_x/eos/modules/fixtures/ipinterface_getall.json +56 -0
  87. data/spec/unit/puppet_x/eos/modules/fixtures/mlag_get.json +21 -0
  88. data/spec/unit/puppet_x/eos/modules/fixtures/mlag_get_interfaces.json +18 -0
  89. data/spec/unit/puppet_x/eos/modules/fixtures/ntp_get.json +5 -0
  90. data/spec/unit/puppet_x/eos/modules/fixtures/ospf_instance_getall.json +58 -0
  91. data/spec/unit/puppet_x/eos/modules/fixtures/portchannel_get.json +54 -0
  92. data/spec/unit/puppet_x/eos/modules/fixtures/portchannel_getlacpmode.json +5 -0
  93. data/spec/unit/puppet_x/eos/modules/fixtures/portchannel_getmembers.json +5 -0
  94. data/spec/unit/puppet_x/eos/modules/fixtures/portchannel_po1.json +7 -0
  95. data/spec/unit/puppet_x/eos/modules/fixtures/snmp_get.json +14 -0
  96. data/spec/unit/puppet_x/eos/modules/fixtures/switchport_get.json +5 -0
  97. data/spec/unit/puppet_x/eos/modules/fixtures/switchport_get_et1.json +7 -0
  98. data/spec/unit/puppet_x/eos/modules/fixtures/switchport_getall_interfaces.json +230 -0
  99. data/spec/unit/puppet_x/eos/modules/fixtures/system_domain_list.json +5 -0
  100. data/spec/unit/puppet_x/eos/modules/fixtures/system_domain_name.json +5 -0
  101. data/spec/unit/puppet_x/eos/modules/fixtures/system_hostname.json +6 -0
  102. data/spec/unit/puppet_x/eos/modules/fixtures/system_name_servers.json +5 -0
  103. data/spec/unit/puppet_x/eos/modules/fixtures/vlan_getall.json +123 -0
  104. data/spec/unit/puppet_x/eos/modules/fixtures/vxlan_get.json +24 -0
  105. data/spec/unit/puppet_x/eos/modules/interface_spec.rb +281 -0
  106. data/spec/unit/puppet_x/eos/modules/ipinterface_spec.rb +143 -0
  107. data/spec/unit/puppet_x/eos/modules/mlag_spec.rb +349 -0
  108. data/spec/unit/puppet_x/eos/modules/ntp_spec.rb +136 -0
  109. data/spec/unit/puppet_x/eos/modules/ospf_spec.rb +143 -0
  110. data/spec/unit/puppet_x/eos/modules/portchannel_spec.rb +357 -0
  111. data/spec/unit/puppet_x/eos/modules/radius_spec.rb +509 -0
  112. data/spec/unit/puppet_x/eos/modules/snmp_spec.rb +202 -0
  113. data/spec/unit/puppet_x/eos/modules/switchport_get_et1.json +7 -0
  114. data/spec/unit/puppet_x/eos/modules/switchport_spec.rb +307 -0
  115. data/spec/unit/puppet_x/eos/modules/system_spec.rb +170 -0
  116. data/spec/unit/puppet_x/eos/modules/tacacs_spec.rb +448 -0
  117. data/spec/unit/puppet_x/eos/modules/vlan_spec.rb +244 -0
  118. data/spec/unit/puppet_x/eos/modules/vxlan_spec.rb +189 -0
  119. data/spec/unit/puppet_x/eos/provider_spec.rb +35 -0
  120. data/spec/unit/puppet_x/net_dev/eos_api/common_methods_spec.rb +34 -0
  121. data/spec/unit/puppet_x/net_dev/eos_api/snmp_methods_spec.rb +842 -0
  122. data/spec/unit/puppet_x/net_dev/eos_api_spec.rb +1000 -0
  123. metadata +369 -0
@@ -0,0 +1,170 @@
1
+ #
2
+ # Copyright (c) 2014, Arista Networks, Inc.
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are
7
+ # met:
8
+ #
9
+ # Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ #
12
+ # Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ #
16
+ # Neither the name of Arista Networks nor the names of its
17
+ # contributors may be used to endorse or promote products derived from
18
+ # this software without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS
24
+ # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27
+ # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30
+ # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ #
32
+ require 'spec_helper'
33
+ require 'puppet_x/eos/modules/system'
34
+
35
+ describe PuppetX::Eos::System do
36
+ let(:eapi) { double }
37
+ let(:instance) { PuppetX::Eos::System.new eapi }
38
+
39
+ context 'when initializing a new System instance' do
40
+ subject { instance }
41
+ it { is_expected.to be_a_kind_of PuppetX::Eos::System }
42
+ end
43
+
44
+ context 'with Eapi#enable' do
45
+ context '#get_hostname' do
46
+ subject { instance.get_hostname }
47
+
48
+ let :response do
49
+ dir = File.dirname(__FILE__)
50
+ file = File.join(dir, 'fixtures/system_hostname.json')
51
+ JSON.load(File.read(file))
52
+ end
53
+
54
+ before :each do
55
+ allow(eapi).to receive(:enable).with('show hostname')
56
+ .and_return(response)
57
+ end
58
+
59
+ it { is_expected.to eq 'localhost' }
60
+ end
61
+
62
+ context '#get_domain_name' do
63
+ subject { instance.get_domain_name }
64
+
65
+ let :response do
66
+ dir = File.dirname(__FILE__)
67
+ file = File.join(dir, 'fixtures/system_domain_name.json')
68
+ JSON.load(File.read(file))
69
+ end
70
+
71
+ before :each do
72
+ allow(eapi).to receive(:enable).with('show ip domain-name', 'text')
73
+ .and_return(response)
74
+ end
75
+
76
+ it { is_expected.to eq 'arista.com' }
77
+ end
78
+
79
+ context '#get_name_servers' do
80
+ subject { instance.get_name_servers }
81
+
82
+ let :response do
83
+ dir = File.dirname(__FILE__)
84
+ file = File.join(dir, 'fixtures/system_name_servers.json')
85
+ JSON.load(File.read(file))
86
+ end
87
+
88
+ before :each do
89
+ allow(eapi).to receive(:enable).with('show ip name-server', 'text')
90
+ .and_return(response)
91
+ end
92
+
93
+ it { is_expected.to eq %w(1.2.3.4 5.6.7.8) }
94
+ end
95
+
96
+ context '#get_domain_list' do
97
+ subject { instance.get_domain_list }
98
+
99
+ let :response do
100
+ dir = File.dirname(__FILE__)
101
+ file = File.join(dir, 'fixtures/system_domain_list.json')
102
+ JSON.load(File.read(file))
103
+ end
104
+
105
+ before :each do
106
+ allow(eapi).to receive(:enable)
107
+ .with('show running-config section ip\sdomain-list', 'text')
108
+ .and_return response
109
+ end
110
+
111
+ it { is_expected.to eq %w(arista.com arista.net) }
112
+ end
113
+ end
114
+
115
+ context 'with Eapi#config' do
116
+ context '#set_hostname' do
117
+ subject { instance.set_hostname(name) }
118
+
119
+ let(:name) { (0...50).map { ('a'..'z').to_a[rand(26)] }.join }
120
+
121
+ before :each do
122
+ allow(eapi).to receive(:config).with("hostname #{name}")
123
+ .and_return([{}])
124
+ end
125
+
126
+ it { is_expected.to be_truthy }
127
+ end
128
+
129
+ context '#set_domain_name' do
130
+ subject { instance.set_domain_name('arista.com') }
131
+
132
+ before :each do
133
+ allow(eapi).to receive(:config).with('ip domain-name arista.com')
134
+ .and_return([{}])
135
+ end
136
+
137
+ it { is_expected.to be_truthy }
138
+ end
139
+
140
+ context '#set_name_servers' do
141
+ subject { instance.set_name_servers(servers) }
142
+
143
+ let(:servers) { %w(1.2.3.4 5.6.7.8) }
144
+
145
+ before :each do
146
+ servers.each do |srv|
147
+ allow(eapi).to receive(:config).with("ip name-server #{srv}")
148
+ .and_return([{}])
149
+ end
150
+ end
151
+
152
+ it { is_expected.to be_truthy }
153
+ end
154
+
155
+ context '#set_domain_list' do
156
+ subject { instance.set_domain_list(domains) }
157
+
158
+ let(:domains) { %w(arista.com arista.net) }
159
+
160
+ before :each do
161
+ domains.each do |name|
162
+ allow(eapi).to receive(:config).with("ip domain-list #{name}")
163
+ .and_return([{}])
164
+ end
165
+ end
166
+
167
+ it { is_expected.to be_truthy }
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,448 @@
1
+ require 'spec_helper'
2
+
3
+ describe PuppetX::Eos::Tacacs do
4
+ let(:eapi) { PuppetX::Eos::Eapi.new }
5
+ let(:instance) { described_class.new(eapi) }
6
+
7
+ describe '#getall' do
8
+ subject { instance.getall }
9
+
10
+ context 'when all tacacs settings are the default' do
11
+ before :each do
12
+ allow(instance).to receive(:running_configuration)
13
+ .and_return(fixture(:running_configuration_tacacs_default))
14
+ end
15
+
16
+ describe 'the return value' do
17
+ it { is_expected.to be_an Array }
18
+ it 'has only one resource hash' do
19
+ expect(subject.size).to eq(1)
20
+ end
21
+ end
22
+
23
+ describe 'the single resource hash' do
24
+ subject { instance.getall.first }
25
+
26
+ it { is_expected.to include(name: 'settings') }
27
+ it { is_expected.to include(enable: true) }
28
+ it { is_expected.to_not include(:key) }
29
+ it { is_expected.to_not include(:key_format) }
30
+ it { is_expected.to include(timeout: 5) }
31
+ end
32
+ end
33
+
34
+ context 'when a global timeout and key are configured' do
35
+ before :each do
36
+ allow(instance).to receive(:running_configuration)
37
+ .and_return(fixture(:running_configuration_tacacs_configured))
38
+ end
39
+
40
+ describe 'the return value' do
41
+ it { is_expected.to be_an Array }
42
+ it 'has only one resource hash' do
43
+ expect(subject.size).to eq(1)
44
+ end
45
+ end
46
+
47
+ describe 'the single resource hash' do
48
+ subject { instance.getall.first }
49
+
50
+ it { is_expected.to include(name: 'settings') }
51
+ it { is_expected.to include(enable: true) }
52
+ it { is_expected.to include(key: '070E234F1F5B4A') }
53
+ it { is_expected.to include(key_format: 7) }
54
+ it { is_expected.to include(timeout: 7) }
55
+ end
56
+ end
57
+ end
58
+
59
+ describe '#set_global_key' do
60
+ let :opts do
61
+ { key: '070E234F1F5B4A', key_format: 7 }
62
+ end
63
+
64
+ before :each do
65
+ allow(instance.api).to receive(:config)
66
+ end
67
+
68
+ subject { instance.set_global_key(opts) }
69
+
70
+ context 'when key_format is 7 (hashed)' do
71
+ it 'uses Eapi#config to set the global key' do
72
+ expect(instance.api).to receive(:config)
73
+ .with('tacacs-server key 7 070E234F1F5B4A')
74
+ subject
75
+ end
76
+ end
77
+
78
+ context 'when key_format is not provided' do
79
+ let :opts do
80
+ { key: '070E234F1F5B4A' }
81
+ end
82
+
83
+ it 'assumes a default format of 7' do
84
+ expect(instance.api).to receive(:config)
85
+ .with('tacacs-server key 7 070E234F1F5B4A')
86
+ subject
87
+ end
88
+ end
89
+
90
+ context 'when key is not provided' do
91
+ let :opts do
92
+ { key_format: 7 }
93
+ end
94
+
95
+ it 'raises ArgumentError that key is required' do
96
+ expect { subject }
97
+ .to raise_error ArgumentError, /key option is required/
98
+ end
99
+ end
100
+
101
+ context 'when the API call returns [{}]' do
102
+ before :each do
103
+ allow(instance.api).to receive(:config)
104
+ .and_return([{}])
105
+ end
106
+
107
+ it { is_expected.to eq true }
108
+ end
109
+
110
+ context 'when the API call does not return [{}]' do
111
+ before :each do
112
+ allow(instance.api).to receive(:config)
113
+ .and_return([{'errors' => ['blarg']}])
114
+ end
115
+
116
+ it { is_expected.to eq false }
117
+ end
118
+ end
119
+
120
+ describe '#set_timeout' do
121
+ let :opts do
122
+ { timeout: 50 }
123
+ end
124
+
125
+ before :each do
126
+ allow(instance.api).to receive(:config).and_return([{}])
127
+ end
128
+
129
+ subject { instance.set_timeout(opts) }
130
+
131
+ context 'when timeout is not provided' do
132
+ let :opts do
133
+ {}
134
+ end
135
+
136
+ it 'raises ArgumentError' do
137
+ expect { subject }
138
+ .to raise_error ArgumentError, /timeout option is required/
139
+ end
140
+ end
141
+
142
+ context 'when timeout is provided' do
143
+ it 'calls Eapi#config to configure tacacs-server timeout' do
144
+ expect(instance.api).to receive(:config)
145
+ .with('tacacs-server timeout 50')
146
+ .and_return([{}])
147
+ subject
148
+ end
149
+ end
150
+
151
+ context 'when the API call returns [{}]' do
152
+ it { is_expected.to eq true }
153
+ end
154
+
155
+ context 'when the API call does not return [{}]' do
156
+ before :each do
157
+ allow(instance.api).to receive(:config)
158
+ .and_return([{'errors' => ['blarg']}])
159
+ end
160
+
161
+ it { is_expected.to eq false }
162
+ end
163
+ end
164
+
165
+ describe '#servers' do
166
+ subject { instance.servers }
167
+
168
+ context 'when there are tacacs servers defined' do
169
+ before :each do
170
+ allow(instance).to receive(:running_configuration)
171
+ .and_return(fixture(:running_configuration_tacacs_servers))
172
+ end
173
+ it { is_expected.to be_an Array }
174
+ it 'parses 4 results' do
175
+ expect(subject.size).to eq(4)
176
+ end
177
+ it 'includes only Hashes as elements of the Array' do
178
+ subject.each { |result| expect(result).to be_a Hash }
179
+ end
180
+ it 'includes hostname in every result' do
181
+ subject.each { |result| expect(result).to include(:hostname) }
182
+ end
183
+ it 'includes port in every result' do
184
+ subject.each { |result| expect(result).to include(:port) }
185
+ end
186
+ it 'includes one entry with multiplex true' do
187
+ expected = {
188
+ port: 4949,
189
+ hostname: "1.2.3.4",
190
+ timeout: 6,
191
+ key_format: 7,
192
+ key: "06070D221D1C5A",
193
+ multiplex: true
194
+ }
195
+ expect(subject).to include(expected)
196
+ end
197
+ end
198
+
199
+ context 'when there are no tacacs servers defined' do
200
+ before :each do
201
+ allow(instance).to receive(:running_configuration)
202
+ .and_return(fixture(:running_configuration_tacacs_default))
203
+ end
204
+ it { is_expected.to be_an Array }
205
+ it { is_expected.to be_empty }
206
+ end
207
+ end
208
+
209
+ describe '#update_server' do
210
+ subject { instance.update_server(opts) }
211
+
212
+ let :opts do
213
+ { hostname: '10.11.12.13' }
214
+ end
215
+
216
+ before :each do
217
+ allow(instance.api).to receive(:config).and_return([{}])
218
+ end
219
+
220
+ context 'when only hostname is provided' do
221
+ it 'calls Eapi#config to configure tacacs-server host' do
222
+ expect(instance.api).to receive(:config)
223
+ .with('tacacs-server host 10.11.12.13')
224
+ .and_return([{}])
225
+ subject
226
+ end
227
+ end
228
+
229
+ context 'when configuring a single-connection server' do
230
+ let :opts do
231
+ { hostname: '10.11.12.13', multiplex: true }
232
+ end
233
+ it 'calls Eapi#config to with single-connection' do
234
+ expect(instance.api).to receive(:config)
235
+ .with('tacacs-server host 10.11.12.13 single-connection')
236
+ .and_return([{}])
237
+ subject
238
+ end
239
+ end
240
+ end
241
+
242
+ describe '#remove_server' do
243
+ subject { instance.remove_server(opts) }
244
+
245
+ let :opts do
246
+ { hostname: '10.11.12.13' }
247
+ end
248
+
249
+ before :each do
250
+ allow(instance.api).to receive(:config).and_return([{}])
251
+ end
252
+
253
+ context 'when only hostname is provided' do
254
+ it 'calls Eapi#config to configure no tacacs-server host' do
255
+ expect(instance.api).to receive(:config)
256
+ .with('no tacacs-server host 10.11.12.13')
257
+ .and_return([{}])
258
+ subject
259
+ end
260
+ end
261
+
262
+ context 'when hostname and port are provided' do
263
+ let :opts do
264
+ { hostname: '10.11.12.13', port: 4949 }
265
+ end
266
+ it 'calls Eapi#config to configure no tacacs-server host port 4949' do
267
+ expect(instance.api).to receive(:config)
268
+ .with('no tacacs-server host 10.11.12.13 port 4949')
269
+ .and_return([{}])
270
+ subject
271
+ end
272
+ end
273
+ end
274
+
275
+ describe '#server_groups' do
276
+ context 'with two server groups defined' do
277
+ before :each do
278
+ allow(instance).to receive(:running_configuration)
279
+ .and_return(fixture(:running_configuration_tacacs_groups))
280
+ end
281
+
282
+ describe 'the return value' do
283
+ subject { instance.server_groups }
284
+
285
+ it { is_expected.to be_an Array }
286
+ it 'returns 2 server groups' do
287
+ expect(subject.size).to eq 2
288
+ end
289
+
290
+ describe 'each value of the return Array' do
291
+ it 'each value is a hash' do
292
+ subject.each {|v| expect(v).to be_a Hash }
293
+ end
294
+ it 'each value has a name attribute' do
295
+ subject.each {|v| expect(v).to include(name: /TAC-GR/) }
296
+ end
297
+ it 'each value has a servers attribute' do
298
+ subject.each {|v| expect(v).to include(servers: Array) }
299
+ end
300
+ end
301
+
302
+ describe 'each server attribute' do
303
+ it 'is a hash' do
304
+ subject.each do |group|
305
+ group[:servers].each do |server|
306
+ expect(server).to be_a Hash
307
+ end
308
+ end
309
+ end
310
+ it 'includes the hostname, port attributes' do
311
+ subject.each do |group|
312
+ group[:servers].each do |server|
313
+ expect(server).to include(hostname: String, port: Fixnum)
314
+ end
315
+ end
316
+ end
317
+ end
318
+ end
319
+ end
320
+
321
+ context 'with a server group with no servers' do
322
+ before :each do
323
+ allow(instance).to receive(:running_configuration)
324
+ .and_return(fixture(:running_configuration_tacacs_groups_3))
325
+ end
326
+
327
+ describe 'the return value' do
328
+ subject { instance.server_groups }
329
+
330
+ it { is_expected.to be_an Array }
331
+ it 'returns 3 server groups' do
332
+ expect(subject.size).to eq 3
333
+ end
334
+
335
+ describe 'each value of the return Array' do
336
+ it 'each value is a hash' do
337
+ subject.each {|v| expect(v).to be_a Hash }
338
+ end
339
+ it 'each value has a name attribute' do
340
+ subject.each {|v| expect(v).to include(name: /TAC-GR/) }
341
+ end
342
+ it 'each value has a servers attribute' do
343
+ subject.each {|v| expect(v).to include(servers: Array) }
344
+ end
345
+ end
346
+
347
+ describe 'each server attribute' do
348
+ it 'is a hash' do
349
+ subject.each do |group|
350
+ group[:servers].each do |server|
351
+ expect(server).to be_a Hash
352
+ end
353
+ end
354
+ end
355
+ it 'includes the hostname, port attributes' do
356
+ subject.each do |group|
357
+ group[:servers].each do |server|
358
+ expect(server).to include(hostname: String, port: Fixnum)
359
+ end
360
+ end
361
+ end
362
+ end
363
+ end
364
+ end
365
+
366
+ context 'with no server groups defined' do
367
+ before :each do
368
+ allow(instance).to receive(:running_configuration)
369
+ .and_return(fixture(:running_configuration_tacacs_default))
370
+ end
371
+
372
+ describe 'the return value' do
373
+ subject { instance.server_groups }
374
+
375
+ it { is_expected.to be_an Array }
376
+ it 'returns 0 server groups' do
377
+ expect(subject.size).to eq 0
378
+ end
379
+ end
380
+ end
381
+ end
382
+
383
+ describe '#update_server_group' do
384
+ before :each do
385
+ allow(instance.api).to receive(:config).and_return([{}])
386
+ end
387
+
388
+ subject { instance.update_server_group(opts) }
389
+
390
+ context 'with no servers specified' do
391
+ let :opts do
392
+ { name: 'TAC-GR-EMPTY', servers: [] }
393
+ end
394
+
395
+ it { is_expected.to eq(true) }
396
+
397
+ it 're-creates the server group after clearing it' do
398
+ expect(instance.api).to receive(:config)
399
+ .with('no aaa group server tacacs+ TAC-GR-EMPTY').ordered
400
+ expect(instance.api).to receive(:config)
401
+ .with(['aaa group server tacacs+ TAC-GR-EMPTY']).ordered
402
+ subject
403
+ end
404
+ end
405
+
406
+ context 'with two servers specified' do
407
+ let :opts do
408
+ { name: 'TAC-GR',
409
+ servers: [
410
+ { hostname: 'one' },
411
+ { hostname: 'two', port: 50 }
412
+ ]
413
+ }
414
+ end
415
+
416
+ it { is_expected.to eq(true) }
417
+ it 'uses the default port when not provided' do
418
+ expect(instance.api).to receive(:config)
419
+ .with([/TAC-GR/, 'server one port 49', String ])
420
+ subject
421
+ end
422
+ it 'creates the group of servers using a single config call' do
423
+ expect(instance.api).to receive(:config)
424
+ .with([/TAC-GR/, /server one/, /server two/])
425
+ subject
426
+ end
427
+ end
428
+ end
429
+
430
+ describe '#remove_server_group' do
431
+ let :opts do
432
+ { name: 'TAC-GR' }
433
+ end
434
+
435
+ subject { instance.remove_server_group(opts) }
436
+
437
+ before :each do
438
+ allow(instance.api).to receive(:config).and_return([{}])
439
+ end
440
+
441
+ it { is_expected.to eq true }
442
+ it 'removes the group specified by name' do
443
+ expect(instance.api).to receive(:config)
444
+ .with('no aaa group server tacacs+ TAC-GR')
445
+ subject
446
+ end
447
+ end
448
+ end