From 00a0ebf3979cafeb71fdf90a57e2f499f54919b6 Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Fri, 30 Oct 2015 14:35:53 -0400 Subject: [PATCH 001/110] Add build badge for Jenkins --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4dc6ebb..a9fc8aa 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Arista eAPI Ruby Library +Jenkins [![Build Status](https://revproxy.arista.com/eosplus/ci/buildStatus/icon?job=rbeapi_start)](https://revproxy.arista.com/eosplus/ci/job/rbeapi_start/) + #### Table of Contents 1. [Overview] (#overview) From 08ee8fd354d104eac1e6370bf0de878a69387455 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 30 Nov 2015 12:34:28 -0700 Subject: [PATCH 002/110] Working on filling code coverage gaps. --- .../api/acl_spec.rb} | 0 spec/system/rbeapi/api/bgp_neighbors_spec.rb | 354 +++++++++++++++++ spec/system/rbeapi/api/bgp_spec.rb | 375 ++++++++++++++++++ .../api/ospf_interfaces_spec.rb} | 0 .../api/ospf_spec.rb} | 0 spec/system/rbeapi/api/staticroutes_spec.rb | 177 +++++++++ 6 files changed, 906 insertions(+) rename spec/system/{api_acl_spec.rb => rbeapi/api/acl_spec.rb} (100%) create mode 100644 spec/system/rbeapi/api/bgp_neighbors_spec.rb create mode 100644 spec/system/rbeapi/api/bgp_spec.rb rename spec/system/{api_ospf_interfaces_spec.rb => rbeapi/api/ospf_interfaces_spec.rb} (100%) rename spec/system/{api_ospf_spec.rb => rbeapi/api/ospf_spec.rb} (100%) create mode 100644 spec/system/rbeapi/api/staticroutes_spec.rb diff --git a/spec/system/api_acl_spec.rb b/spec/system/rbeapi/api/acl_spec.rb similarity index 100% rename from spec/system/api_acl_spec.rb rename to spec/system/rbeapi/api/acl_spec.rb diff --git a/spec/system/rbeapi/api/bgp_neighbors_spec.rb b/spec/system/rbeapi/api/bgp_neighbors_spec.rb new file mode 100644 index 0000000..9a54027 --- /dev/null +++ b/spec/system/rbeapi/api/bgp_neighbors_spec.rb @@ -0,0 +1,354 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' +require 'rbeapi/api/bgp' + +describe Rbeapi::Api::BgpNeighbors do + subject { described_class.new(node) } + + let(:node) do + Rbeapi::Client.config.read(fixture_file('dut.conf')) + Rbeapi::Client.connect_to('dut') + end + + describe '#get' do + let(:entity) do + { peer_group: nil, + remote_as: nil, + send_community: false, + shutdown: false, + description: nil, + next_hop_self: false, + route_map_in: nil, + route_map_out: nil } + end + + before do + node.config(['no router bgp 64600', 'router bgp 64600', + 'neighbor eBGP_GROUP peer-group']) + end + + it 'returns the BGP neighbor resource' do + expect(subject.get('eBGP_GROUP')).to eq(entity) + end + end + + describe '#getall' do + let(:entity) do + { + 'eBGP_GROUP' => { + peer_group: nil, remote_as: nil, send_community: false, + shutdown: false, description: nil, next_hop_self: false, + route_map_in: nil, route_map_out: nil + }, + '192.168.255.1' => { + peer_group: 'eBGP_GROUP', remote_as: '65000', send_community: true, + shutdown: true, description: nil, next_hop_self: true, + route_map_in: nil, route_map_out: nil + }, + '192.168.255.3' => { + peer_group: 'eBGP_GROUP', remote_as: '65001', send_community: true, + shutdown: true, description: nil, next_hop_self: true, + route_map_in: nil, route_map_out: nil + } + } + end + + before do + node.config(['no router bgp 64600', 'router bgp 64600', + 'neighbor 192.168.255.1 peer-group eBGP_GROUP', + 'neighbor 192.168.255.1 remote-as 65000', + 'neighbor 192.168.255.3 peer-group eBGP_GROUP', + 'neighbor 192.168.255.3 remote-as 65001']) + end + + it 'returns all the neighbors' do + expect(subject.getall).to eq(entity) + end + + it 'returns a hash collection' do + expect(subject.getall).to be_a_kind_of(Hash) + end + + it 'has three entries' do + expect(subject.getall.size).to eq(3) + end + end + + describe '#create' do + let(:before) do + { peer_group: nil, + remote_as: nil, + send_community: true, + shutdown: true, + description: nil, + next_hop_self: true, + route_map_in: nil, + route_map_out: nil } + end + + let(:after) do + { peer_group: nil, + remote_as: nil, + send_community: false, + shutdown: true, + description: nil, + next_hop_self: false, + route_map_in: nil, + route_map_out: nil } + end + + before { node.config(['no router bgp 64600', 'router bgp 64600']) } + + it 'create a new BGP neighbor' do + expect(subject.get('edge')).to eq(before) + expect(subject.create('edge')).to be_truthy + + expect(subject.get('edge')).to eq(after) + end + end + + describe '#delete' do + let(:before) do + { peer_group: nil, + remote_as: nil, + send_community: false, + shutdown: true, + description: nil, + next_hop_self: false, + route_map_in: nil, + route_map_out: nil } + end + + let(:after) do + { peer_group: nil, + remote_as: nil, + send_community: true, + shutdown: true, + description: nil, + next_hop_self: true, + route_map_in: nil, + route_map_out: nil } + end + + it 'delete a BGP resource' do + expect(subject.get('edge')).to eq(before) + expect(subject.delete('edge')).to be_truthy + + expect(subject.get('edge')).to eq(after) + end + end + + describe '#set_peer_group' do + before do + node.config(['no router bgp 64600', 'router bgp 64600', + 'neighbor eBGP_GROUP peer-group']) + end + + it 'set the peer group' do + expect(subject.get('192.168.255.1')[:peer_group]).to eq(nil) + expect(subject.set_peer_group('192.168.255.1', value: 'eBGP_GROUP')) + .to be_truthy + expect(subject.get('192.168.255.1')[:peer_group]).to eq('eBGP_GROUP') + end + + it 'remove the peer group value' do + expect(subject.set_peer_group('192.168.255.1', value: 'eBGP_GROUP')) + .to be_truthy + expect(subject.get('192.168.255.1')[:peer_group]).to eq('eBGP_GROUP') + expect(subject.set_peer_group('192.168.255.1', enable: false)) + .to be_truthy + expect(subject.get('192.168.255.1')[:peer_group]).to eq(nil) + end + + it 'defaults the peer group value' do + expect(subject.set_peer_group('192.168.255.1', value: 'eBGP_GROUP')) + .to be_truthy + expect(subject.set_peer_group('192.168.255.1', default: true)) + .to be_truthy + expect(subject.get('192.168.255.1')[:peer_group]).to eq(nil) + end + end + + describe '#set_remote_as' do + it 'set the remote AS value' do + expect(subject.get('eng')[:remote_as]).to eq(nil) + expect(subject.set_remote_as('eng', value: '10')).to be_truthy + expect(subject.get('eng')[:remote_as]).to eq('10') + end + + it 'remove the remote AS value' do + expect(subject.get('eng')[:remote_as]).to eq('10') + expect(subject.set_remote_as('eng', enable: false)) + .to be_truthy + expect(subject.get('eng')[:remote_as]).to eq(nil) + end + + it 'defaults the remote AS value' do + expect(subject.set_remote_as('eng', value: '10')).to be_truthy + expect(subject.set_remote_as('eng', default: true)) + .to be_truthy + expect(subject.get('eng')[:remote_as]).to eq(nil) + end + end + + describe '#set_shutdown' do + it 'shutdown neighbor' do + expect(subject.get('eng')[:shutdown]).to eq(false) + expect(subject.set_shutdown('eng')).to be_truthy + expect(subject.get('eng')[:shutdown]).to eq(true) + end + + it 'negate shutdown neighbor' do + expect(subject.get('eng')[:shutdown]).to eq(true) + expect(subject.set_shutdown('eng', enable: false)).to be_truthy + expect(subject.get('eng')[:shutdown]).to eq(true) + end + + it 'default shutdown neighbor' do + expect(subject.get('eng')[:shutdown]).to eq(true) + expect(subject.set_shutdown('eng', default: true)).to be_truthy + expect(subject.get('eng')[:shutdown]).to eq(false) + end + end + + describe '#set_send_community' do + it 'enable neighbor send community' do + expect(subject.get('eng')[:send_community]).to eq(false) + expect(subject.set_send_community('eng')).to be_truthy + expect(subject.get('eng')[:send_community]).to eq(true) + end + + it 'negate neighbor send community' do + expect(subject.get('eng')[:send_community]).to eq(true) + expect(subject.set_send_community('eng', enable: false)).to be_truthy + expect(subject.get('eng')[:send_community]).to eq(false) + end + + it 'default neighbor send community' do + expect(subject.set_send_community('eng')).to be_truthy + expect(subject.get('eng')[:send_community]).to eq(true) + expect(subject.set_send_community('eng', default: true)).to be_truthy + expect(subject.get('eng')[:send_community]).to eq(false) + end + end + + describe '#set_next_hop_self' do + it 'enable neighbor next hop self' do + expect(subject.get('eng')[:next_hop_self]).to eq(false) + expect(subject.set_next_hop_self('eng')).to be_truthy + expect(subject.get('eng')[:next_hop_self]).to eq(true) + end + + it 'negate neighbor next hop self' do + expect(subject.get('eng')[:next_hop_self]).to eq(true) + expect(subject.set_next_hop_self('eng', enable: false)).to be_truthy + expect(subject.get('eng')[:next_hop_self]).to eq(false) + end + + it 'default neighbor next hop self' do + expect(subject.set_next_hop_self('eng')).to be_truthy + expect(subject.get('eng')[:next_hop_self]).to eq(true) + expect(subject.set_next_hop_self('eng', default: true)).to be_truthy + expect(subject.get('eng')[:next_hop_self]).to eq(false) + end + end + + describe '#set_route_map_in' do + it 'set route map in value' do + expect(subject.get('eng')[:route_map_in]).to eq(nil) + expect(subject.set_route_map_in('eng', value: 'edge')).to be_truthy + expect(subject.get('eng')[:route_map_in]).to eq('edge') + end + + it 'negate route map in value' do + expect(subject.get('eng')[:route_map_in]).to eq('edge') + expect(subject.set_route_map_in('eng', value: 'edge', enable: false)) + .to be_truthy + expect(subject.get('eng')[:route_map_in]).to eq(nil) + end + + it 'default route map in value' do + expect(subject.set_route_map_in('eng', value: 'edge')).to be_truthy + expect(subject.get('eng')[:route_map_in]).to eq('edge') + expect(subject.set_route_map_in('eng', value: 'edge', default: true)) + .to be_truthy + expect(subject.get('eng')[:route_map_in]).to eq(nil) + end + end + + describe '#set_route_map_out' do + it 'set route map out value' do + expect(subject.get('eng')[:route_map_out]).to eq(nil) + expect(subject.set_route_map_out('eng', value: 'edge')).to be_truthy + expect(subject.get('eng')[:route_map_out]).to eq('edge') + end + + it 'negate route map out value' do + expect(subject.get('eng')[:route_map_out]).to eq('edge') + expect(subject.set_route_map_out('eng', value: 'edge', enable: false)) + .to be_truthy + expect(subject.get('eng')[:route_map_out]).to eq(nil) + end + + it 'default route map out value' do + expect(subject.set_route_map_out('eng', value: 'edge')).to be_truthy + expect(subject.get('eng')[:route_map_out]).to eq('edge') + expect(subject.set_route_map_out('eng', value: 'edge', default: true)) + .to be_truthy + expect(subject.get('eng')[:route_map_out]).to eq(nil) + end + end + + describe '#set_description' do + it 'set the description value' do + expect(subject.get('eng')[:description]).to eq(nil) + expect(subject.set_description('eng', value: 'text')).to be_truthy + expect(subject.get('eng')[:description]).to eq('text') + end + + it 'negate the description value' do + expect(subject.get('eng')[:description]).to eq('text') + expect(subject.set_description('eng', enable: false)).to be_truthy + expect(subject.get('eng')[:description]).to eq(nil) + end + + it 'defaults the description value' do + expect(subject.set_description('eng', value: 'text')).to be_truthy + expect(subject.get('eng')[:description]).to eq('text') + expect(subject.set_description('eng', default: true)).to be_truthy + expect(subject.get('eng')[:description]).to eq(nil) + end + end +end diff --git a/spec/system/rbeapi/api/bgp_spec.rb b/spec/system/rbeapi/api/bgp_spec.rb new file mode 100644 index 0000000..063c11c --- /dev/null +++ b/spec/system/rbeapi/api/bgp_spec.rb @@ -0,0 +1,375 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' +require 'rbeapi/api/bgp' + +describe Rbeapi::Api::Bgp do + subject { described_class.new(node) } + + let(:node) do + Rbeapi::Client.config.read(fixture_file('dut.conf')) + Rbeapi::Client.connect_to('dut') + end + + let(:test) do + { bgp_as: '64600', + router_id: '192.168.254.1', + shutdown: false, + maximum_paths: 32, + maximum_ecmp_paths: 32, + networks: [ + { prefix: '192.168.254.1', masklen: 32, route_map: nil }, + { prefix: '192.168.254.2', masklen: 32, route_map: 'rmap' } + ], + neighbors: { + 'eBGP_GROUP' => { + peer_group: nil, remote_as: nil, send_community: false, + shutdown: false, description: nil, next_hop_self: false, + route_map_in: nil, route_map_out: nil + }, + '192.168.255.1' => { + peer_group: 'eBGP_GROUP', remote_as: '65000', send_community: true, + shutdown: true, description: nil, next_hop_self: true, + route_map_in: nil, route_map_out: nil + }, + '192.168.255.3' => { + peer_group: 'eBGP_GROUP', remote_as: '65001', send_community: true, + shutdown: true, description: nil, next_hop_self: true, + route_map_in: nil, route_map_out: nil + } + } + } + end + + describe '#get' do + before do + node.config(['no router bgp 64600', 'router bgp 64600', + 'no shutdown', + 'router-id 192.168.254.1', + 'bgp convergence time 300', + 'bgp convergence slow-peer time 90', + 'no bgp confederation identifier', + 'no update wait-for-convergence', + 'no update wait-install', + 'bgp log-neighbor-changes', + 'bgp default ipv4-unicast', + 'no bgp default ipv6-unicast', + 'timers bgp 60 180', + 'distance bgp 20 200 200', + 'graceful-restart stalepath-time 300', + 'no bgp cluster-id', + 'bgp client-to-client reflection', + 'graceful-restart-helper', + 'bgp peer-mac-resolution-timeout 0', + 'bgp enforce-first-as', + 'no default-metric', + 'no bgp always-compare-med', + 'no bgp bestpath med missing-as-worst', + 'no bgp bestpath med confed', + 'no bgp host-routes fib direct-install', + 'maximum-paths 32 ecmp 32', + 'bgp listen limit 1000', + 'no bgp aspath-cmp-include-nexthop', + 'no bgp tie-break-on-age', + 'no bgp tie-break-on-router-id', + 'no bgp tie-break-on-originator-id', + 'no bgp tie-break-on-cluster-list-length', + 'neighbor eBGP_GROUP peer-group', + 'no neighbor eBGP_GROUP remote-as', + 'no neighbor eBGP_GROUP import-localpref', + 'no neighbor eBGP_GROUP export-localpref', + 'no neighbor eBGP_GROUP description', + 'no neighbor eBGP_GROUP next-hop-self', + 'no neighbor eBGP_GROUP next-hop-peer', + 'no neighbor eBGP_GROUP allowas-in', + 'no neighbor eBGP_GROUP send-community', + 'no neighbor eBGP_GROUP shutdown', + 'no neighbor eBGP_GROUP remove-private-as', + 'no neighbor eBGP_GROUP out-delay', + 'no neighbor eBGP_GROUP local-as', + 'no neighbor eBGP_GROUP weight', + 'no neighbor eBGP_GROUP transport connection-mode passive', + 'no neighbor eBGP_GROUP update-source', + 'no neighbor eBGP_GROUP dont-capability-negotiate', + 'neighbor eBGP_GROUP fall-over bfd', + 'no neighbor eBGP_GROUP local-v6-addr', + 'neighbor eBGP_GROUP soft-reconfiguration inbound', + 'no neighbor eBGP_GROUP ebgp-multihop', + 'no neighbor eBGP_GROUP route-reflector-client', + 'no neighbor eBGP_GROUP timers', + 'no neighbor eBGP_GROUP route-map in', + 'neighbor eBGP_GROUP graceful-restart-helper', + 'no neighbor eBGP_GROUP route-map out', + 'no neighbor eBGP_GROUP prefix-list in', + 'no neighbor eBGP_GROUP prefix-list out', + 'neighbor eBGP_GROUP password 7 6C/HkrwJ53+dsHumQf49Wg==', + 'no neighbor eBGP_GROUP default-originate', + 'neighbor eBGP_GROUP enforce-first-as', + 'no neighbor eBGP_GROUP metric-out', + 'neighbor eBGP_GROUP maximum-routes 12000', + 'neighbor 192.168.255.1 peer-group eBGP_GROUP', + 'neighbor 192.168.255.1 remote-as 65000', + 'neighbor 192.168.255.3 peer-group eBGP_GROUP', + 'neighbor 192.168.255.3 remote-as 65001', + 'network 192.168.254.1/32', + 'network 192.168.254.2/32 route-map rmap', + 'bgp redistribute-internal', + 'aggregate-address 192.168.255.0/28 summary-only', + 'no redistribute connected', + 'no redistribute ospf match internal', + 'no redistribute ospf match external', + 'no redistribute ospf match nssa-external', + 'no redistribute ospf3 match internal', + 'no redistribute ospf3 match external', + 'no redistribute static', + 'no redistribute rip', + 'no redistribute aggregate', + 'address-family ipv4', + 'default neighbor eBGP_GROUP activate', + 'no neighbor eBGP_GROUP route-map in', + 'no neighbor eBGP_GROUP route-map out', + 'no neighbor eBGP_GROUP default-originate', + 'default neighbor 192.168.255.1 activate', + 'default neighbor 192.168.255.3 activate', + 'address-family ipv6', + 'default neighbor eBGP_GROUP activate', + 'no neighbor eBGP_GROUP route-map in', + 'no neighbor eBGP_GROUP route-map out', + 'no neighbor eBGP_GROUP prefix-list in', + 'no neighbor eBGP_GROUP prefix-list out', + 'no neighbor eBGP_GROUP default-originate', + 'default neighbor 192.168.255.1 activate', + 'default neighbor 192.168.255.3 activate']) + end + + it 'returns the BGP resource' do + expect(subject.get).to eq(test) + end + end + + describe '#create' do + let(:response) do + { + bgp_as: '1000', + router_id: nil, + shutdown: false, + maximum_paths: 1, + maximum_ecmp_paths: 128, + networks: [], + neighbors: {} + } + end + + before do + node.config(['no router bgp 64600']) + end + + it 'create a new BGP resource' do + expect(subject.get).to eq(nil) + expect(subject.create('1000')).to be_truthy + expect(subject.get).to eq(response) + end + + it 'create with enable' do + expect(subject.get).to eq(nil) + expect(subject.create('1000', enable: true)).to be_truthy + expect(subject.get).to eq(response) + end + + it 'create with router_id' do + expect(subject.get).to eq(nil) + expect(subject.create('1000', router_id: '1.2.3.4')).to be_truthy + expect(subject.get[:router_id]).to eq('1.2.3.4') + end + + it 'create with maximum paths' do + expect(subject.get).to eq(nil) + expect(subject.create('1000', maximum_paths: 3)).to be_truthy + expect(subject.get[:maximum_paths]).to eq(3) + end + + it 'create with maximum paths and ecmp paths' do + expect(subject.get).to eq(nil) + expect(subject.create('1000', maximum_paths: 13, + maximum_ecmp_paths: 13)).to be_truthy + expect(subject.get[:maximum_paths]).to eq(13) + expect(subject.get[:maximum_ecmp_paths]).to eq(13) + end + + it 'raises ArgumentError for create with ecmp paths only' do + expect { subject.create('1000', maximum_ecmp_paths: 13) }.to \ + raise_error ArgumentError + end + + it 'create with all options set' do + expect(subject.create('1000', enable: true, router_id: '1.2.3.4', + maximum_paths: 13, + maximum_ecmp_paths: 13)).to be_truthy + expect(subject.get[:router_id]).to eq('1.2.3.4') + expect(subject.get[:maximum_paths]).to eq(13) + expect(subject.get[:maximum_ecmp_paths]).to eq(13) + end + end + + describe '#delete' do + before do + node.config(['no router bgp 1000', 'router bgp 1000']) + end + + let(:response) do + { + bgp_as: '1000', + router_id: nil, + shutdown: false, + maximum_paths: 1, + maximum_ecmp_paths: 128, + networks: [], + neighbors: {} + } + end + + it 'delete a BGP resource' do + expect(subject.get).to eq(response) + expect(subject.delete).to be_truthy + expect(subject.get).to eq(nil) + end + end + + describe '#default' do + before do + node.config(['no router bgp 1000', 'router bgp 1000', + 'maximum-paths 13 ecmp 15']) + end + + let(:before) do + { + bgp_as: '1000', + router_id: nil, + shutdown: false, + maximum_paths: 13, + maximum_ecmp_paths: 15, + networks: [], + neighbors: {} + } + end + + it 'sets router to default value' do + expect(subject.get).to eq(before) + expect(subject.default).to be_truthy + expect(subject.get).to eq(nil) + end + end + + describe '#set_router_id' do + before do + node.config(['no router bgp 1000', 'router bgp 1000']) + end + + it 'set the router id' do + expect(subject.set_router_id(value: '1.2.3.4')).to be_truthy + expect(subject.get[:router_id]).to eq('1.2.3.4') + end + + it 'remove the router-id without a value' do + expect(subject.set_router_id(enable: false)).to be_truthy + expect(subject.get[:router_id]).to eq(nil) + end + + it 'remove the router-id with a value' do + expect(subject.set_router_id(value: '1.2.3.4', enable: false)) + .to be_truthy + expect(subject.get[:router_id]).to eq(nil) + end + + it 'defaults the router-id without a value' do + expect(subject.set_router_id(value: '1.2.3.4')).to be_truthy + expect(subject.set_router_id(default: true)).to be_truthy + expect(subject.get[:router_id]).to eq(nil) + end + + it 'defaults the router-id with a value' do + expect(subject.set_router_id(value: '1.2.3.4', default: true)) + .to be_truthy + expect(subject.get[:router_id]).to eq(nil) + end + end + + describe '#set_shutdown' do + it 'enable BGP routing process' do + expect(subject.set_shutdown(enable: true)).to be_truthy + end + + it 'disable BGP routing process' do + expect(subject.set_shutdown(enable: false)).to be_truthy + end + + it 'default BGP routing process state' do + expect(subject.set_shutdown(default: true)).to be_truthy + end + end + + describe '#set_maximum_paths' do + it 'set the maximum paths and ecmp paths' do + expect(subject.set_maximum_paths(13, 16)).to be_truthy + end + + it 'remove the maximum paths' do + expect(subject.set_maximum_paths(0, 0, enable: false)).to be_truthy + end + + it 'defaults the maximum paths' do + expect(subject.set_maximum_paths(0, 0, default: true)).to be_truthy + end + end + + describe '#add_network' do + it 'add a BGP network with a route map' do + expect(subject.add_network('1.2.3.0', 24, 'eng')).to be_truthy + end + + it 'add a BGP network without a route map' do + expect(subject.add_network('1.2.3.0', 24)).to be_truthy + end + end + + describe '#remove_network' do + it 'remove a BGP network with a route map' do + expect(subject.remove_network('1.2.3.0', 24, 'eng')).to be_truthy + end + + it 'remove a BGP network without a route map' do + expect(subject.remove_network('1.2.3.0', 24)).to be_truthy + end + end +end diff --git a/spec/system/api_ospf_interfaces_spec.rb b/spec/system/rbeapi/api/ospf_interfaces_spec.rb similarity index 100% rename from spec/system/api_ospf_interfaces_spec.rb rename to spec/system/rbeapi/api/ospf_interfaces_spec.rb diff --git a/spec/system/api_ospf_spec.rb b/spec/system/rbeapi/api/ospf_spec.rb similarity index 100% rename from spec/system/api_ospf_spec.rb rename to spec/system/rbeapi/api/ospf_spec.rb diff --git a/spec/system/rbeapi/api/staticroutes_spec.rb b/spec/system/rbeapi/api/staticroutes_spec.rb new file mode 100644 index 0000000..a4980e2 --- /dev/null +++ b/spec/system/rbeapi/api/staticroutes_spec.rb @@ -0,0 +1,177 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' +require 'rbeapi/api/staticroutes' + +describe Rbeapi::Api::Staticroutes do + subject { described_class.new(node) } + + let(:node) do + Rbeapi::Client.config.read(fixture_file('dut.conf')) + Rbeapi::Client.connect_to('dut') + end + + describe '#getall' do + let(:resource) { subject.getall } + + before do + node.config(['no ip route 1.2.3.4/32', + 'no ip route 192.0.2.0/24', + 'no ip route 192.0.3.0/24', + 'ip route 1.2.3.4/32 Ethernet7 4 tag 3 name frank', + 'ip route 1.2.3.4/32 Null0 32 tag 3 name fred', + 'ip route 192.0.2.0/24 Ethernet7 3 tag 0 name dummy1', + 'ip route 192.0.3.0/24 192.0.3.1 1 tag 0 name dummy2']) + end + + it 'returns the staticroute collection' do + expect(subject.getall).to include(destination: '1.2.3.4/32', + nexthop: 'Ethernet7', + distance: '4', + tag: '3', + name: 'frank') + expect(subject.getall).to include(destination: '1.2.3.4/32', + nexthop: 'Null0', + distance: '32', + tag: '3', + name: 'fred') + expect(subject.getall).to include(destination: '192.0.2.0/24', + nexthop: 'Ethernet7', + distance: '3', + tag: '0', + name: 'dummy1') + expect(subject.getall).to include(destination: '192.0.3.0/24', + nexthop: '192.0.3.1', + distance: '1', + tag: '0', + name: 'dummy2') + end + + it 'returns a hash collection' do + expect(subject.getall).to be_a_kind_of(Array) + end + + it 'has four entries' do + expect(subject.getall.size).to eq(4) + end + end + + describe '#create' do + let(:resource) { subject.getall } + + before(:each) do + node.config(['no ip route 1.2.3.4/32', + 'no ip route 192.0.2.0/24', + 'no ip route 192.0.3.0/24']) + end + + context 'creates a new staticroute resoure' do + it 'with minimum input' do + expect(subject.getall).to eq([]) + expect(subject.create('192.0.2.0/24', 'Ethernet1')).to be_truthy + expect(subject.getall).to eq(resource) + end + + it 'with a router_ip' do + node.config(['ip route 192.0.2.0/24 Ethernet1']) + expect(subject.getall).to eq(resource) + + expect(subject.create('192.0.2.0/24', 'Ethernet1', + router_ip: '192.168.1.1')).to be_truthy + expect(subject.getall).to eq(resource) + end + + it 'with distance (metric)' do + node.config(['ip route 192.0.2.0/24 Ethernet1']) + expect(subject.getall).to eq(resource) + + expect(subject.create('192.0.2.0/24', 'Ethernet1', distance: 254)) + .to be_truthy + expect(subject.getall).to include(destination: '192.0.2.0/24', + nexthop: 'Ethernet1', + distance: '254', + tag: '0', + name: nil) + end + + it 'with a tag' do + node.config(['ip route 192.0.2.0/24 Ethernet1']) + expect(subject.getall).to eq(resource) + + expect(subject.create('192.0.2.0/24', 'Ethernet1', tag: 3)) + .to be_truthy + expect(subject.getall).to include(destination: '192.0.2.0/24', + nexthop: 'Ethernet1', + distance: '1', + tag: '3', + name: nil) + end + + it 'with a name' do + node.config(['ip route 192.0.2.0/24 Ethernet1']) + expect(subject.getall).to eq(resource) + + expect(subject.create('192.0.2.0/24', 'Ethernet1', name: 'my_route')) + .to be_truthy + expect(subject.getall).to include(destination: '192.0.2.0/24', + nexthop: 'Ethernet1', + distance: '1', + tag: '0', + name: 'my_route') + end + end + end + + describe '#delete' do + let(:resource) { subject.getall } + + before do + node.config(['ip route 192.0.2.0/24 Ethernet1']) + end + + context 'deletes a staticroute resource' do + it 'given only a destination network' do + expect(subject.getall).to eq(resource) + expect(subject.delete('192.0.2.0/24')).to be_truthy + expect(subject.getall).to eq([]) + end + + it 'given a destination and nexthop' do + expect(subject.getall).to eq(resource) + expect(subject.delete('192.0.2.0/24', 'Ethernet1')).to be_truthy + expect(subject.getall).to eq([]) + end + end + end +end From e26b9743216e8cfe9867c11b9e5663c2b498be47 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 30 Nov 2015 16:26:37 -0700 Subject: [PATCH 003/110] Ensure that nil is returned when you try to get nonexistent username. --- lib/rbeapi/api/users.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rbeapi/api/users.rb b/lib/rbeapi/api/users.rb index c546f9a..6d5cde9 100644 --- a/lib/rbeapi/api/users.rb +++ b/lib/rbeapi/api/users.rb @@ -94,7 +94,7 @@ def get(name) (username\s+#{name}\s+ sshkey\s+(?.*)$)?/x) user = config.scan(user_re) - return nil unless user + return nil unless user && user[0] parse_user_entry(user[0]) end From cdd3dc06575b055521708b07c1b7fcff62aba5da Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Tue, 1 Dec 2015 14:03:16 -0700 Subject: [PATCH 004/110] Adding users system test. Currently having an issue with sha512 encryption. --- spec/system/rbeapi/api/users_spec.rb | 322 +++++++++++++++++++++++++++ 1 file changed, 322 insertions(+) create mode 100644 spec/system/rbeapi/api/users_spec.rb diff --git a/spec/system/rbeapi/api/users_spec.rb b/spec/system/rbeapi/api/users_spec.rb new file mode 100644 index 0000000..d6d8a1a --- /dev/null +++ b/spec/system/rbeapi/api/users_spec.rb @@ -0,0 +1,322 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' +require 'rbeapi/api/users' + +describe Rbeapi::Api::Users do + subject { described_class.new(node) } + + let(:node) do + Rbeapi::Client.config.read(fixture_file('dut.conf')) + Rbeapi::Client.connect_to('dut') + end + + let(:sshkey) do + 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKL1UtBALa4CvFUsHUipN' \ + 'ymA04qCXuAtTwNcMj84bTUzUI+q7mdzRCTLkllXeVxKuBnaTm2PW7W67K5C' \ + 'Vpl0EVCm6IY7FS7kc4nlnD/tFvTvShy/fzYQRAdM7ZfVtegW8sMSFJzBR/T' \ + '/Y/sxI16Y/dQb8fC3la9T25XOrzsFrQiKRZmJGwg8d+0RLxpfMg0s/9ATwQ' \ + 'Kp6tPoLE4f3dKlAgSk5eENyVLA3RsypWADHpenHPcB7sa8D38e1TS+n+EUy' \ + 'Adb3Yov+5ESAbgLIJLd52Xv+FyYi0c2L49ByBjcRrupp4zfXn4DNRnEG4K6' \ + 'GcmswHuMEGZv5vjJ9OYaaaaaaa' + end + + let(:secret) do + '$1$Ehb5lL0D$N3MgrkfMFxmeh0FSZ5sEZ1' + end + + let(:test) do + { name: 'rbeapi', + privilege: 1, + role: nil, + nopassword: false, + encryption: 'md5', + secret: secret, + sshkey: sshkey + } + end + + describe '#getall' do + let(:resource) { subject.getall } + + let(:test1_entries) do + { 'admin' => { name: 'admin', privilege: 1, + role: 'network-admin', nopassword: true, + encryption: nil, secret: nil, sshkey: nil }, + 'rbeapi' => { name: 'rbeapi', privilege: 1, role: nil, + nopassword: false, encryption: 'md5', + secret: secret, + sshkey: sshkey } + } + end + + before do + node.config(['no username rbeapi', + 'no username user1', + 'username admin privilege 1 role network-admin nopassword', + "username rbeapi privilege 1 secret 5 #{secret}", + "username rbeapi sshkey #{sshkey}"]) + end + + it 'returns the username collection' do + expect(subject.getall).to include(test1_entries) + end + + it 'returns a hash collection' do + expect(subject.getall).to be_a_kind_of(Hash) + end + + it 'has two entries' do + expect(subject.getall.size).to eq(2) + end + end + + describe '#get' do + it 'returns the user resource for given name' do + expect(subject.get('rbeapi')).to eq(test) + end + + it 'returns a hash' do + expect(subject.get('rbeapi')).to be_a_kind_of(Hash) + end + + it 'has two entries' do + expect(subject.get('rbeapi').size).to eq(7) + end + end + + describe '#create' do + before do + node.config(['no username rbeapi']) + end + + it 'create a new user name with no password' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', nopassword: :true)).to be_truthy + expect(subject.get('rbeapi')[:nopassword]).to eq(true) + end + + it 'create a new user name with no password and privilege' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', + privilege: 4, + nopassword: :true)).to be_truthy + expect(subject.get('rbeapi')[:privilege]).to eq(4) + end + + it 'create a new user name with no password, privilege, and role' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', + privilege: 4, + role: 'net-minion', + nopassword: :true)).to be_truthy + expect(subject.get('rbeapi')[:privilege]).to eq(4) + expect(subject.get('rbeapi')[:role]).to eq('net-minion') + expect(subject.get('rbeapi')[:nopassword]).to eq(true) + end + + it 'create a new user name with a password' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', secret: 'icanttellyou')).to be_truthy + expect(subject.get('rbeapi')[:encryption]).to eq('md5') + end + + it 'create a new user name with a password and privilege' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', + secret: 'icanttellyou', + privilege: 5)).to be_truthy + expect(subject.get('rbeapi')[:encryption]).to eq('md5') + expect(subject.get('rbeapi')[:privilege]).to eq(5) + end + + it 'create a new user name with a password, privilege, and role' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', + secret: 'icanttellyou', + privilege: 5, role: 'net')).to be_truthy + expect(subject.get('rbeapi')[:encryption]).to eq('md5') + expect(subject.get('rbeapi')[:privilege]).to eq(5) + expect(subject.get('rbeapi')[:role]).to eq('net') + end + + it 'create a new user name with a password and md5 encryption' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', + secret: '$1$Wb4zN5EH$ILNgYb3Ehzs85S9KpoFW4.', + encryption: 'md5')).to be_truthy + expect(subject.get('rbeapi')[:encryption]).to eq('md5') + expect(subject.get('rbeapi')[:secret]) + .to eq('$1$Wb4zN5EH$ILNgYb3Ehzs85S9KpoFW4.') + end + + it 'create a new user name with a password and sha512 encryption' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', + secret: '$6$somesalt$rkDq7Az4Efjo', + encryption: 'sha512')).to be_truthy + expect(subject.get('rbeapi')).to eq(nil) + end + + it 'create a new user name with a password, sha512 encryption, and key' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', + secret: '$6$somesalt$rkDq7Az4Efjo', + encryption: 'sha512', + sshkey: sshkey)).to be_truthy + end + + it 'raises ArgumentError for create without required args ' do + expect { subject.create('rbeapi') }.to \ + raise_error ArgumentError + end + + it 'raises ArgumentError for invalid encryption value' do + expect { subject.create('name', encryption: 'bogus') }.to \ + raise_error ArgumentError + end + end + + describe '#delete' do + before do + node.config(['username user1 privilege 1 role network-admin nopassword']) + end + + it 'delete a username resource' do + expect(subject.get('user1')[:name]).to eq('user1') + expect(subject.delete('user1')).to be_truthy + expect(subject.get('user1')).to eq(nil) + end + end + + describe '#default' do + before do + node.config(['username user1 privilege 1 role network-admin nopassword']) + end + + it 'sets username resource to default value' do + expect(subject.get('user1')[:name]).to eq('user1') + expect(subject.default('user1')).to be_truthy + expect(subject.get('user1')).to eq(nil) + end + end + + describe '#set_privilege' do + before do + node.config(['no username rbeapi', + 'username rbeapi role network-admin nopassword']) + end + + it 'set the privilege' do + expect(subject.set_privilege('rbeapi', value: '13')).to be_truthy + expect(subject.get('rbeapi')[:privilege]).to eq(13) + end + + it 'remove the privilege without a value' do + expect(subject.set_privilege('rbeapi', enable: false)).to be_truthy + expect(subject.get('rbeapi')).to eq(nil) + end + + it 'remove the privilege with a value' do + expect(subject.set_privilege('rbeapi', value: '13', enable: false)) + .to be_truthy + expect(subject.get('rbeapi')).to eq(nil) + end + + it 'defaults the privilege without a value' do + expect(subject.set_privilege('rbeapi', default: true)).to be_truthy + expect(subject.get('rbeapi')).to eq(nil) + end + + it 'defaults the privilege with a value' do + expect(subject.set_privilege('rbeapi', value: '3', default: true)) + .to be_truthy + expect(subject.get('rbeapi')).to eq(nil) + end + end + + describe '#set_role' do + before do + node.config(['no username rbeapi', 'username rbeapi nopassword']) + end + + it 'set the role' do + expect(subject.set_role('rbeapi', value: 'net-minion')).to be_truthy + expect(subject.get('rbeapi')[:role]).to eq('net-minion') + end + + it 'remove the role without a value' do + expect(subject.set_role('rbeapi', enable: false)).to be_truthy + expect(subject.get('rbeapi')[:role]).to eq(nil) + end + + it 'remove the role with a value' do + expect(subject.set_role('rbeapi', value: 'net', enable: false)) + .to be_truthy + expect(subject.get('rbeapi')[:role]).to eq(nil) + end + + it 'defaults the role without a value' do + expect(subject.set_role('rbeapi', default: true)).to be_truthy + expect(subject.get('rbeapi')[:role]).to eq(nil) + end + + it 'defaults the role with a value' do + expect(subject.set_role('rbeapi', value: 'net', default: true)) + .to be_truthy + expect(subject.get('rbeapi')[:role]).to eq(nil) + end + end + + describe '#set_sshkey' do + before do + node.config(['no username rbeapi', 'username rbeapi nopassword']) + end + + it 'set the sshkey' do + expect(subject.set_sshkey('rbeapi', value: sshkey)).to be_truthy + end + + it 'remove the sshkey with a value' do + expect(subject.set_sshkey('rbeapi', value: sshkey, enable: false)) + .to be_truthy + expect(subject.get('rbeapi')[:sshkey]).to eq(nil) + end + + it 'defaults the sshkey without a value' do + expect(subject.set_sshkey('rbeapi', default: true)).to be_truthy + expect(subject.get('rbeapi')[:sshkey]).to eq(nil) + end + end +end From 648851f3f5828015ea7517b9d632e6b68bc9b6c3 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Wed, 2 Dec 2015 19:33:48 -0700 Subject: [PATCH 005/110] Add vrrp system test --- spec/system/rbeapi/api/vrrp_spec.rb | 703 ++++++++++++++++++++++++++++ 1 file changed, 703 insertions(+) create mode 100644 spec/system/rbeapi/api/vrrp_spec.rb diff --git a/spec/system/rbeapi/api/vrrp_spec.rb b/spec/system/rbeapi/api/vrrp_spec.rb new file mode 100644 index 0000000..55f2ddc --- /dev/null +++ b/spec/system/rbeapi/api/vrrp_spec.rb @@ -0,0 +1,703 @@ +require 'spec_helper' + +require 'rbeapi/client' +require 'rbeapi/api/vrrp' + +describe Rbeapi::Api::Vrrp do + subject { described_class.new(node) } + + let(:node) do + Rbeapi::Client.config.read(fixture_file('dut.conf')) + Rbeapi::Client.connect_to('dut') + end + + before :all do + @sec_ips = ['1.2.3.1', '1.2.3.2', '1.2.3.3', '1.2.3.4'] + @tracks = [{ name: 'Ethernet3', action: 'decrement', amount: 33 }, + { name: 'Ethernet2', action: 'decrement', amount: 22 }, + { name: 'Ethernet2', action: 'shutdown' }] + end + + describe '#get' do + before do + node.config(['no interface Vlan150', 'no interface Vlan100', + 'interface Vlan100', 'interface Vlan150', + 'ip address 40.10.5.8/24', 'vrrp 30 priority 100', + 'vrrp 30 timers advertise 1', + 'vrrp 30 mac-address advertisement-interval 30', + 'no vrrp 30 preempt', 'vrrp 30 preempt delay minimum 0', + 'vrrp 30 preempt delay reload 0', 'vrrp 30 delay reload 0', + 'no vrrp 30 authentication', 'vrrp 30 ip 40.10.5.31', + 'vrrp 30 ipv6 ::', 'vrrp 30 description The description', + 'vrrp 30 shutdown', 'vrrp 30 track Ethernet1 decrement 5', + 'no vrrp 30 bfd ip', 'no vrrp 30 bfd ipv6', + 'vrrp 30 ip version 2', 'vrrp 40 priority 200', + 'vrrp 40 timers advertise 1', + 'vrrp 40 mac-address advertisement-interval 30', + 'vrrp 40 preempt', 'vrrp 40 preempt delay minimum 0', + 'vrrp 40 preempt delay reload 0', 'vrrp 40 delay reload 0', + 'no vrrp 40 authentication', 'vrrp 40 ip 40.10.5.32', + 'vrrp 40 ipv6 ::', 'no vrrp 40 description', + 'no vrrp 40 shutdown', + 'vrrp 40 track Ethernet3 decrement 33', + 'vrrp 40 track Ethernet2 decrement 22', + 'vrrp 40 track Ethernet2 shutdown', 'no vrrp 40 bfd ip', + 'no vrrp 40 bfd ipv6', 'vrrp 40 ip version 2']) + end + + let(:entity) do + { 30 => { primary_ip: '40.10.5.31', delay_reload: 0, + description: 'The description', enable: false, ip_version: 2, + mac_addr_adv_interval: 30, preempt: false, preempt_delay_min: 0, + preempt_delay_reload: 0, priority: 100, secondary_ip: [], + timers_advertise: 1, + track: [ + { name: 'Ethernet1', action: 'decrement', amount: 5 } + ] + }, + 40 => { primary_ip: '40.10.5.32', delay_reload: 0, description: nil, + enable: true, ip_version: 2, mac_addr_adv_interval: 30, + preempt: true, preempt_delay_min: 0, preempt_delay_reload: 0, + priority: 200, secondary_ip: [], timers_advertise: 1, + track: @tracks + } + } + end + + it 'returns the virtual router resource' do + expect(subject.get('Vlan150')).to eq(entity) + end + end + + describe '#getall' do + it 'returns a hash collection' do + expect(subject.getall).to be_a_kind_of(Hash) + end + + it 'returns the virtual router collection' do + expect(subject.getall).to include('Vlan100') + expect(subject.getall).to include('Vlan150') + end + end + + describe '#create' do + before do + node.config(['no interface Vlan100']) + end + + it 'creates a new virtual router with enable true' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, enable: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'creates a new virtual router with enable false' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, enable: false)).to be_truthy + expect(subject.get('Vlan100')).to include(9) + end + + it 'creates a new virtual router with primary ip' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, primary_ip: '1.2.3.4')).to be_truthy + expect(subject.get('Vlan100')[9][:primary_ip]).to eq('1.2.3.4') + end + + it 'creates a new virtual router with priority' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, primary_ip: '1.2.3.4', + priority: 100)).to be_truthy + expect(subject.get('Vlan100')[9][:priority]).to eq(100) + end + + it 'creates a new virtual router with description' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, description: 'Desc')).to be_truthy + expect(subject.get('Vlan100')[9][:description]).to eq('Desc') + end + + it 'creates a new virtual router with secondary ips' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, primary_ip: '100.99.98.100')) + .to be_truthy + expect(subject.create('Vlan100', 9, + secondary_ip: ['100.99.98.71', + '100.99.98.70'])).to be_truthy + expect(subject.get('Vlan100')[9][:secondary_ip]).to eq(['100.99.98.70', + '100.99.98.71']) + end + + it 'creates a new virtual router with ip version 2' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', + 9, + primary_ip: '100.99.98.100', + ip_version: 2)).to be_truthy + expect(subject.get('Vlan100')[9][:ip_version]).to eq(2) + end + + it 'creates a new virtual router with timers advertise' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, timers_advertise: 77)).to be_truthy + expect(subject.get('Vlan100')[9][:timers_advertise]).to eq(77) + end + + it 'creates a new virtual router with mac addr adv interval' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, mac_addr_adv_interval: 77)) + .to be_truthy + expect(subject.get('Vlan100')[9][:mac_addr_adv_interval]).to eq(77) + end + + it 'creates a new virtual router with preemt true' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, primary_ip: '100.99.98.100')) + .to be_truthy + expect(subject.create('Vlan100', 9, preempt: true)).to be_truthy + expect(subject.get('Vlan100')[9][:preempt]).to eq(true) + end + + it 'creates a new virtual router with preemt false' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, preempt: false)).to be_truthy + expect(subject.get('Vlan100')[9][:preempt]).to eq(false) + end + + it 'creates a new virtual router with preempt delay min' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, preempt_delay_min: 100)) + .to be_truthy + expect(subject.get('Vlan100')[9][:preempt_delay_min]).to eq(100) + end + + it 'creates a new virtual router with preempt delay reload' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, preempt_delay_reload: 100)) + .to be_truthy + expect(subject.get('Vlan100')[9][:preempt_delay_reload]).to eq(100) + end + + it 'creates a new virtual router with preempt delay reload' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, delay_reload: 100)).to be_truthy + expect(subject.get('Vlan100')[9][:delay_reload]).to eq(100) + end + + it 'creates a new virtual router with track values' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, primary_ip: '100.99.98.100')) + .to be_truthy + expect(subject.create('Vlan100', + 9, + track: [{ name: 'Ethernet3', + action: 'decrement', + amount: 33 }, + { name: 'Ethernet2', + action: 'decrement', + amount: 22 }, + { name: 'Ethernet2', + action: 'shutdown' }])).to be_truthy + expect(subject.get('Vlan100')[9][:track]).to eq(@tracks) + end + + it 'creates a new virtual router resource with enable and primary ip' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, enable: true, primary_ip: '1.2.3.4')) + .to be_truthy + expect(subject.get('Vlan100')[9][:primary_ip]).to eq('1.2.3.4') + end + + it 'creates a new virtual router resource with enable and priority' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, primary_ip: '100.99.98.100')) + .to be_truthy + expect(subject.create('Vlan100', 9, enable: true, priority: 100)) + .to be_truthy + expect(subject.get('Vlan100')[9][:priority]).to eq(100) + end + + it 'creates a new virtual router resource with enable and description' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, enable: true, description: 'Desc')) + .to be_truthy + expect(subject.get('Vlan100')[9][:description]).to eq('Desc') + end + + it 'creates a new virtual router resource with enable and secondary_ip' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, primary_ip: '100.99.98.100')) + .to be_truthy + expect(subject.create('Vlan100', + 9, + enable: true, + secondary_ip: ['1.2.3.1', + '1.2.3.2', + '1.2.3.3', '1.2.3.4'])).to be_truthy + expect(subject.get('Vlan100')[9][:secondary_ip]).to eq(@sec_ips) + end + + it 'creates a new virtual router resource with all options set' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, primary_ip: '100.99.98.100')) + .to be_truthy + expect(subject.create('Vlan100', + 9, + enable: true, + priority: 100, + description: 'Desc', + secondary_ip: ['100.99.98.71', + '100.99.98.70'], + ip_version: 2, + timers_advertise: 77, + mac_addr_adv_interval: 77, + preempt: true, + preempt_delay_min: 100, + preempt_delay_reload: 100, + delay_reload: 100, + track: [{ name: 'Ethernet3', + action: 'decrement', + amount: 33 }, + { name: 'Ethernet2', + action: 'decrement', + amount: 22 }, + { name: 'Ethernet2', + action: 'shutdown' }])).to be_truthy + end + + it 'raises ArgumentError for create without options' do + expect { subject.create('Vlan100', 9) }.to \ + raise_error ArgumentError + end + end + + describe '#delete' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'deletes a virtual router resource' do + expect(subject.delete('Vlan100', 9)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#default' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'sets virtual router resource to default' do + expect(subject.default('Vlan100', 9)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_shutdown' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'enable Vlan100 vrid 9' do + expect(subject.set_shutdown('Vlan100', 9)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'disable Vlan100 vrid 9' do + expect(subject.create('Vlan100', 9, primary_ip: '100.99.98.100')) + .to be_truthy + expect(subject.set_shutdown('Vlan100', 9, enable: false)).to be_truthy + expect(subject.get('Vlan100')[9][:enable]).to eq(false) + end + + it 'defaults Vlan100 vrid 9' do + expect(subject.set_shutdown('Vlan100', 9, default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_shutdown('Vlan100', 9, enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_primary_ip' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'set primary IP address' do + expect(subject.set_primary_ip('Vlan100', 9, + value: '1.2.3.4')).to be_truthy + expect(subject.get('Vlan100')[9][:primary_ip]).to eq('1.2.3.4') + end + + it 'disable primary IP address' do + expect(subject.set_primary_ip('Vlan100', 9, value: '1.2.3.4', + enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults primary IP address' do + expect(subject.set_primary_ip('Vlan100', 9, value: '1.2.3.4', + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_primary_ip('Vlan100', 9, enable: false, + value: '1.2.3.4', + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_priority' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'set priority' do + expect(subject.set_priority('Vlan100', 9, value: 13)).to be_truthy + expect(subject.get('Vlan100')[9][:priority]).to eq(13) + end + + it 'disable priority' do + expect(subject.set_priority('Vlan100', 9, enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults priority' do + expect(subject.set_priority('Vlan100', 9, default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_priority('Vlan100', 9, enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_description' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'set description' do + expect(subject.set_description('Vlan100', 9, + value: 'Howdy')).to be_truthy + expect(subject.get('Vlan100')[9][:description]).to eq('Howdy') + end + + it 'disable description' do + expect(subject.set_description('Vlan100', 9, enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults description' do + expect(subject.set_description('Vlan100', 9, default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_description('Vlan100', 9, enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_secondary_ip' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'set secondary IP addresses' do + # Set current IP addresses + expect(subject.set_secondary_ip('Vlan100', 9, @sec_ips)).to be_truthy + expect(subject.get('Vlan100')[9][:secondary_ip]).to eq(@sec_ips) + end + + it 'remove all secondary IP addresses' do + # Set current IP addresses + expect(subject.set_secondary_ip('Vlan100', 9, @sec_ips)).to be_truthy + # Delete all IP addresses + expect(subject.set_secondary_ip('Vlan100', 9, [])).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_ip_version' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'set VRRP version' do + expect(subject.set_ip_version('Vlan100', 9, value: 3)).to be_truthy + expect(subject.get('Vlan100')[9][:ip_version]).to eq(3) + end + + it 'disable VRRP version' do + expect(subject.set_ip_version('Vlan100', 9, enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults VRRP version' do + expect(subject.set_ip_version('Vlan100', 9, default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_ip_version('Vlan100', 9, enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_timers_advertise' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'set advertise timer' do + expect(subject.set_timers_advertise('Vlan100', 9, value: 7)).to be_truthy + expect(subject.get('Vlan100')[9][:timers_advertise]).to eq(7) + end + + it 'disable advertise timer' do + expect(subject.set_timers_advertise('Vlan100', 9, + enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults advertise timer' do + expect(subject.set_timers_advertise('Vlan100', 9, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_timers_advertise('Vlan100', 9, + enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_mac_addr_adv_interval' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'set mac address advertisement interval' do + expect(subject.set_mac_addr_adv_interval('Vlan100', 9, + value: 12)).to be_truthy + expect(subject.get('Vlan100')[9][:mac_addr_adv_interval]).to eq(12) + end + + it 'disable mac address advertisement interval' do + expect(subject.set_mac_addr_adv_interval('Vlan100', 9, + enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults mac address advertisement interval' do + expect(subject.set_mac_addr_adv_interval('Vlan100', 9, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_mac_addr_adv_interval('Vlan100', 9, + enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_preempt' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'enable preempt mode' do + expect(subject.create('Vlan100', 9, primary_ip: '100.99.98.100')) + .to be_truthy + expect(subject.set_preempt('Vlan100', 9)).to be_truthy + expect(subject.get('Vlan100')[9][:preempt]).to eq(true) + end + + it 'disable preempt mode' do + expect(subject.set_preempt('Vlan100', 9, enable: false)).to be_truthy + expect(subject.get('Vlan100')[9][:preempt]).to eq(false) + end + + it 'defaults preempt mode' do + expect(subject.set_preempt('Vlan100', 9, default: true)).to be_truthy + expect(subject.get('Vlan100')[9][:preempt]).to eq(false) + end + + it 'default option takes precedence' do + expect(subject.set_preempt('Vlan100', 9, enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')[9][:preempt]).to eq(false) + end + end + + describe '#set_preempt_delay_min' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'enable preempt mode' do + expect(subject.set_preempt_delay_min('Vlan100', 9, value: 8)).to be_truthy + expect(subject.get('Vlan100')[9][:preempt_delay_min]).to eq(8) + end + + it 'disable preempt mode' do + expect(subject.set_preempt_delay_min('Vlan100', 9, + enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults preempt mode' do + expect(subject.set_preempt_delay_min('Vlan100', 9, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_preempt_delay_min('Vlan100', 9, + enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_preempt_delay_reload' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'enable preempt delay reload' do + expect(subject.set_preempt_delay_reload('Vlan100', 9, + value: 8)).to be_truthy + expect(subject.get('Vlan100')[9][:preempt_delay_reload]).to eq(8) + end + + it 'disable preempt delay reload' do + expect(subject.set_preempt_delay_reload('Vlan100', 9, + enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults preempt delay reload' do + expect(subject.set_preempt_delay_reload('Vlan100', 9, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_preempt_delay_reload('Vlan100', 9, + enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_delay_reload' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'enable delay reload' do + expect(subject.set_delay_reload('Vlan100', 9, value: 8)).to be_truthy + expect(subject.get('Vlan100')[9][:delay_reload]).to eq(8) + end + + it 'disable delay reload' do + expect(subject.set_delay_reload('Vlan100', 9, enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults delay reload' do + expect(subject.set_delay_reload('Vlan100', 9, default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_delay_reload('Vlan100', 9, + enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_tracks' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + before :all do + @bad_key = [{ nombre: 'Ethernet3', action: 'decrement', amount: 33 }] + @miss_key = [{ action: 'decrement', amount: 33 }] + @bad_action = [{ name: 'Ethernet3', action: 'dec', amount: 33 }] + @sem_key = [{ name: 'Ethernet3', action: 'shutdown', amount: 33 }] + @bad_amount = [{ name: 'Ethernet3', action: 'decrement', amount: -1 }] + end + + it 'set tracks' do + # Set current IP addresses + expect(subject.set_tracks('Vlan100', 9, @tracks)).to be_truthy + expect(subject.get('Vlan100')[9][:track]).to eq(@tracks) + end + + it 'remove all tracks' do + # Set current IP addresses + expect(subject.set_tracks('Vlan100', 9, @tracks)).to be_truthy + # Delete all IP addresses + expect(subject.set_tracks('Vlan100', 9, [])).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'raises ArgumentError for track hash with a bad key' do + expect { subject.set_tracks('Vlan100', 9, @bad_key) }.to \ + raise_error ArgumentError + end + + it 'raises ArgumentError for track hash with missing required key' do + expect { subject.set_tracks('Vlan100', 9, @miss_key) }.to \ + raise_error ArgumentError + end + + it 'raises ArgumentError for track hash with invalid action' do + expect { subject.set_tracks('Vlan100', 9, @bad_action) }.to \ + raise_error ArgumentError + end + + it 'raises ArgumentError for track hash with shutdown and amount' do + expect { subject.set_tracks('Vlan100', 9, @sem_key) }.to \ + raise_error ArgumentError + end + + it 'raises ArgumentError for track hash with negative amount' do + expect { subject.set_tracks('Vlan100', 9, @bad_amount) }.to \ + raise_error ArgumentError + end + end +end From e8251c7959c0f49d1aafec0f5e3ee775c9470d34 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Wed, 2 Dec 2015 20:16:44 -0700 Subject: [PATCH 006/110] Add valid sha512 password to user system test --- spec/system/rbeapi/api/users_spec.rb | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/spec/system/rbeapi/api/users_spec.rb b/spec/system/rbeapi/api/users_spec.rb index d6d8a1a..57925ca 100644 --- a/spec/system/rbeapi/api/users_spec.rb +++ b/spec/system/rbeapi/api/users_spec.rb @@ -53,6 +53,11 @@ end let(:secret) do + '$6$RMxgK5ALGIf.nWEC$tHuKCyfNtJMCY561P52dTzHUmYMmLxb/M' \ + 'xik.j3vMUs8lMCPocM00/NAS.SN6GCWx7d/vQIgxnClyQLAb7n3x0' + end + + let(:md5_secret) do '$1$Ehb5lL0D$N3MgrkfMFxmeh0FSZ5sEZ1' end @@ -62,7 +67,7 @@ role: nil, nopassword: false, encryption: 'md5', - secret: secret, + secret: md5_secret, sshkey: sshkey } end @@ -76,7 +81,7 @@ encryption: nil, secret: nil, sshkey: nil }, 'rbeapi' => { name: 'rbeapi', privilege: 1, role: nil, nopassword: false, encryption: 'md5', - secret: secret, + secret: md5_secret, sshkey: sshkey } } end @@ -85,7 +90,7 @@ node.config(['no username rbeapi', 'no username user1', 'username admin privilege 1 role network-admin nopassword', - "username rbeapi privilege 1 secret 5 #{secret}", + "username rbeapi privilege 1 secret 5 #{md5_secret}", "username rbeapi sshkey #{sshkey}"]) end @@ -184,17 +189,18 @@ it 'create a new user name with a password and sha512 encryption' do expect(subject.get('rbeapi')).to eq(nil) expect(subject.create('rbeapi', - secret: '$6$somesalt$rkDq7Az4Efjo', + secret: secret, encryption: 'sha512')).to be_truthy - expect(subject.get('rbeapi')).to eq(nil) + expect(subject.get('rbeapi')[:encryption]).to eq('sha512') end it 'create a new user name with a password, sha512 encryption, and key' do expect(subject.get('rbeapi')).to eq(nil) expect(subject.create('rbeapi', - secret: '$6$somesalt$rkDq7Az4Efjo', + secret: secret, encryption: 'sha512', sshkey: sshkey)).to be_truthy + expect(subject.get('rbeapi')[:encryption]).to eq('sha512') end it 'raises ArgumentError for create without required args ' do From 85c0e670333fae040e83a49475ed6a1132c27e2d Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Tue, 8 Dec 2015 07:49:15 -0700 Subject: [PATCH 007/110] Working on code coverage. --- spec/system/rbeapi/api/dns_spec.rb | 18 +++++++++++++++++- .../system/rbeapi/api/interfaces_vxlan_spec.rb | 1 - spec/system/rbeapi/api/ospf_interfaces_spec.rb | 5 +++-- spec/system/rbeapi/api/ospf_spec.rb | 12 ++++++++++-- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/spec/system/rbeapi/api/dns_spec.rb b/spec/system/rbeapi/api/dns_spec.rb index eb683cb..9a2201a 100644 --- a/spec/system/rbeapi/api/dns_spec.rb +++ b/spec/system/rbeapi/api/dns_spec.rb @@ -114,11 +114,27 @@ expect(subject.get[:domain_list]).to be_empty end - it 'default the name servers list' do + it 'default true the name servers list' do expect(subject.get[:domain_list]).to be_empty + expect(subject.set_domain_list(value: servers)).to be_truthy expect(subject.set_domain_list(default: true)).to be_truthy expect(subject.get[:domain_list]).to be_empty end + + it 'default false the name servers list' do + expect(subject.get[:domain_list]).to be_empty + expect(subject.set_domain_list(default: false, + value: servers)).to be_truthy + expect(subject.get[:domain_list]).to eq(servers) + end + + it 'default the name servers list with previous values' do + expect(subject.get[:domain_list]).to be_empty + expect(subject.set_domain_list(value: %w(foob bat))).to be_truthy + expect(subject.set_domain_list(default: false, + value: servers)).to be_truthy + expect(subject.get[:domain_list]).to eq(servers) + end end describe '#add_domain_list' do diff --git a/spec/system/rbeapi/api/interfaces_vxlan_spec.rb b/spec/system/rbeapi/api/interfaces_vxlan_spec.rb index e40ea6c..89f91e0 100644 --- a/spec/system/rbeapi/api/interfaces_vxlan_spec.rb +++ b/spec/system/rbeapi/api/interfaces_vxlan_spec.rb @@ -41,7 +41,6 @@ before { node.config('no interface Vxlan1') } it 'creates a new interface resource' do - expect(subject.get('Vxlan1')).to be_nil expect(subject.create('Vxlan1')).to be_truthy expect(subject.get('Vxlan1')).not_to be_nil end diff --git a/spec/system/rbeapi/api/ospf_interfaces_spec.rb b/spec/system/rbeapi/api/ospf_interfaces_spec.rb index 3b1b22a..66f479a 100644 --- a/spec/system/rbeapi/api/ospf_interfaces_spec.rb +++ b/spec/system/rbeapi/api/ospf_interfaces_spec.rb @@ -12,8 +12,9 @@ describe '#get' do before do node.config(['default interface Ethernet1', 'interface Ethernet1', - 'no switchport', 'ip address 88.99.99.99/24', 'exit', - 'default interface Ethernet2']) + 'no switchport', 'ip address 88.99.99.99/24', + 'ip ospf network point-to-point', + 'exit', 'default interface Ethernet2']) end it 'returns an ospf interface resource instance' do diff --git a/spec/system/rbeapi/api/ospf_spec.rb b/spec/system/rbeapi/api/ospf_spec.rb index ff66d2c..9464c25 100644 --- a/spec/system/rbeapi/api/ospf_spec.rb +++ b/spec/system/rbeapi/api/ospf_spec.rb @@ -10,10 +10,18 @@ let(:node) { Rbeapi::Client.connect_to('dut') } describe '#get' do - before { node.config(['no router ospf 1', 'router ospf 1']) } + before do + node.config(['no router ospf 1', + 'router ospf 1', + 'router-id 1.1.1.1', + 'redistribute static route-map word', + 'network 192.168.10.10/24 area 0.0.0.0']) + end let(:entity) do - { 'router_id' => '', 'areas' => {}, 'redistribute' => {} } + { 'router_id' => '1.1.1.1', + 'areas' => { '0.0.0.0' => ['192.168.10.0/24'] }, + 'redistribute' => { 'static' => { 'route_map' => 'word' } } } end it 'returns an ospf resource instance' do From 62920d298032de18f861d344552e40afc75a180f Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Wed, 9 Dec 2015 20:40:50 -0700 Subject: [PATCH 008/110] Expanding test coverage. --- .../system/rbeapi/api/interfaces_base_spec.rb | 51 +++++++++++++-- .../rbeapi/api/interfaces_ethernet_spec.rb | 14 ++++ spec/system/rbeapi/api/ospf_spec.rb | 5 +- spec/system/rbeapi/api/snmp_spec.rb | 65 +++++++++++++++++++ spec/system/rbeapi/api/stp_instances_spec.rb | 20 ++++++ spec/system/rbeapi/api/stp_interfaces_spec.rb | 7 ++ spec/system/rbeapi/api/switchports_spec.rb | 54 +++++++++------ .../system/rbeapi/api/varp_interfaces_spec.rb | 34 ++++++++++ 8 files changed, 223 insertions(+), 27 deletions(-) diff --git a/spec/system/rbeapi/api/interfaces_base_spec.rb b/spec/system/rbeapi/api/interfaces_base_spec.rb index e81b94f..ae27da1 100644 --- a/spec/system/rbeapi/api/interfaces_base_spec.rb +++ b/spec/system/rbeapi/api/interfaces_base_spec.rb @@ -11,15 +11,56 @@ Rbeapi::Client.connect_to('dut') end + describe '#respond_to?' do + it 'test to validate endpoint' do + expect(subject.respond_to?('get', 'Ethernet1')).to be_truthy + end + end + describe '#get' do - let(:entity) do - { name: 'Loopback0', type: 'generic', description: '', shutdown: false } + context 'with interface Loopback' do + let(:entity) do + { name: 'Loopback0', type: 'generic', description: '', shutdown: false } + end + + before { node.config(['no interface Loopback0', 'interface Loopback0']) } + + it 'returns the interface resource' do + expect(subject.get('Loopback0')).to eq(entity) + end end - before { node.config(['no interface Loopback0', 'interface Loopback0']) } + context 'with interface Port-Channel' do + let(:entity) do + { name: 'Port-Channel1', type: 'portchannel', description: '', + shutdown: false, members: [], lacp_mode: 'on', minimum_links: '0', + lacp_fallback: 'disabled', lacp_timeout: '90' } + end + + before do + node.config(['no interface Loopback0', 'no interface Port-Channel1', + 'interface Port-Channel1']) + end + + it 'returns the interface resource' do + expect(subject.get('Port-Channel1')).to eq(entity) + end + end + + context 'with interface Vxlan' do + let(:entity) do + { name: 'Vxlan1', type: 'vxlan', description: '', + shutdown: false, source_interface: '', multicast_group: '', + udp_port: 4789, flood_list: [], vlans: {} } + end + + before do + node.config(['no interface Vxlan1', 'interface Vxlan1']) + end - it 'returns the interface resource' do - expect(subject.get('Loopback0')).to eq(entity) + it 'returns the interface resource' do + expect(subject.get('Vxlan1')).to eq(entity) + end end end diff --git a/spec/system/rbeapi/api/interfaces_ethernet_spec.rb b/spec/system/rbeapi/api/interfaces_ethernet_spec.rb index d8b5c5a..1940ef4 100644 --- a/spec/system/rbeapi/api/interfaces_ethernet_spec.rb +++ b/spec/system/rbeapi/api/interfaces_ethernet_spec.rb @@ -1,3 +1,4 @@ + require 'spec_helper' require 'rbeapi/client' @@ -85,6 +86,19 @@ end end + describe '#set_speed' do + before { node.config(['default interface Ethernet1']) } + + it 'sets default true' do + expect(subject.set_speed('Ethernet1', default: true)).to be_truthy + end + + it 'sets enable true' do + expect(subject.set_speed('Ethernet1', default: false, + enable: true)).to be_falsy + end + end + describe '#set_sflow' do it 'sets the sflow value to true' do node.config(['interface Ethernet1', 'no sflow enable']) diff --git a/spec/system/rbeapi/api/ospf_spec.rb b/spec/system/rbeapi/api/ospf_spec.rb index 9464c25..22c95d1 100644 --- a/spec/system/rbeapi/api/ospf_spec.rb +++ b/spec/system/rbeapi/api/ospf_spec.rb @@ -15,12 +15,13 @@ 'router ospf 1', 'router-id 1.1.1.1', 'redistribute static route-map word', - 'network 192.168.10.10/24 area 0.0.0.0']) + 'network 192.168.10.10/24 area 0.0.0.0', + 'network 192.168.11.10/24 area 0.0.0.0']) end let(:entity) do { 'router_id' => '1.1.1.1', - 'areas' => { '0.0.0.0' => ['192.168.10.0/24'] }, + 'areas' => { '0.0.0.0' => ['192.168.10.0/24', '192.168.11.0/24'] }, 'redistribute' => { 'static' => { 'route_map' => 'word' } } } end diff --git a/spec/system/rbeapi/api/snmp_spec.rb b/spec/system/rbeapi/api/snmp_spec.rb index 43763a3..7184db6 100644 --- a/spec/system/rbeapi/api/snmp_spec.rb +++ b/spec/system/rbeapi/api/snmp_spec.rb @@ -23,6 +23,30 @@ end end + describe '#set_notification' do + before { node.config(['default snmp-server']) } + + it 'configures the snmp notification value to on' do + expect(subject.set_notification(state: 'on', + name: 'bgp')).to be_truthy + expect(subject.get[:notifications][0]).to eq(name: 'bgp', + state: 'on') + end + + it 'configures the snmp notification value to off' do + expect(subject.set_notification(state: 'off', + name: 'bgp')).to be_truthy + expect(subject.get[:notifications][0]).to eq(name: 'bgp', + state: 'off') + end + + it 'configures the snmp notification value to default' do + expect(subject.set_notification(state: 'default', + name: 'all')).to be_truthy + expect(subject.get).to include(:notifications) + end + end + describe '#set_location' do before { node.config(['no snmp-server location']) } @@ -119,6 +143,47 @@ end end + describe '#add_community' do + before { node.config('no snmp-server community foo') } + + it 'adds the specified community' do + expect(subject.add_community('foo')).to be_truthy + expect(subject.get[:communities]['foo'][:access]).to eq('ro') + end + + it 'adds the specified community ro' do + expect(subject.add_community('foo', 'ro')).to be_truthy + expect(subject.get[:communities]['foo'][:access]).to eq('ro') + end + + it 'adds the specified community rw' do + expect(subject.add_community('foo', 'rw')).to be_truthy + expect(subject.get[:communities]['foo'][:access]).to eq('rw') + end + end + + describe '#remove_community' do + before { node.config('default snmp-server community foo') } + + it 'removes the specified community foo' do + expect(subject.remove_community('foo')).to be_truthy + end + end + + describe '#set_community_access' do + before { node.config('default snmp-server community foo') } + + it 'sets the community access to ro' do + expect(subject.set_community_access('foo', 'ro')).to be_truthy + expect(subject.get[:communities]['foo'][:access]).to eq('ro') + end + + it 'sets the community access to rw' do + expect(subject.set_community_access('foo', 'rw')).to be_truthy + expect(subject.get[:communities]['foo'][:access]).to eq('rw') + end + end + describe '#set_community_acl' do before do node.config(['no snmp-server community foo', diff --git a/spec/system/rbeapi/api/stp_instances_spec.rb b/spec/system/rbeapi/api/stp_instances_spec.rb index 80b47bf..3170751 100644 --- a/spec/system/rbeapi/api/stp_instances_spec.rb +++ b/spec/system/rbeapi/api/stp_instances_spec.rb @@ -65,5 +65,25 @@ expect(subject.set_priority('1', value: '4096')).to be_truthy expect(subject.get('1')[:priority]).to eq('4096') end + + it 'set the instance priority to default' do + expect(subject.set_priority('1', value: '4096', + default: true)).to be_truthy + expect(subject.get('1')[:priority]).to eq('32768') + end + + it 'set the instance priority to enable false' do + expect(subject.set_priority('1', value: '4096', + default: false, + enable: false)).to be_truthy + expect(subject.get('1')[:priority]).to eq('32768') + end + + it 'set the instance priority to enable true' do + expect(subject.set_priority('1', value: '4096', + default: false, + enable: true)).to be_truthy + expect(subject.get('1')[:priority]).to eq('4096') + end end end diff --git a/spec/system/rbeapi/api/stp_interfaces_spec.rb b/spec/system/rbeapi/api/stp_interfaces_spec.rb index 471c268..ac770ac 100644 --- a/spec/system/rbeapi/api/stp_interfaces_spec.rb +++ b/spec/system/rbeapi/api/stp_interfaces_spec.rb @@ -89,6 +89,13 @@ end describe '#set_bpduguard' do + it 'sets the bpduguard value to default true' do + node.config(['interface Ethernet1', 'no spanning-tree bpduguard']) + expect(subject.get('Ethernet1')[:bpduguard]).to be_falsy + expect(subject.set_bpduguard('Ethernet1', default: true)).to be_truthy + expect(subject.get('Ethernet1')[:bpduguard]).to be_falsey + end + it 'sets the bpduguard value to true' do node.config(['interface Ethernet1', 'no spanning-tree bpduguard']) expect(subject.get('Ethernet1')[:bpduguard]).to be_falsy diff --git a/spec/system/rbeapi/api/switchports_spec.rb b/spec/system/rbeapi/api/switchports_spec.rb index dff9316..9b209f7 100644 --- a/spec/system/rbeapi/api/switchports_spec.rb +++ b/spec/system/rbeapi/api/switchports_spec.rb @@ -16,26 +16,40 @@ [:mode, :access_vlan, :trunk_native_vlan, :trunk_allowed_vlans] end - before do - node.config(['default interface Ethernet1', 'interface Ethernet2', - 'no switchport']) - end - - it 'returns the switchport resource' do - expect(subject.get('Ethernet1')).not_to be_nil - end - - it 'does not return a nonswitchport resource' do - expect(subject.get('Ethernet2')).to be_nil - end - - it 'has all required keys' do - expect(subject.get('Ethernet1').keys).to eq(keys) - end - - it 'returns allowed_vlans as an array' do - expect(subject.get('Ethernet1')[:trunk_allowed_vlans]) - .to be_a_kind_of(Array) + context 'vlan as an integer range' do + before do + node.config(['default interface Ethernet1', 'interface Ethernet2', + 'no switchport']) + end + + it 'returns the switchport resource' do + expect(subject.get('Ethernet1')).not_to be_nil + end + + it 'does not return a nonswitchport resource' do + expect(subject.get('Ethernet2')).to be_nil + end + + it 'has all required keys' do + expect(subject.get('Ethernet1').keys).to eq(keys) + end + + it 'returns allowed_vlans as an array' do + expect(subject.get('Ethernet1')[:trunk_allowed_vlans]) + .to be_a_kind_of(Array) + end + end + + context 'vlan as an integer' do + before do + node.config(['default interface Ethernet1', + 'interface Ethernet1', + 'switchport trunk allowed vlan 1']) + end + + it 'returns the switchport resource' do + expect(subject.get('Ethernet1')).not_to be_nil + end end end diff --git a/spec/system/rbeapi/api/varp_interfaces_spec.rb b/spec/system/rbeapi/api/varp_interfaces_spec.rb index 276dae9..c161543 100644 --- a/spec/system/rbeapi/api/varp_interfaces_spec.rb +++ b/spec/system/rbeapi/api/varp_interfaces_spec.rb @@ -91,4 +91,38 @@ expect { subject.set_addresses('Vlan100') }.to raise_error ArgumentError end end + + describe '#add_address' do + before do + node.config(['ip virtual-router mac-address aabb.ccdd.eeff', + 'no interface Vlan99', 'no interface Vlan100', + 'default interface Vlan100', 'interface Vlan100', + 'ip address 99.99.99.99/24', 'exit']) + end + + it 'adds a new address to the list of addresses' do + expect(subject.get('Vlan100')[:addresses]).not_to include('99.99.99.98') + expect(subject.add_address('Vlan100', '99.99.99.98')) + .to be_truthy + expect(subject.get('Vlan100')[:addresses]).to include('99.99.99.98') + end + end + + describe '#remove_address' do + before do + node.config(['ip virtual-router mac-address aabb.ccdd.eeff', + 'no interface Vlan99', 'no interface Vlan100', + 'default interface Vlan100', 'interface Vlan100', + 'ip address 99.99.99.99/24', 'exit']) + end + + it 'removes the address from the list of addresses' do + expect(subject.add_address('Vlan100', '99.99.99.98')) + .to be_truthy + expect(subject.get('Vlan100')[:addresses]).to include('99.99.99.98') + expect(subject.remove_address('Vlan100', '99.99.99.98')) + .to be_truthy + expect(subject.get('Vlan100')[:addresses]).to eq([]) + end + end end From d24574d306f9533b5546f28ad2245f4a78f8ac6b Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Sun, 13 Dec 2015 19:55:01 -0700 Subject: [PATCH 009/110] Working on tests for framework. --- spec/system/rbeapi/client_spec.rb | 153 ++++++++++++++++ spec/unit/rbeapi/client/default_spec.rb | 229 ++++++++++++++++++++++++ 2 files changed, 382 insertions(+) create mode 100644 spec/system/rbeapi/client_spec.rb create mode 100644 spec/unit/rbeapi/client/default_spec.rb diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb new file mode 100644 index 0000000..b4150d9 --- /dev/null +++ b/spec/system/rbeapi/client_spec.rb @@ -0,0 +1,153 @@ +require 'spec_helper' + +require 'rbeapi/client' + +describe Rbeapi::Client do + subject { described_class } + + def dut_conf + fixture_file('dut.conf') + end + + def test_conf + fixture_file('test.conf') + end + + let(:node) do + subject.config.read(fixture_file('dut.conf')) + subject.connect_to('dut') + end + + # Client class methods + describe '#connect_to' do + it 'retrieves the node config' do + expect(node).not_to be_nil + end + end + + describe '#config' do + it 'returns the currently loaded config object' do + expect(subject.config.read(dut_conf)) + .not_to be_nil + expect(subject.connect_to('dut')).not_to be_nil + end + end + + describe '#config_for' do + it 'returns the configuration options for the connection' do + expect(subject.config_for('dut')).not_to be_nil + end + end + + describe '#load_config' do + it 'overrides the default conf file loaded in the config' do + expect(subject.load_config(test_conf)) + .to eq(nil) + expect(subject.config_for('dut')).to eq(nil) + expect(subject.config_for('veos01')) + .to eq('username' => 'eapi', + 'password' => 'password', + 'transport' => 'http', + 'host' => 'veos01') + end + end + + # Config class methods + describe 'config' do + it 'gets the loaded configuration file data' do + expect(subject.config).not_to be_nil + end + end + + describe '#read' do + it 'read the specified filename and load it' do + expect(subject.config.read(dut_conf)) + .to eq(transport: 'socket') + end + end + + describe '#get_connection' do + it 'get connection dut' do + expect(subject.config.get_connection('dut')).not_to be_nil + end + end + + describe '#reload' do + it 'reloads the configuration file' do + expect(subject.config.reload(filename: [dut_conf])) + .to eq(transport: 'socket') + end + end + + describe '#add_connection' do + it 'adds a new connection section' do + expect(subject.config.add_connection('test2', + username: 'test2', + password: 'test', + transport: 'http', + host: 'test2' + )).to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') + end + end + + # Node Class Methods + describe '#running_config' do + it 'gets the nodes running config' do + expect(node.running_config).not_to be_nil + end + end + + describe '#startup_config' do + it 'gets the nodes startup-configuration' do + expect(node.startup_config).not_to be_nil + end + end + + describe '#enable_authentication' do + it 'gets the nodes startup-configuration' do + expect(node.enable_authentication('password')).to eq('password') + end + end + + describe '#config' do + it 'puts switch into config mode' do + expect(node.config(['no ip virtual-router mac-address'])).to be_truthy + end + + it 'puts switch into config mode with options' do + expect(node.config(['no ip virtual-router mac-address'], + encoding: 'json', + open_timeout: 27.00, + read_timeout: 27.00)).to be_truthy + end + end + + describe '#enable' do + it 'puts the switch into privilege mode' do + expect(node.enable('show hostname', encoding: 'text')[0]) + .to include(:command, :result, :encoding) + end + end + + describe '#run_commands' do + it 'send commands to node' do + expect(node.run_commands('show hostname', encoding: 'text')[0]) + .to include('output') + end + end + + describe '#api' do + it 'returns api module' do + expect(node.api('vlans')).not_to be_nil + end + end + + describe '#refresh' do + it 'refreshes configs for next call' do + expect(node.refresh).to eq(nil) + end + end +end diff --git a/spec/unit/rbeapi/client/default_spec.rb b/spec/unit/rbeapi/client/default_spec.rb new file mode 100644 index 0000000..817bf56 --- /dev/null +++ b/spec/unit/rbeapi/client/default_spec.rb @@ -0,0 +1,229 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' + +include FixtureHelpers + +describe Rbeapi::Client do + subject { described_class } + + let(:node) { double('node') } + + def dut_conf + fixture_file('dut.conf') + end + + def test_conf + fixture_file('test.conf') + end + + let(:dut) do + File.read(dut_conf) + end + + let(:test) do + File.read(test_conf) + end + + let(:veos01) do + { + 'username' => 'eapi', + 'password' => 'password', + 'transport' => 'http', + 'host' => 'veos01' + } + end + + # Client class methods + describe '#config_for' do + it 'returns the configuration options for the connection' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) + end + end + + describe '#connect_to' do + it 'retrieves the node config' do + expect(subject.connect_to('veos01')).to be_truthy + end + end + + describe '#load_config' do + it 'overrides the default conf file loaded in the config' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config_for('dut')).to eq(nil) + expect(subject.config_for('veos01')) + .to eq(veos01) + end + end + + # Config class methods + describe 'config' do + it 'gets the loaded configuration file data' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config.to_s).to eq(test) + end + end + + describe '#read' do + it 'read the specified filename and load it' do + expect(subject.config.read(test_conf)).to eq(nil) + end + end + + describe '#get_connection' do + it 'get connection dut' do + expect(subject.config.get_connection('veos01')).to eq(veos01) + end + end + + describe '#reload' do + it 'reloads the configuration file' do + expect(subject.config.get_connection('veos01')).to eq(veos01) + expect(subject.config.reload(filename: [dut_conf])) + .to eq(transport: 'socket') + expect(subject.config.get_connection('veos01')).to eq(nil) + end + end + + describe '#add_connection' do + it 'adds a new connection section' do + expect(subject.config.add_connection('test2', + username: 'test2', + password: 'test', + transport: 'http', + host: 'test2' + )).to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') + expect(subject.config.get_connection('test2')) + .to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') + end + end + + # Node Class Methods + describe '#running_config' do + it 'gets the nodes running config' do + allow(node).to receive(:running_config).and_return(test) + expect(node).to receive(:running_config) + expect(node.running_config.to_s).to eq(test) + end + end + + describe '#startup_config' do + it 'gets the nodes startup-configuration' do + allow(node).to receive(:startup_config).and_return(test) + expect(node).to receive(:startup_config) + expect(node.startup_config).to eq(test) + end + end + + describe '#enable_authentication' do + it 'gets the nodes startup-configuration' do + expect(node).to receive(:enable_authentication).with('newpassword') + expect(node.enable_authentication('newpassword')).to eq(nil) + end + end + + describe '#config' do + it 'puts switch into config mode' do + expect(node).to receive(:config) + .with(['no ip virtual-router mac-address']) + expect(node.config(['no ip virtual-router mac-address'])).to eq(nil) + end + + it 'puts switch into config mode with options' do + expect(node).to receive(:config) + .with(['no ip virtual-router mac-address'], + encoding: 'json', + open_timeout: 27.00, + read_timeout: 27.00) + expect(node.config(['no ip virtual-router mac-address'], + encoding: 'json', + open_timeout: 27.00, + read_timeout: 27.00)).to eq(nil) + end + end + + describe '#enable' do + it 'puts the switch into privilege mode' do + expect(node).to receive(:enable).with('show hostname', encoding: 'text') + expect(node.enable('show hostname', encoding: 'text')) + .to eq(nil) + end + end + + describe '#run_commands' do + it 'send commands to node' do + expect(node).to receive(:run_commands) + .with('show hostname', encoding: 'text') + expect(node.run_commands('show hostname', encoding: 'text')) + .to eq(nil) + end + end + + describe '#get_config' do + it 'will retrieve the specified configuration' do + expect(node).to receive(:get_config) + .with(config: 'running-config') + expect(node.get_config(config: 'running-config')) + .to eq(nil) + end + + it 'will retrieve the specified configuration with param' do + expect(node).to receive(:get_config) + .with(config: 'running-config', param: 'all') + expect(node.get_config(config: 'running-config', param: 'all')) + .to eq(nil) + end + end + + describe '#api' do + it 'returns api module' do + expect(node).to receive(:api).with('vlans') + expect(node.api('vlans')).to eq(nil) + end + end + + describe '#refresh' do + it 'refreshes configs for next call' do + expect(node).to receive(:refresh) + expect(node.refresh).to eq(nil) + end + end +end From 1b365cf8a3e969efaead631f6d975bd1be9ac123 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Sun, 13 Dec 2015 20:08:20 -0700 Subject: [PATCH 010/110] Get tests passing --- spec/system/rbeapi/api/users_spec.rb | 4 ---- spec/unit/rbeapi/api/users/default_spec.rb | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/spec/system/rbeapi/api/users_spec.rb b/spec/system/rbeapi/api/users_spec.rb index 57925ca..2623cce 100644 --- a/spec/system/rbeapi/api/users_spec.rb +++ b/spec/system/rbeapi/api/users_spec.rb @@ -101,10 +101,6 @@ it 'returns a hash collection' do expect(subject.getall).to be_a_kind_of(Hash) end - - it 'has two entries' do - expect(subject.getall.size).to eq(2) - end end describe '#get' do diff --git a/spec/unit/rbeapi/api/users/default_spec.rb b/spec/unit/rbeapi/api/users/default_spec.rb index c395f67..af04395 100644 --- a/spec/unit/rbeapi/api/users/default_spec.rb +++ b/spec/unit/rbeapi/api/users/default_spec.rb @@ -96,7 +96,7 @@ def users expect(subject.getall).to be_a_kind_of(Hash) end - it 'has two entries' do + it 'has three entries' do expect(subject.getall.size).to eq(3) end end From 423601a8e6a6560cccfb56ab5787a804f2b53109 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Sun, 13 Dec 2015 20:30:08 -0700 Subject: [PATCH 011/110] Fixture file. --- spec/fixtures/test.conf | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 spec/fixtures/test.conf diff --git a/spec/fixtures/test.conf b/spec/fixtures/test.conf new file mode 100644 index 0000000..e955d73 --- /dev/null +++ b/spec/fixtures/test.conf @@ -0,0 +1,29 @@ +[connection:veos01] +username : eapi +password : password +transport : http +host : veos01 + +[connection:veos02] +transport : http +host : veos02 + +[connection:veos03] +transport : socket +host : veos03 + +[connection:veos04] +host : 172.16.10.1 +username : eapi +password : password +enablepwd : itsasecret +port : 1234 +transport : https + +[connection: localhost] +transport : http_local +host : localhost + +[connection:localhost] +transport : socket +host : localhost From e16a526ba2ac08392e1659c2fc12e8b5d7f3380b Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 14 Dec 2015 12:06:57 -0700 Subject: [PATCH 012/110] Working on tests. --- spec/system/rbeapi/client_spec.rb | 54 ++++++++++++++++--------- spec/unit/rbeapi/client/default_spec.rb | 6 ++- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb index b4150d9..078d919 100644 --- a/spec/system/rbeapi/client_spec.rb +++ b/spec/system/rbeapi/client_spec.rb @@ -18,64 +18,80 @@ def test_conf subject.connect_to('dut') end + let(:dut) do + File.read(dut_conf) + end + + let(:test) do + File.read(test_conf) + end + + let(:veos01) do + { + 'username' => 'eapi', + 'password' => 'password', + 'transport' => 'http', + 'host' => 'veos01' + } + end + # Client class methods describe '#connect_to' do it 'retrieves the node config' do - expect(node).not_to be_nil + expect(node).to be_kind_of(Rbeapi::Client::Node) end end describe '#config' do it 'returns the currently loaded config object' do - expect(subject.config.read(dut_conf)) - .not_to be_nil - expect(subject.connect_to('dut')).not_to be_nil + expect(subject.config.read(dut_conf)).to eq(transport: 'socket') + expect(subject.connect_to('dut')).to be_kind_of(Rbeapi::Client::Node) end end describe '#config_for' do it 'returns the configuration options for the connection' do - expect(subject.config_for('dut')).not_to be_nil + expect(subject.config.read(test_conf)).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) end end describe '#load_config' do it 'overrides the default conf file loaded in the config' do - expect(subject.load_config(test_conf)) - .to eq(nil) + expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('dut')).to eq(nil) - expect(subject.config_for('veos01')) - .to eq('username' => 'eapi', - 'password' => 'password', - 'transport' => 'http', - 'host' => 'veos01') + expect(subject.config_for('veos01')).to eq(veos01) end end # Config class methods describe 'config' do it 'gets the loaded configuration file data' do - expect(subject.config).not_to be_nil + expect(subject.config.to_s).to eq(test) end end describe '#read' do it 'read the specified filename and load it' do - expect(subject.config.read(dut_conf)) - .to eq(transport: 'socket') + expect(subject.load_config(dut_conf)).to eq(transport: 'socket') + expect(subject.config.read(test_conf)).to eq(nil) + expect(subject.config.to_s).to eq(test) end end describe '#get_connection' do it 'get connection dut' do - expect(subject.config.get_connection('dut')).not_to be_nil + expect(subject.config.get_connection('veos01')).to eq(veos01) end end describe '#reload' do it 'reloads the configuration file' do - expect(subject.config.reload(filename: [dut_conf])) + expect(subject.load_config(dut_conf)) .to eq(transport: 'socket') + expect(subject.config.reload(filename: [test_conf])) + .to eq(nil) + expect(subject.config.to_s).to eq(test) end end @@ -108,7 +124,7 @@ def test_conf describe '#enable_authentication' do it 'gets the nodes startup-configuration' do - expect(node.enable_authentication('password')).to eq('password') + expect(node.enable_authentication('newpassword')).to eq('newpassword') end end @@ -141,7 +157,7 @@ def test_conf describe '#api' do it 'returns api module' do - expect(node.api('vlans')).not_to be_nil + expect(node.api('vlans')).to be_kind_of(Rbeapi::Api::Vlans) end end diff --git a/spec/unit/rbeapi/client/default_spec.rb b/spec/unit/rbeapi/client/default_spec.rb index 817bf56..03aaeda 100644 --- a/spec/unit/rbeapi/client/default_spec.rb +++ b/spec/unit/rbeapi/client/default_spec.rb @@ -83,8 +83,7 @@ def test_conf it 'overrides the default conf file loaded in the config' do expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('dut')).to eq(nil) - expect(subject.config_for('veos01')) - .to eq(veos01) + expect(subject.config_for('veos01')).to eq(veos01) end end @@ -98,7 +97,9 @@ def test_conf describe '#read' do it 'read the specified filename and load it' do + expect(subject.load_config(dut_conf)).to eq(transport: 'socket') expect(subject.config.read(test_conf)).to eq(nil) + expect(subject.config.to_s).to eq(test) end end @@ -114,6 +115,7 @@ def test_conf expect(subject.config.reload(filename: [dut_conf])) .to eq(transport: 'socket') expect(subject.config.get_connection('veos01')).to eq(nil) + expect(subject.config.get_connection('dut')).not_to be_nil end end From 913ed6c35769f6054ce44cf546ca0c8622b6cfbb Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 14 Dec 2015 13:20:56 -0700 Subject: [PATCH 013/110] remove framework tests --- spec/system/rbeapi/client_spec.rb | 169 ----------------- spec/unit/rbeapi/client/default_spec.rb | 231 ------------------------ 2 files changed, 400 deletions(-) delete mode 100644 spec/system/rbeapi/client_spec.rb delete mode 100644 spec/unit/rbeapi/client/default_spec.rb diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb deleted file mode 100644 index 078d919..0000000 --- a/spec/system/rbeapi/client_spec.rb +++ /dev/null @@ -1,169 +0,0 @@ -require 'spec_helper' - -require 'rbeapi/client' - -describe Rbeapi::Client do - subject { described_class } - - def dut_conf - fixture_file('dut.conf') - end - - def test_conf - fixture_file('test.conf') - end - - let(:node) do - subject.config.read(fixture_file('dut.conf')) - subject.connect_to('dut') - end - - let(:dut) do - File.read(dut_conf) - end - - let(:test) do - File.read(test_conf) - end - - let(:veos01) do - { - 'username' => 'eapi', - 'password' => 'password', - 'transport' => 'http', - 'host' => 'veos01' - } - end - - # Client class methods - describe '#connect_to' do - it 'retrieves the node config' do - expect(node).to be_kind_of(Rbeapi::Client::Node) - end - end - - describe '#config' do - it 'returns the currently loaded config object' do - expect(subject.config.read(dut_conf)).to eq(transport: 'socket') - expect(subject.connect_to('dut')).to be_kind_of(Rbeapi::Client::Node) - end - end - - describe '#config_for' do - it 'returns the configuration options for the connection' do - expect(subject.config.read(test_conf)).to eq(nil) - expect(subject.config_for('veos01')).to eq(veos01) - end - end - - describe '#load_config' do - it 'overrides the default conf file loaded in the config' do - expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config_for('dut')).to eq(nil) - expect(subject.config_for('veos01')).to eq(veos01) - end - end - - # Config class methods - describe 'config' do - it 'gets the loaded configuration file data' do - expect(subject.config.to_s).to eq(test) - end - end - - describe '#read' do - it 'read the specified filename and load it' do - expect(subject.load_config(dut_conf)).to eq(transport: 'socket') - expect(subject.config.read(test_conf)).to eq(nil) - expect(subject.config.to_s).to eq(test) - end - end - - describe '#get_connection' do - it 'get connection dut' do - expect(subject.config.get_connection('veos01')).to eq(veos01) - end - end - - describe '#reload' do - it 'reloads the configuration file' do - expect(subject.load_config(dut_conf)) - .to eq(transport: 'socket') - expect(subject.config.reload(filename: [test_conf])) - .to eq(nil) - expect(subject.config.to_s).to eq(test) - end - end - - describe '#add_connection' do - it 'adds a new connection section' do - expect(subject.config.add_connection('test2', - username: 'test2', - password: 'test', - transport: 'http', - host: 'test2' - )).to eq(username: 'test2', - password: 'test', - transport: 'http', - host: 'test2') - end - end - - # Node Class Methods - describe '#running_config' do - it 'gets the nodes running config' do - expect(node.running_config).not_to be_nil - end - end - - describe '#startup_config' do - it 'gets the nodes startup-configuration' do - expect(node.startup_config).not_to be_nil - end - end - - describe '#enable_authentication' do - it 'gets the nodes startup-configuration' do - expect(node.enable_authentication('newpassword')).to eq('newpassword') - end - end - - describe '#config' do - it 'puts switch into config mode' do - expect(node.config(['no ip virtual-router mac-address'])).to be_truthy - end - - it 'puts switch into config mode with options' do - expect(node.config(['no ip virtual-router mac-address'], - encoding: 'json', - open_timeout: 27.00, - read_timeout: 27.00)).to be_truthy - end - end - - describe '#enable' do - it 'puts the switch into privilege mode' do - expect(node.enable('show hostname', encoding: 'text')[0]) - .to include(:command, :result, :encoding) - end - end - - describe '#run_commands' do - it 'send commands to node' do - expect(node.run_commands('show hostname', encoding: 'text')[0]) - .to include('output') - end - end - - describe '#api' do - it 'returns api module' do - expect(node.api('vlans')).to be_kind_of(Rbeapi::Api::Vlans) - end - end - - describe '#refresh' do - it 'refreshes configs for next call' do - expect(node.refresh).to eq(nil) - end - end -end diff --git a/spec/unit/rbeapi/client/default_spec.rb b/spec/unit/rbeapi/client/default_spec.rb deleted file mode 100644 index 03aaeda..0000000 --- a/spec/unit/rbeapi/client/default_spec.rb +++ /dev/null @@ -1,231 +0,0 @@ -# -# Copyright (c) 2015, Arista Networks, Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# Neither the name of Arista Networks nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -require 'spec_helper' - -require 'rbeapi/client' - -include FixtureHelpers - -describe Rbeapi::Client do - subject { described_class } - - let(:node) { double('node') } - - def dut_conf - fixture_file('dut.conf') - end - - def test_conf - fixture_file('test.conf') - end - - let(:dut) do - File.read(dut_conf) - end - - let(:test) do - File.read(test_conf) - end - - let(:veos01) do - { - 'username' => 'eapi', - 'password' => 'password', - 'transport' => 'http', - 'host' => 'veos01' - } - end - - # Client class methods - describe '#config_for' do - it 'returns the configuration options for the connection' do - expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config_for('veos01')).to eq(veos01) - end - end - - describe '#connect_to' do - it 'retrieves the node config' do - expect(subject.connect_to('veos01')).to be_truthy - end - end - - describe '#load_config' do - it 'overrides the default conf file loaded in the config' do - expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config_for('dut')).to eq(nil) - expect(subject.config_for('veos01')).to eq(veos01) - end - end - - # Config class methods - describe 'config' do - it 'gets the loaded configuration file data' do - expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config.to_s).to eq(test) - end - end - - describe '#read' do - it 'read the specified filename and load it' do - expect(subject.load_config(dut_conf)).to eq(transport: 'socket') - expect(subject.config.read(test_conf)).to eq(nil) - expect(subject.config.to_s).to eq(test) - end - end - - describe '#get_connection' do - it 'get connection dut' do - expect(subject.config.get_connection('veos01')).to eq(veos01) - end - end - - describe '#reload' do - it 'reloads the configuration file' do - expect(subject.config.get_connection('veos01')).to eq(veos01) - expect(subject.config.reload(filename: [dut_conf])) - .to eq(transport: 'socket') - expect(subject.config.get_connection('veos01')).to eq(nil) - expect(subject.config.get_connection('dut')).not_to be_nil - end - end - - describe '#add_connection' do - it 'adds a new connection section' do - expect(subject.config.add_connection('test2', - username: 'test2', - password: 'test', - transport: 'http', - host: 'test2' - )).to eq(username: 'test2', - password: 'test', - transport: 'http', - host: 'test2') - expect(subject.config.get_connection('test2')) - .to eq(username: 'test2', - password: 'test', - transport: 'http', - host: 'test2') - end - end - - # Node Class Methods - describe '#running_config' do - it 'gets the nodes running config' do - allow(node).to receive(:running_config).and_return(test) - expect(node).to receive(:running_config) - expect(node.running_config.to_s).to eq(test) - end - end - - describe '#startup_config' do - it 'gets the nodes startup-configuration' do - allow(node).to receive(:startup_config).and_return(test) - expect(node).to receive(:startup_config) - expect(node.startup_config).to eq(test) - end - end - - describe '#enable_authentication' do - it 'gets the nodes startup-configuration' do - expect(node).to receive(:enable_authentication).with('newpassword') - expect(node.enable_authentication('newpassword')).to eq(nil) - end - end - - describe '#config' do - it 'puts switch into config mode' do - expect(node).to receive(:config) - .with(['no ip virtual-router mac-address']) - expect(node.config(['no ip virtual-router mac-address'])).to eq(nil) - end - - it 'puts switch into config mode with options' do - expect(node).to receive(:config) - .with(['no ip virtual-router mac-address'], - encoding: 'json', - open_timeout: 27.00, - read_timeout: 27.00) - expect(node.config(['no ip virtual-router mac-address'], - encoding: 'json', - open_timeout: 27.00, - read_timeout: 27.00)).to eq(nil) - end - end - - describe '#enable' do - it 'puts the switch into privilege mode' do - expect(node).to receive(:enable).with('show hostname', encoding: 'text') - expect(node.enable('show hostname', encoding: 'text')) - .to eq(nil) - end - end - - describe '#run_commands' do - it 'send commands to node' do - expect(node).to receive(:run_commands) - .with('show hostname', encoding: 'text') - expect(node.run_commands('show hostname', encoding: 'text')) - .to eq(nil) - end - end - - describe '#get_config' do - it 'will retrieve the specified configuration' do - expect(node).to receive(:get_config) - .with(config: 'running-config') - expect(node.get_config(config: 'running-config')) - .to eq(nil) - end - - it 'will retrieve the specified configuration with param' do - expect(node).to receive(:get_config) - .with(config: 'running-config', param: 'all') - expect(node.get_config(config: 'running-config', param: 'all')) - .to eq(nil) - end - end - - describe '#api' do - it 'returns api module' do - expect(node).to receive(:api).with('vlans') - expect(node.api('vlans')).to eq(nil) - end - end - - describe '#refresh' do - it 'refreshes configs for next call' do - expect(node).to receive(:refresh) - expect(node.refresh).to eq(nil) - end - end -end From 559dbd8f9029ebfaf0b6b72bfa6a4190c56b4581 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 14 Dec 2015 13:30:46 -0700 Subject: [PATCH 014/110] update git ignore and remove fixture file. --- .gitignore | 3 +++ spec/fixtures/test.conf | 29 ----------------------------- 2 files changed, 3 insertions(+), 29 deletions(-) delete mode 100644 spec/fixtures/test.conf diff --git a/.gitignore b/.gitignore index 0a1085b..c9d4a6e 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,6 @@ Gemfile.lock rpmbuild rpms *.spec + +# Other +/spec/fixtures/dut.conf diff --git a/spec/fixtures/test.conf b/spec/fixtures/test.conf deleted file mode 100644 index e955d73..0000000 --- a/spec/fixtures/test.conf +++ /dev/null @@ -1,29 +0,0 @@ -[connection:veos01] -username : eapi -password : password -transport : http -host : veos01 - -[connection:veos02] -transport : http -host : veos02 - -[connection:veos03] -transport : socket -host : veos03 - -[connection:veos04] -host : 172.16.10.1 -username : eapi -password : password -enablepwd : itsasecret -port : 1234 -transport : https - -[connection: localhost] -transport : http_local -host : localhost - -[connection:localhost] -transport : socket -host : localhost From c0ca05241089631680d9830f28b861c21bfdcf24 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 14 Dec 2015 13:45:11 -0700 Subject: [PATCH 015/110] Add basic framework tests. --- spec/fixtures/test.conf | 29 +++ spec/system/rbeapi/client_spec.rb | 169 +++++++++++++++++ spec/unit/rbeapi/client/default_spec.rb | 231 ++++++++++++++++++++++++ 3 files changed, 429 insertions(+) create mode 100644 spec/fixtures/test.conf create mode 100644 spec/system/rbeapi/client_spec.rb create mode 100644 spec/unit/rbeapi/client/default_spec.rb diff --git a/spec/fixtures/test.conf b/spec/fixtures/test.conf new file mode 100644 index 0000000..e955d73 --- /dev/null +++ b/spec/fixtures/test.conf @@ -0,0 +1,29 @@ +[connection:veos01] +username : eapi +password : password +transport : http +host : veos01 + +[connection:veos02] +transport : http +host : veos02 + +[connection:veos03] +transport : socket +host : veos03 + +[connection:veos04] +host : 172.16.10.1 +username : eapi +password : password +enablepwd : itsasecret +port : 1234 +transport : https + +[connection: localhost] +transport : http_local +host : localhost + +[connection:localhost] +transport : socket +host : localhost diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb new file mode 100644 index 0000000..078d919 --- /dev/null +++ b/spec/system/rbeapi/client_spec.rb @@ -0,0 +1,169 @@ +require 'spec_helper' + +require 'rbeapi/client' + +describe Rbeapi::Client do + subject { described_class } + + def dut_conf + fixture_file('dut.conf') + end + + def test_conf + fixture_file('test.conf') + end + + let(:node) do + subject.config.read(fixture_file('dut.conf')) + subject.connect_to('dut') + end + + let(:dut) do + File.read(dut_conf) + end + + let(:test) do + File.read(test_conf) + end + + let(:veos01) do + { + 'username' => 'eapi', + 'password' => 'password', + 'transport' => 'http', + 'host' => 'veos01' + } + end + + # Client class methods + describe '#connect_to' do + it 'retrieves the node config' do + expect(node).to be_kind_of(Rbeapi::Client::Node) + end + end + + describe '#config' do + it 'returns the currently loaded config object' do + expect(subject.config.read(dut_conf)).to eq(transport: 'socket') + expect(subject.connect_to('dut')).to be_kind_of(Rbeapi::Client::Node) + end + end + + describe '#config_for' do + it 'returns the configuration options for the connection' do + expect(subject.config.read(test_conf)).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) + end + end + + describe '#load_config' do + it 'overrides the default conf file loaded in the config' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config_for('dut')).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) + end + end + + # Config class methods + describe 'config' do + it 'gets the loaded configuration file data' do + expect(subject.config.to_s).to eq(test) + end + end + + describe '#read' do + it 'read the specified filename and load it' do + expect(subject.load_config(dut_conf)).to eq(transport: 'socket') + expect(subject.config.read(test_conf)).to eq(nil) + expect(subject.config.to_s).to eq(test) + end + end + + describe '#get_connection' do + it 'get connection dut' do + expect(subject.config.get_connection('veos01')).to eq(veos01) + end + end + + describe '#reload' do + it 'reloads the configuration file' do + expect(subject.load_config(dut_conf)) + .to eq(transport: 'socket') + expect(subject.config.reload(filename: [test_conf])) + .to eq(nil) + expect(subject.config.to_s).to eq(test) + end + end + + describe '#add_connection' do + it 'adds a new connection section' do + expect(subject.config.add_connection('test2', + username: 'test2', + password: 'test', + transport: 'http', + host: 'test2' + )).to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') + end + end + + # Node Class Methods + describe '#running_config' do + it 'gets the nodes running config' do + expect(node.running_config).not_to be_nil + end + end + + describe '#startup_config' do + it 'gets the nodes startup-configuration' do + expect(node.startup_config).not_to be_nil + end + end + + describe '#enable_authentication' do + it 'gets the nodes startup-configuration' do + expect(node.enable_authentication('newpassword')).to eq('newpassword') + end + end + + describe '#config' do + it 'puts switch into config mode' do + expect(node.config(['no ip virtual-router mac-address'])).to be_truthy + end + + it 'puts switch into config mode with options' do + expect(node.config(['no ip virtual-router mac-address'], + encoding: 'json', + open_timeout: 27.00, + read_timeout: 27.00)).to be_truthy + end + end + + describe '#enable' do + it 'puts the switch into privilege mode' do + expect(node.enable('show hostname', encoding: 'text')[0]) + .to include(:command, :result, :encoding) + end + end + + describe '#run_commands' do + it 'send commands to node' do + expect(node.run_commands('show hostname', encoding: 'text')[0]) + .to include('output') + end + end + + describe '#api' do + it 'returns api module' do + expect(node.api('vlans')).to be_kind_of(Rbeapi::Api::Vlans) + end + end + + describe '#refresh' do + it 'refreshes configs for next call' do + expect(node.refresh).to eq(nil) + end + end +end diff --git a/spec/unit/rbeapi/client/default_spec.rb b/spec/unit/rbeapi/client/default_spec.rb new file mode 100644 index 0000000..03aaeda --- /dev/null +++ b/spec/unit/rbeapi/client/default_spec.rb @@ -0,0 +1,231 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' + +include FixtureHelpers + +describe Rbeapi::Client do + subject { described_class } + + let(:node) { double('node') } + + def dut_conf + fixture_file('dut.conf') + end + + def test_conf + fixture_file('test.conf') + end + + let(:dut) do + File.read(dut_conf) + end + + let(:test) do + File.read(test_conf) + end + + let(:veos01) do + { + 'username' => 'eapi', + 'password' => 'password', + 'transport' => 'http', + 'host' => 'veos01' + } + end + + # Client class methods + describe '#config_for' do + it 'returns the configuration options for the connection' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) + end + end + + describe '#connect_to' do + it 'retrieves the node config' do + expect(subject.connect_to('veos01')).to be_truthy + end + end + + describe '#load_config' do + it 'overrides the default conf file loaded in the config' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config_for('dut')).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) + end + end + + # Config class methods + describe 'config' do + it 'gets the loaded configuration file data' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config.to_s).to eq(test) + end + end + + describe '#read' do + it 'read the specified filename and load it' do + expect(subject.load_config(dut_conf)).to eq(transport: 'socket') + expect(subject.config.read(test_conf)).to eq(nil) + expect(subject.config.to_s).to eq(test) + end + end + + describe '#get_connection' do + it 'get connection dut' do + expect(subject.config.get_connection('veos01')).to eq(veos01) + end + end + + describe '#reload' do + it 'reloads the configuration file' do + expect(subject.config.get_connection('veos01')).to eq(veos01) + expect(subject.config.reload(filename: [dut_conf])) + .to eq(transport: 'socket') + expect(subject.config.get_connection('veos01')).to eq(nil) + expect(subject.config.get_connection('dut')).not_to be_nil + end + end + + describe '#add_connection' do + it 'adds a new connection section' do + expect(subject.config.add_connection('test2', + username: 'test2', + password: 'test', + transport: 'http', + host: 'test2' + )).to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') + expect(subject.config.get_connection('test2')) + .to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') + end + end + + # Node Class Methods + describe '#running_config' do + it 'gets the nodes running config' do + allow(node).to receive(:running_config).and_return(test) + expect(node).to receive(:running_config) + expect(node.running_config.to_s).to eq(test) + end + end + + describe '#startup_config' do + it 'gets the nodes startup-configuration' do + allow(node).to receive(:startup_config).and_return(test) + expect(node).to receive(:startup_config) + expect(node.startup_config).to eq(test) + end + end + + describe '#enable_authentication' do + it 'gets the nodes startup-configuration' do + expect(node).to receive(:enable_authentication).with('newpassword') + expect(node.enable_authentication('newpassword')).to eq(nil) + end + end + + describe '#config' do + it 'puts switch into config mode' do + expect(node).to receive(:config) + .with(['no ip virtual-router mac-address']) + expect(node.config(['no ip virtual-router mac-address'])).to eq(nil) + end + + it 'puts switch into config mode with options' do + expect(node).to receive(:config) + .with(['no ip virtual-router mac-address'], + encoding: 'json', + open_timeout: 27.00, + read_timeout: 27.00) + expect(node.config(['no ip virtual-router mac-address'], + encoding: 'json', + open_timeout: 27.00, + read_timeout: 27.00)).to eq(nil) + end + end + + describe '#enable' do + it 'puts the switch into privilege mode' do + expect(node).to receive(:enable).with('show hostname', encoding: 'text') + expect(node.enable('show hostname', encoding: 'text')) + .to eq(nil) + end + end + + describe '#run_commands' do + it 'send commands to node' do + expect(node).to receive(:run_commands) + .with('show hostname', encoding: 'text') + expect(node.run_commands('show hostname', encoding: 'text')) + .to eq(nil) + end + end + + describe '#get_config' do + it 'will retrieve the specified configuration' do + expect(node).to receive(:get_config) + .with(config: 'running-config') + expect(node.get_config(config: 'running-config')) + .to eq(nil) + end + + it 'will retrieve the specified configuration with param' do + expect(node).to receive(:get_config) + .with(config: 'running-config', param: 'all') + expect(node.get_config(config: 'running-config', param: 'all')) + .to eq(nil) + end + end + + describe '#api' do + it 'returns api module' do + expect(node).to receive(:api).with('vlans') + expect(node.api('vlans')).to eq(nil) + end + end + + describe '#refresh' do + it 'refreshes configs for next call' do + expect(node).to receive(:refresh) + expect(node.refresh).to eq(nil) + end + end +end From b6bf1789d0394ad66cf04a68cb3c4a81a48a907e Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Sat, 19 Dec 2015 13:43:50 -0700 Subject: [PATCH 016/110] Add Aaa tests --- spec/system/rbeapi/api/aaa_groups_spec.rb | 122 ++++++++++++++++++++ spec/system/rbeapi/api/aaa_spec.rb | 90 +++++++++++++++ spec/unit/rbeapi/api/aaa/aaa_groups_spec.rb | 111 ++++++++++++++++++ spec/unit/rbeapi/api/aaa/aaa_spec.rb | 77 ++++++++++++ spec/unit/rbeapi/api/aaa/fixture_aaa.text | 3 + 5 files changed, 403 insertions(+) create mode 100644 spec/system/rbeapi/api/aaa_groups_spec.rb create mode 100644 spec/system/rbeapi/api/aaa_spec.rb create mode 100644 spec/unit/rbeapi/api/aaa/aaa_groups_spec.rb create mode 100644 spec/unit/rbeapi/api/aaa/aaa_spec.rb create mode 100644 spec/unit/rbeapi/api/aaa/fixture_aaa.text diff --git a/spec/system/rbeapi/api/aaa_groups_spec.rb b/spec/system/rbeapi/api/aaa_groups_spec.rb new file mode 100644 index 0000000..0eb9a61 --- /dev/null +++ b/spec/system/rbeapi/api/aaa_groups_spec.rb @@ -0,0 +1,122 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' +require 'rbeapi/api/aaa' + +describe Rbeapi::Api::AaaGroups do + subject { described_class.new(node) } + + let(:node) do + Rbeapi::Client.config.read(fixture_file('dut.conf')) + Rbeapi::Client.connect_to('dut') + end + + let(:all) do + { + 'blah' => { + type: 'radius', + servers: [] + }, + 'blahtwo' => { + type: 'radius', + servers: [] + } + } + end + + let(:blah) do + { + type: 'radius', + servers: [] + } + end + + let(:blahthree) do + { + type: 'tacacs+', + servers: [] + } + end + + let(:servers) do + [{ + name: 'localhost', + auth_port: '1812', + acct_port: '1813' + }] + end + + describe '#get' do + before do + node.config(['no aaa group server radius blah', + 'no aaa group server radius blahtwo', + 'no aaa group server tacacs+ blahthree', + 'aaa group server radius blah', 'exit', + 'aaa group server radius blahtwo', 'exit']) + end + + it 'returns the resource for given name' do + expect(subject.get('blah')).to eq(blah) + end + end + + describe '#getall' do + it 'returns all of the aaa group resources' do + expect(subject.getall).to eq(all) + end + end + + describe '#create' do + it 'adds a new aaa group' do + expect(subject.create('blahthree', 'tacacs+')).to eq(true) + expect(subject.get('blahthree')).to eq(blahthree) + end + end + + describe '#delete' do + it 'removes specified aaa group' do + expect(subject.get('blahthree')).to eq(blahthree) + expect(subject.delete('blahthree')).to eq(true) + expect(subject.get('blahthree')).to eq(nil) + end + end + + describe '#set_servers' do + it 'removes all servers and then adds one' do + expect(subject.set_servers('blahtwo', [{ name: 'localhost' }])) + .to eq(true) + expect(subject.get('blahtwo')[:servers]).to eq(servers) + end + end +end diff --git a/spec/system/rbeapi/api/aaa_spec.rb b/spec/system/rbeapi/api/aaa_spec.rb new file mode 100644 index 0000000..3b37571 --- /dev/null +++ b/spec/system/rbeapi/api/aaa_spec.rb @@ -0,0 +1,90 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' +require 'rbeapi/api/aaa' + +describe Rbeapi::Api::Aaa do + subject { described_class.new(node) } + + let(:node) do + Rbeapi::Client.config.read(fixture_file('dut.conf')) + Rbeapi::Client.connect_to('dut') + end + + let(:test) do + { + groups: { + 'blah' => { + type: 'radius', + servers: [] + }, + 'blahtwo' => { + type: 'radius', + servers: [] + } + } + } + end + + describe '#get' do + before do + node.config(['no aaa group server radius blah', + 'no aaa group server radius blahtwo', + 'aaa group server radius blah', 'exit', + 'aaa group server radius blahtwo', 'exit']) + end + + it 'returns the resource for given name' do + expect(subject.get).to eq(test) + end + + it 'returns a hash' do + expect(subject.get).to be_a_kind_of(Hash) + end + + it 'has two entries' do + expect(subject.get[:groups].size).to eq(2) + end + end + + describe '#groups' do + it 'returns new node instance' do + expect(subject.groups).to be_a_kind_of(Rbeapi::Api::AaaGroups) + end + + it 'returns a hash' do + expect(subject.groups).to be_a_kind_of(Object) + end + end +end diff --git a/spec/unit/rbeapi/api/aaa/aaa_groups_spec.rb b/spec/unit/rbeapi/api/aaa/aaa_groups_spec.rb new file mode 100644 index 0000000..ba41189 --- /dev/null +++ b/spec/unit/rbeapi/api/aaa/aaa_groups_spec.rb @@ -0,0 +1,111 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/api/aaa' + +include FixtureHelpers + +describe Rbeapi::Api::AaaGroups do + subject { described_class.new(node) } + + let(:node) { double('node') } + + let(:all) do + { + 'blah' => { + type: 'radius', + servers: [] + } + } + end + + let(:blah) do + { + type: 'radius', + servers: [] + } + end + + let(:blahthree) do + { + type: 'tacacs+', + servers: [] + } + end + + def aaa + aaa = Fixtures[:aaa] + return aaa if aaa + fixture('aaa', format: :text, dir: File.dirname(__FILE__)) + end + + before :each do + allow(subject.node).to receive(:running_config).and_return(aaa) + end + + describe '#get' do + it 'returns the resource for given name' do + expect(subject.get('blah')).to eq(blah) + end + end + + describe '#getall' do + it 'returns all of the aaa group resources' do + expect(subject.getall).to eq(all) + end + end + + describe '#create' do + it 'adds a new aaa group' do + expect(node).to receive(:config) + .with(['aaa group server tacacs+ blahthree', 'exit']) + expect(subject.create('blahthree', 'tacacs+')).to eq(true) + end + end + + describe '#delete' do + it 'removes specified aaa group' do + expect(subject.delete('blahthree')).to eq(true) + expect(subject.get('blahthree')).to eq(nil) + end + end + + describe '#set_servers' do + it 'removes all servers and then adds one' do + expect(node).to receive(:config) + .with(['aaa group server radius blah', 'server localhost ', 'exit']) + expect(subject.set_servers('blah', [{ name: 'localhost' }])) + .to eq(true) + end + end +end diff --git a/spec/unit/rbeapi/api/aaa/aaa_spec.rb b/spec/unit/rbeapi/api/aaa/aaa_spec.rb new file mode 100644 index 0000000..090bc71 --- /dev/null +++ b/spec/unit/rbeapi/api/aaa/aaa_spec.rb @@ -0,0 +1,77 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/api/aaa' + +include FixtureHelpers + +describe Rbeapi::Api::Aaa do + subject { described_class.new(node) } + + let(:node) { double('node') } + + let(:test) do + { + groups: { + 'blah' => { + type: 'radius', + servers: [] + } + } + } + end + + def aaa + aaa = Fixtures[:aaa] + return aaa if aaa + fixture('aaa', format: :text, dir: File.dirname(__FILE__)) + end + + before :each do + allow(subject.node).to receive(:running_config).and_return(aaa) + end + + describe '#get' do + it 'returns the resource for given name' do + expect(subject.get).to eq(test) + end + + it 'returns a hash' do + expect(subject.get).to be_a_kind_of(Hash) + end + + it 'has two entries' do + expect(subject.get.size).to eq(1) + end + end +end diff --git a/spec/unit/rbeapi/api/aaa/fixture_aaa.text b/spec/unit/rbeapi/api/aaa/fixture_aaa.text new file mode 100644 index 0000000..78b8bd2 --- /dev/null +++ b/spec/unit/rbeapi/api/aaa/fixture_aaa.text @@ -0,0 +1,3 @@ +aaa group server radius blah +no aaa root +aaa authentication policy local allow-nopassword-remote-login \ No newline at end of file From f929ebbe6d95da34c0aa001e1fb591d8b57ad598 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Tue, 22 Dec 2015 09:22:20 -0700 Subject: [PATCH 017/110] Shorten config block in bgp test. --- spec/system/rbeapi/api/bgp_spec.rb | 128 ++++------------------------- 1 file changed, 14 insertions(+), 114 deletions(-) diff --git a/spec/system/rbeapi/api/bgp_spec.rb b/spec/system/rbeapi/api/bgp_spec.rb index 063c11c..d04078a 100644 --- a/spec/system/rbeapi/api/bgp_spec.rb +++ b/spec/system/rbeapi/api/bgp_spec.rb @@ -72,105 +72,29 @@ } end + let(:response) do + { + bgp_as: '1000', + router_id: nil, + shutdown: false, + maximum_paths: 1, + maximum_ecmp_paths: 128, + networks: [], + neighbors: {} + } + end + describe '#get' do before do node.config(['no router bgp 64600', 'router bgp 64600', - 'no shutdown', - 'router-id 192.168.254.1', - 'bgp convergence time 300', - 'bgp convergence slow-peer time 90', - 'no bgp confederation identifier', - 'no update wait-for-convergence', - 'no update wait-install', - 'bgp log-neighbor-changes', - 'bgp default ipv4-unicast', - 'no bgp default ipv6-unicast', - 'timers bgp 60 180', - 'distance bgp 20 200 200', - 'graceful-restart stalepath-time 300', - 'no bgp cluster-id', - 'bgp client-to-client reflection', - 'graceful-restart-helper', - 'bgp peer-mac-resolution-timeout 0', - 'bgp enforce-first-as', - 'no default-metric', - 'no bgp always-compare-med', - 'no bgp bestpath med missing-as-worst', - 'no bgp bestpath med confed', - 'no bgp host-routes fib direct-install', - 'maximum-paths 32 ecmp 32', - 'bgp listen limit 1000', - 'no bgp aspath-cmp-include-nexthop', - 'no bgp tie-break-on-age', - 'no bgp tie-break-on-router-id', - 'no bgp tie-break-on-originator-id', - 'no bgp tie-break-on-cluster-list-length', - 'neighbor eBGP_GROUP peer-group', - 'no neighbor eBGP_GROUP remote-as', - 'no neighbor eBGP_GROUP import-localpref', - 'no neighbor eBGP_GROUP export-localpref', - 'no neighbor eBGP_GROUP description', - 'no neighbor eBGP_GROUP next-hop-self', - 'no neighbor eBGP_GROUP next-hop-peer', - 'no neighbor eBGP_GROUP allowas-in', - 'no neighbor eBGP_GROUP send-community', - 'no neighbor eBGP_GROUP shutdown', - 'no neighbor eBGP_GROUP remove-private-as', - 'no neighbor eBGP_GROUP out-delay', - 'no neighbor eBGP_GROUP local-as', - 'no neighbor eBGP_GROUP weight', - 'no neighbor eBGP_GROUP transport connection-mode passive', - 'no neighbor eBGP_GROUP update-source', - 'no neighbor eBGP_GROUP dont-capability-negotiate', - 'neighbor eBGP_GROUP fall-over bfd', - 'no neighbor eBGP_GROUP local-v6-addr', - 'neighbor eBGP_GROUP soft-reconfiguration inbound', - 'no neighbor eBGP_GROUP ebgp-multihop', - 'no neighbor eBGP_GROUP route-reflector-client', - 'no neighbor eBGP_GROUP timers', - 'no neighbor eBGP_GROUP route-map in', - 'neighbor eBGP_GROUP graceful-restart-helper', - 'no neighbor eBGP_GROUP route-map out', - 'no neighbor eBGP_GROUP prefix-list in', - 'no neighbor eBGP_GROUP prefix-list out', - 'neighbor eBGP_GROUP password 7 6C/HkrwJ53+dsHumQf49Wg==', - 'no neighbor eBGP_GROUP default-originate', - 'neighbor eBGP_GROUP enforce-first-as', - 'no neighbor eBGP_GROUP metric-out', - 'neighbor eBGP_GROUP maximum-routes 12000', + 'router-id 192.168.254.1', 'maximum-paths 32 ecmp 32', 'neighbor 192.168.255.1 peer-group eBGP_GROUP', 'neighbor 192.168.255.1 remote-as 65000', 'neighbor 192.168.255.3 peer-group eBGP_GROUP', 'neighbor 192.168.255.3 remote-as 65001', 'network 192.168.254.1/32', 'network 192.168.254.2/32 route-map rmap', - 'bgp redistribute-internal', - 'aggregate-address 192.168.255.0/28 summary-only', - 'no redistribute connected', - 'no redistribute ospf match internal', - 'no redistribute ospf match external', - 'no redistribute ospf match nssa-external', - 'no redistribute ospf3 match internal', - 'no redistribute ospf3 match external', - 'no redistribute static', - 'no redistribute rip', - 'no redistribute aggregate', - 'address-family ipv4', - 'default neighbor eBGP_GROUP activate', - 'no neighbor eBGP_GROUP route-map in', - 'no neighbor eBGP_GROUP route-map out', - 'no neighbor eBGP_GROUP default-originate', - 'default neighbor 192.168.255.1 activate', - 'default neighbor 192.168.255.3 activate', - 'address-family ipv6', - 'default neighbor eBGP_GROUP activate', - 'no neighbor eBGP_GROUP route-map in', - 'no neighbor eBGP_GROUP route-map out', - 'no neighbor eBGP_GROUP prefix-list in', - 'no neighbor eBGP_GROUP prefix-list out', - 'no neighbor eBGP_GROUP default-originate', - 'default neighbor 192.168.255.1 activate', - 'default neighbor 192.168.255.3 activate']) + 'aggregate-address 192.168.255.0/28 summary-only']) end it 'returns the BGP resource' do @@ -179,18 +103,6 @@ end describe '#create' do - let(:response) do - { - bgp_as: '1000', - router_id: nil, - shutdown: false, - maximum_paths: 1, - maximum_ecmp_paths: 128, - networks: [], - neighbors: {} - } - end - before do node.config(['no router bgp 64600']) end @@ -247,18 +159,6 @@ node.config(['no router bgp 1000', 'router bgp 1000']) end - let(:response) do - { - bgp_as: '1000', - router_id: nil, - shutdown: false, - maximum_paths: 1, - maximum_ecmp_paths: 128, - networks: [], - neighbors: {} - } - end - it 'delete a BGP resource' do expect(subject.get).to eq(response) expect(subject.delete).to be_truthy From 37387e3efba3bb853a770fc396682677acfdfb27 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Tue, 22 Dec 2015 16:28:55 -0700 Subject: [PATCH 018/110] Checking in. --- lib/rbeapi/api/aaa.rb | 42 ++++++++++++++++++++++------------ lib/rbeapi/api/acl.rb | 2 +- lib/rbeapi/api/dns.rb | 2 +- lib/rbeapi/api/interfaces.rb | 2 +- lib/rbeapi/api/ipinterfaces.rb | 2 +- lib/rbeapi/api/logging.rb | 2 +- lib/rbeapi/api/mlag.rb | 2 +- lib/rbeapi/api/ntp.rb | 4 ++-- lib/rbeapi/api/ospf.rb | 2 +- lib/rbeapi/api/prefixlists.rb | 2 +- lib/rbeapi/api/radius.rb | 2 +- lib/rbeapi/api/routemaps.rb | 2 +- lib/rbeapi/api/snmp.rb | 2 +- lib/rbeapi/api/staticroutes.rb | 2 +- lib/rbeapi/api/stp.rb | 2 +- lib/rbeapi/api/switchports.rb | 2 +- lib/rbeapi/api/system.rb | 2 +- lib/rbeapi/api/tacacs.rb | 2 +- lib/rbeapi/api/users.rb | 2 +- lib/rbeapi/api/varp.rb | 2 +- lib/rbeapi/api/vlans.rb | 2 +- lib/rbeapi/api/vrrp.rb | 2 +- 22 files changed, 50 insertions(+), 36 deletions(-) diff --git a/lib/rbeapi/api/aaa.rb b/lib/rbeapi/api/aaa.rb index f6289c7..5392136 100644 --- a/lib/rbeapi/api/aaa.rb +++ b/lib/rbeapi/api/aaa.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Aaa class manages Authorization, Authentication and Accounting (AAA) @@ -47,6 +47,8 @@ def get response end + ## + # Returns an object node for working with AaaGroups class. def groups return @groups if @groups @groups = AaaGroups.new node @@ -55,20 +57,20 @@ def groups end ## - # The AaaGroups class manages the server groups on a EOS node. + # The AaaGroups class manages the server groups on an EOS node. class AaaGroups < Entity DEFAULT_RADIUS_AUTH_PORT = 1812 DEFAULT_RADIUS_ACCT_PORT = 1813 - # Regular express that parses the radius servers from the aaa group - # server radius configuration block + # Regular expression that parses the radius servers from the aaa group + # server radius configuration block. RADIUS_GROUP_SERVER = /\s{3}server [ ]([^\s]+) [ ]auth-port[ ](\d+) [ ]acct-port[ ](\d+)/x - # Regular expression that parse the tacacs servers from the aaa group - # server tacacs+ configuration block + # Regular expression that parses the tacacs servers from the aaa group + # server tacacs+ configuration block. TACACS_GROUP_SERVER = /\s{3}server [ ]([^\s]+) (?:[ ]vrf[ ](\w+))? @@ -76,20 +78,20 @@ class AaaGroups < Entity ## # get returns the aaa server group resource hash that describes the - # current configuration for the specified server group name + # current configuration for the specified server group name. # # The resource hash returned contains the following: # * type: (String) The server group type. Valid values are either - # 'tacacs' or 'radius' + # 'tacacs' or 'radius'. # * servers: (Array) The set of servers associated with the group. - # Servers are returned as either IP address or host name + # Servers are returned as either IP address or host name. # - # @param [String] :name The server group name to return f:rom the nodes + # @param [String] :name The server group name to return from the nodes # current running configuration. If the name is not configured a nil # object is returned. # # @return [nil, Hash] returns the resource hash for the - # specified name. If the name does not exist, a nil object is returned + # specified name. If the name does not exist, a nil object is returned. def get(name) block = get_block("aaa group server ([^\s]+) #{name}") return nil unless block @@ -99,6 +101,18 @@ def get(name) response end + ## + # getall returns a aaa server groups hash + # + # The resource hash returned contains the following: + # * name: (String) The server group name. + # * type: (String) The server group type. Valid values are either + # 'tacacs' or 'radius' + # * servers: (Array) The set of servers associated with the group. + # Servers are returned as either IP address or host name + # + # @return [Hash] returns the resource hashes for + # configured aaa groups. If none exist, a nil object is returned def getall cfg = config.scan(/aaa group server (?:radius|tacacs\+) (.+)$/) cfg.each_with_object({}) do |name, hsh| @@ -109,7 +123,7 @@ def getall ## # parse_type scans the specified configuration block and returns the - # server group type as either 'tacacs' or 'radius' The type value is + # server group type as either 'tacacs' or 'radius'. The type value is # expected to always be present in the config. # # @api private @@ -175,8 +189,8 @@ def parse_radius_server(config) private :parse_radius_server ## - # parse_tacacs_server scans the provide configuration block and returns - # the list of servers configured. The configuration block is expected to + # parse_tacacs_server scans the provided configuration block and returns + # the list of configured servers. The configuration block is expected to # be a tacacs configuration block. If there are no servers configured # for the group the servers value will return an empty array. # diff --git a/lib/rbeapi/api/acl.rb b/lib/rbeapi/api/acl.rb index f4a591b..8503cd3 100644 --- a/lib/rbeapi/api/acl.rb +++ b/lib/rbeapi/api/acl.rb @@ -33,7 +33,7 @@ require 'rbeapi/api' ## -# Eos is the toplevel namespace for working with Arista EOS nodes +# Rbeapi toplevel namespace module Rbeapi ## # Api is module namespace for working with the EOS command API diff --git a/lib/rbeapi/api/dns.rb b/lib/rbeapi/api/dns.rb index 787443d..9263020 100644 --- a/lib/rbeapi/api/dns.rb +++ b/lib/rbeapi/api/dns.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Dns class manages DNS settings on an EOS node. diff --git a/lib/rbeapi/api/interfaces.rb b/lib/rbeapi/api/interfaces.rb index d154219..dee136b 100644 --- a/lib/rbeapi/api/interfaces.rb +++ b/lib/rbeapi/api/interfaces.rb @@ -36,7 +36,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Api module namespace + # Api is module namespace for working with the EOS command API module Api ## # The Interfaces class manages all physical and logical interfaces on an diff --git a/lib/rbeapi/api/ipinterfaces.rb b/lib/rbeapi/api/ipinterfaces.rb index 568f3ac..873c482 100644 --- a/lib/rbeapi/api/ipinterfaces.rb +++ b/lib/rbeapi/api/ipinterfaces.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api # # The Ipinterface class provides an instance for managing logical diff --git a/lib/rbeapi/api/logging.rb b/lib/rbeapi/api/logging.rb index 05e1f99..dc9816e 100644 --- a/lib/rbeapi/api/logging.rb +++ b/lib/rbeapi/api/logging.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Logging class manages logging settings on an EOS node. diff --git a/lib/rbeapi/api/mlag.rb b/lib/rbeapi/api/mlag.rb index 99779b7..a397c97 100644 --- a/lib/rbeapi/api/mlag.rb +++ b/lib/rbeapi/api/mlag.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Mlag class provides a configuration instance for working with diff --git a/lib/rbeapi/api/ntp.rb b/lib/rbeapi/api/ntp.rb index e1d756d..337a794 100644 --- a/lib/rbeapi/api/ntp.rb +++ b/lib/rbeapi/api/ntp.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Eos is the toplevel namespace for working with Arista EOS nodes +# Rbeapi toplevel namespace module Rbeapi ## - # Api is module namesapce for working with the EOS command API + # Api is module namespace for working with the EOS command API module Api ## # The Ntp class provides an instance for working with the nodes diff --git a/lib/rbeapi/api/ospf.rb b/lib/rbeapi/api/ospf.rb index 46486af..eb4c120 100644 --- a/lib/rbeapi/api/ospf.rb +++ b/lib/rbeapi/api/ospf.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Ospf class is a global class that provides an instance for working diff --git a/lib/rbeapi/api/prefixlists.rb b/lib/rbeapi/api/prefixlists.rb index 379819c..6bef554 100644 --- a/lib/rbeapi/api/prefixlists.rb +++ b/lib/rbeapi/api/prefixlists.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Prefixlists class provides a configuration instance for working diff --git a/lib/rbeapi/api/radius.rb b/lib/rbeapi/api/radius.rb index 86c1481..399ca86 100644 --- a/lib/rbeapi/api/radius.rb +++ b/lib/rbeapi/api/radius.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # Radius provides instance methods to retrieve and set radius configuration diff --git a/lib/rbeapi/api/routemaps.rb b/lib/rbeapi/api/routemaps.rb index ca6494c..fca8556 100644 --- a/lib/rbeapi/api/routemaps.rb +++ b/lib/rbeapi/api/routemaps.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Routemaps class manages routemaps. A route map is a list of rules diff --git a/lib/rbeapi/api/snmp.rb b/lib/rbeapi/api/snmp.rb index fd2ea60..309a814 100644 --- a/lib/rbeapi/api/snmp.rb +++ b/lib/rbeapi/api/snmp.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Api is module namespace for working with eAPI abstractions + # Api is module namespace for working with the EOS command API module Api ## # The Snmp class provides a class implementation for working with the diff --git a/lib/rbeapi/api/staticroutes.rb b/lib/rbeapi/api/staticroutes.rb index 739aa64..1efe459 100644 --- a/lib/rbeapi/api/staticroutes.rb +++ b/lib/rbeapi/api/staticroutes.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Staticroutes class provides a configuration instance for working diff --git a/lib/rbeapi/api/stp.rb b/lib/rbeapi/api/stp.rb index 79def53..caf9926 100644 --- a/lib/rbeapi/api/stp.rb +++ b/lib/rbeapi/api/stp.rb @@ -34,7 +34,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Stp class provides a base class instance for working with diff --git a/lib/rbeapi/api/switchports.rb b/lib/rbeapi/api/switchports.rb index 373b7d5..eb92d0b 100644 --- a/lib/rbeapi/api/switchports.rb +++ b/lib/rbeapi/api/switchports.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Api is module namesapce for working with the EOS command API + # Api is module namespace for working with the EOS command API module Api ## # The Switchport class provides a base class instance for working with diff --git a/lib/rbeapi/api/system.rb b/lib/rbeapi/api/system.rb index 34b0e06..45fceaa 100644 --- a/lib/rbeapi/api/system.rb +++ b/lib/rbeapi/api/system.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The System class configures the node system services such as diff --git a/lib/rbeapi/api/tacacs.rb b/lib/rbeapi/api/tacacs.rb index a955349..b3e9cf9 100644 --- a/lib/rbeapi/api/tacacs.rb +++ b/lib/rbeapi/api/tacacs.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Api is module namesapce for working with the EOS command API + # Api is module namespace for working with the EOS command API module Api ## # Tacacs provides instance methods to retrieve and set tacacs configuration diff --git a/lib/rbeapi/api/users.rb b/lib/rbeapi/api/users.rb index 6d5cde9..d4cadd4 100644 --- a/lib/rbeapi/api/users.rb +++ b/lib/rbeapi/api/users.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Api is module namesapce for working with the EOS command API + # Api is module namespace for working with the EOS command API module Api ## # The Users class provides configuration of local user resources for diff --git a/lib/rbeapi/api/varp.rb b/lib/rbeapi/api/varp.rb index 47d6d53..09f9ec6 100644 --- a/lib/rbeapi/api/varp.rb +++ b/lib/rbeapi/api/varp.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Varp class provides an instance for working with the global diff --git a/lib/rbeapi/api/vlans.rb b/lib/rbeapi/api/vlans.rb index 5ce3ad2..4934c05 100644 --- a/lib/rbeapi/api/vlans.rb +++ b/lib/rbeapi/api/vlans.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Api is module namesapce for working with the EOS command API + # Api is module namespace for working with the EOS command API module Api ## # The Vlan class provides a class implementation for working with the diff --git a/lib/rbeapi/api/vrrp.rb b/lib/rbeapi/api/vrrp.rb index 69cf370..a8b1b1d 100644 --- a/lib/rbeapi/api/vrrp.rb +++ b/lib/rbeapi/api/vrrp.rb @@ -32,7 +32,7 @@ require 'rbeapi/api' ## -# Eos is the toplevel namespace for working with Arista EOS nodes +# Rbeapi toplevel namespace module Rbeapi ## # Api is module namespace for working with the EOS command API From 7391d9fd97304dfb7774301f77215f61e82ebc21 Mon Sep 17 00:00:00 2001 From: John Corbin Date: Wed, 23 Dec 2015 07:25:14 -0800 Subject: [PATCH 019/110] Added support for trunk groups. Fixes #38 --- lib/rbeapi/api/switchports.rb | 56 +++++++++++++++++++++ spec/system/rbeapi/api/switchports_spec.rb | 58 +++++++++++++++++++++- 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/lib/rbeapi/api/switchports.rb b/lib/rbeapi/api/switchports.rb index 373b7d5..3cefe6d 100644 --- a/lib/rbeapi/api/switchports.rb +++ b/lib/rbeapi/api/switchports.rb @@ -69,6 +69,7 @@ def get(name) response.merge!(parse_access_vlan(config)) response.merge!(parse_trunk_native_vlan(config)) response.merge!(parse_trunk_allowed_vlans(config)) + response.merge!(parse_trunk_groups(config)) response end @@ -76,16 +77,19 @@ def parse_mode(config) mdata = /(?<=\s{3}switchport\smode\s)(.+)$/.match(config) { mode: mdata[1] } end + private :parse_mode def parse_access_vlan(config) mdata = /(?<=access\svlan\s)(.+)$/.match(config) { access_vlan: mdata[1] } end + private :parse_access_vlan def parse_trunk_native_vlan(config) mdata = /(?<=trunk\snative\svlan\s)(.+)$/.match(config) { trunk_native_vlan: mdata[1] } end + private :parse_trunk_native_vlan def parse_trunk_allowed_vlans(config) mdata = /(?<=trunk\sallowed\svlan\s)(.+)$/.match(config) @@ -101,6 +105,14 @@ def parse_trunk_allowed_vlans(config) end { trunk_allowed_vlans: values } end + private :parse_trunk_allowed_vlans + + def parse_trunk_groups(config) + mdata = config.scan(/(?<=trunk\sgroup\s)(.+)$/) + mdata = mdata.flatten if mdata.length > 0 + { trunk_groups: mdata } + end + private :parse_trunk_groups ## # Retrieves all switchport interfaces from the running-config @@ -248,6 +260,50 @@ def set_access_vlan(name, opts = {}) cmd = command_builder('switchport access vlan', opts) configure_interface(name, cmd) end + + ## + # Configures the trunk group vlans for the specified interface. + # Trunk groups not currently set are added and trunk groups + # currently configured but not in the passed in value array are removed. + # + # @param [String] name The name of the interface to configure + # @param [Hash] opts The configuration parameters for the interface + # @option opts [string] :value Set of values to configure the trunk group + # @option opts [Boolean] :enable If false then the command is + # negated. Default is true. + # @option opts [Boolean] :default The value should be set to default + # Default takes precedence over enable. + # + # @return [Boolean] True if the commands succeed otherwise False + def set_trunk_groups(name, opts = {}) + default = opts.fetch(:default, false) + if default + return configure_interface(name, 'default switchport trunk group') + end + + enable = opts.fetch(:enable, true) + unless enable + return configure_interface(name, 'no switchport trunk group') + end + + value = opts.fetch(:value, []) + fail ArgumentError, 'value must be an Array' unless value.is_a?(Array) + + value = Set.new value + current_value = Set.new get(name)[:trunk_groups] + + cmds = [] + # Add trunk groups that are not currently in the list + value.difference(current_value).each do |group| + cmds << "switchport trunk group #{group}" + end + + # Remove trunk groups that are not in the new list + current_value.difference(value).each do |group| + cmds << "no switchport trunk group #{group}" + end + configure_interface(name, cmds) if cmds.length > 0 + end end end end diff --git a/spec/system/rbeapi/api/switchports_spec.rb b/spec/system/rbeapi/api/switchports_spec.rb index dff9316..e9658a1 100644 --- a/spec/system/rbeapi/api/switchports_spec.rb +++ b/spec/system/rbeapi/api/switchports_spec.rb @@ -13,7 +13,8 @@ describe '#get' do let(:keys) do - [:mode, :access_vlan, :trunk_native_vlan, :trunk_allowed_vlans] + [:mode, :access_vlan, :trunk_native_vlan, :trunk_allowed_vlans, + :trunk_groups] end before do @@ -206,4 +207,59 @@ expect(subject.get('Ethernet1')[:trunk_allowed_vlans].length).to eq(4094) end end + + describe '#set_trunk_groups' do + before do + node.config(['interface Ethernet1', 'default switchport trunk group']) + end + + it 'raises an ArgumentError if value is not an array' do + expect { subject.set_trunk_groups('Ethernet1', value: 'foo') } + .to raise_error(ArgumentError) + end + + it 'sets trunk group to foo bar bang' do + node.config(['interface Ethernet1', 'switchport trunk group bang', + 'switchport trunk group baz']) + expect(subject.get('Ethernet1')[:trunk_groups]).to eq(%w(bang baz)) + expect(subject.set_trunk_groups('Ethernet1', value: %w(foo bar bang))) + .to be_truthy + expect(subject.get('Ethernet1')[:trunk_groups].sort) + .to eq(%w(bang bar foo)) + end + + it 'clears trunk group if no value specified' do + node.config(['interface Ethernet1', 'switchport trunk group bang', + 'switchport trunk group baz']) + expect(subject.get('Ethernet1')[:trunk_groups]).to eq(%w(bang baz)) + expect(subject.set_trunk_groups('Ethernet1')).to be_truthy + expect(subject.get('Ethernet1')[:trunk_groups]).to be_empty + end + + it 'negate switchport trunk group' do + node.config(['interface Ethernet1', 'switchport trunk group bang', + 'switchport trunk group baz']) + expect(subject.get('Ethernet1')[:trunk_groups]).to eq(%w(bang baz)) + expect(subject.set_trunk_groups('Ethernet1', value: %w(foo bar bang))) + .to be_truthy + expect(subject.get('Ethernet1')[:trunk_groups].sort) + .to eq(%w(bang bar foo)) + expect(subject.set_trunk_groups('Ethernet1', enable: false)) + .to be_truthy + expect(subject.get('Ethernet1')[:trunk_groups]).to be_empty + end + + it 'default switchport trunk group' do + node.config(['interface Ethernet1', 'switchport trunk group bang', + 'switchport trunk group baz']) + expect(subject.get('Ethernet1')[:trunk_groups]).to eq(%w(bang baz)) + expect(subject.set_trunk_groups('Ethernet1', value: %w(foo bar bang))) + .to be_truthy + expect(subject.get('Ethernet1')[:trunk_groups].sort) + .to eq(%w(bang bar foo)) + expect(subject.set_trunk_groups('Ethernet1', default: true)) + .to be_truthy + expect(subject.get('Ethernet1')[:trunk_groups]).to be_empty + end + end end From c7d93f427d293ab645a2e5c41d679ff395ff5f59 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Wed, 23 Dec 2015 09:10:44 -0700 Subject: [PATCH 020/110] Shorten config block. --- spec/system/rbeapi/api/vrrp_spec.rb | 38 ++++++++++++++++------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/spec/system/rbeapi/api/vrrp_spec.rb b/spec/system/rbeapi/api/vrrp_spec.rb index 55f2ddc..486982e 100644 --- a/spec/system/rbeapi/api/vrrp_spec.rb +++ b/spec/system/rbeapi/api/vrrp_spec.rb @@ -20,29 +20,33 @@ describe '#get' do before do - node.config(['no interface Vlan150', 'no interface Vlan100', - 'interface Vlan100', 'interface Vlan150', - 'ip address 40.10.5.8/24', 'vrrp 30 priority 100', + node.config(['no interface Vlan150', + 'no interface Vlan100', + 'interface Vlan100', + 'interface Vlan150', + 'ip address 40.10.5.8/24', + 'vrrp 30 priority 100', 'vrrp 30 timers advertise 1', 'vrrp 30 mac-address advertisement-interval 30', - 'no vrrp 30 preempt', 'vrrp 30 preempt delay minimum 0', - 'vrrp 30 preempt delay reload 0', 'vrrp 30 delay reload 0', - 'no vrrp 30 authentication', 'vrrp 30 ip 40.10.5.31', - 'vrrp 30 ipv6 ::', 'vrrp 30 description The description', - 'vrrp 30 shutdown', 'vrrp 30 track Ethernet1 decrement 5', - 'no vrrp 30 bfd ip', 'no vrrp 30 bfd ipv6', - 'vrrp 30 ip version 2', 'vrrp 40 priority 200', + 'no vrrp 30 preempt', + 'vrrp 30 preempt delay reload 0', + 'vrrp 30 delay reload 0', + 'vrrp 30 ip 40.10.5.31', + 'vrrp 30 description The description', + 'vrrp 30 shutdown', + 'vrrp 30 track Ethernet1 decrement 5', + 'vrrp 30 ip version 2', + 'vrrp 40 priority 200', 'vrrp 40 timers advertise 1', 'vrrp 40 mac-address advertisement-interval 30', - 'vrrp 40 preempt', 'vrrp 40 preempt delay minimum 0', - 'vrrp 40 preempt delay reload 0', 'vrrp 40 delay reload 0', - 'no vrrp 40 authentication', 'vrrp 40 ip 40.10.5.32', - 'vrrp 40 ipv6 ::', 'no vrrp 40 description', - 'no vrrp 40 shutdown', + 'vrrp 40 preempt', + 'vrrp 40 preempt delay reload 0', + 'vrrp 40 delay reload 0', + 'vrrp 40 ip 40.10.5.32', 'vrrp 40 track Ethernet3 decrement 33', 'vrrp 40 track Ethernet2 decrement 22', - 'vrrp 40 track Ethernet2 shutdown', 'no vrrp 40 bfd ip', - 'no vrrp 40 bfd ipv6', 'vrrp 40 ip version 2']) + 'vrrp 40 track Ethernet2 shutdown', + 'vrrp 40 ip version 2']) end let(:entity) do From 4ab55c67319c76d5716c71dba9212372c68e7850 Mon Sep 17 00:00:00 2001 From: John Corbin Date: Fri, 1 Jan 2016 15:31:54 -0800 Subject: [PATCH 021/110] Add lacp_mode option when setting port-channel members. Fixes #58 --- lib/rbeapi/api/interfaces.rb | 29 ++++++-- .../rbeapi/api/interfaces_portchannel_spec.rb | 68 +++++++++++++++++++ 2 files changed, 91 insertions(+), 6 deletions(-) diff --git a/lib/rbeapi/api/interfaces.rb b/lib/rbeapi/api/interfaces.rb index d154219..e60f511 100644 --- a/lib/rbeapi/api/interfaces.rb +++ b/lib/rbeapi/api/interfaces.rb @@ -773,24 +773,41 @@ def set_minimum_links(name, opts = {}) # @param [Array] :members The array of physical interface members to add # to the port-channel logical interface. # + # @param [str] :mode The LACP mode to configure the member interfaces to. + # Valid values are 'on, 'passive', 'active'. When there are + # existing channel-group members and their lacp mode differs + # from this attribute, all of those members will be removed and + # then re-added using the specified lacp mode. If this attribute + # is omitted, the existing lacp mode will be used for new + # member additions. + # # @return [Boolean] returns true if the command completed successfully - def set_members(name, members) + def set_members(name, members, mode = nil) current_members = Set.new parse_members(name)[:members] members = Set.new members + lacp_mode = parse_lacp_mode(name)[:lacp_mode] + if mode && mode != lacp_mode + lacp_mode = mode + set_lacp_mode(name, lacp_mode) + end + + cmds = [] + grpid = /(\d+)/.match(name)[0] + # remove members from the current port-channel interface current_members.difference(members).each do |intf| - result = remove_member(name, intf) - return false unless result + cmds << "interface #{intf}" + cmds << "no channel-group #{grpid}" end # add new member interfaces to the port-channel members.difference(current_members).each do |intf| - result = add_member(name, intf) - return false unless result + cmds << "interface #{intf}" + cmds << "channel-group #{grpid} mode #{lacp_mode}" end - true + configure(cmds) end ## diff --git a/spec/system/rbeapi/api/interfaces_portchannel_spec.rb b/spec/system/rbeapi/api/interfaces_portchannel_spec.rb index 8afd324..6814e98 100644 --- a/spec/system/rbeapi/api/interfaces_portchannel_spec.rb +++ b/spec/system/rbeapi/api/interfaces_portchannel_spec.rb @@ -134,6 +134,74 @@ expect(subject.get('Port-Channel1')[:members]).to eq(%w(Ethernet1 Ethernet3)) end + + it 'updates the member interfaces and mode on existing interface' do + node.config(['no interface Port-Channel1', 'interface Ethernet1-2', + 'channel-group 1 mode on']) + expect(subject.get('Port-Channel1')[:members]).to eq(%w(Ethernet1 + Ethernet2)) + expect(subject.get('Port-Channel1')[:lacp_mode]).to eq('on') + expect(subject.set_members('Port-Channel1', + %w(Ethernet1 Ethernet3), + 'active')).to be_truthy + expect(subject.get('Port-Channel1')[:members]).to eq(%w(Ethernet1 + Ethernet3)) + expect(subject.get('Port-Channel1')[:lacp_mode]).to eq('active') + end + end + + describe '#add_member' do + before do + node.config(['no interface Port-Channel1', + 'interface Port-Channel1']) + end + + it 'adds new members to the port-channel interface' do + node.config(['no interface Port-Channel1', 'interface Port-Channel1']) + expect(subject.get('Port-Channel1')[:members]).not_to include('Ethernet1') + expect(subject.add_member('Port-Channel1', 'Ethernet1')).to be_truthy + expect(subject.get('Port-Channel1')[:members]).to eq(['Ethernet1']) + end + + it 'updates the member interfaces on existing interface' do + node.config(['no interface Port-Channel1', 'interface Ethernet1-2', + 'channel-group 1 mode on']) + expect(subject.get('Port-Channel1')[:members]).to eq(%w(Ethernet1 + Ethernet2)) + expect(subject.add_member('Port-Channel1', 'Ethernet3')).to be_truthy + expect(subject.get('Port-Channel1')[:members]).to eq(%w(Ethernet1 + Ethernet2 + Ethernet3)) + expect(subject.get('Port-Channel1')[:lacp_mode]).to eq('on') + end + + it 'no update to the member interfaces on existing interface' do + node.config(['no interface Port-Channel1', 'interface Ethernet1-2', + 'channel-group 1 mode active']) + expect(subject.get('Port-Channel1')[:members]).to eq(%w(Ethernet1 + Ethernet2)) + expect(subject.add_member('Port-Channel1', 'Ethernet2')).to be_truthy + expect(subject.get('Port-Channel1')[:members]).to eq(%w(Ethernet1 + Ethernet2)) + expect(subject.get('Port-Channel1')[:lacp_mode]).to eq('active') + end + end + + describe '#remove_member' do + before do + node.config(['no interface Port-Channel1', + 'interface Port-Channel1']) + end + + it 'removes the member interface on existing interface' do + node.config(['no interface Port-Channel1', 'interface Ethernet1-2', + 'channel-group 1 mode on']) + expect(subject.get('Port-Channel1')[:members]).to eq(%w(Ethernet1 + Ethernet2)) + expect(subject.remove_member('Port-Channel1', 'Ethernet1')).to be_truthy + expect(subject.get('Port-Channel1')[:members]).to eq(['Ethernet2']) + expect(subject.get('Port-Channel1')[:lacp_mode]).to eq('on') + end end describe '#set_lacp_mode' do From c40e1bc75d9b10e731f4eab0e5b4fa625d800ab9 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Sat, 2 Jan 2016 14:35:53 -0700 Subject: [PATCH 022/110] Working on beefing up framework tests. --- spec/fixtures/test.conf | 46 +++--- spec/system/rbeapi/client_spec.rb | 78 ++++++++-- spec/unit/rbeapi/client/default_spec.rb | 180 ++++++++++++++++++------ 3 files changed, 236 insertions(+), 68 deletions(-) diff --git a/spec/fixtures/test.conf b/spec/fixtures/test.conf index e955d73..595eda7 100644 --- a/spec/fixtures/test.conf +++ b/spec/fixtures/test.conf @@ -1,29 +1,39 @@ [connection:veos01] -username : eapi -password : password -transport : http -host : veos01 +username: eapi +password: password +transport: http +host: veos01 [connection:veos02] -transport : http -host : veos02 +transport: http +host: veos02 [connection:veos03] -transport : socket -host : veos03 +transport: socket +host: veos03 [connection:veos04] -host : 172.16.10.1 -username : eapi -password : password -enablepwd : itsasecret -port : 1234 -transport : https +host: 172.16.10.1 +username: eapi +password: password +enablepwd: itsasecret +port: 1234 +transport: https + +[connection:veos05] +host: 172.16.131.40 +username: admin +password: admin +enablepwd: password +transport: https +port: 1234 +open_timeout: 12 +read_timeout: 12 [connection: localhost] -transport : http_local -host : localhost +transport: http_local +host: localhost [connection:localhost] -transport : socket -host : localhost +transport: socket +host: localhost diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb index 078d919..83867dd 100644 --- a/spec/system/rbeapi/client_spec.rb +++ b/spec/system/rbeapi/client_spec.rb @@ -35,6 +35,34 @@ def test_conf } end + let(:veos05) do + { + 'host' => '172.16.131.40', + 'username' => 'admin', + 'password' => 'admin', + 'enablepwd' => 'password', + 'transport' => 'https', + 'port' => 1234, + 'open_timeout' => 12, + 'read_timeout' => 12 + } + end + + let(:test_data) do + [ + '[connection:veos01]', + '[connection:veos02]', + '[connection:veos03', + '[connection:veos04]', + '[connection:veos05]', + '[connection: localhost]', + 'username', + 'password', + 'transport', + 'host' + ] + end + # Client class methods describe '#connect_to' do it 'retrieves the node config' do @@ -50,10 +78,15 @@ def test_conf end describe '#config_for' do - it 'returns the configuration options for the connection' do + it 'returns the configuration options for veos01' do expect(subject.config.read(test_conf)).to eq(nil) expect(subject.config_for('veos01')).to eq(veos01) end + + it 'returns the configuration options for veos05' do + expect(subject.config.read(test_conf)).to eq(nil) + expect(subject.config_for('veos05')).to eq(veos05) + end end describe '#load_config' do @@ -67,7 +100,7 @@ def test_conf # Config class methods describe 'config' do it 'gets the loaded configuration file data' do - expect(subject.config.to_s).to eq(test) + expect(subject.config.to_s).to include(test_data[0]) end end @@ -75,14 +108,18 @@ def test_conf it 'read the specified filename and load it' do expect(subject.load_config(dut_conf)).to eq(transport: 'socket') expect(subject.config.read(test_conf)).to eq(nil) - expect(subject.config.to_s).to eq(test) + expect(subject.config.to_s).to include(test_data[0]) end end describe '#get_connection' do - it 'get connection dut' do + it 'get connection veos01' do expect(subject.config.get_connection('veos01')).to eq(veos01) end + + it 'get connection veos05' do + expect(subject.config.get_connection('veos05')).to eq(veos05) + end end describe '#reload' do @@ -91,7 +128,7 @@ def test_conf .to eq(transport: 'socket') expect(subject.config.reload(filename: [test_conf])) .to eq(nil) - expect(subject.config.to_s).to eq(test) + expect(subject.config.to_s).to include(test_data[0]) end end @@ -143,15 +180,40 @@ def test_conf describe '#enable' do it 'puts the switch into privilege mode' do + expect(node.enable('show hostname')[0]) + .to include(:command, :result, :encoding) + end + + it 'puts the switch into privilege mode with encoding' do expect(node.enable('show hostname', encoding: 'text')[0]) .to include(:command, :result, :encoding) end + + it 'puts the switch into privilege mode with open and read timeout' do + expect(node.enable('show hostname', + open_timeout: 29, + read_timeout: 29)[0]).to include(:command, + :result, + :encoding) + end end describe '#run_commands' do - it 'send commands to node' do - expect(node.run_commands('show hostname', encoding: 'text')[0]) - .to include('output') + it 'sends commands to node' do + expect(node.run_commands(['show hostname'])[0]) + .to include('fqdn', 'hostname') + end + + it 'sends commands to node with encoding' do + expect(node.run_commands('show hostname', encoding: 'text')[0]['output']) + .to include('FQDN', 'Hostname') + end + + it 'sends commands with open and read timeout' do + expect(node.run_commands('show hostname', + open_timeout: 26, + read_timeout: 26)[0]).to include('fqdn', + 'hostname') end end diff --git a/spec/unit/rbeapi/client/default_spec.rb b/spec/unit/rbeapi/client/default_spec.rb index 03aaeda..bdbd874 100644 --- a/spec/unit/rbeapi/client/default_spec.rb +++ b/spec/unit/rbeapi/client/default_spec.rb @@ -38,7 +38,10 @@ describe Rbeapi::Client do subject { described_class } - let(:node) { double('node') } + let(:node) do + subject.config.read(fixture_file('dut.conf')) + subject.connect_to('dut') + end def dut_conf fixture_file('dut.conf') @@ -65,24 +68,68 @@ def test_conf } end + let(:veos05) do + { + 'host' => '172.16.131.40', + 'username' => 'admin', + 'password' => 'admin', + 'enablepwd' => 'password', + 'transport' => 'https', + 'port' => 1234, + 'open_timeout' => 12, + 'read_timeout' => 12 + } + end + + let(:test_data) do + [ + '[connection:veos01]', + '[connection:veos02]', + '[connection:veos03', + '[connection:veos04]', + '[connection:veos05]', + '[connection: localhost]', + 'username', + 'password', + 'transport', + 'host' + ] + end + # Client class methods describe '#config_for' do it 'returns the configuration options for the connection' do expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('veos01')).to eq(veos01) end + + it 'returns nil if connection does not exist' do + expect(subject.config_for('veos22')).to eq(nil) + end end describe '#connect_to' do it 'retrieves the node config' do expect(subject.connect_to('veos01')).to be_truthy end + + it 'returns nil if connection does not exist' do + expect(subject.connect_to('veos22')).to eq(nil) + end end describe '#load_config' do it 'overrides the default conf file loaded in the config' do expect(subject.load_config(test_conf)).to eq(nil) + end + + it 'returns nil if connection does not exit' do + expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('dut')).to eq(nil) + end + + it 'returns conf settings if connection exists' do + expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('veos01')).to eq(veos01) end end @@ -91,22 +138,31 @@ def test_conf describe 'config' do it 'gets the loaded configuration file data' do expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config.to_s).to eq(test) + expect(subject.config.to_s).to include(test_data[0]) end end describe '#read' do - it 'read the specified filename and load it' do - expect(subject.load_config(dut_conf)).to eq(transport: 'socket') + it 'read the specified filename and load dut' do + expect(subject.config.read(dut_conf)).to eq(transport: 'socket') + expect(subject.config.to_s) + .to include('host', 'username', 'password', '[connection:dut]') + end + + it 'read the specified filename and load test' do expect(subject.config.read(test_conf)).to eq(nil) - expect(subject.config.to_s).to eq(test) + expect(subject.config.to_s).to include(test_data[0]) end end describe '#get_connection' do - it 'get connection dut' do + it 'get connection veos01' do expect(subject.config.get_connection('veos01')).to eq(veos01) end + + it 'get connection veos05' do + expect(subject.config.get_connection('veos05')).to eq(veos05) + end end describe '#reload' do @@ -141,90 +197,130 @@ def test_conf # Node Class Methods describe '#running_config' do it 'gets the nodes running config' do - allow(node).to receive(:running_config).and_return(test) - expect(node).to receive(:running_config) - expect(node.running_config.to_s).to eq(test) + expect(node.running_config).to be_truthy + end + + it 'expects running config to return a string' do + expect(node.running_config).to be_kind_of(String) end end describe '#startup_config' do it 'gets the nodes startup-configuration' do - allow(node).to receive(:startup_config).and_return(test) - expect(node).to receive(:startup_config) - expect(node.startup_config).to eq(test) + expect(node.startup_config).to be_truthy + end + + it 'expects startup-configuration to be a string' do + expect(node.startup_config).to be_kind_of(String) end end describe '#enable_authentication' do it 'gets the nodes startup-configuration' do - expect(node).to receive(:enable_authentication).with('newpassword') - expect(node.enable_authentication('newpassword')).to eq(nil) + expect(node.enable_authentication('newpassword')).to eq('newpassword') end end describe '#config' do it 'puts switch into config mode' do - expect(node).to receive(:config) - .with(['no ip virtual-router mac-address']) - expect(node.config(['no ip virtual-router mac-address'])).to eq(nil) + expect(node.config(['no ip virtual-router mac-address'])) + .to be_truthy + end + + it 'expects config to return array' do + expect(node.config(['no ip virtual-router mac-address'])) + .to be_kind_of(Array) end - it 'puts switch into config mode with options' do - expect(node).to receive(:config) - .with(['no ip virtual-router mac-address'], - encoding: 'json', - open_timeout: 27.00, - read_timeout: 27.00) + it 'puts switch into config mode with options and returns array' do expect(node.config(['no ip virtual-router mac-address'], encoding: 'json', open_timeout: 27.00, - read_timeout: 27.00)).to eq(nil) + read_timeout: 27.00)) + .to be_kind_of(Array) + end + + it 'returns error if invalid command' do + expect { node.config(['no ip virtual-router mac-addresses']) } + .to raise_error Rbeapi::Eapilib::CommandError end end describe '#enable' do it 'puts the switch into privilege mode' do - expect(node).to receive(:enable).with('show hostname', encoding: 'text') - expect(node.enable('show hostname', encoding: 'text')) - .to eq(nil) + expect(node.enable('show hostname')[0][:result]) + .to include('fqdn', 'hostname') + end + + it 'puts the switch into privilege mode with encoding' do + expect(node.enable('show hostname', encoding: 'text')[0][:encoding]) + .to eq('text') + end + + it 'puts the switch into privilege mode with strict option' do + expect(node.enable('show hostname', strict: true)[0]) + .to include(:command, :result, :encoding) + end + + it 'puts the switch into privilege mode with read and open timeout' do + expect(node.enable('show hostname', + read_timeout: 29, + open_timeout: 29)[0]) + .to include(:command, :result, :encoding) + end + + it 'raises invalid command error' do + expect { node.enable(['show hostname', 'do this thing']) } + .to raise_error Rbeapi::Eapilib::CommandError end end describe '#run_commands' do + it 'expects run_commands to be a string' do + expect(node.run_commands('show hostname', encoding: 'text')[0]['output']) + .to be_kind_of String + end + it 'send commands to node' do - expect(node).to receive(:run_commands) - .with('show hostname', encoding: 'text') - expect(node.run_commands('show hostname', encoding: 'text')) - .to eq(nil) + expect(node.run_commands('show hostname', encoding: 'text')[0]['output']) + .to include('Hostname:', 'FQDN:') + end + + it 'expects run_commands to raise a command error' do + expect { node.run_commands('do this thing') } + .to raise_error Rbeapi::Eapilib::CommandError end end describe '#get_config' do - it 'will retrieve the specified configuration' do - expect(node).to receive(:get_config) - .with(config: 'running-config') + it 'will retrieve the specified configuration and return array' do expect(node.get_config(config: 'running-config')) - .to eq(nil) + .to be_kind_of(Array) end - it 'will retrieve the specified configuration with param' do - expect(node).to receive(:get_config) - .with(config: 'running-config', param: 'all') + it 'will retrieve with param and return array' do expect(node.get_config(config: 'running-config', param: 'all')) - .to eq(nil) + .to be_kind_of(Array) + end + + it 'raises invalid command error' do + expect { node.get_config(config: 'running-configurations') } + .to raise_error Rbeapi::Eapilib::CommandError end end describe '#api' do it 'returns api module' do - expect(node).to receive(:api).with('vlans') - expect(node.api('vlans')).to eq(nil) + expect(node.api('vlans')).to be_kind_of(Rbeapi::Api::Vlans) + end + + it 'returns error if invalid name' do + expect { node.api('vlanss') }.to raise_error end end describe '#refresh' do it 'refreshes configs for next call' do - expect(node).to receive(:refresh) expect(node.refresh).to eq(nil) end end From 193d87b817c18f1f9ad7d6202640086cb7de8fb3 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Sun, 3 Jan 2016 23:01:25 -0700 Subject: [PATCH 023/110] Expanding test coverage. --- spec/unit/rbeapi/client/default_spec.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/spec/unit/rbeapi/client/default_spec.rb b/spec/unit/rbeapi/client/default_spec.rb index bdbd874..57f142d 100644 --- a/spec/unit/rbeapi/client/default_spec.rb +++ b/spec/unit/rbeapi/client/default_spec.rb @@ -240,6 +240,19 @@ def test_conf .to be_kind_of(Array) end + describe 'set dry run' do + before do + # Prevents puts from writing to console + allow($stdout).to receive(:puts) + node.dry_run = true + end + + it 'expects config to do dry run' do + expect(node.config(['no ip virtual-router mac-address'])) + .to eq(nil) + end + end + it 'returns error if invalid command' do expect { node.config(['no ip virtual-router mac-addresses']) } .to raise_error Rbeapi::Eapilib::CommandError @@ -286,6 +299,11 @@ def test_conf .to include('Hostname:', 'FQDN:') end + it 'sends commands with enablepwd set' do + expect(node.enable_authentication('icanttellyou')).to eq('icanttellyou') + expect(node.run_commands('show hostname')).to be_truthy + end + it 'expects run_commands to raise a command error' do expect { node.run_commands('do this thing') } .to raise_error Rbeapi::Eapilib::CommandError From 9508dbb767b498cbd0c2b6d5f09804a3c3e954c5 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 4 Jan 2016 10:47:18 -0700 Subject: [PATCH 024/110] Remove unit tests because node cannot be mocked for these tests. --- spec/system/rbeapi/client_spec.rb | 194 ++++++++++--- spec/unit/rbeapi/client/default_spec.rb | 345 ------------------------ 2 files changed, 160 insertions(+), 379 deletions(-) delete mode 100644 spec/unit/rbeapi/client/default_spec.rb diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb index 83867dd..df3269d 100644 --- a/spec/system/rbeapi/client_spec.rb +++ b/spec/system/rbeapi/client_spec.rb @@ -1,3 +1,34 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# require 'spec_helper' require 'rbeapi/client' @@ -64,35 +95,39 @@ def test_conf end # Client class methods - describe '#connect_to' do - it 'retrieves the node config' do - expect(node).to be_kind_of(Rbeapi::Client::Node) + describe '#config_for' do + it 'returns the configuration options for the connection' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) end - end - describe '#config' do - it 'returns the currently loaded config object' do - expect(subject.config.read(dut_conf)).to eq(transport: 'socket') - expect(subject.connect_to('dut')).to be_kind_of(Rbeapi::Client::Node) + it 'returns nil if connection does not exist' do + expect(subject.config_for('veos22')).to eq(nil) end end - describe '#config_for' do - it 'returns the configuration options for veos01' do - expect(subject.config.read(test_conf)).to eq(nil) - expect(subject.config_for('veos01')).to eq(veos01) + describe '#connect_to' do + it 'retrieves the node config' do + expect(subject.connect_to('veos01')).to be_truthy end - it 'returns the configuration options for veos05' do - expect(subject.config.read(test_conf)).to eq(nil) - expect(subject.config_for('veos05')).to eq(veos05) + it 'returns nil if connection does not exist' do + expect(subject.connect_to('veos22')).to eq(nil) end end describe '#load_config' do it 'overrides the default conf file loaded in the config' do expect(subject.load_config(test_conf)).to eq(nil) + end + + it 'returns nil if connection does not exit' do + expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('dut')).to eq(nil) + end + + it 'returns conf settings if connection exists' do + expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('veos01')).to eq(veos01) end end @@ -100,13 +135,19 @@ def test_conf # Config class methods describe 'config' do it 'gets the loaded configuration file data' do + expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config.to_s).to include(test_data[0]) end end describe '#read' do - it 'read the specified filename and load it' do - expect(subject.load_config(dut_conf)).to eq(transport: 'socket') + it 'read the specified filename and load dut' do + expect(subject.config.read(dut_conf)).to eq(transport: 'socket') + expect(subject.config.to_s) + .to include('host', 'username', 'password', '[connection:dut]') + end + + it 'read the specified filename and load test' do expect(subject.config.read(test_conf)).to eq(nil) expect(subject.config.to_s).to include(test_data[0]) end @@ -124,11 +165,11 @@ def test_conf describe '#reload' do it 'reloads the configuration file' do - expect(subject.load_config(dut_conf)) + expect(subject.config.get_connection('veos01')).to eq(veos01) + expect(subject.config.reload(filename: [dut_conf])) .to eq(transport: 'socket') - expect(subject.config.reload(filename: [test_conf])) - .to eq(nil) - expect(subject.config.to_s).to include(test_data[0]) + expect(subject.config.get_connection('veos01')).to eq(nil) + expect(subject.config.get_connection('dut')).not_to be_nil end end @@ -143,19 +184,38 @@ def test_conf password: 'test', transport: 'http', host: 'test2') + expect(subject.config.get_connection('test2')) + .to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') end end # Node Class Methods + describe 'node' do + it 'retrieves the node' do + expect(node).to be_kind_of(Rbeapi::Client::Node) + end + end + describe '#running_config' do it 'gets the nodes running config' do - expect(node.running_config).not_to be_nil + expect(node.running_config).to be_truthy + end + + it 'expects running config to return a string' do + expect(node.running_config).to be_kind_of(String) end end describe '#startup_config' do it 'gets the nodes startup-configuration' do - expect(node.startup_config).not_to be_nil + expect(node.startup_config).to be_truthy + end + + it 'expects startup-configuration to be a string' do + expect(node.startup_config).to be_kind_of(String) end end @@ -167,46 +227,81 @@ def test_conf describe '#config' do it 'puts switch into config mode' do - expect(node.config(['no ip virtual-router mac-address'])).to be_truthy + expect(node.config(['no ip virtual-router mac-address'])) + .to be_truthy end - it 'puts switch into config mode with options' do + it 'expects config to return array' do + expect(node.config(['no ip virtual-router mac-address'])) + .to be_kind_of(Array) + end + + it 'puts switch into config mode with options and returns array' do expect(node.config(['no ip virtual-router mac-address'], encoding: 'json', open_timeout: 27.00, - read_timeout: 27.00)).to be_truthy + read_timeout: 27.00)) + .to be_kind_of(Array) + end + + describe 'set dry run' do + before do + # Prevents puts from writing to console + allow($stdout).to receive(:puts) + node.dry_run = true + end + + it 'expects config to do dry run' do + expect(node.config(['no ip virtual-router mac-address'])) + .to eq(nil) + end + end + + it 'returns error if invalid command' do + expect { node.config(['no ip virtual-router mac-addresses']) } + .to raise_error Rbeapi::Eapilib::CommandError end end describe '#enable' do it 'puts the switch into privilege mode' do - expect(node.enable('show hostname')[0]) - .to include(:command, :result, :encoding) + expect(node.enable('show hostname')[0][:result]) + .to include('fqdn', 'hostname') end it 'puts the switch into privilege mode with encoding' do - expect(node.enable('show hostname', encoding: 'text')[0]) + expect(node.enable('show hostname', encoding: 'text')[0][:encoding]) + .to eq('text') + end + + it 'puts the switch into privilege mode with strict option' do + expect(node.enable('show hostname', strict: true)[0]) .to include(:command, :result, :encoding) end - it 'puts the switch into privilege mode with open and read timeout' do + it 'puts the switch into privilege mode with read and open timeout' do expect(node.enable('show hostname', open_timeout: 29, read_timeout: 29)[0]).to include(:command, :result, :encoding) end + + it 'raises invalid command error' do + expect { node.enable(['show hostname', 'do this thing']) } + .to raise_error Rbeapi::Eapilib::CommandError + end end describe '#run_commands' do - it 'sends commands to node' do - expect(node.run_commands(['show hostname'])[0]) - .to include('fqdn', 'hostname') + it 'expects run_commands to be a string' do + expect(node.run_commands('show hostname', encoding: 'text')[0]['output']) + .to be_kind_of String end it 'sends commands to node with encoding' do expect(node.run_commands('show hostname', encoding: 'text')[0]['output']) - .to include('FQDN', 'Hostname') + .to include('FQDN:', 'Hostname:') end it 'sends commands with open and read timeout' do @@ -215,12 +310,43 @@ def test_conf read_timeout: 26)[0]).to include('fqdn', 'hostname') end + + it 'sends commands with enablepwd set' do + expect(node.enable_authentication('icanttellyou')).to eq('icanttellyou') + expect(node.run_commands('show hostname')).to be_truthy + end + + it 'expects run_commands to raise a command error' do + expect { node.run_commands('do this thing') } + .to raise_error Rbeapi::Eapilib::CommandError + end + end + + describe '#get_config' do + it 'will retrieve the specified configuration and return array' do + expect(node.get_config(config: 'running-config')) + .to be_kind_of(Array) + end + + it 'will retrieve with param and return array' do + expect(node.get_config(config: 'running-config', param: 'all')) + .to be_kind_of(Array) + end + + it 'raises invalid command error' do + expect { node.get_config(config: 'running-configurations') } + .to raise_error Rbeapi::Eapilib::CommandError + end end describe '#api' do it 'returns api module' do expect(node.api('vlans')).to be_kind_of(Rbeapi::Api::Vlans) end + + it 'returns error if invalid name' do + expect { node.api('vlanss') }.to raise_error + end end describe '#refresh' do diff --git a/spec/unit/rbeapi/client/default_spec.rb b/spec/unit/rbeapi/client/default_spec.rb deleted file mode 100644 index 57f142d..0000000 --- a/spec/unit/rbeapi/client/default_spec.rb +++ /dev/null @@ -1,345 +0,0 @@ -# -# Copyright (c) 2015, Arista Networks, Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# Neither the name of Arista Networks nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -require 'spec_helper' - -require 'rbeapi/client' - -include FixtureHelpers - -describe Rbeapi::Client do - subject { described_class } - - let(:node) do - subject.config.read(fixture_file('dut.conf')) - subject.connect_to('dut') - end - - def dut_conf - fixture_file('dut.conf') - end - - def test_conf - fixture_file('test.conf') - end - - let(:dut) do - File.read(dut_conf) - end - - let(:test) do - File.read(test_conf) - end - - let(:veos01) do - { - 'username' => 'eapi', - 'password' => 'password', - 'transport' => 'http', - 'host' => 'veos01' - } - end - - let(:veos05) do - { - 'host' => '172.16.131.40', - 'username' => 'admin', - 'password' => 'admin', - 'enablepwd' => 'password', - 'transport' => 'https', - 'port' => 1234, - 'open_timeout' => 12, - 'read_timeout' => 12 - } - end - - let(:test_data) do - [ - '[connection:veos01]', - '[connection:veos02]', - '[connection:veos03', - '[connection:veos04]', - '[connection:veos05]', - '[connection: localhost]', - 'username', - 'password', - 'transport', - 'host' - ] - end - - # Client class methods - describe '#config_for' do - it 'returns the configuration options for the connection' do - expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config_for('veos01')).to eq(veos01) - end - - it 'returns nil if connection does not exist' do - expect(subject.config_for('veos22')).to eq(nil) - end - end - - describe '#connect_to' do - it 'retrieves the node config' do - expect(subject.connect_to('veos01')).to be_truthy - end - - it 'returns nil if connection does not exist' do - expect(subject.connect_to('veos22')).to eq(nil) - end - end - - describe '#load_config' do - it 'overrides the default conf file loaded in the config' do - expect(subject.load_config(test_conf)).to eq(nil) - end - - it 'returns nil if connection does not exit' do - expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config_for('dut')).to eq(nil) - end - - it 'returns conf settings if connection exists' do - expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config_for('veos01')).to eq(veos01) - end - end - - # Config class methods - describe 'config' do - it 'gets the loaded configuration file data' do - expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config.to_s).to include(test_data[0]) - end - end - - describe '#read' do - it 'read the specified filename and load dut' do - expect(subject.config.read(dut_conf)).to eq(transport: 'socket') - expect(subject.config.to_s) - .to include('host', 'username', 'password', '[connection:dut]') - end - - it 'read the specified filename and load test' do - expect(subject.config.read(test_conf)).to eq(nil) - expect(subject.config.to_s).to include(test_data[0]) - end - end - - describe '#get_connection' do - it 'get connection veos01' do - expect(subject.config.get_connection('veos01')).to eq(veos01) - end - - it 'get connection veos05' do - expect(subject.config.get_connection('veos05')).to eq(veos05) - end - end - - describe '#reload' do - it 'reloads the configuration file' do - expect(subject.config.get_connection('veos01')).to eq(veos01) - expect(subject.config.reload(filename: [dut_conf])) - .to eq(transport: 'socket') - expect(subject.config.get_connection('veos01')).to eq(nil) - expect(subject.config.get_connection('dut')).not_to be_nil - end - end - - describe '#add_connection' do - it 'adds a new connection section' do - expect(subject.config.add_connection('test2', - username: 'test2', - password: 'test', - transport: 'http', - host: 'test2' - )).to eq(username: 'test2', - password: 'test', - transport: 'http', - host: 'test2') - expect(subject.config.get_connection('test2')) - .to eq(username: 'test2', - password: 'test', - transport: 'http', - host: 'test2') - end - end - - # Node Class Methods - describe '#running_config' do - it 'gets the nodes running config' do - expect(node.running_config).to be_truthy - end - - it 'expects running config to return a string' do - expect(node.running_config).to be_kind_of(String) - end - end - - describe '#startup_config' do - it 'gets the nodes startup-configuration' do - expect(node.startup_config).to be_truthy - end - - it 'expects startup-configuration to be a string' do - expect(node.startup_config).to be_kind_of(String) - end - end - - describe '#enable_authentication' do - it 'gets the nodes startup-configuration' do - expect(node.enable_authentication('newpassword')).to eq('newpassword') - end - end - - describe '#config' do - it 'puts switch into config mode' do - expect(node.config(['no ip virtual-router mac-address'])) - .to be_truthy - end - - it 'expects config to return array' do - expect(node.config(['no ip virtual-router mac-address'])) - .to be_kind_of(Array) - end - - it 'puts switch into config mode with options and returns array' do - expect(node.config(['no ip virtual-router mac-address'], - encoding: 'json', - open_timeout: 27.00, - read_timeout: 27.00)) - .to be_kind_of(Array) - end - - describe 'set dry run' do - before do - # Prevents puts from writing to console - allow($stdout).to receive(:puts) - node.dry_run = true - end - - it 'expects config to do dry run' do - expect(node.config(['no ip virtual-router mac-address'])) - .to eq(nil) - end - end - - it 'returns error if invalid command' do - expect { node.config(['no ip virtual-router mac-addresses']) } - .to raise_error Rbeapi::Eapilib::CommandError - end - end - - describe '#enable' do - it 'puts the switch into privilege mode' do - expect(node.enable('show hostname')[0][:result]) - .to include('fqdn', 'hostname') - end - - it 'puts the switch into privilege mode with encoding' do - expect(node.enable('show hostname', encoding: 'text')[0][:encoding]) - .to eq('text') - end - - it 'puts the switch into privilege mode with strict option' do - expect(node.enable('show hostname', strict: true)[0]) - .to include(:command, :result, :encoding) - end - - it 'puts the switch into privilege mode with read and open timeout' do - expect(node.enable('show hostname', - read_timeout: 29, - open_timeout: 29)[0]) - .to include(:command, :result, :encoding) - end - - it 'raises invalid command error' do - expect { node.enable(['show hostname', 'do this thing']) } - .to raise_error Rbeapi::Eapilib::CommandError - end - end - - describe '#run_commands' do - it 'expects run_commands to be a string' do - expect(node.run_commands('show hostname', encoding: 'text')[0]['output']) - .to be_kind_of String - end - - it 'send commands to node' do - expect(node.run_commands('show hostname', encoding: 'text')[0]['output']) - .to include('Hostname:', 'FQDN:') - end - - it 'sends commands with enablepwd set' do - expect(node.enable_authentication('icanttellyou')).to eq('icanttellyou') - expect(node.run_commands('show hostname')).to be_truthy - end - - it 'expects run_commands to raise a command error' do - expect { node.run_commands('do this thing') } - .to raise_error Rbeapi::Eapilib::CommandError - end - end - - describe '#get_config' do - it 'will retrieve the specified configuration and return array' do - expect(node.get_config(config: 'running-config')) - .to be_kind_of(Array) - end - - it 'will retrieve with param and return array' do - expect(node.get_config(config: 'running-config', param: 'all')) - .to be_kind_of(Array) - end - - it 'raises invalid command error' do - expect { node.get_config(config: 'running-configurations') } - .to raise_error Rbeapi::Eapilib::CommandError - end - end - - describe '#api' do - it 'returns api module' do - expect(node.api('vlans')).to be_kind_of(Rbeapi::Api::Vlans) - end - - it 'returns error if invalid name' do - expect { node.api('vlanss') }.to raise_error - end - end - - describe '#refresh' do - it 'refreshes configs for next call' do - expect(node.refresh).to eq(nil) - end - end -end From 49538e73d9ebd402f48caec6a422ab6f2577dedf Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 4 Jan 2016 12:55:26 -0700 Subject: [PATCH 025/110] Add unit tests back. --- spec/unit/rbeapi/client_spec.rb | 168 ++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 spec/unit/rbeapi/client_spec.rb diff --git a/spec/unit/rbeapi/client_spec.rb b/spec/unit/rbeapi/client_spec.rb new file mode 100644 index 0000000..57af804 --- /dev/null +++ b/spec/unit/rbeapi/client_spec.rb @@ -0,0 +1,168 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' + +include FixtureHelpers + +describe Rbeapi::Client do + subject { described_class } + + let(:node) { double('node') } + + def dut_conf + fixture_file('dut.conf') + end + + def test_conf + fixture_file('test.conf') + end + + let(:dut) do + File.read(dut_conf) + end + + let(:test) do + File.read(test_conf) + end + + let(:veos01) do + { + 'username' => 'eapi', + 'password' => 'password', + 'transport' => 'http', + 'host' => 'veos01' + } + end + + let(:veos05) do + { + 'host' => '172.16.131.40', + 'username' => 'admin', + 'password' => 'admin', + 'enablepwd' => 'password', + 'transport' => 'https', + 'port' => 1234, + 'open_timeout' => 12, + 'read_timeout' => 12 + } + end + + let(:test_data) do + [ + '[connection:veos01]', + '[connection:veos02]', + '[connection:veos03', + '[connection:veos04]', + '[connection:veos05]', + '[connection: localhost]', + 'username', + 'password', + 'transport', + 'host' + ] + end + + # Client class methods + describe '#config_for' do + it 'returns the configuration options for the connection' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) + end + end + + describe '#connect_to' do + it 'retrieves the node config' do + expect(subject.connect_to('veos01')).to be_truthy + end + end + + describe '#load_config' do + it 'overrides the default conf file loaded in the config' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config_for('dut')).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) + end + end + + # Config class methods + describe 'config' do + it 'gets the loaded configuration file data' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config.to_s).to include(test_data[0]) + end + end + + describe '#read' do + it 'read the specified filename and load it' do + expect(subject.load_config(dut_conf)).to eq(transport: 'socket') + expect(subject.config.read(test_conf)).to eq(nil) + expect(subject.config.to_s).to include(test_data[0]) + end + end + + describe '#get_connection' do + it 'get connection dut' do + expect(subject.config.get_connection('veos01')).to eq(veos01) + end + end + + describe '#reload' do + it 'reloads the configuration file' do + expect(subject.config.get_connection('veos01')).to eq(veos01) + expect(subject.config.reload(filename: [dut_conf])) + .to eq(transport: 'socket') + expect(subject.config.get_connection('veos01')).to eq(nil) + expect(subject.config.get_connection('dut')).not_to be_nil + end + end + + describe '#add_connection' do + it 'adds a new connection section' do + expect(subject.config.add_connection('test2', + username: 'test2', + password: 'test', + transport: 'http', + host: 'test2' + )).to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') + expect(subject.config.get_connection('test2')) + .to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') + end + end +end From 52c2b394862034d6b2cf8d5add2c64140cd93345 Mon Sep 17 00:00:00 2001 From: John Corbin Date: Tue, 5 Jan 2016 06:27:26 -0800 Subject: [PATCH 026/110] Relax check on getall entries Routemaps that exist on the switch before test was run will be returned by getall. There is no easy way to clear out all the routemaps and didn't want to loop on the entries not created by test and delete them. --- spec/system/rbeapi/api/routemaps_spec.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/spec/system/rbeapi/api/routemaps_spec.rb b/spec/system/rbeapi/api/routemaps_spec.rb index 4b6edca..a40b456 100644 --- a/spec/system/rbeapi/api/routemaps_spec.rb +++ b/spec/system/rbeapi/api/routemaps_spec.rb @@ -15,8 +15,7 @@ let(:resource) { subject.get } before do - node.config(['no route-map test', 'no route-map test1', - 'no route-map test2', 'no route-map test3', + node.config(['no route-map test', 'route-map test permit 10', 'route-map test permit 20', 'description descript', 'match ip address prefix-list MYLOOPBACK', @@ -90,8 +89,8 @@ expect(subject.getall).to be_a_kind_of(Hash) end - it 'has a key for description' do - expect(subject.getall.count).to eq(2) + it 'has at least two entries' do + expect(subject.getall.count).to be > 2 end it 'returns the routemap collection' do From 244e122e4f3774c29d89222a9af27db54e84adcc Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Wed, 6 Jan 2016 21:02:25 -0700 Subject: [PATCH 027/110] test timeout values --- lib/rbeapi/eapilib.rb | 8 ++++++++ spec/system/rbeapi/client_spec.rb | 19 +++++++++++++++++++ spec/unit/rbeapi/client_spec.rb | 2 -- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/rbeapi/eapilib.rb b/lib/rbeapi/eapilib.rb index c16bce2..9472e67 100644 --- a/lib/rbeapi/eapilib.rb +++ b/lib/rbeapi/eapilib.rb @@ -162,6 +162,14 @@ def timeouts(opts = {}) @read_timeout = opts.fetch(:read_timeout, DEFAULT_HTTP_READ_TIMEOUT) end + ## + # Gets values for open_timeout and read_timeout + # + # @return [Hash] open_timeout and read_timeout + def get_timeouts + { open_timeout: @open_timeout, read_timeout: @read_timeout } + end + ## # Generates the eAPI JSON request message. # diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb index df3269d..b422caf 100644 --- a/spec/system/rbeapi/client_spec.rb +++ b/spec/system/rbeapi/client_spec.rb @@ -354,4 +354,23 @@ def test_conf expect(node.refresh).to eq(nil) end end + + describe 'test timeouts' do + it 'loads default timeout values' do + expect(node.connection.get_timeouts).to eq(open_timeout: 10, + read_timeout: 10) + end + + describe 'loads veos05' do + let(:node) do + subject.config.read(fixture_file('test.conf')) + subject.connect_to('veos05') + end + + it 'loads timeout values from conf file' do + expect(node.connection.get_timeouts).to eq(open_timeout: 12, + read_timeout: 12) + end + end + end end diff --git a/spec/unit/rbeapi/client_spec.rb b/spec/unit/rbeapi/client_spec.rb index 57af804..2e52615 100644 --- a/spec/unit/rbeapi/client_spec.rb +++ b/spec/unit/rbeapi/client_spec.rb @@ -38,8 +38,6 @@ describe Rbeapi::Client do subject { described_class } - let(:node) { double('node') } - def dut_conf fixture_file('dut.conf') end From 9c93a32febb52d4da2d1eb4fe72c0db3130384c2 Mon Sep 17 00:00:00 2001 From: John Corbin Date: Wed, 6 Jan 2016 20:29:47 -0800 Subject: [PATCH 028/110] Test check should be at least 2, not more than 2. --- spec/system/rbeapi/api/routemaps_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/rbeapi/api/routemaps_spec.rb b/spec/system/rbeapi/api/routemaps_spec.rb index a40b456..ee3cff4 100644 --- a/spec/system/rbeapi/api/routemaps_spec.rb +++ b/spec/system/rbeapi/api/routemaps_spec.rb @@ -90,7 +90,7 @@ end it 'has at least two entries' do - expect(subject.getall.count).to be > 2 + expect(subject.getall.count).to be >= 2 end it 'returns the routemap collection' do From eb7721924aabf7cef1987615348b82300da64995 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Thu, 7 Jan 2016 11:19:45 -0700 Subject: [PATCH 029/110] Get initial unit tests running. --- .../rbeapi/api/switchports/default_spec.rb | 245 +++++++++++++++ .../api/switchports/fixture_switchports.text | 284 ++++++++++++++++++ 2 files changed, 529 insertions(+) create mode 100644 spec/unit/rbeapi/api/switchports/default_spec.rb create mode 100644 spec/unit/rbeapi/api/switchports/fixture_switchports.text diff --git a/spec/unit/rbeapi/api/switchports/default_spec.rb b/spec/unit/rbeapi/api/switchports/default_spec.rb new file mode 100644 index 0000000..d34dccf --- /dev/null +++ b/spec/unit/rbeapi/api/switchports/default_spec.rb @@ -0,0 +1,245 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/api/switchports' + +include FixtureHelpers + +describe Rbeapi::Api::Switchports do + subject { described_class.new(node) } + + let(:node) { double('node') } + + def switchports + switchports = Fixtures[:switchports] + return switchports if switchports + fixture('switchports', format: :text, dir: File.dirname(__FILE__)) + end + + before :each do + allow(subject.node).to receive(:running_config).and_return(switchports) + end + + describe '#get' do + let(:keys) do + [:mode, :access_vlan, :trunk_native_vlan, :trunk_allowed_vlans, + :trunk_groups] + end + + context 'vlan as an integer range' do + it 'returns the switchport resource' do + expect(subject.get('Ethernet1')).not_to be_nil + end + + it 'does not return a nonswitchport resource' do + expect(subject.get('Ethernet2')).to be_nil + end + + it 'has all required keys' do + expect(subject.get('Ethernet1').keys).to eq(keys) + end + + it 'returns allowed_vlans as an array' do + expect(subject.get('Ethernet1')[:trunk_allowed_vlans]) + .to be_a_kind_of(Array) + end + end + + context 'vlan as an integer' do + it 'returns the switchport resource' do + expect(subject.get('Ethernet1')).not_to be_nil + end + end + end + + describe '#getall' do + it 'returns the switchport collection' do + expect(subject.getall).to include('Ethernet1') + end + + it 'returns a hash collection' do + expect(subject.getall).to be_a_kind_of(Hash) + end + end + + describe '#create' do + it 'creates a new switchport resource' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'no ip address', 'switchport']) + expect(subject.create('Ethernet1')).to be_truthy + end + end + + describe '#delete' do + it 'deletes a switchport resource' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'no switchport']) + expect(subject.delete('Ethernet1')).to be_truthy + end + end + + describe '#default' do + it 'sets Ethernet1 to default' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'default switchport']) + expect(subject.default('Ethernet1')).to be_truthy + end + end + + describe '#set_mode' do + it 'sets mode value to access' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'switchport mode access']) + expect(subject.set_mode('Ethernet1', value: 'access')).to be_truthy + end + + it 'sets the mode value to trunk' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'switchport mode trunk']) + expect(subject.set_mode('Ethernet1', value: 'trunk')).to be_truthy + end + + it 'negate the mode value' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'no switchport mode']) + expect(subject.set_mode('Ethernet1', enable: false)).to be_truthy + end + + it 'default the mode value' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'default switchport mode']) + expect(subject.set_mode('Ethernet1', default: true)).to be_truthy + end + end + + describe '#set_access_vlan' do + it 'sets the access vlan value to 100' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'switchport access vlan 100']) + expect(subject.set_access_vlan('Ethernet1', value: '100')).to be_truthy + end + + it 'negates the access vlan value' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'no switchport access vlan']) + expect(subject.set_access_vlan('Ethernet1', enable: false)).to be_truthy + end + + it 'defaults the access vlan value' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'default switchport access vlan']) + expect(subject.set_access_vlan('Ethernet1', default: true)).to be_truthy + end + end + + describe '#set_trunk_native_vlan' do + it 'sets the trunk native vlan to 100' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'switchport trunk native vlan 100']) + expect(subject.set_trunk_native_vlan('Ethernet1', value: '100')) + .to be_truthy + end + + it 'negates the trunk native vlan' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'no switchport trunk native vlan']) + expect(subject.set_trunk_native_vlan('Ethernet1', enable: false)) + .to be_truthy + end + + it 'defaults the trunk native vlan' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'default switchport trunk native vlan']) + expect(subject.set_trunk_native_vlan('Ethernet1', default: true)) + .to be_truthy + end + end + + describe '#set_trunk_allowed_vlans' do + it 'raises an ArgumentError if value is not an array' do + expect { subject.set_trunk_allowed_vlans('Ethernet1', value: '1-100') } + .to raise_error(ArgumentError) + end + + it 'sets vlan 8 and 9 to the trunk allowed vlans' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'switchport trunk allowed vlan none', + 'switchport trunk allowed vlan 8,9']) + expect(subject.set_trunk_allowed_vlans('Ethernet1', value: [8, 9])) + .to be_truthy + end + + it 'negate switchport trunk allowed vlan' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'no switchport trunk allowed vlan']) + expect(subject.set_trunk_allowed_vlans('Ethernet1', enable: false)) + .to be_truthy + end + + it 'default switchport trunk allowed vlan' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'default switchport trunk allowed vlan']) + expect(subject.set_trunk_allowed_vlans('Ethernet1', default: true)) + .to be_truthy + end + end + + describe '#set_trunk_groups' do + it 'raises an ArgumentError if value is not an array' do + expect { subject.set_trunk_groups('Ethernet1', value: 'foo') } + .to raise_error(ArgumentError) + end + + it 'sets trunk group to foo bar bang' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'switchport trunk group foo', + 'switchport trunk group bar', 'switchport trunk group bang']) + expect(subject.set_trunk_groups('Ethernet1', value: %w(foo bar bang))) + .to be_truthy + end + + it 'negate switchport trunk group' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'no switchport trunk group']) + expect(subject.set_trunk_groups('Ethernet1', enable: false)) + .to be_truthy + end + + it 'default switchport trunk group' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'default switchport trunk group']) + expect(subject.set_trunk_groups('Ethernet1', default: true)) + .to be_truthy + end + end +end diff --git a/spec/unit/rbeapi/api/switchports/fixture_switchports.text b/spec/unit/rbeapi/api/switchports/fixture_switchports.text new file mode 100644 index 0000000..060b80c --- /dev/null +++ b/spec/unit/rbeapi/api/switchports/fixture_switchports.text @@ -0,0 +1,284 @@ +interface Ethernet1 + no description + no shutdown + default load-interval + logging event link-status use-global + no dcbx mode + no mac-address + no link-debounce + no flowcontrol send + no flowcontrol receive + no mac timestamp + no speed + no l2 mtu + default logging event congestion-drops + default unidirectional + switchport access vlan 1 + switchport trunk native vlan 1 + switchport trunk allowed vlan 1-4094 + switchport mode access + switchport mac address learning + no switchport private-vlan mapping + switchport + default encapsulation dot1q vlan + no l2-protocol encapsulation dot1q vlan 0 + snmp trap link-status + no channel-group + lacp rate normal + lacp port-priority 32768 + lldp transmit + lldp receive + no msrp + no mvrp + no switchport port-security + switchport port-security maximum 1 + default qos trust + qos cos 5 + qos dscp 2 + no shape rate + mc-tx-queue 0 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + mc-tx-queue 1 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + mc-tx-queue 2 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + mc-tx-queue 3 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 0 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 1 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 2 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 3 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 4 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 5 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 6 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 7 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + sflow enable + no spanning-tree portfast + spanning-tree portfast auto + no spanning-tree link-type + no spanning-tree bpduguard + no spanning-tree bpdufilter + no spanning-tree cost + spanning-tree port-priority 128 + no spanning-tree guard + no spanning-tree bpduguard rate-limit + logging event spanning-tree use-global + switchport tap native vlan 1 + no switchport tap identity + switchport tap allowed vlan 1-4094 + switchport tool allowed vlan 1-4094 + no switchport tool identity + no switchport tap truncation + no switchport tool truncation + no switchport tap default group + no switchport tool group + no switchport tool dot1q remove outer +! +interface Ethernet2 + no description + no shutdown + default load-interval + mtu 1500 + logging event link-status use-global + no dcbx mode + no mac-address + no link-debounce + no flowcontrol send + no flowcontrol receive + no mac timestamp + no speed + no l2 mtu + default logging event congestion-drops + default unidirectional + no switchport + default encapsulation dot1q vlan + no l2-protocol encapsulation dot1q vlan 0 + snmp trap link-status + no ip proxy-arp + no ip local-proxy-arp + no ip address + no ip verify unicast + default arp timeout 14400 + default ipv6 nd cache expire 14400 + bfd interval 300 min_rx 300 multiplier 3 + no bfd echo + default ip dhcp smart-relay + no ip helper-address + no ipv6 dhcp relay destination + ip dhcp relay information option circuit-id Ethernet2 + no ip igmp + ip igmp version 3 + ip igmp last-member-query-count 2 + ip igmp last-member-query-interval 10 + ip igmp query-max-response-time 100 + ip igmp query-interval 125 + ip igmp startup-query-count 2 + ip igmp startup-query-interval 310 + ip igmp router-alert optional connected + ip igmp host-proxy + no ip igmp host-proxy report-interval + ip igmp host-proxy version 3 + no ip igmp host-proxy + no ipv6 enable + no ipv6 address + no ipv6 verify unicast + no ipv6 nd ra suppress + ipv6 nd ra interval msec 200000 + ipv6 nd ra lifetime 1800 + no ipv6 nd ra mtu suppress + no ipv6 nd managed-config-flag + no ipv6 nd other-config-flag + ipv6 nd reachable-time 0 + ipv6 nd router-preference medium + ipv6 nd ra dns-servers lifetime 300 + ipv6 nd ra dns-suffixes lifetime 300 + ipv6 nd ra hop-limit 64 + no channel-group + lacp rate normal + lacp port-priority 32768 + lldp transmit + lldp receive + ip mfib fastdrop + no msrp + no mvrp + default ntp serve + no ip pim sparse-mode + no ip pim border-router + ip pim query-interval 30 + ip pim join-prune-interval 60 + ip pim dr-priority 1 + no ip pim neighbor-filter + default ip pim bfd-instance + no ip pim bsr-border + default qos trust + qos cos 5 + qos dscp 2 + no shape rate + mc-tx-queue 0 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + mc-tx-queue 1 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + mc-tx-queue 2 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + mc-tx-queue 3 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 0 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 1 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 2 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 3 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 4 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 5 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 6 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 7 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + sflow enable +! From 71aaa8d1a968ba89148f1bba69bfdc69328cd22c Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Thu, 7 Jan 2016 17:01:47 -0700 Subject: [PATCH 030/110] Ensure all parse methods are private. --- lib/rbeapi/api/dns.rb | 3 +++ lib/rbeapi/api/logging.rb | 1 + lib/rbeapi/api/ntp.rb | 1 + lib/rbeapi/api/system.rb | 2 ++ 4 files changed, 7 insertions(+) diff --git a/lib/rbeapi/api/dns.rb b/lib/rbeapi/api/dns.rb index 787443d..835eee3 100644 --- a/lib/rbeapi/api/dns.rb +++ b/lib/rbeapi/api/dns.rb @@ -64,17 +64,20 @@ def parse_domain_name mdata = /ip domain-name ([\w.]+)/.match(config) { domain_name: mdata.nil? ? '' : mdata[1] } end + private :parse_domain_name def parse_name_servers servers = config.scan(/(?:ip name-server vrf )(?:\w+)\s(.+)/) values = servers.each_with_object([]) { |srv, arry| arry << srv.first } { name_servers: values } end + private :parse_name_servers def parse_domain_list search = config.scan(/(?<=^ip\sdomain-list\s).+$/) { domain_list: search } end + private :parse_domain_list ## # Configure the domain-name value in the running-config diff --git a/lib/rbeapi/api/logging.rb b/lib/rbeapi/api/logging.rb index 05e1f99..9f1908e 100644 --- a/lib/rbeapi/api/logging.rb +++ b/lib/rbeapi/api/logging.rb @@ -80,6 +80,7 @@ def parse_hosts hosts = config.scan(/(?<=^logging\shost\s)[^\s]+/) { hosts: hosts } end + private :parse_hosts ## # set_enable configures the global logging instance on the node as either diff --git a/lib/rbeapi/api/ntp.rb b/lib/rbeapi/api/ntp.rb index e1d756d..11df1ba 100644 --- a/lib/rbeapi/api/ntp.rb +++ b/lib/rbeapi/api/ntp.rb @@ -95,6 +95,7 @@ def parse_servers end { servers: values } end + private :parse_servers ## # set_source_interface configures the ntp source value in the nodes diff --git a/lib/rbeapi/api/system.rb b/lib/rbeapi/api/system.rb index 34b0e06..1b4487e 100644 --- a/lib/rbeapi/api/system.rb +++ b/lib/rbeapi/api/system.rb @@ -62,11 +62,13 @@ def parse_hostname(config) mdata = /(?<=^hostname\s)(.+)$/.match(config) { hostname: mdata.nil? ? '' : mdata[1] } end + private :parse_hostname def parse_iprouting(config) mdata = /no\sip\srouting/.match(config) { iprouting: mdata.nil? ? true : false } end + private :parse_iprouting ## # Configures the system hostname value in the running-config From a295697e4004a14d98b0a33470fc7b3f8c277a05 Mon Sep 17 00:00:00 2001 From: John Corbin Date: Fri, 8 Jan 2016 10:06:54 -0800 Subject: [PATCH 031/110] Catch errors and syslog them when parsing eapi conf file. Created utils method to syslog warning messages. Updated add_connection to return nil instead of returning connection values. Updated tests to deal with add_connection return value change. Added test case for bad conf file and empty conf file. Added test case to verify EAPI_CONF path is used. Fixes issue #82 --- lib/rbeapi/client.rb | 17 ++++++---- lib/rbeapi/utils.rb | 10 ++++++ spec/fixtures/eapi.conf.yaml | 6 ++++ spec/fixtures/empty.conf | 0 spec/fixtures/env_path.conf | 5 +++ spec/system/rbeapi/client_spec.rb | 32 +++---------------- spec/unit/rbeapi/client_spec.rb | 53 +++++++++++++++++++++---------- 7 files changed, 71 insertions(+), 52 deletions(-) create mode 100644 spec/fixtures/eapi.conf.yaml create mode 100644 spec/fixtures/empty.conf create mode 100644 spec/fixtures/env_path.conf diff --git a/lib/rbeapi/client.rb b/lib/rbeapi/client.rb index 640c0dd..4395a87 100644 --- a/lib/rbeapi/client.rb +++ b/lib/rbeapi/client.rb @@ -90,7 +90,7 @@ def config_for(name) end ## - # Retrieves the node config form the loaded configuration file and + # Retrieves the node config from the loaded configuration file and # returns a Rbeapi::Node instance for working with the remote node. # # @param [String] :name The named configuration to use for creating the @@ -110,10 +110,7 @@ def connect_to(name) ## # Builds a connection object to a remote node using the specified # options and return an instance of Rbeapi::Connection. All - # configuration options can be passed via the :opts param or can be - # overridden using environment variables. Environment variables are - # specified by prepending EAPI to the option name. For instance to - # override the host param use EAPI_HOST. + # configuration options can be passed via the :opts param. # # @param [Hash] :opts the options to create a message with # @option :opts [String] :host The IP address or hostname of the remote @@ -205,7 +202,12 @@ def autoload(opts = {}) # # @param [String] :filename The full path to the filename to load def read(filename) - super(filename: filename) + begin + super(filename: filename) + rescue IniFile::Error => exc + Rbeapi::Utils.syslog_warning("#{exc}: in eapi conf file: #{filename}") + return + end # For each section, if the host parameter is omitted then the # connection name is used @@ -252,13 +254,14 @@ def get_connection(name) end ## - # Adds a new connection section to the current configuration + # Adds a new connection section to the current configuration # # @param [String] :name The name of the connection to add to the # configuration. # @param [Hash] :values The properties for the connection def add_connection(name, values) self["connection:#{name}"] = values + nil end end diff --git a/lib/rbeapi/utils.rb b/lib/rbeapi/utils.rb index 348e05b..d5337ab 100644 --- a/lib/rbeapi/utils.rb +++ b/lib/rbeapi/utils.rb @@ -30,6 +30,8 @@ # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # +require 'syslog' + ## # Rbeapi toplevel namespace module Rbeapi @@ -64,5 +66,13 @@ def self.class_from_string(name) mod.const_get(cls) end end + + ## + # Syslogs a warning message. + # + # @param [String] :message The message to log. + def self.syslog_warning(message) + Syslog.open('rbeapi', Syslog::LOG_PID) { |s| s.warning message } + end end end diff --git a/spec/fixtures/eapi.conf.yaml b/spec/fixtures/eapi.conf.yaml new file mode 100644 index 0000000..9102805 --- /dev/null +++ b/spec/fixtures/eapi.conf.yaml @@ -0,0 +1,6 @@ +--- +:username: admin +:password: admin +:use_ssl: true +:port: 199 +:hostname: bogus diff --git a/spec/fixtures/empty.conf b/spec/fixtures/empty.conf new file mode 100644 index 0000000..e69de29 diff --git a/spec/fixtures/env_path.conf b/spec/fixtures/env_path.conf new file mode 100644 index 0000000..d5a5d12 --- /dev/null +++ b/spec/fixtures/env_path.conf @@ -0,0 +1,5 @@ +[connection:env_path] +host: 172.16.131.40 +username: admin +password: admin +transport: https diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb index df3269d..80ec084 100644 --- a/spec/system/rbeapi/client_spec.rb +++ b/spec/system/rbeapi/client_spec.rb @@ -81,16 +81,7 @@ def test_conf let(:test_data) do [ - '[connection:veos01]', - '[connection:veos02]', - '[connection:veos03', - '[connection:veos04]', - '[connection:veos05]', - '[connection: localhost]', - 'username', - 'password', - 'transport', - 'host' + '[connection:veos01]' ] end @@ -142,7 +133,7 @@ def test_conf describe '#read' do it 'read the specified filename and load dut' do - expect(subject.config.read(dut_conf)).to eq(transport: 'socket') + expect(subject.config.read(dut_conf)).to eq(nil) expect(subject.config.to_s) .to include('host', 'username', 'password', '[connection:dut]') end @@ -166,8 +157,7 @@ def test_conf describe '#reload' do it 'reloads the configuration file' do expect(subject.config.get_connection('veos01')).to eq(veos01) - expect(subject.config.reload(filename: [dut_conf])) - .to eq(transport: 'socket') + expect(subject.config.reload(filename: [dut_conf])).to eq(nil) expect(subject.config.get_connection('veos01')).to eq(nil) expect(subject.config.get_connection('dut')).not_to be_nil end @@ -180,10 +170,7 @@ def test_conf password: 'test', transport: 'http', host: 'test2' - )).to eq(username: 'test2', - password: 'test', - transport: 'http', - host: 'test2') + )).to eq(nil) expect(subject.config.get_connection('test2')) .to eq(username: 'test2', password: 'test', @@ -219,12 +206,6 @@ def test_conf end end - describe '#enable_authentication' do - it 'gets the nodes startup-configuration' do - expect(node.enable_authentication('newpassword')).to eq('newpassword') - end - end - describe '#config' do it 'puts switch into config mode' do expect(node.config(['no ip virtual-router mac-address'])) @@ -311,11 +292,6 @@ def test_conf 'hostname') end - it 'sends commands with enablepwd set' do - expect(node.enable_authentication('icanttellyou')).to eq('icanttellyou') - expect(node.run_commands('show hostname')).to be_truthy - end - it 'expects run_commands to raise a command error' do expect { node.run_commands('do this thing') } .to raise_error Rbeapi::Eapilib::CommandError diff --git a/spec/unit/rbeapi/client_spec.rb b/spec/unit/rbeapi/client_spec.rb index 57af804..ab99da1 100644 --- a/spec/unit/rbeapi/client_spec.rb +++ b/spec/unit/rbeapi/client_spec.rb @@ -48,6 +48,14 @@ def test_conf fixture_file('test.conf') end + def empty_conf + fixture_file('empty.conf') + end + + def yaml_conf + fixture_file('eapi.conf.yaml') + end + let(:dut) do File.read(dut_conf) end @@ -80,21 +88,26 @@ def test_conf let(:test_data) do [ - '[connection:veos01]', - '[connection:veos02]', - '[connection:veos03', - '[connection:veos04]', - '[connection:veos05]', - '[connection: localhost]', - 'username', - 'password', - 'transport', - 'host' + '[connection:veos01]' ] end + let(:default_entry) { "[connection:localhost]\ntransport : socket\n" } + # Client class methods describe '#config_for' do + # Verify that the EAPI_CONF env variable path is used by default + # when the Config class is instantiated/reload-ed. + it 'env path to config file' do + # Store env path for the eapi conf file and reload the class + conf = fixture_dir + '/env_path.conf' + ENV.store('EAPI_CONF', conf) + subject.config.reload + + # Verify env_path.conf file was loaded + expect(subject.config.to_s).to include('[connection:env_path]') + end + it 'returns the configuration options for the connection' do expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('veos01')).to eq(veos01) @@ -121,11 +134,21 @@ def test_conf expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config.to_s).to include(test_data[0]) end + + it 'loading empty config file does not fail' do + expect(subject.load_config(empty_conf)).to eq(nil) + expect(subject.config.to_s).to eq(default_entry) + end + + it 'does not load bad config file data' do + expect(subject.load_config(yaml_conf)).to eq(nil) + expect(subject.config.to_s).to eq('') + end end describe '#read' do it 'read the specified filename and load it' do - expect(subject.load_config(dut_conf)).to eq(transport: 'socket') + expect(subject.load_config(dut_conf)).to eq(nil) expect(subject.config.read(test_conf)).to eq(nil) expect(subject.config.to_s).to include(test_data[0]) end @@ -140,8 +163,7 @@ def test_conf describe '#reload' do it 'reloads the configuration file' do expect(subject.config.get_connection('veos01')).to eq(veos01) - expect(subject.config.reload(filename: [dut_conf])) - .to eq(transport: 'socket') + expect(subject.config.reload(filename: [dut_conf])).to eq(nil) expect(subject.config.get_connection('veos01')).to eq(nil) expect(subject.config.get_connection('dut')).not_to be_nil end @@ -154,10 +176,7 @@ def test_conf password: 'test', transport: 'http', host: 'test2' - )).to eq(username: 'test2', - password: 'test', - transport: 'http', - host: 'test2') + )).to eq(nil) expect(subject.config.get_connection('test2')) .to eq(username: 'test2', password: 'test', From 9cf4f68eb621b0c2e830ca7878a5fdbf7d663402 Mon Sep 17 00:00:00 2001 From: John Corbin Date: Fri, 8 Jan 2016 10:19:25 -0800 Subject: [PATCH 032/110] Set enable password for a connection. Fixes issue #72 --- lib/rbeapi/client.rb | 6 +++++- spec/system/rbeapi/client_spec.rb | 20 +++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/lib/rbeapi/client.rb b/lib/rbeapi/client.rb index 640c0dd..2e3fe98 100644 --- a/lib/rbeapi/client.rb +++ b/lib/rbeapi/client.rb @@ -105,6 +105,10 @@ def connect_to(name) config = Rbeapi::Utils.transform_keys_to_symbols(config) connection = connect config Node.new(connection) + node = Node.new(connection) + enablepwd = config.fetch(:enablepwd, nil) + node.enable_authentication(enablepwd) if enablepwd + node end ## @@ -122,7 +126,7 @@ def connect_to(name) # the eAPI connection with # @option :opts [String] :password The password to use to authenticate # the eAPI connection with - # @option :opts [String] :enable_pwd The enable password (if defined) to + # @option :opts [String] :enablepwd The enable password (if defined) to # pass to the remote node to enter privilege mode # @option :opts [String] :use_ssl Specifies whether or not to use the # HTTP or HTTPS protocol diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb index df3269d..db562f6 100644 --- a/spec/system/rbeapi/client_spec.rb +++ b/spec/system/rbeapi/client_spec.rb @@ -57,6 +57,8 @@ def test_conf File.read(test_conf) end + let(:enablepwd) { 'enable_admin' } + let(:veos01) do { 'username' => 'eapi', @@ -311,17 +313,25 @@ def test_conf 'hostname') end - it 'sends commands with enablepwd set' do - expect(node.enable_authentication('icanttellyou')).to eq('icanttellyou') - expect(node.run_commands('show hostname')).to be_truthy - end - it 'expects run_commands to raise a command error' do expect { node.run_commands('do this thing') } .to raise_error Rbeapi::Eapilib::CommandError end end + describe '#run_commands with enable password' do + # Before the tests Set the enable password on the dut + before(:each) { node.config(["enable secret 0 #{enablepwd}"]) } + + # After the tests clear the enable password on the dut + after(:each) { node.config(['no enable secret']) } + + it 'sends commands with enablepwd set' do + expect(node.enable_authentication(enablepwd)).to eq(enablepwd) + expect(node.run_commands('show hostname')).to be_truthy + end + end + describe '#get_config' do it 'will retrieve the specified configuration and return array' do expect(node.get_config(config: 'running-config')) From 2b40fa0dc739eb861274a1dde9f1011f6e9274bd Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Sat, 9 Jan 2016 11:45:07 -0700 Subject: [PATCH 033/110] Update get and getall documentation. --- lib/rbeapi/api/aaa.rb | 50 ++++++++++++----- lib/rbeapi/api/acl.rb | 60 ++++++++++++++++++++- lib/rbeapi/api/bgp.rb | 81 ++++++++++++++++++++++++++++ lib/rbeapi/api/dns.rb | 19 +++++++ lib/rbeapi/api/interfaces.rb | 98 +++++++++++++++++++++++++--------- lib/rbeapi/api/ipinterfaces.rb | 13 ++++- lib/rbeapi/api/logging.rb | 10 +++- lib/rbeapi/api/mlag.rb | 28 ++++++---- lib/rbeapi/api/ntp.rb | 2 +- lib/rbeapi/api/ospf.rb | 31 +++++++---- lib/rbeapi/api/prefixlists.rb | 22 ++++++-- lib/rbeapi/api/radius.rb | 16 +++--- lib/rbeapi/api/routemaps.rb | 10 ++-- lib/rbeapi/api/snmp.rb | 6 +-- lib/rbeapi/api/stp.rb | 51 +++++++++++++----- lib/rbeapi/api/switchports.rb | 70 +++++++++++++++++++++++- lib/rbeapi/api/system.rb | 23 +++++++- lib/rbeapi/api/tacacs.rb | 17 +++--- lib/rbeapi/api/users.rb | 11 +++- lib/rbeapi/api/varp.rb | 46 +++++++++++++--- lib/rbeapi/api/vlans.rb | 18 +++++-- 21 files changed, 566 insertions(+), 116 deletions(-) diff --git a/lib/rbeapi/api/aaa.rb b/lib/rbeapi/api/aaa.rb index 5392136..16dd75b 100644 --- a/lib/rbeapi/api/aaa.rb +++ b/lib/rbeapi/api/aaa.rb @@ -41,6 +41,25 @@ module Api # The Aaa class manages Authorization, Authentication and Accounting (AAA) # on an EOS node. class Aaa < Entity + ## + # get returns a hash of all Aaa resources + # + # @example + # { + # : { + # : { + # type: , + # servers: + # }, + # : { + # type: , + # servers: + # } + # } + # } + # + # @return [Hash] Returns the Aaa resources as a + # Hash. If no Aaa resources are found, an empty hash is returned. def get response = {} response[:groups] = groups.getall @@ -80,18 +99,18 @@ class AaaGroups < Entity # get returns the aaa server group resource hash that describes the # current configuration for the specified server group name. # - # The resource hash returned contains the following: - # * type: (String) The server group type. Valid values are either - # 'tacacs' or 'radius'. - # * servers: (Array) The set of servers associated with the group. - # Servers are returned as either IP address or host name. + # @example + # { + # type: , + # servers: + # } # # @param [String] :name The server group name to return from the nodes # current running configuration. If the name is not configured a nil # object is returned. # # @return [nil, Hash] returns the resource hash for the - # specified name. If the name does not exist, a nil object is returned. + # specified name. If the name does not exist, a nil object is returned def get(name) block = get_block("aaa group server ([^\s]+) #{name}") return nil unless block @@ -104,12 +123,17 @@ def get(name) ## # getall returns a aaa server groups hash # - # The resource hash returned contains the following: - # * name: (String) The server group name. - # * type: (String) The server group type. Valid values are either - # 'tacacs' or 'radius' - # * servers: (Array) The set of servers associated with the group. - # Servers are returned as either IP address or host name + # @example + # { + # : { + # type: , + # servers: + # }, + # : { + # type: , + # servers: + # } + # } # # @return [Hash] returns the resource hashes for # configured aaa groups. If none exist, a nil object is returned @@ -174,7 +198,6 @@ def parse_servers(config, type) # @param [String] :config The aaa server group block configuration for the # group name to parse # - # # @return [Hash] resource hash attribute def parse_radius_server(config) values = config.scan(RADIUS_GROUP_SERVER).map do |(name, auth, acct)| @@ -199,7 +222,6 @@ def parse_radius_server(config) # @param [String] :config The aaa server group block configuration for the # group name to parse # - # # @return [Hash] resource hash attribute def parse_tacacs_server(config) values = config.scan(TACACS_GROUP_SERVER).map do |(name, vrf, port)| diff --git a/lib/rbeapi/api/acl.rb b/lib/rbeapi/api/acl.rb index 8503cd3..dafd5f7 100644 --- a/lib/rbeapi/api/acl.rb +++ b/lib/rbeapi/api/acl.rb @@ -56,10 +56,29 @@ def initialize(node) ## # get returns the specified ACL from the nodes current configuration. # + # @example + # { + # : { + # seqno: , + # action: , + # srcaddr: , + # srcprefixle: , + # log: + # }, + # : { + # seqno: , + # action: , + # srcaddr: , + # srcprefixle: , + # log: + # }, + # ... + # } + # # @param [String] :name The ACL name. # # @return [nil, Hash] Returns the ACL resource as a - # Hash. + # Hash. Returns nil if name does not exist. def get(name) config = get_block("ip access-list standard #{name}") return nil unless config @@ -72,6 +91,45 @@ def get(name) # configuration as a hash. The ACL resource collection hash is # keyed by the ACL name. # + # @example + # { + # : { + # : { + # seqno: , + # action: , + # srcaddr: , + # srcprefixle: , + # log: + # }, + # : { + # seqno: , + # action: , + # srcaddr: , + # srcprefixle: , + # log: + # }, + # ... + # }, + # : { + # : { + # seqno: , + # action: , + # srcaddr: , + # srcprefixle: , + # log: + # }, + # : { + # seqno: , + # action: , + # srcaddr: , + # srcprefixle: , + # log: + # }, + # ... + # }, + # ... + # } + # # @return [nil, Hash] Returns a hash that represents # the entire ACL collection from the nodes running configuration. # If there are no ACLs configured, this method will return an diff --git a/lib/rbeapi/api/bgp.rb b/lib/rbeapi/api/bgp.rb index 079e897..67d3a63 100644 --- a/lib/rbeapi/api/bgp.rb +++ b/lib/rbeapi/api/bgp.rb @@ -51,6 +51,50 @@ def initialize(node) # get returns the BGP routing configuration from the nodes current # configuration. # + # @example + # { + # bgp_as: , + # router_id: , + # shutdown: , + # maximum_paths: , + # maximum_ecmp_paths: + # networks: [ + # { + # prefix: , + # masklen: , + # route_map: + # }, + # { + # prefix: , + # masklen: , + # route_map: + # } + # ], + # neighbors: { + # name: { + # peer_group: , + # remote_as: , + # send_community: , + # shutdown: , + # description: , + # next_hop_selp: , + # route_map_in: , + # route_map_out: + # }, + # name: { + # peer_group: , + # remote_as: , + # send_community: , + # shutdown: , + # description: , + # next_hop_selp: , + # route_map_in: , + # route_map_out: + # }, + # ... + # } + # } + # # @return [nil, Hash] Returns the BGP resource as a # Hash. def get @@ -397,6 +441,18 @@ class BgpNeighbors < Entity # get returns a single BGP neighbor entry from the nodes current # configuration. # + # @example + # { + # peer_group: , + # remote_as: , + # send_community: , + # shutdown: , + # description: + # next_hop_self: + # route_map_in: + # route_map_out: + # } + # # @param [String] :name The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). @@ -422,6 +478,31 @@ def get(name) # getall returns the collection of all neighbor entries for the # BGP router instance. # + # @example + # { + # : { + # peer_group: , + # remote_as: , + # send_community: , + # shutdown: , + # description: + # next_hop_self: + # route_map_in: + # route_map_out: + # }, + # : { + # peer_group: , + # remote_as: , + # send_community: , + # shutdown: , + # description: + # next_hop_self: + # route_map_in: + # route_map_out: + # }, + # ... + # } + # # @return [nil, Hash] Returns a hash that # represents the entire BGP neighbor collection from the nodes # running configuration. If there a BGP router is not configured diff --git a/lib/rbeapi/api/dns.rb b/lib/rbeapi/api/dns.rb index 9263020..2f95494 100644 --- a/lib/rbeapi/api/dns.rb +++ b/lib/rbeapi/api/dns.rb @@ -60,17 +60,36 @@ def get response end + ## + # parse_domain_name parses the domain-name from config + # + # @api private + # + # @return [Hash] resource hash attribute def parse_domain_name mdata = /ip domain-name ([\w.]+)/.match(config) { domain_name: mdata.nil? ? '' : mdata[1] } end + ## + # parse_name_servers parses the name-server values from + # config + # + # @api private + # + # @return [Hash] resource hash attribute def parse_name_servers servers = config.scan(/(?:ip name-server vrf )(?:\w+)\s(.+)/) values = servers.each_with_object([]) { |srv, arry| arry << srv.first } { name_servers: values } end + ## + # parse_domain_list parses the domain-list from config + # + # @api private + # + # @return [Hash] resource hash attribute def parse_domain_list search = config.scan(/(?<=^ip\sdomain-list\s).+$/) { domain_list: search } diff --git a/lib/rbeapi/api/interfaces.rb b/lib/rbeapi/api/interfaces.rb index a4617bc..f2e2de3 100644 --- a/lib/rbeapi/api/interfaces.rb +++ b/lib/rbeapi/api/interfaces.rb @@ -47,10 +47,52 @@ def initialize(node) @instances = {} end + ## + # get returns a hash of interface configurations for the given name + # + # @example + # { + # name: , + # type: , + # description: , + # shutdown: + # } + # + # @param [String] :name The interface name to return a resource for from + # the nodes configuration + # + # @return [nil, Hash] Returns the interface resource as a + # Hash. If the specified name is not found in the nodes current + # configuration a nil object is returned def get(name) get_instance(name).get(name) end + ## + # getall returns a hash of interface configurations + # + # @example + # { + # : { + # name: , + # type: , + # description: , + # shutdown: , + # ... + # }, + # : { + # name: , + # type: , + # description: , + # shutdown: , + # ... + # }, + # ... + # } + # + # @return [Hash] Returns the interface resources as a + # Hash. If none exist in the nodes current + # configuration an empty hash is returned def getall interfaces = config.scan(/(?<=^interface\s).+$/) @@ -60,6 +102,13 @@ def getall end end + ## + # get_instance returns an interface instance for the given name + # + # @param [String] :name The interface name to return an instance for + # + # @return [Object] Returns the interface instance as an + # Object. def get_instance(name) name = name[0, 2].upcase case name @@ -287,20 +336,18 @@ class EthernetInterface < BaseInterface # get returns the specified Ethernet interface resource hash that # represents the interface's current configuration in the node. # - # The resource hash returned contains the following information: - # - # * name (string): the interface name (eg Ethernet1) - # * type (string): will always be 'ethernet' - # * description (string): the interface description value - # * speed (string): the current speed setting for the interface speed - # * forced (boolean): true if auto negotiation is disabled otherwise - # false - # * sflow (boolean): true if sflow is enabled on the interface - # otherwise false - # * flowcontrol_send (string): the interface flowcontrol send value. - # Valid values are 'on' or 'off' - # * flowconrol_receive (string): the interface flowcontrol receive - # value. Valid values are 'on' or 'off' + # @example + # { + # name: , + # type: , + # description: , + # shutdown: , + # speed: , + # forced: , + # sflow: , + # flowcontrol_send: , + # flowcontrol_receive: + # } # # @param [String] :name The interface name to return a resource hash # for from the node's running configuration @@ -319,7 +366,6 @@ def get(name) response.merge!(parse_sflow(config)) response.merge!(parse_flowcontrol_send(config)) response.merge!(parse_flowcontrol_receive(config)) - response end @@ -955,16 +1001,18 @@ class VxlanInterface < BaseInterface # BaseInterface get method and adds the Vxlan specific attributes to # the hash # - # The returned resource hash contains the following - # - # * name: (String) The full interface name identifier - # * type: (String) 'vxlan' - # * description: (String) The configured interface description - # * shutdown: (Boolean) The admin state of the interface - # * source_interface: (String) The vxlan source-interface value - # * multicast_group: (String) The vxlan multicast-group value - # * udp_port: (Fixnum) The vxlan udp-port value - # * flood_list: (Array) The list of VTEPs to flood traffic towards + # @example + # { + # name: , + # type: , + # description: , + # shutdown: , + # source_interface: , + # multicast_group: , + # udp_port: , + # flood_list: , + # vlans: + # } # # @param [String] :name The interface name to return from the nodes # configuration. This optional parameter defaults to Vxlan1 diff --git a/lib/rbeapi/api/ipinterfaces.rb b/lib/rbeapi/api/ipinterfaces.rb index 873c482..ddeb80c 100644 --- a/lib/rbeapi/api/ipinterfaces.rb +++ b/lib/rbeapi/api/ipinterfaces.rb @@ -79,7 +79,17 @@ def get(name) # # @example # { - # : {...} + # : { + # address: + # mtu: + # helper_addresses: array + # }, + # : { + # address: + # mtu: + # helper_addresses: array + # }, + # ... # } # # @see get Ipaddress resource example @@ -103,6 +113,7 @@ def getall # ipaddress resource hash. # # @api private + # # @param [String] :config The IP interface configuration block returned # from the node's running configuration # diff --git a/lib/rbeapi/api/logging.rb b/lib/rbeapi/api/logging.rb index dc9816e..8d2458c 100644 --- a/lib/rbeapi/api/logging.rb +++ b/lib/rbeapi/api/logging.rb @@ -46,7 +46,7 @@ class Logging < Entity # # @example # { - # enable: [true, false] + # enable: [true, false], # hosts: array # } # @@ -65,6 +65,10 @@ def get # command is expected to always be in the node's configuration. This # methods return value is intended to be merged into the logging resource # hash. + # + # @api private + # + # @return [Hash] resource hash attribute def parse_enable value = /no logging on/ !~ config { enable: value } @@ -76,6 +80,10 @@ def parse_enable # logging hosts are configured, then the value for hosts will be an empty # array. The return value is intended to be merged into the logging # resource hash + # + # @api private + # + # @return [Hash] resource hash attribute def parse_hosts hosts = config.scan(/(?<=^logging\shost\s)[^\s]+/) { hosts: hosts } diff --git a/lib/rbeapi/api/mlag.rb b/lib/rbeapi/api/mlag.rb index a397c97..e88a67f 100644 --- a/lib/rbeapi/api/mlag.rb +++ b/lib/rbeapi/api/mlag.rb @@ -50,15 +50,25 @@ class Mlag < Entity # get scans the current nodes configuration and returns the values as # a Hash describing the current state. # - # The resource hash returned contains the following: - # * domain_id: (String) The MLAG domain-id value - # * local_interface: (String) The MLAG local-interface value - # * peer_address: (String) The IP address of the MLAG peer - # * peer_link: (String) The MLAG transit peer-link value - # * shutdown: (Boolean) The administrative staet of the mlag - # configuration - # * interfaces: (Hash) The list of configured MLAG interfaces. (See - # parse_interfaces for the Hash details) + # @example + # { + # global: { + # domain_id: , + # local_interface: , + # peer_address: , + # peer_link: , + # shutdown: + # }, + # interfaces: { + # : { + # mlag_id: + # }, + # : { + # mlag_id: + # }, + # ... + # } + # } # # @see parse_interfaces # diff --git a/lib/rbeapi/api/ntp.rb b/lib/rbeapi/api/ntp.rb index 337a794..e1f2b68 100644 --- a/lib/rbeapi/api/ntp.rb +++ b/lib/rbeapi/api/ntp.rb @@ -48,7 +48,7 @@ class Ntp < Entity # # @example # { - # source_interface: + # source_interface: , # servers: { # prefer: [true, false] # } diff --git a/lib/rbeapi/api/ospf.rb b/lib/rbeapi/api/ospf.rb index eb4c120..8772825 100644 --- a/lib/rbeapi/api/ospf.rb +++ b/lib/rbeapi/api/ospf.rb @@ -48,13 +48,15 @@ class Ospf < Entity # # @example # { - # "router_id": - # "areas": { + # router_id: + # areas: { # : array # }, - # "redistribute" + # redistribute: {} # } # + # @param [String] :inst The ospf instance name + # # @return [Hash] A Ruby hash object that provides the OSPF settings as # key / value pairs. def get(inst) @@ -90,9 +92,16 @@ def get(inst) # # @example # { - # : {...} - # "interfaces": {...} + # : { + # router_id: , + # areas: {}, + # redistribute: {} + # }, + # interfaces: {} # } + # + # @return [Hash] A Ruby hash object that provides the OSPF settings as + # key / value pairs. def getall instances = config.scan(/(?<=^router\sospf\s)\d+$/) response = instances.each_with_object({}) do |inst, hsh| @@ -147,8 +156,7 @@ class OspfInterfaces < Entity # # Example # { - # "name": , - # "network_type": + # network_type: # } # # @param [String] :name The interface name to return the configuration @@ -174,8 +182,13 @@ def get(name) # # Example # { - # : {...}, - # : {...} + # : { + # network_type: + # }, + # : { + # network_type: + # }, + # ... # } # # @return [nil, Hash] A Ruby hash that represents the diff --git a/lib/rbeapi/api/prefixlists.rb b/lib/rbeapi/api/prefixlists.rb index 6bef554..1c42c31 100644 --- a/lib/rbeapi/api/prefixlists.rb +++ b/lib/rbeapi/api/prefixlists.rb @@ -48,16 +48,17 @@ class Prefixlists < Entity # @example # { # : { - # "next_hop": , - # "name": + # next_hop: , + # name: # } # } # + # @param [String] :name The name of the prefix-list to return + # # @returns [Hash The method will return all of the # configured static routes on the node as a Ruby hash object. If # there are no static routes configured, this method will return # an empty hash - def get(name) config = get_block("ip prefix-list #{name}") return nil unless config @@ -69,6 +70,21 @@ def get(name) end end + ## + # Returns the static routes configured on the node + # + # @example + # { + # : { + # next_hop: , + # name: + # } + # } + # + # @returns [Hash The method will return all of the + # configured static routes on the node as a Ruby hash object. If + # there are no static routes configured, this method will return + # an empty hash def getall lists = config.scan(/(?<=^ip\sprefix-list\s).+/) lists.each_with_object({}) do |name, hsh| diff --git a/lib/rbeapi/api/radius.rb b/lib/rbeapi/api/radius.rb index 399ca86..33b449a 100644 --- a/lib/rbeapi/api/radius.rb +++ b/lib/rbeapi/api/radius.rb @@ -61,14 +61,14 @@ class Radius < Entity # This method is intended to be used by a provider's instances class # method. # - # The resource hash returned contains the following information: - # * key: (String) the key either in plain text or hashed format - # * key_format: (Fixnum) e.g. 0 or 7 - # * timeout: (Fixnum) seconds before the timeout period ends - # * retransmit: (Fixnum), e.g. 3, attempts after first timeout expiry. - # * servers: (Array), - # - # @api public + # @example + # { + # key: , + # key_format: , + # timeout: , + # retransmit: , + # servers: + # } # # @return [Array] Single element Array of resource hashes def get diff --git a/lib/rbeapi/api/routemaps.rb b/lib/rbeapi/api/routemaps.rb index fca8556..7be95b3 100644 --- a/lib/rbeapi/api/routemaps.rb +++ b/lib/rbeapi/api/routemaps.rb @@ -81,8 +81,8 @@ class Routemaps < Entity # } # } # - # @param [String] name The routemap name to return a resource for from the - # nodes configuration + # @param [String] :name The routemap name to return a resource for from + # the nodes configuration # # @return [nil, Hash] Returns the routemap resource as a # Hash. If the specified name is not found in the nodes current @@ -174,10 +174,11 @@ def getall ## # parse entries is a private method to get the routemap rules. # + # @api private + # # @return [nil, Hash] returns a hash that represents the # rules for routemaps from the nodes running configuration. If # there are no routemaps configured, this method will return nil. - # def parse_entries(name) entries = config.scan(/^route-map\s#{name}\s.+$/) return nil if entries.empty? @@ -196,11 +197,12 @@ def parse_entries(name) ## # parse rule is a private method to parse a rule. # + # @api private + # # @return [Hash] returns a hash that represents the # rules for routemaps from the nodes running configuration. If # there are no routemaps configured, this method will return an empty # hash. - # def parse_rules(rules) rules.split("\n").each_with_object({}) do |rule, rule_hsh| mdata = /\s{3}(\w+)\s/.match(rule) diff --git a/lib/rbeapi/api/snmp.rb b/lib/rbeapi/api/snmp.rb index 309a814..6f24e44 100644 --- a/lib/rbeapi/api/snmp.rb +++ b/lib/rbeapi/api/snmp.rb @@ -57,9 +57,9 @@ class Snmp < Entity # # @example # { - # location: - # contact: - # chassis_id: + # location: , + # contact: , + # chassis_id: , # source_interface: # } # diff --git a/lib/rbeapi/api/stp.rb b/lib/rbeapi/api/stp.rb index caf9926..bd2a25f 100644 --- a/lib/rbeapi/api/stp.rb +++ b/lib/rbeapi/api/stp.rb @@ -48,13 +48,20 @@ class Stp < Entity # @example # { # mode: - # instances: {...} - # interfaces: {...} + # instances: { + # : { + # priority: + # } + # } + # interfaces: { + # : { + # portfast: , + # portfast_type: , + # bpduguard: + # } + # } # } # - # @see StpInstances instances get example - # @eee StpInterfaces interfaces get example - # # @return [Hash] returns a Hash of attributes derived from eAPI def get response = {} @@ -150,6 +157,8 @@ class StpInstances < Entity # priority: # } # + # @param [String] :inst The named stp instance to return + # # @return [nil, Hash: {...} + # : { + # priority: + # }, + # : { + # priority: + # }, + # ... # } # - # @see get Instance get example - # # @return [Hash] returns all configured stp instances # found in the nodes running configuration def getall @@ -265,10 +278,14 @@ class StpInterfaces < Entity # # @example # { - # portfast: [true, false] - # bpduguard: [true, false] + # portfast: , + # portfast_type: , + # bpduguard: # } # + # @param [String] :name The interface name to return a resource for from + # the nodes configuration + # # @return [nil, Hash] returns the stp interface as a # resource hash def get(name) @@ -289,11 +306,19 @@ def get(name) # # @example # { - # : {...} + # : { + # portfast: , + # portfast_type: , + # bpduguard: + # }, + # : { + # portfast: , + # portfast_type: , + # bpduguard: + # }, + # ... # } # - # @see get Interface example - # # @return [Hash] returns the stp interfaces config as a # resource hash from the nodes running configuration def getall diff --git a/lib/rbeapi/api/switchports.rb b/lib/rbeapi/api/switchports.rb index 16c89af..b10ed7b 100644 --- a/lib/rbeapi/api/switchports.rb +++ b/lib/rbeapi/api/switchports.rb @@ -55,7 +55,7 @@ class Switchports < Entity # "access_vlan": # } # - # @param [String] name The full name of the interface to get. The + # @param [String] :name The full name of the interface to get. The # interface name must be the full interface (ie Ethernet, not Et) # # @return [Hash] a hash that includes the switchport properties @@ -73,24 +73,63 @@ def get(name) response end + ## + # parse_mode parses switchport mode from the provided config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_mode(config) mdata = /(?<=\s{3}switchport\smode\s)(.+)$/.match(config) { mode: mdata[1] } end private :parse_mode + ## + # parse_access_vlan parses access vlan from the provided + # config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_access_vlan(config) mdata = /(?<=access\svlan\s)(.+)$/.match(config) { access_vlan: mdata[1] } end private :parse_access_vlan + ## + # parse_trunk_native_vlan parses trunk native vlan from + # the provided config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_trunk_native_vlan(config) mdata = /(?<=trunk\snative\svlan\s)(.+)$/.match(config) { trunk_native_vlan: mdata[1] } end private :parse_trunk_native_vlan + ## + # parse_trunk_allowed_vlans parses trunk allowed vlan from + # the provided config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_trunk_allowed_vlans(config) mdata = /(?<=trunk\sallowed\svlan\s)(.+)$/.match(config) return { trunk_allowed_vlans: [] } unless mdata[1] != 'none' @@ -107,6 +146,16 @@ def parse_trunk_allowed_vlans(config) end private :parse_trunk_allowed_vlans + ## + # parse_trunk_groups parses trunk group values from the + # provided config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_trunk_groups(config) mdata = config.scan(/(?<=trunk\sgroup\s)(.+)$/) mdata = mdata.flatten if mdata.length > 0 @@ -117,6 +166,25 @@ def parse_trunk_groups(config) ## # Retrieves all switchport interfaces from the running-config # + # @example + # { + # : { + # mode: , + # access_vlan: , + # trunk_native_vlan: , + # trunk_allowed_vlans: , + # trunk_groups: + # }, + # : { + # mode: , + # access_vlan: , + # trunk_native_vlan: , + # trunk_allowed_vlans: , + # trunk_groups: + # }, + # ... + # } + # # @return [Array] an array of switchport hashes def getall interfaces = config.scan(/(?<=^interface\s)([Et|Po].+)$/) diff --git a/lib/rbeapi/api/system.rb b/lib/rbeapi/api/system.rb index 45fceaa..d93724b 100644 --- a/lib/rbeapi/api/system.rb +++ b/lib/rbeapi/api/system.rb @@ -42,11 +42,12 @@ module Api # hostname and domain name class System < Entity ## - # Returns the system settings + # Returns the system settings for hostname and iprouting # # @example # { - # hostname: + # hostname: , + # iprouting: # } # # @return [Hash] A Ruby hash object that provides the system settings as @@ -58,11 +59,29 @@ def get response end + ## + # parse_hostname parses hostname values from the provided config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_hostname(config) mdata = /(?<=^hostname\s)(.+)$/.match(config) { hostname: mdata.nil? ? '' : mdata[1] } end + ## + # parse_iprouting parses ip routing from the provided config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_iprouting(config) mdata = /no\sip\srouting/.match(config) { iprouting: mdata.nil? ? true : false } diff --git a/lib/rbeapi/api/tacacs.rb b/lib/rbeapi/api/tacacs.rb index b3e9cf9..4b34ae5 100644 --- a/lib/rbeapi/api/tacacs.rb +++ b/lib/rbeapi/api/tacacs.rb @@ -63,15 +63,14 @@ class Tacacs < Entity # This method is intended to be used by a provider's instances class # method. # - # The resource hash returned contains the following information: - # * name: ('settings') - # * enable: (true | false) if tacacs functionality is enabled. This is - # always true for EOS. - # * key: (String) the key either in plain text or hashed format - # * key_format: (Integer) e.g. 0 or 7 - # * timeout: (Integer) seconds before the timeout period ends - # - # @api public + # @example + # { + # name: , + # enable: , + # key: , + # key_format: , + # timeout: + # } # # @return [Array] Single element Array of resource hashes def get diff --git a/lib/rbeapi/api/users.rb b/lib/rbeapi/api/users.rb index d4cadd4..593157e 100644 --- a/lib/rbeapi/api/users.rb +++ b/lib/rbeapi/api/users.rb @@ -76,7 +76,7 @@ def initialize(node) # sshkey: # } # - # @param [String] name The user name to return a resource for from the + # @param [String] :name The user name to return a resource for from the # nodes configuration # # @return [nil, Hash] Returns the user resource as a @@ -114,6 +114,15 @@ def get(name) # secret: , # sshkey: # }, + # : { + # name: , + # privilege: , + # role: , + # nopassword: , + # encryption: <'cleartext', 'md5', 'sha512'> + # secret: , + # sshkey: + # }, # ... # ] # diff --git a/lib/rbeapi/api/varp.rb b/lib/rbeapi/api/varp.rb index 09f9ec6..45a4dcd 100644 --- a/lib/rbeapi/api/varp.rb +++ b/lib/rbeapi/api/varp.rb @@ -44,10 +44,18 @@ class Varp < Entity ## # Returns the global VARP configuration from the node # - # Example + # @example # { - # "mac_address": , - # "interfaces": {...} + # mac_address: , + # interfaces: { + # : { + # addresses: + # }, + # : { + # addresses: + # }, + # ... + # } # } # # @return [Hash] A Ruby hash object that provides the Varp settings as @@ -59,6 +67,15 @@ def get response end + ## + # parse_mac_address parses mac-address values from the provided config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_mac_address(config) # ip virtual-router mac-address value will always # be stored in aa:bb:cc:dd:ee:ff format @@ -97,7 +114,7 @@ class VarpInterfaces < Entity ## # Returns a single VARP interface configuration # - # Example + # @example # { # "addresses": array # } @@ -119,10 +136,15 @@ def get(name) # Returns the collection of MLAG interfaces as a hash index by the # interface name # - # Example + # @example # { - # "name": {...}, - # "name": {...} + # : { + # addresses: + # }, + # : { + # addresses: + # }, + # ... # } # # @return [nil, Hash] A Ruby hash that represents the @@ -138,6 +160,16 @@ def getall end end + ## + # parse_addresses parses ip virtual-router address from the provided + # config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_addresses(config) addrs = config.scan(/(?<=\s{3}ip\svirtual-router\saddress\s).+$/) { addresses: addrs } diff --git a/lib/rbeapi/api/vlans.rb b/lib/rbeapi/api/vlans.rb index 4934c05..5567030 100644 --- a/lib/rbeapi/api/vlans.rb +++ b/lib/rbeapi/api/vlans.rb @@ -50,12 +50,12 @@ class Vlans < Entity # # @example # { - # name: - # state: + # name: , + # state: , # trunk_groups: array[] Returns the vlan resource as a @@ -78,7 +78,17 @@ def get(id) # # @example # { - # : {...} + # : { + # name: , + # state: , + # trunk_groups: array[: { + # name: , + # state: , + # trunk_groups: array[ Date: Sat, 9 Jan 2016 11:46:07 -0700 Subject: [PATCH 034/110] Making changes for auto doc generation. --- Rakefile | 19 ++ guide/Makefile | 177 ++++++++++++++ guide/_static/arista_logo_11-trans-w.png | Bin 0 -> 26494 bytes guide/_static/arista_logo_jpg-11.jpg | Bin 0 -> 45261 bytes guide/_static/favicon.ico | Bin 0 -> 4286 bytes guide/conf.py | 279 +++++++++++++++++++++++ guide/cookbook.rst | 4 + guide/developing.rst | 4 + guide/faq.rst | 4 + guide/index.rst | 23 ++ guide/installation.rst | 4 + guide/license.rst | 5 + guide/overview.rst | 20 ++ guide/quickstart.rst | 4 + guide/release-notes.rst | 6 + guide/testing.rst | 4 + guide/troubleshooting.rst | 1 + 17 files changed, 554 insertions(+) create mode 100644 guide/Makefile create mode 100644 guide/_static/arista_logo_11-trans-w.png create mode 100644 guide/_static/arista_logo_jpg-11.jpg create mode 100644 guide/_static/favicon.ico create mode 100644 guide/conf.py create mode 100644 guide/cookbook.rst create mode 100644 guide/developing.rst create mode 100644 guide/faq.rst create mode 100644 guide/index.rst create mode 100644 guide/installation.rst create mode 100644 guide/license.rst create mode 100644 guide/overview.rst create mode 100644 guide/quickstart.rst create mode 100644 guide/release-notes.rst create mode 100644 guide/testing.rst create mode 100644 guide/troubleshooting.rst diff --git a/Rakefile b/Rakefile index 27626c2..f41752a 100644 --- a/Rakefile +++ b/Rakefile @@ -155,3 +155,22 @@ task ci_spec: [:ci_prep, 'ci:setup:rspec', :spec] require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) + +desc 'Generate typedoc.rst for the guide' +task :typedoc do + system 'rbeapi doc -r type \ + | awk \'/This page/{flag=1}/augeas/{flag=0}/eos_/{flag=1}/ exec/\ + {flag=0}/\*This page/{flag=1}flag\' \ + | pandoc --from=markdown --to=rst --output=- \ + > guide/typedoc.rst' +end + +desc 'Generate Getting Started Guide HTML' +task guide: [:typedoc] do + system 'make -C guide html' +end + +desc 'Clean Getting Started docs' +task :guide_clean do + system 'make -C guide clean' +end diff --git a/guide/Makefile b/guide/Makefile new file mode 100644 index 0000000..1985178 --- /dev/null +++ b/guide/Makefile @@ -0,0 +1,177 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Rbeapi.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Rbeapi.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Rbeapi" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Rbeapi" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/guide/_static/arista_logo_11-trans-w.png b/guide/_static/arista_logo_11-trans-w.png new file mode 100644 index 0000000000000000000000000000000000000000..dec3830240e8774e8036da4e39f15fc024d348f3 GIT binary patch literal 26494 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 literal 0 HcmV?d00001 diff --git a/guide/_static/favicon.ico b/guide/_static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..cf55b0c85d981ebce5ef33b723be1ede8f26cbc1 GIT binary patch literal 4286 zcmeH|yK7WI6o+SnCWS<;)Fi^D5FfQ7iHK{FbShZ*2Z&K(VX64Q-8NtmA7CTcCLqKn zWe~L4LJ=QmXOYCxM?#2RaNY4c!GXhJW*>J$s=eXM+;ir4e&^oFor!Y=eujsg{C2au zo!jG_I}D`UX^?#P>aIX+1tyQVIryP?&3#`?+er@3e)z2VNYAHm2!4ZClsoAatHt}i z@|RveVMw%$cg$QyEL&((F1(II&GeWI=Hz?fgPDIx+!Hi;M?AK}JLCPzdJ~VrU!%L6 zw{NJ!@0RgQt}VJpMl0XQK=5jJr1l{EGM;x+KInGBlF`o-UueRZ^+aEQ7oflEkHo!J zt7GQRnHpW6x|hG(3FC9g_{jG+sx`5DG_oI_nc7reotN)-!SB!`Be*)JUFu~keu+MrX)hCt5qX*;+&|Ytdw>7Ad zGgjVJ*US*-x~Mw>vR}2|^^_U92S)picyCJIN}l?%@mwc9U~9>ZfIVX`T3x#_o_+8M z^cu*%E(9;`<@|ncGz(f2w0TB+PJ%s~CxRDqw?RK&bd7>O&xrqH(?j;>AjlbO|9{`e z)1y%hJ$AuY(C_)2*q*U($tCwlqaMxX@I7z(>t~VsKX9~}Pu_XFaywe}=|o4LtEPXQc)SzOc53M*XY&-SfviRHOl-%utL?79R v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +html_logo = '_static/arista_logo_11-trans-w.png' + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +html_favicon = '_static/favicon.ico' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'rbeapidoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ('index', 'rbeapi.tex', u'Rbeapi Documentation', + u'Arista Networks - EOS+ Consulting Services', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +latex_logo = '_static/arista_logo_jpg-11.jpg' + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'rbeapi', u'Rbeapi Documentation', + [u'Arista Networks - EOS+ Consulting Services'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'Rbeapi', u'Rbeapi Documentation', + u'Arista Networks - EOS+ Consulting Services', 'Rbeapi', 'Ruby API for EOS.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/guide/cookbook.rst b/guide/cookbook.rst new file mode 100644 index 0000000..c5535bd --- /dev/null +++ b/guide/cookbook.rst @@ -0,0 +1,4 @@ +Cookbook +============ + +.. contents:: :local: \ No newline at end of file diff --git a/guide/developing.rst b/guide/developing.rst new file mode 100644 index 0000000..5e7e5e4 --- /dev/null +++ b/guide/developing.rst @@ -0,0 +1,4 @@ +Developing +========== + +.. contents:: :local: \ No newline at end of file diff --git a/guide/faq.rst b/guide/faq.rst new file mode 100644 index 0000000..eb5392d --- /dev/null +++ b/guide/faq.rst @@ -0,0 +1,4 @@ +FAQ +=== + +.. contents:: :local: \ No newline at end of file diff --git a/guide/index.rst b/guide/index.rst new file mode 100644 index 0000000..fb21811 --- /dev/null +++ b/guide/index.rst @@ -0,0 +1,23 @@ +.. Rbeapi documentation master file, created by + sphinx-quickstart on Fri Jan 8 11:04:02 2016. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to Rbeapi's documentation! +================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + overview + quickstart + installation + cookbook + troubleshooting + developing + testing + faq + release-notes + license \ No newline at end of file diff --git a/guide/installation.rst b/guide/installation.rst new file mode 100644 index 0000000..3c4aa04 --- /dev/null +++ b/guide/installation.rst @@ -0,0 +1,4 @@ +Installation +============ + +.. contents:: :local: \ No newline at end of file diff --git a/guide/license.rst b/guide/license.rst new file mode 100644 index 0000000..df32f7b --- /dev/null +++ b/guide/license.rst @@ -0,0 +1,5 @@ +License +======= + +.. include:: ../LICENSE + :literal: \ No newline at end of file diff --git a/guide/overview.rst b/guide/overview.rst new file mode 100644 index 0000000..d97ec29 --- /dev/null +++ b/guide/overview.rst @@ -0,0 +1,20 @@ +Overview +======== + +.. contents:: :local: + +Introduction +------------ + +The Ruby Client for eAPI provides a native Ruby implementation for programming Arista EOS network devices using Ruby. The Ruby client provides the ability to build native applications in Ruby that can communicate with EOS either locally via Unix domain sockets (on-box) or remotely over a HTTP/S transport (off-box). It uses a standard INI-style configuration file to specifiy one or more connection profiles. + +The rbeapi implemenation also provides an API layer for building native Ruby objects that allow for configuration and state extraction of EOS nodes. The API layer provides a consistent implementation for working with EOS configuration resources. The implementation of the API layer is highly extensible and can be used as a foundation for building custom data models. + +The libray is freely provided to the open source community for building robust applications using Arista EOS eAPI. Support is provided as best effort through Github iusses. + +Prerequisites +------------- + +* Arista EOS 4.12 or later +* Arista eAPI enabled for at least one transport (see official EOS Config Guide at arista.com for details) +* Ruby 1.9.3 or later \ No newline at end of file diff --git a/guide/quickstart.rst b/guide/quickstart.rst new file mode 100644 index 0000000..41feb59 --- /dev/null +++ b/guide/quickstart.rst @@ -0,0 +1,4 @@ +Quick Start +=========== + +.. contents:: :local: \ No newline at end of file diff --git a/guide/release-notes.rst b/guide/release-notes.rst new file mode 100644 index 0000000..31b3783 --- /dev/null +++ b/guide/release-notes.rst @@ -0,0 +1,6 @@ +Release Notes +============= + +.. toctree:: + :maxdepth: 2 + :titlesonly: \ No newline at end of file diff --git a/guide/testing.rst b/guide/testing.rst new file mode 100644 index 0000000..79ab0db --- /dev/null +++ b/guide/testing.rst @@ -0,0 +1,4 @@ +Testing Modules +=============== + +.. contents:: :local: \ No newline at end of file diff --git a/guide/troubleshooting.rst b/guide/troubleshooting.rst new file mode 100644 index 0000000..3fa493d --- /dev/null +++ b/guide/troubleshooting.rst @@ -0,0 +1 @@ +.. _troubleshooting: \ No newline at end of file From 99e9106857d2dd9c9c17d47e9c1a42e48e042e59 Mon Sep 17 00:00:00 2001 From: John Corbin Date: Mon, 11 Jan 2016 07:37:10 -0800 Subject: [PATCH 035/110] Add terminal to configure command to work around AAA issue found in pyeapi. --- lib/rbeapi/client.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rbeapi/client.rb b/lib/rbeapi/client.rb index 640c0dd..6e0f069 100644 --- a/lib/rbeapi/client.rb +++ b/lib/rbeapi/client.rb @@ -332,7 +332,7 @@ def enable_authentication(password) def config(commands, opts = {}) commands = [*commands] unless commands.respond_to?('each') - commands.insert(0, 'configure') + commands.insert(0, 'configure terminal') if @dry_run puts '[rbeapi dry-run commands]' From 5f14b37db94ca64f3676b5aa87a0787e2cdb55f6 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 11 Jan 2016 11:33:46 -0700 Subject: [PATCH 036/110] Adding missing documentation. --- lib/rbeapi/api/dns.rb | 26 +++++++++++- lib/rbeapi/api/ospf.rb | 79 +++++++++++++++++++++++++++++++++++ lib/rbeapi/api/prefixlists.rb | 27 ++++++++++++ lib/rbeapi/api/snmp.rb | 9 ++++ 4 files changed, 140 insertions(+), 1 deletion(-) diff --git a/lib/rbeapi/api/dns.rb b/lib/rbeapi/api/dns.rb index 2f95494..09089ae 100644 --- a/lib/rbeapi/api/dns.rb +++ b/lib/rbeapi/api/dns.rb @@ -41,7 +41,7 @@ module Api # The Dns class manages DNS settings on an EOS node. class Dns < Entity ## - # Returns the DNS resource + # get returns the DNS resource # # @example # { @@ -154,10 +154,22 @@ def set_name_servers(opts = {}) configure cmds end + ## + # add_name_server adds an ip name-server. + # + # @param [String] :server The name of the ip name-server to create + # + # @return [Boolean] returns true if the command completed successfully def add_name_server(server) configure "ip name-server #{server}" end + ## + # remove_name_server removes the specified ip name-server. + # + # @param [String] :server The name of the ip name-server to remove + # + # @return [Boolean] returns true if the command completed successfully def remove_name_server(server) configure "no ip name-server #{server}" end @@ -209,10 +221,22 @@ def set_domain_list(opts = {}) configure cmds end + ## + # add_domain_list adds an ip domain-list. + # + # @param [String] :name The name of the ip domain-list to add + # + # @return [Boolean] returns true if the command completed successfully def add_domain_list(name) configure "ip domain-list #{name}" end + ## + # remove_domain_list removes a specified ip domain-list. + # + # @param [String] :name The name of the ip domain-list to remove + # + # @return [Boolean] returns true if the command completed successfully def remove_domain_list(name) configure "no ip domain-list #{name}" end diff --git a/lib/rbeapi/api/ospf.rb b/lib/rbeapi/api/ospf.rb index 8772825..8f4fea4 100644 --- a/lib/rbeapi/api/ospf.rb +++ b/lib/rbeapi/api/ospf.rb @@ -117,28 +117,91 @@ def interfaces @interfaces end + ## + # create will create a router ospf with the specified pid + # + # @param [String] :pid The router ospf to create + # + # @return [Boolean] returns true if the command completed successfully def create(pid) configure "router ospf #{pid}" end + ## + # delete will remove the specified router ospf + # + # @param [String] :pid The router ospf to remove + # + # @return [Boolean] returns true if the command completed successfully def delete(pid) configure "no router ospf #{pid}" end + ## + # set_router_id sets router ospf router-id with pid and options + # + # @param [String] :pid The router ospf name + # + # @param [hash] :opts Optional keyword arguments + # + # @option :opts [Boolean] :enable If false then the command is + # negated. Default is true. + # + # @option :opts [Boolean] :default Configure the router-id to default. + # + # @return [Boolean] returns true if the command completed successfully def set_router_id(pid, opts = {}) cmd = command_builder('router-id', opts) cmds = ["router ospf #{pid}", cmd] configure cmds end + ## + # add_network adds network settings for router ospf and network area. + # + # @param [String] :pid The pid for router ospf + # + # @param [String] :net The network name + # + # @param [String] :area The network area name + # + # @return [Boolean] returns true if the command completed successfully def add_network(pid, net, area) configure ["router ospf #{pid}", "network #{net} area #{area}"] end + ## + # remove_network removes network settings for router ospf and network + # area. + # + # @param [String] :pid The pid for router ospf + # + # @param [String] :net The network name + # + # @param [String] :area The network area name + # + # @return [Boolean] returns true if the command completed successfully def remove_network(pid, net, area) configure ["router ospf #{pid}", "no network #{net} area #{area}"] end + ## + # set_redistribute sets router ospf router-id with pid and options + # + # @param [String] :pid The router ospf name + # + # @param [String] :proto The redistribute value + # + # @param [hash] :opts Optional keyword arguments + # + # @option :opts [String] :routemap The route-map value + # + # @option :opts [Boolean] :enable If false then the command is + # negated. Default is true. + # + # @option :opts [Boolean] :default Configure the router-id to default. + # + # @return [Boolean] returns true if the command completed successfully def set_redistribute(pid, proto, opts = {}) routemap = opts[:routemap] cmds = ["router ospf #{pid}", "redistribute #{proto}"] @@ -202,6 +265,22 @@ def getall end end + ## + # set_network_type sets network type with options + # + # @param [String] :name The name of the interface + # + # @param [hash] :opts Optional keyword arguments + # + # @option :opts [String] :value The point-to-point value + # + # @option :opts [Boolean] :enable If false then the command is + # negated. Default is true. + # + # @option :opts [Boolean] :default Configure the ip ospf network + # to default. + # + # @return [Boolean] returns true if the command completed successfully def set_network_type(name, opts = {}) value = opts[:value] return false unless [nil, 'point-to-point'].include?(value) diff --git a/lib/rbeapi/api/prefixlists.rb b/lib/rbeapi/api/prefixlists.rb index 1c42c31..9e076fa 100644 --- a/lib/rbeapi/api/prefixlists.rb +++ b/lib/rbeapi/api/prefixlists.rb @@ -93,10 +93,29 @@ def getall end end + ## + # create will create a new ip prefix-list with designated name. + # + # @param [String] :name The name of the ip prefix-list + # + # @return [Boolean] returns true if the command completed successfully def create(name) configure "ip prefix-list #{name}" end + ## + # add_rule will create an ip prefix-list with the designated name, + # seqno, action and prefix. + # + # @param [String] :name The name of the ip prefix-list + # + # @param [String] :seq The seq value + # + # @param [String] :action The action value + # + # @param [String] :prefix The prefix value + # + # @return [Boolean] returns true if the command completed successfully def add_rule(name, action, prefix, seq = nil) cmd = "ip prefix-list #{name}" cmd << " seq #{seq}" if seq @@ -104,6 +123,14 @@ def add_rule(name, action, prefix, seq = nil) configure cmd end + ## + # delete will remove the designated prefix-list + # + # @param [String] :name The name of the ip prefix-list + # + # @param [String] :seq The seq value + # + # @return [Boolean] returns true if the command completed successfully def delete(name, seq = nil) cmd = "no ip prefix-list #{name}" cmd << " seq #{seq}" if seq diff --git a/lib/rbeapi/api/snmp.rb b/lib/rbeapi/api/snmp.rb index 6f24e44..3006260 100644 --- a/lib/rbeapi/api/snmp.rb +++ b/lib/rbeapi/api/snmp.rb @@ -403,6 +403,15 @@ def set_community_acl(name, opts = {}) configure cmds end + ## + # set_community_access configures snmp-server community with designated + # name and access values. + # + # @param [String] :name The snmp-server community name value + # + # @param [String] :access The snmp-server community access value + # + # @return [Boolean] returns true if the command completed successfully def set_community_access(name, access) configure "snmp-server community #{name} #{access}" end From ae4cd44f708418e8db7139edf65954391a841b81 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 11 Jan 2016 11:41:17 -0700 Subject: [PATCH 037/110] rubocop issues. --- lib/rbeapi/api/prefixlists.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rbeapi/api/prefixlists.rb b/lib/rbeapi/api/prefixlists.rb index 9e076fa..0a2435d 100644 --- a/lib/rbeapi/api/prefixlists.rb +++ b/lib/rbeapi/api/prefixlists.rb @@ -97,7 +97,7 @@ def getall # create will create a new ip prefix-list with designated name. # # @param [String] :name The name of the ip prefix-list - # + # # @return [Boolean] returns true if the command completed successfully def create(name) configure "ip prefix-list #{name}" @@ -114,7 +114,7 @@ def create(name) # @param [String] :action The action value # # @param [String] :prefix The prefix value - # + # # @return [Boolean] returns true if the command completed successfully def add_rule(name, action, prefix, seq = nil) cmd = "ip prefix-list #{name}" From 8e6b1b53e25fba7213bf10876b6f79cfc9c3582d Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 11 Jan 2016 11:44:55 -0700 Subject: [PATCH 038/110] Change this back. --- lib/rbeapi/api/vrrp.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rbeapi/api/vrrp.rb b/lib/rbeapi/api/vrrp.rb index a8b1b1d..69cf370 100644 --- a/lib/rbeapi/api/vrrp.rb +++ b/lib/rbeapi/api/vrrp.rb @@ -32,7 +32,7 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Eos is the toplevel namespace for working with Arista EOS nodes module Rbeapi ## # Api is module namespace for working with the EOS command API From 47983e8a327d88cec21221a2d2ef2665af40228d Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 11 Jan 2016 13:40:09 -0700 Subject: [PATCH 039/110] Update copyright year and getall count to spec. --- spec/unit/rbeapi/api/switchports/default_spec.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/spec/unit/rbeapi/api/switchports/default_spec.rb b/spec/unit/rbeapi/api/switchports/default_spec.rb index d34dccf..6217276 100644 --- a/spec/unit/rbeapi/api/switchports/default_spec.rb +++ b/spec/unit/rbeapi/api/switchports/default_spec.rb @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, Arista Networks, Inc. +# Copyright (c) 2016, Arista Networks, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -90,6 +90,10 @@ def switchports it 'returns a hash collection' do expect(subject.getall).to be_a_kind_of(Hash) end + + it 'returns a hash collection' do + expect(subject.getall.count).to eq(1) + end end describe '#create' do From 61f99bce1e1936c819699b7d4c107fe6c444bc2f Mon Sep 17 00:00:00 2001 From: John Corbin Date: Mon, 11 Jan 2016 13:15:26 -0800 Subject: [PATCH 040/110] Copy configuration entry before modifying with connection specific info. Fixes issue #86 --- lib/rbeapi/client.rb | 5 ++-- spec/fixtures/wildcard.conf | 43 +++++++++++++++++++++++++++++++++ spec/unit/rbeapi/client_spec.rb | 26 ++++++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 spec/fixtures/wildcard.conf diff --git a/lib/rbeapi/client.rb b/lib/rbeapi/client.rb index dac0e44..ed2bd16 100644 --- a/lib/rbeapi/client.rb +++ b/lib/rbeapi/client.rb @@ -99,8 +99,9 @@ def config_for(name) # @return [Rbeapi::Node, nil] Returns an instance of Rbeapi::Node. If # the named configuration is not found then nil is returned def connect_to(name) - config = config_for(name) - return nil unless config + config_entry = config_for(name) + return nil unless config_entry + config = config_entry.dup config['host'] = name if config['host'] == '*' config = Rbeapi::Utils.transform_keys_to_symbols(config) connection = connect config diff --git a/spec/fixtures/wildcard.conf b/spec/fixtures/wildcard.conf new file mode 100644 index 0000000..69a3e65 --- /dev/null +++ b/spec/fixtures/wildcard.conf @@ -0,0 +1,43 @@ +[connection:veos01] +username: eapi +password: password +transport: http +host: veos01 + +[connection:veos02] +transport: http +host: veos02 + +[connection:veos03] +transport: socket +host: veos03 + +[connection:veos04] +host: 172.16.10.1 +username: eapi +password: password +enablepwd: itsasecret +port: 1234 +transport: https + +[connection:veos05] +host: 172.16.131.40 +username: admin +password: admin +enablepwd: password +transport: https +port: 1234 +open_timeout: 12 +read_timeout: 12 + +[connection: localhost] +transport: http_local +host: localhost + +[connection:localhost] +transport: socket +host: localhost + +[connection:*] +username: foo +password: bar diff --git a/spec/unit/rbeapi/client_spec.rb b/spec/unit/rbeapi/client_spec.rb index 51de6a6..4af7038 100644 --- a/spec/unit/rbeapi/client_spec.rb +++ b/spec/unit/rbeapi/client_spec.rb @@ -54,6 +54,10 @@ def yaml_conf fixture_file('eapi.conf.yaml') end + def wildcard_conf + fixture_file('wildcard.conf') + end + let(:dut) do File.read(dut_conf) end @@ -84,6 +88,14 @@ def yaml_conf } end + let(:wildcard) do + { + 'username' => 'foo', + 'password' => 'bar', + 'host' => '*' + } + end + let(:test_data) do [ '[connection:veos01]' @@ -116,6 +128,14 @@ def yaml_conf it 'retrieves the node config' do expect(subject.connect_to('veos01')).to be_truthy end + + it 'check connection wildcard host name' do + expect(subject.load_config(wildcard_conf)).to eq(nil) + expect(subject.connect_to('host1')).to be_truthy + expect(subject.config.get_connection('host1')) .to eq(wildcard) + expect(subject.connect_to('host2')).to be_truthy + expect(subject.config.get_connection('host2')) .to eq(wildcard) + end end describe '#load_config' do @@ -156,6 +176,12 @@ def yaml_conf it 'get connection dut' do expect(subject.config.get_connection('veos01')).to eq(veos01) end + + it 'connection wildcard works' do + expect(subject.load_config(wildcard_conf)).to eq(nil) + expect(subject.config.get_connection('host1')) .to eq(wildcard) + expect(subject.config.get_connection('host2')) .to eq(wildcard) + end end describe '#reload' do From 1dab3ef15528093f56a19abd02ac152897a29507 Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Tue, 12 Jan 2016 06:19:14 -0500 Subject: [PATCH 041/110] Bump version strings --- Gemfile | 2 +- README.md | 22 +++++++++++----------- lib/rbeapi/version.rb | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Gemfile b/Gemfile index 4d206b8..548e7a7 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,7 @@ group :development, :test do gem 'pry', require: false gem 'pry-doc', require: false gem 'pry-stack_explorer', require: false - gem 'rbeapi', '0.4.0', path: '.' + gem 'rbeapi', '0.5.0', path: '.' gem 'ci_reporter_rspec', require: false gem 'simplecov-json', require: false gem 'simplecov-rcov', require: false diff --git a/README.md b/README.md index e0790cb..311a565 100644 --- a/README.md +++ b/README.md @@ -230,21 +230,21 @@ Copy the RPMs to an EOS device then run the 'swix create' command. Examples: Puppet Open Source: cd /mnt/flash; \ - swix create rbeapi-0.4.0-1.swix \ - rubygem-rbeapi-0.4.0-1.eos4.noarch.rpm \ + swix create rbeapi-0.5.0-1.swix \ + rubygem-rbeapi-0.5.0-1.eos4.noarch.rpm \ rubygem-inifile-3.0.0-3.eos4.noarch.rpm \ rubygem-netaddr-1.5.0-2.eos4.noarch.rpm \ rubygem-net_http_unix-0.2.1-3.eos4.noarch.rpm Puppet-enterprise agent (3.x): cd/mnt/flash; \ - swix create rbeapi-puppet3-0.4.0-1.swix \ - rubygem-rbeapi-puppet3-0.4.0-1.eos4.noarch.rpm \ + swix create rbeapi-puppet3-0.5.0-1.swix \ + rubygem-rbeapi-puppet3-0.5.0-1.eos4.noarch.rpm \ rubygem-inifile-puppet3-3.0.0-3.eos4.noarch.rpm \ rubygem-netaddr-puppet3-1.5.0-2.eos4.noarch.rpm Puppet-All-in-one agent (2015.x/4.x): cd/mnt/flash; \ - swix create rbeapi-puppet-aio-0.4.0-1.swix \ - rubygem-rbeapi-puppet-aio-0.4.0-1.eos4.noarch.rpm \ + swix create rbeapi-puppet-aio-0.5.0-1.swix \ + rubygem-rbeapi-puppet-aio-0.5.0-1.eos4.noarch.rpm \ rubygem-inifile-puppet-aio-3.0.0-3.eos4.noarch.rpm \ rubygem-netaddr-puppet-aio-1.5.0-2.eos4.noarch.rpm \ rubygem-net_http_unix-puppet-aio-0.2.1-3.eos4.noarch.rpm @@ -255,13 +255,13 @@ Copy the RPMs to an EOS device then run the 'swix create' command. Arista# copy flash: Arista# bash -bash-4.1# cd /mnt/flash/ - -bash-4.1# swix create rbeapi-puppet3-0.4.0-1.swix \ - rubygem-rbeapi-puppet3-0.4.0-1.eos4.noarch.rpm \ + -bash-4.1# swix create rbeapi-puppet3-0.5.0-1.swix \ + rubygem-rbeapi-puppet3-0.5.0-1.eos4.noarch.rpm \ rubygem-inifile-puppet3-3.0.0-1.eos4.noarch.rpm \ rubygem-netaddr-puppet3-1.5.0-1.eos4.noarch.rpm -bash-4.1# exit - Arista# copy flash:rbeapi-puppet3-0.4.0-1.swix extension: - Arista# extension rbeapi-puppet3-0.4.0-1.swix + Arista# copy flash:rbeapi-puppet3-0.5.0-1.swix extension: + Arista# extension rbeapi-puppet3-0.5.0-1.swix Arista# copy installed-extensions boot-extensions ``` @@ -270,7 +270,7 @@ Copy the RPMs to an EOS device then run the 'swix create' command. On EOS: ``` Arista# no extension pe-rbeapi-0.3.0-1.swix - Arista# extension rbeapi-puppet3-0.4.0-1.swix + Arista# extension rbeapi-puppet3-0.5.0-1.swix Arista# copy installed-extensions boot-extensions ``` diff --git a/lib/rbeapi/version.rb b/lib/rbeapi/version.rb index d179c37..53c83dc 100644 --- a/lib/rbeapi/version.rb +++ b/lib/rbeapi/version.rb @@ -33,5 +33,5 @@ # # # Rbeapi toplevel namespace module Rbeapi - VERSION = '0.4.0' + VERSION = '0.5.0' end From 190971060875c200fc5b151d3cd3e4c290b78533 Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Tue, 12 Jan 2016 11:23:09 -0500 Subject: [PATCH 042/110] Update CHANGELOG / release notes --- CHANGELOG.md | 20 ++++++++++++ guide/release-notes-0.5.0.rst | 60 +++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 guide/release-notes-0.5.0.rst diff --git a/CHANGELOG.md b/CHANGELOG.md index c88f90c..24b152b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,26 @@ Ruby Client for eAPI ==================== +## v0.5.0, January, 2016 + +- Add optional ‘mode’ parameter to set_members() method in port-channel + interfaces API +- Add support for trunk groups +- Ensure multiple connections based on the wildcard settings do not clobber + each other. +- Add ‘terminal’ to the ‘configure’ command to workaround AAA issue +- Fix issue where ‘enablepw’ in the eapi.conf was not properly used +- Catch errors and syslog them when parsing eapi conf file. + In the event of an unparsable eapi.conf, a syslog warning will be generated + but the app will continue to attempt to utilize the default localhost conn. +- Ensure that nil is returned when getting nonexistent username +- Ensure all parse methods are private +- Add tests for timeout values +- Update framework tests +- Add unit tests for switchports +- Address code coverage gaps + + ## v0.4.0, November, 2015 - New users API diff --git a/guide/release-notes-0.5.0.rst b/guide/release-notes-0.5.0.rst new file mode 100644 index 0000000..13c3b4e --- /dev/null +++ b/guide/release-notes-0.5.0.rst @@ -0,0 +1,60 @@ +Release 0.5.0 - January 2016 +---------------------------- + +.. contents:: :local: + +Enhancements +^^^^^^^^^^^^ + +* Add lacp_mode option when setting port-channel members. (`89 `_) [`devrobo `_] + .. comment +* Add support for trunk groups. (`88 `_) [`devrobo `_] + .. comment +* Unit tests for switchports (`94 `_) [`websitescenes `_] + .. comment +* Ensure all parse methods are private. (`93 `_) [`websitescenes `_] + .. comment +* Add tests for timeout values (`92 `_) [`websitescenes `_] + .. comment +* Relax check on getall entries (`91 `_) [`devrobo `_] + .. comment +* Update framework tests (`90 `_) [`websitescenes `_] + .. comment +* Add basic framework tests. (`85 `_) [`websitescenes `_] + .. comment +* Address code coverage gaps (`84 `_) [`websitescenes `_] + .. comment + +Fixed +^^^^^ + +* Copy configuration entry before modifying with connection specific info. (`101 `_) + .. comment +* Add 'terminal' to configure command to work around AAA issue. (`99 `_) + .. comment +* Set enable password for a connection. (`96 `_) + .. comment +* Catch errors and syslog them when parsing eapi conf file. (`95 `_) + In the event of an unparsable ``eapi.conf`` file, which could occur due to other tools which used a YAML syntax instead of INI, rbeapi will log a warning via syslog, but continue to attempt a default connection to localhost. + .. comment +* Ensure that nil is returned when getting nonexistent username. (`83 `_) + .. comment +* Failure when eapi.conf is not formatted correctly (`82 `_) + In the event of an unparsable ``eapi.conf`` file, which could occur due to other tools which used a YAML syntax instead of INI, rbeapi will log a warning via syslog, but continue to attempt a default connection to localhost. +* Enable password setting in the .eapi.conf file not honored (`72 `_) + ``enablepwd`` is now properly used, if defined, in the ``eapi.conf`` +* API interfaces should accept an lacp_mode to configure for port-channel members (`58 `_) + ``set_members()`` now configures LACP mode when adding members to a port-channel + +Known Caveats +^^^^^^^^^^^^^ + +* Add support for commands with input (`100 `_) + .. comment +* Wildcard connection config gets clobbered (`86 `_) + .. comment +* Need to validate value keyword in set methods when array (`40 `_) + .. comment +* get_connect should raise an error instead of returning nil if no connection is found (`31 `_) + .. comment + From e2c0b22b9d24922be99e2f81ae8ed2f8f9c37618 Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Thu, 14 Jan 2016 10:13:01 -0500 Subject: [PATCH 043/110] testing build status icons --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a9fc8aa..6d9d27b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # Arista eAPI Ruby Library -Jenkins [![Build Status](https://revproxy.arista.com/eosplus/ci/buildStatus/icon?job=rbeapi_start)](https://revproxy.arista.com/eosplus/ci/job/rbeapi_start/) - #### Table of Contents 1. [Overview] (#overview) @@ -15,6 +13,11 @@ Jenkins [![Build Status](https://revproxy.arista.com/eosplus/ci/buildStatus/icon 6. [Testing] (#testing) 7. [License] (#license) +## Build status + +Style/package build: [![Start Build Status](https://revproxy.arista.com/eosplus/ci/buildStatus/icon?job=rbeapi_start&style=plastic)](https://revproxy.arista.com/eosplus/ci/job/rbeapi_start) + +Unit/System spec/coverage: [![Spec Build Status](https://revproxy.arista.com/eosplus/ci/buildStatus/icon?job=rbeapi_spec&style=plastic)](https://revproxy.arista.com/eosplus/ci/job/rbeapi_spec) # Overview From 0aa15a00a163be2e81ed165bc7bd7e65af558496 Mon Sep 17 00:00:00 2001 From: John Corbin Date: Thu, 14 Jan 2016 11:51:05 -0800 Subject: [PATCH 044/110] Added support for setting system banners. Fixes #100 --- lib/rbeapi/api/system.rb | 69 +++++++++++++++++-- lib/rbeapi/client.rb | 10 ++- spec/system/rbeapi/api/system_spec.rb | 48 ++++++++++++- spec/unit/rbeapi/api/system/default_spec.rb | 44 ++++++++++-- .../rbeapi/api/system/fixture_system.text | 14 ++++ 5 files changed, 172 insertions(+), 13 deletions(-) diff --git a/lib/rbeapi/api/system.rb b/lib/rbeapi/api/system.rb index 063529a..1d9abfd 100644 --- a/lib/rbeapi/api/system.rb +++ b/lib/rbeapi/api/system.rb @@ -41,13 +41,20 @@ module Api # The System class configures the node system services such as # hostname and domain name class System < Entity + def initialize(node) + super(node) + @banners_re = Regexp.new(/^banner\s+(login|motd)\s?$\n(.*?)$\nEOF$\n/m) + end + ## - # Returns the system settings for hostname and iprouting + # Returns the system settings for hostname, iprouting, and banners # # @example # { # hostname: , - # iprouting: + # iprouting: , + # banner_motd: , + # banner_login: # } # # @return [Hash] A Ruby hash object that provides the system settings as @@ -56,6 +63,7 @@ def get response = {} response.merge!(parse_hostname(config)) response.merge!(parse_iprouting(config)) + response.merge!(parse_banners(config)) response end @@ -89,6 +97,31 @@ def parse_iprouting(config) end private :parse_iprouting + ## + # Parses the global config and returns the value for both motd + # and login banners. + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute. If the + # banner is not set it will return a value of None for that key. + def parse_banners(config) + motd_value = login_value = '' + entries = config.scan(@banners_re) + entries.each do |type, value| + if type == 'motd' + motd_value = value + elsif type == 'login' + login_value = value + end + end + { banner_motd: motd_value, banner_login: login_value } + end + private :parse_banners + ## # Configures the system hostname value in the running-config # @@ -96,7 +129,8 @@ def parse_iprouting(config) # @option opts [string] :value The value to set the hostname to # @option :opts [Boolean] :enable If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default + # @option :opts [Boolean] :default If true configure the command using + # the default keyword. Default is false. # # @return [Boolean] returns true if the command completed successfully def set_hostname(opts = {}) @@ -110,14 +144,39 @@ def set_hostname(opts = {}) # @param [Hash] opts The configuration parameters # @option :opts [Boolean] :enable True if ip routing should be enabled # or False if ip routing should be disabled. Default is true. - # @option opts [Boolean] :default Controls the use of the default - # keyword. Default is false. + # @option :opts [Boolean] :default If true configure the command using + # the default keyword. Default is false. # # @return [Boolean] returns true if the command completed successfully def set_iprouting(opts = {}) cmd = command_builder('ip routing', opts) configure(cmd) end + + ## + # Configures system banners + # + # @param [String] :banner_type banner to be changed (likely either + # login or motd) + # @param [Hash] opts The configuration parameters + # @option opts [string] :value The value to set for the banner. + # @option :opts [Boolean] :enable If false then the command is + # negated. Default is true. + # @option :opts [Boolean] :default If true configure the command using + # the default keyword. Default is false. + # + # @return [Boolean] returns true if the command completed successfully + def set_banner(banner_type, opts = {}) + value = opts[:value] + cmd_string = "banner #{banner_type}" + if value + value += "\n" if value[-1, 1] != "\n" + cmd = [{ cmd: cmd_string, input: value }] + else + cmd = command_builder(cmd_string, opts) + end + configure(cmd) + end end end end diff --git a/lib/rbeapi/client.rb b/lib/rbeapi/client.rb index ed2bd16..e11c53a 100644 --- a/lib/rbeapi/client.rb +++ b/lib/rbeapi/client.rb @@ -327,7 +327,10 @@ def enable_authentication(password) # the empty hash from the response output before return the array # to the caller # - # @param [Array] commands An ordered list of commands to execute + # @param [Array] :commands An ordered list of commands to + # execute. A string in the list is an eapi command. A Hash entry in the + # array consists of the following key value pairs: + # { cmd: 'eapi command', input: 'text passed into stdin for command' } # @option :opts [String] :encoding The encoding scheme to use for sending # and receive eAPI messages. Valid values are json and text. The # default value is json @@ -361,7 +364,10 @@ def config(commands, opts = {}) # # rubocop:disable Metrics/MethodLength # - # @param [Array] commands An ordered list of commands to execute + # @param [Array] :commands An ordered list of commands to + # execute. A string in the list is an eapi command. A Hash entry in the + # array consists of the following key value pairs: + # { cmd: 'eapi command', input: 'text passed into stdin for command' } # @option :opts [String] :encoding The encoding scheme to use for sending # and receive eAPI messages. Valid values are json and text. The # default value is json diff --git a/spec/system/rbeapi/api/system_spec.rb b/spec/system/rbeapi/api/system_spec.rb index f828f78..58df401 100644 --- a/spec/system/rbeapi/api/system_spec.rb +++ b/spec/system/rbeapi/api/system_spec.rb @@ -13,10 +13,14 @@ describe '#get' do let(:entity) do - { hostname: 'localhost', iprouting: true } + { hostname: 'localhost', iprouting: true, banner_motd: '', + banner_login: '' } end - before { node.config(['hostname localhost', 'ip routing']) } + before do + node.config(['hostname localhost', 'ip routing', 'no banner motd', + 'no banner login']) + end it 'returns the snmp resource' do expect(subject.get).to eq(entity) @@ -88,4 +92,44 @@ end end end + + describe '#set_banner' do + before { node.config(['no banner login', 'no banner motd']) } + + it 'configures the login value' do + expect(subject.get[:banner_login]).to eq('') + expect(subject.set_banner('login', value: 'foo')).to be_truthy + expect(subject.get[:banner_login]).to eq('foo') + end + + it 'negates the login value' do + expect(subject.get[:banner_login]).to eq('') + expect(subject.set_banner('login', enable: false)).to be_truthy + expect(subject.get[:banner_login]).to eq('') + end + + it 'defaults the login value' do + expect(subject.get[:banner_login]).to eq('') + expect(subject.set_banner('login', default: true)).to be_truthy + expect(subject.get[:banner_login]).to eq('') + end + + it 'configures the motd value' do + expect(subject.get[:banner_motd]).to eq('') + expect(subject.set_banner('motd', value: 'foo')).to be_truthy + expect(subject.get[:banner_motd]).to eq('foo') + end + + it 'negates the motd value' do + expect(subject.get[:banner_motd]).to eq('') + expect(subject.set_banner('motd', enable: false)).to be_truthy + expect(subject.get[:banner_motd]).to eq('') + end + + it 'defaults the motd value' do + expect(subject.get[:banner_motd]).to eq('') + expect(subject.set_banner('motd', default: true)).to be_truthy + expect(subject.get[:banner_motd]).to eq('') + end + end end diff --git a/spec/unit/rbeapi/api/system/default_spec.rb b/spec/unit/rbeapi/api/system/default_spec.rb index cb4ea8c..ef4e1fc 100644 --- a/spec/unit/rbeapi/api/system/default_spec.rb +++ b/spec/unit/rbeapi/api/system/default_spec.rb @@ -41,7 +41,9 @@ let(:node) { double('node') } let(:test) do - { hostname: 'localhost', iprouting: true } + { hostname: 'localhost', iprouting: true, + banner_motd: "MOTD Banner\nSecond Line\nEOF \n*\\v1?", + banner_login: "Login Banner\nSecond Line\n123456\n EOF" } end def system @@ -56,15 +58,15 @@ def system describe '#get' do it 'returns the username collection' do - expect(subject.get).to include(test) + expect(subject.get).to eq(test) end it 'returns a hash collection' do expect(subject.get).to be_a_kind_of(Hash) end - it 'has two entries' do - expect(subject.get.size).to eq(2) + it 'has four entries' do + expect(subject.get.size).to eq(4) end end @@ -99,4 +101,38 @@ def system expect(subject.set_iprouting(enable: false)).to be_truthy end end + + describe '#set_banner' do + it 'sets the login banner' do + expect(node).to receive(:config).with([{ cmd: 'banner login', + input: "login banner\n" }]) + expect(subject.set_banner('login', value: 'login banner')).to be_truthy + end + + it 'negates the login banner' do + expect(node).to receive(:config).with('no banner login') + expect(subject.set_banner('login', enable: false)).to be_truthy + end + + it 'defaults the login banner' do + expect(node).to receive(:config).with('default banner login') + expect(subject.set_banner('login', default: true)).to be_truthy + end + + it 'sets the motd banner' do + expect(node).to receive(:config).with([{ cmd: 'banner motd', + input: "motd banner\n" }]) + expect(subject.set_banner('motd', value: 'motd banner')).to be_truthy + end + + it 'negates the motd banner' do + expect(node).to receive(:config).with('no banner motd') + expect(subject.set_banner('motd', enable: false)).to be_truthy + end + + it 'defaults the motd banner' do + expect(node).to receive(:config).with('default banner motd') + expect(subject.set_banner('motd', default: true)).to be_truthy + end + end end diff --git a/spec/unit/rbeapi/api/system/fixture_system.text b/spec/unit/rbeapi/api/system/fixture_system.text index f84a0fc..df8459d 100644 --- a/spec/unit/rbeapi/api/system/fixture_system.text +++ b/spec/unit/rbeapi/api/system/fixture_system.text @@ -1,2 +1,16 @@ hostname localhost ip routing +banner login +Login Banner +Second Line +123456 + EOF +EOF +! +banner motd +MOTD Banner +Second Line +EOF +*\v1? +EOF +! From 22246149efeb307b4352e0ce8437934d706be30d Mon Sep 17 00:00:00 2001 From: John Corbin Date: Fri, 15 Jan 2016 15:30:20 -0800 Subject: [PATCH 045/110] Added doc for trunk groups to get. --- lib/rbeapi/api/switchports.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/rbeapi/api/switchports.rb b/lib/rbeapi/api/switchports.rb index b10ed7b..dba8c8e 100644 --- a/lib/rbeapi/api/switchports.rb +++ b/lib/rbeapi/api/switchports.rb @@ -52,7 +52,8 @@ class Switchports < Entity # "mode": [access, trunk], # "trunk_allowed_vlans": array # "trunk_native_vlan": , - # "access_vlan": + # "access_vlan": , + # "trunk_groups": array # } # # @param [String] :name The full name of the interface to get. The From 41db76d61e4159139b3b459fdcb6280648b77c19 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Sun, 17 Jan 2016 19:27:18 -0700 Subject: [PATCH 046/110] Remove getter for timeouts and use attr_reader instead. --- lib/rbeapi/eapilib.rb | 10 ++-------- spec/system/rbeapi/client_spec.rb | 8 ++++---- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/lib/rbeapi/eapilib.rb b/lib/rbeapi/eapilib.rb index 9472e67..701411e 100644 --- a/lib/rbeapi/eapilib.rb +++ b/lib/rbeapi/eapilib.rb @@ -121,6 +121,8 @@ def initialize(message, connection_type = nil, commands = nil) # JSON-RPC. This class should not need to be directly instantiated. class EapiConnection attr_reader :error + attr_reader :open_timeout + attr_reader :read_timeout ## # The connection contains the transport. @@ -162,14 +164,6 @@ def timeouts(opts = {}) @read_timeout = opts.fetch(:read_timeout, DEFAULT_HTTP_READ_TIMEOUT) end - ## - # Gets values for open_timeout and read_timeout - # - # @return [Hash] open_timeout and read_timeout - def get_timeouts - { open_timeout: @open_timeout, read_timeout: @read_timeout } - end - ## # Generates the eAPI JSON request message. # diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb index a05dd99..99c565c 100644 --- a/spec/system/rbeapi/client_spec.rb +++ b/spec/system/rbeapi/client_spec.rb @@ -348,8 +348,8 @@ def test_conf describe 'test timeouts' do it 'loads default timeout values' do - expect(node.connection.get_timeouts).to eq(open_timeout: 10, - read_timeout: 10) + expect(node.connection.open_timeout).to eq(10) + expect(node.connection.read_timeout).to eq(10) end describe 'loads veos05' do @@ -359,8 +359,8 @@ def test_conf end it 'loads timeout values from conf file' do - expect(node.connection.get_timeouts).to eq(open_timeout: 12, - read_timeout: 12) + expect(node.connection.open_timeout).to eq(12) + expect(node.connection.read_timeout).to eq(12) end end end From f02709106f90575e47b4d2cca9e4d87872494ded Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Tue, 19 Jan 2016 11:04:34 -0700 Subject: [PATCH 047/110] Merge in develop and fix conflicts. --- guide/.gitignore | 2 + guide/conf.py | 10 +- lib/rbeapi/api.rb | 73 ++-- lib/rbeapi/api/aaa.rb | 180 ++++----- lib/rbeapi/api/acl.rb | 123 +++--- lib/rbeapi/api/bgp.rb | 349 +++++++++-------- lib/rbeapi/api/dns.rb | 96 ++--- lib/rbeapi/api/interfaces.rb | 672 +++++++++++++++++---------------- lib/rbeapi/api/ipinterfaces.rb | 184 ++++----- lib/rbeapi/api/logging.rb | 64 ++-- lib/rbeapi/api/mlag.rb | 194 +++++----- lib/rbeapi/api/ntp.rb | 78 ++-- lib/rbeapi/api/ospf.rb | 116 +++--- lib/rbeapi/api/prefixlists.rb | 44 +-- lib/rbeapi/api/radius.rb | 126 ++++--- lib/rbeapi/api/routemaps.rb | 174 +++++---- lib/rbeapi/api/snmp.rb | 204 +++++----- lib/rbeapi/api/staticroutes.rb | 47 ++- lib/rbeapi/api/stp.rb | 184 ++++----- lib/rbeapi/api/switchports.rb | 172 +++++---- lib/rbeapi/api/tacacs.rb | 89 +++-- lib/rbeapi/api/users.rb | 136 +++---- lib/rbeapi/api/varp.rb | 103 ++--- lib/rbeapi/api/vlans.rb | 170 ++++----- lib/rbeapi/api/vrrp.rb | 383 ++++++++++--------- lib/rbeapi/utils.rb | 16 +- lib/rbeapi/version.rb | 2 +- 27 files changed, 2121 insertions(+), 1870 deletions(-) create mode 100644 guide/.gitignore diff --git a/guide/.gitignore b/guide/.gitignore new file mode 100644 index 0000000..ff16fe8 --- /dev/null +++ b/guide/.gitignore @@ -0,0 +1,2 @@ +# Sphinx build env +_build diff --git a/guide/conf.py b/guide/conf.py index 8335d42..878b37c 100644 --- a/guide/conf.py +++ b/guide/conf.py @@ -61,11 +61,11 @@ # built documents. # import re -p = re.compile("version\": \"(.*)\"") -with open("../metadata.json") as f: - data = f.read() - ver = p.search(data) - if ver: +p = re.compile("VERSION\s=\s'(.*)'") +with open("../lib/rbeapi/version.rb") as f: + data = f.read() + ver = p.search(data) + if ver: version = ver.group(1) #print "Version: {}".format(version) diff --git a/lib/rbeapi/api.rb b/lib/rbeapi/api.rb index 9693423..ce069ef 100644 --- a/lib/rbeapi/api.rb +++ b/lib/rbeapi/api.rb @@ -32,14 +32,14 @@ require 'rbeapi/eapilib' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## # Rbeapi::Api module Api ## # The Entity class provides a base class implementation for building - # API modules. The Entity class is typically not instantiated directly + # API modules. The Entity class is typically not instantiated directly # but serves as a super class with convenience methods used to # work with the node. class Entity @@ -50,56 +50,56 @@ class Entity ## # Construct the node. # - # @param [Node] :node An instance of Rbeapi::Client::Node used to - # send and receive eAPI messages + # @param node [Node] An instance of Rbeapi::Client::Node used to + # send and receive eAPI messages. def self.instance(node) new(node) end ## # The Entity class provides a base class implementation for building - # API modules. The Entity class is typically not instantiated directly + # API modules. The Entity class is typically not instantiated directly # but serves as a super class with convenience methods used to # work with the node. # - # @param [Node] :node This should be an instance of Rbeapi::Client::Node - # that is used to send and receive eAPI messages + # @param node [Node] This should be an instance of Rbeapi::Client::Node + # that is used to send and receive eAPI messages. # def initialize(node) @node = node end ## - # Returns the running configuration from the node instance. This is + # Returns the running configuration from the node instance. This is # a convenience method to easily access the current running config - # from an API module + # from an API module. # - # @return [String] The current running-config from the node + # @return [String] The current running-config from the node. def config @node.running_config end ## # Provides a convenience method for access the connection error (if - # one exists) of the node's connection instance + # one exists) of the node's connection instance. # # @return [Rbeapi::Eapilib::CommandError] An instance of CommandError - # that can be used to further evaluate the root cause of an error + # that can be used to further evaluate the root cause of an error. def error @node.connection.error end ## # Returns a block of configuration from the current running config - # as a string. The argument is used to search the config and return + # as a string. The argument is used to search the config and return # the text along with any child configuration statements. # - # @param [String] :text The text to be used to find the parent line + # @param text [String] The text to be used to find the parent line # in the nodes configuration. # - # @returns [nil, String] Returns the block of configuration based on - # the supplied argument. If the argument is not found in the - # configuration, nil is returned + # @return [nil, String] Returns the block of configuration based on + # the supplied argument. If the argument is not found in the + # configuration, nil is returned. def get_block(text) mdata = /^#{text}$/.match(config) return nil unless mdata @@ -115,16 +115,16 @@ def get_block(text) end ## - # Method called to send configuration commands to the node. This method + # Method called to send configuration commands to the node. This method # will send the commands to the node and rescue from CommandError or # ConnectionError. # - # @param [String, Array] :commands The commands to send to the node over - # the API connection to configure the system + # @param commands [String, Array] The commands to send to the node over + # the API connection to configure the system. # # @return [Boolean] Returns True if the commands were successful or # returns False if there was an error issuing the commands on the - # node. Use error to further investigate the cause of any errors + # node. Use error to further investigate the cause of any errors. def configure(commands) @node.config(commands) return true @@ -134,26 +134,27 @@ def configure(commands) ## # Method called to build the correct version of a command based on - # the modifier options. If value option is set then it is appended + # the modifier options. If value option is set then it is appended # to the command. If the enable option is false then the 'no' - # keyword is prefixed to the command. If the default value is - # provided and set to true, then the default keyword is used. If + # keyword is prefixed to the command. If the default value is + # provided and set to true, then the default keyword is used. If # both options are provided, then default option takes precedence. # - # @param [String, Array] :commands The commands to send to the node - # over the API connection to configure the system - # @param [Hash] :opts the options for the command + # @param cmd [String, Array] The commands to send to the node + # over the API connection to configure the system. # - # @option :opts [String] :value Optional value that is + # @param opts [Hash] The options for the command. + # + # @option opts value [String] Optional value that is # appended to the command if set. # - # @option :opts [Boolean] :enable Prefix the command with 'no'. + # @option opts enable [Boolean] Prefix the command with 'no'. # Default is true. # - # @option :opts [Boolean] :default Configure the command using + # @option opts default [Boolean] Configure the command using # the default keyword. Default is false. # - # @return [String] Returns built command string + # @return [String] Returns built command string. def command_builder(cmd, opts = {}) enable = opts.fetch(:enable, true) default = opts.fetch(:default, false) @@ -167,13 +168,13 @@ def command_builder(cmd, opts = {}) # configure_interface sends the commands over eAPI to the destination # node to configure a specific interface. # - # @param [String] :name The interface name to apply the configuration - # to. The name value must be the full interface identifier + # @param name [String] The interface name to apply the configuration + # to. The name value must be the full interface identifier. # - # @param [Array] :commands The list of commands to configure the - # interface + # @param commands [Array] The list of commands to configure the + # interface. # - # @return [Boolean] Returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def configure_interface(name, commands) commands = [*commands] commands.insert(0, "interface #{name}") diff --git a/lib/rbeapi/api/aaa.rb b/lib/rbeapi/api/aaa.rb index 16dd75b..956d325 100644 --- a/lib/rbeapi/api/aaa.rb +++ b/lib/rbeapi/api/aaa.rb @@ -32,17 +32,17 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Aaa class manages Authorization, Authentication and Accounting (AAA) # on an EOS node. class Aaa < Entity ## - # get returns a hash of all Aaa resources + # get returns a hash of all Aaa resources. # # @example # { @@ -105,12 +105,12 @@ class AaaGroups < Entity # servers: # } # - # @param [String] :name The server group name to return from the nodes - # current running configuration. If the name is not configured a nil + # @param name [String] The server group name to return from the nodes + # current running configuration. If the name is not configured a nil # object is returned. # - # @return [nil, Hash] returns the resource hash for the - # specified name. If the name does not exist, a nil object is returned + # @return [nil, Hash] Returns the resource hash for the + # specified name. If the name does not exist, a nil object is returned. def get(name) block = get_block("aaa group server ([^\s]+) #{name}") return nil unless block @@ -121,22 +121,22 @@ def get(name) end ## - # getall returns a aaa server groups hash + # getall returns a aaa server groups hash. # # @example - # { - # : { - # type: , - # servers: - # }, - # : { - # type: , - # servers: + # { + # : { + # type: , + # servers: + # }, + # : { + # type: , + # servers: + # } # } - # } # - # @return [Hash] returns the resource hashes for - # configured aaa groups. If none exist, a nil object is returned + # @return [Hash] Returns the resource hashes for + # configured aaa groups. If none exist, a nil object is returned. def getall cfg = config.scan(/aaa group server (?:radius|tacacs\+) (.+)$/) cfg.each_with_object({}) do |name, hsh| @@ -147,15 +147,15 @@ def getall ## # parse_type scans the specified configuration block and returns the - # server group type as either 'tacacs' or 'radius'. The type value is + # server group type as either 'tacacs' or 'radius'. The type value is # expected to always be present in the config. # # @api private # - # @param [String] :config The aaa server group block configuration for the - # group name to parse + # @param config [String] The aaa server group block configuration for the + # group name to parse. # - # @return [Hash] resource hash attribute + # @return [Hash] Resource hash attribute. def parse_type(config) value = config.scan(/aaa group server ([^\s]+)/).first { type: value.first } @@ -164,7 +164,7 @@ def parse_type(config) ## # parse_servers scans the specified configuraiton block and returns the - # list of servers configured for the group. If there are no servers + # list of servers configured for the group. If there are no servers # configured for the group the servers value will return an empty array. # # @api private @@ -172,13 +172,13 @@ def parse_type(config) # @see parse_radius_server # @see parse_tacacs_server # - # @param [String] :config The aaa server group block configuration for the - # group name to parse + # @param config [String] The aaa server group block configuration for the + # group name to parse. # - # @param [String] :type The aaa server block type. Valid values are + # @param type [String] The aaa server block type. Valid values are # either radius or tacacs+. # - # @return [Hash] resource hash attribute + # @return [Hash] Resource hash attribute def parse_servers(config, type) case type when 'radius' then parse_radius_server(config) @@ -189,13 +189,13 @@ def parse_servers(config, type) ## # parse_radius_server scans the provide configuration block and returns - # the list of servers configured. The configuration block is expected to - # be a radius configuration block. If there are no servers configured + # the list of servers configured. The configuration block is expected to + # be a radius configuration block. If there are no servers configured # for the group the servers value will return an empty array. # # @api private # - # @param [String] :config The aaa server group block configuration for the + # @param config [String] The aaa server group block configuration for the # group name to parse # # @return [Hash] resource hash attribute @@ -213,16 +213,16 @@ def parse_radius_server(config) ## # parse_tacacs_server scans the provided configuration block and returns - # the list of configured servers. The configuration block is expected to - # be a tacacs configuration block. If there are no servers configured + # the list of configured servers. The configuration block is expected to + # be a tacacs configuration block. If there are no servers configured # for the group the servers value will return an empty array. # # @api private # - # @param [String] :config The aaa server group block configuration for the - # group name to parse + # @param config [String] The aaa server group block configuration for the + # group name to parse. # - # @return [Hash] resource hash attribute + # @return [Hash] Resource hash attribute. def parse_tacacs_server(config) values = config.scan(TACACS_GROUP_SERVER).map do |(name, vrf, port)| { @@ -237,17 +237,17 @@ def parse_tacacs_server(config) ## # find_type is a utility method to find the type of aaa server group for - # the specified name. This method will scan the current running + # the specified name. This method will scan the current running # configuration on the node and return the server group type as either - # 'radius' or 'tacacs+'. If the server group is not configured, then nil + # 'radius' or 'tacacs+'. If the server group is not configured, then nil # will be returned. # # @api private # - # @param [String] :name The aaa server group name to find in the config - # and return the type value for + # @param name [String] The aaa server group name to find in the config + # and return the type value for. # - # @return [nil, String] returns either the type name as 'radius' or + # @return [nil, String] Returns either the type name as 'radius' or # 'tacacs+' or nil if the server group is not configured. def find_type(name) mdata = /aaa group server ([^\s]+) #{name}/.match(config) @@ -258,19 +258,19 @@ def find_type(name) ## # create adds a new aaa group server to the nodes current configuration. # If the specified name and type are already created then this method - # will return successfully. If the name is configured but the type is + # will return successfully. If the name is configured but the type is # different, this method will not return successfully (returns false). # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # aaa group server # - # @param [String] :name The name of the aaa group server to create in the + # @param name [String] The name of the aaa group server to create in the # nodes running configuration # - # @param [String] :type The type of aaa group server to create in the - # nodes running configuration. Valid values include 'radius' or + # @param type [String] The type of aaa group server to create in the + # nodes running configuration. Valid values include 'radius' or # 'tacacs+' # # @return [Boolean] returns true if the commands complete successfully @@ -280,19 +280,19 @@ def create(name, type) ## # delete removes a current aaa server group from the nodes current - # configuration. This method will automatically determine the server - # group type based on the name. If the name is not configured in the + # configuration. This method will automatically determine the server + # group type based on the name. If the name is not configured in the # nodes current configuration, this method will return successfully. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # no aaa group server [radius | tacacs+] # - # @param [String] :name The name of the aaa group server to create in the - # nodes running configuration + # @param name [String] The name of the aaa group server to create in the + # nodes running configuration. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def delete(name) type = find_type(name) return true unless type @@ -301,22 +301,20 @@ def delete(name) ## # set_servers configures the set of servers for a specified aaa server - # group. This is an atomic operation that first removes all current - # servers and then adds the new servers back. If any of the servers + # group. This is an atomic operation that first removes all current + # servers and then adds the new servers back. If any of the servers # failes to be removed or added, this method will return unsuccessfully. # # @see remove_server # @see add_server # - # @param [String] :name The name of the aaa group server to add the new + # @param name [String] The name of the aaa group server to add the new # server configuration to. # - # @param [String] :server The IP address or host name of the server to + # @param servers [String] The IP address or host name of the server to # add to the configuration # - # @param [Hash] :opts Optional configuration parameters - # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully def set_servers(name, servers) current = get(name) current[:servers].each do |srv| @@ -330,22 +328,22 @@ def set_servers(name, servers) end ## - # add_server adds a new server to the specified aaa server group. If + # add_server adds a new server to the specified aaa server group. If # the server is already configured in the list of servers, this method # will still return successfully. # # @see add_radius_server # @see add_tacacs_server # - # @param [String] :name The name of the aaa group server to add the new + # @param name [String] The name of the aaa group server to add the new # server configuration to. # - # @param [String] :server The IP address or host name of the server to - # add to the configuration + # @param server [String] The IP address or host name of the server to + # add to the configuration. # - # @param [Hash] :opts Optional configuration parameters + # @param opts [Hash] Optional configuration parameters. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def add_server(name, server, opts = {}) type = find_type(name) return false unless type @@ -359,24 +357,24 @@ def add_server(name, server, opts = {}) ## # add_radius_server adds a new radius server to the nodes current # configuration. If the server already exists in the specified group - # name this method will still return successfully + # name this method will still return successfully. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commmands + # commmands # aaa group server radius # server [acct-port ] [auth-port ] # [vrf ] # - # @param [String] :name The name of the aaa group server to add the new + # @param name [String] The name of the aaa group server to add the new # server configuration to. # - # @param [String] :server The IP address or host name of the server to - # add to the configuration + # @param server [String] The IP address or host name of the server to + # add to the configuration. # - # @param [Hash] :opts Optional configuration parameters + # @param opts [Hash] Optional configuration parameters. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def add_radius_server(name, server, opts = {}) # order of command options matter here! server = "server #{server} " @@ -388,25 +386,25 @@ def add_radius_server(name, server, opts = {}) ## # add_tacacs_server adds a new tacacs server to the nodes current - # configuration. If the server already exists in the specified group - # name this method will still return successfully + # configuration. If the server already exists in the specified group + # name this method will still return successfully. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commmands + # commmands # aaa group server tacacs+ # server [acct-port ] [auth-port ] # [vrf ] # - # @param [String] :name The name of the aaa group server to add the new + # @param name [String] The name of the aaa group server to add the new # server configuration to. # - # @param [String] :server The IP address or host name of the server to - # add to the configuration + # @param server [String] The IP address or host name of the server to + # add to the configuration. # - # @param [Hash] :opts Optional configuration parameters + # @param opts [Hash] Optional configuration parameters. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def add_tacacs_server(name, server, opts = {}) # order of command options matter here! server = "server #{server} " @@ -417,20 +415,22 @@ def add_tacacs_server(name, server, opts = {}) ## # remove_server deletes an existing server from the specified aaa server - # group. If the specified server is not configured in the specified + # group. If the specified server is not configured in the specified # server group, this method will still return true. # - # @eos_version 4.13.7M + # eos_version 4.13.7M # - # @commands + # commands # aaa group server [radius | tacacs+] # no server # - # @param [String] :name The name of the aaa group server to remove + # @param name [String] The name of the aaa group server to remove. # - # @param [String] :server The IP address or host name of the server + # @param server [String] The IP address or host name of the server. # - # @return [Boolean] returns true if the commands complete successfully + # @param opts [Hash] Optional configuration parameters. + # + # @return [Boolean] returns true if the commands complete successfully. def remove_server(name, server, opts = {}) type = find_type(name) return false unless type diff --git a/lib/rbeapi/api/acl.rb b/lib/rbeapi/api/acl.rb index dafd5f7..6124523 100644 --- a/lib/rbeapi/api/acl.rb +++ b/lib/rbeapi/api/acl.rb @@ -33,10 +33,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Acl class manages the set of standard ACLs. @@ -75,7 +75,7 @@ def initialize(node) # ... # } # - # @param [String] :name The ACL name. + # @param name [String] The ACL name. # # @return [nil, Hash] Returns the ACL resource as a # Hash. Returns nil if name does not exist. @@ -144,11 +144,11 @@ def getall ## # mask_to_prefixlen converts a subnet mask from dotted decimal to - # bit length + # bit length. # - # @param [String] :mask The dotted decimal subnet mask to convert + # @param mask [String] The dotted decimal subnet mask to convert. # - # @return [String] The subnet mask as a valid prefix length + # @return [String] The subnet mask as a valid prefix length. def mask_to_prefixlen(mask) mask = '255.255.255.255' unless mask NetAddr::CIDR.create('0.0.0.0/' + mask).netmask_ext @@ -160,9 +160,9 @@ def mask_to_prefixlen(mask) # # @api private # - # @param [String] :config The switch config. + # @param config [String] The switch config. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_entries(config) entries = {} @@ -187,38 +187,38 @@ def parse_entries(config) ## # create will create a new ACL resource in the nodes current - # configuration with the specified name. If the create method + # configuration with the specified name. If the create method # is called and the ACL already exists, this method will still # return true. The ACL will not have any entries. Use add_entry # to add entries to the ACL. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # ip access-list standard # - # @param [String] :name The ACL name to create on the node. Must + # @param name [String] The ACL name to create on the node. Must # begin with an alphabetic character. Cannot contain spaces or # quotation marks. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(name) configure("ip access-list standard #{name}") end ## # delete will delete an existing ACL resource from the nodes current - # running configuration. If the delete method is called and the ACL + # running configuration. If the delete method is called and the ACL # does not exist, this method will succeed. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # no ip access-list standard # - # @param [String] :name The ACL name to delete on the node. + # @param name [String] The ACL name to delete on the node. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete(name) configure("no ip access-list standard #{name}") end @@ -228,15 +228,15 @@ def delete(name) # command has the same effect as deleting the ACL from the nodes # running configuration. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # default no ip access-list standard # - # @param [String] :name The ACL name to set to the default value + # @param name [String] The ACL name to set to the default value # on the node. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully def default(name) configure("default ip access-list standard #{name}") end @@ -246,17 +246,22 @@ def default(name) # # @api private # - # @param [Hash] :opts the options for the entry - # @option :opts [String] :seqno The sequence number of the entry in + # @param entry [Hash] the options for the entry. + # + # @option entry seqno [String] The sequence number of the entry in # the ACL to add. Default is nil, will be assigned. - # @option :opts [String] :action The action triggered by the ACL. Valid - # values are 'permit', 'deny', or 'remark' - # @option :opts [String] :addr The IP address to permit or deny. - # @option :opts [String] :prefixlen The prefixlen for the IP address. - # @option :opts [Boolean] :log Triggers an informational log message + # + # @option entry action [String] The action triggered by the ACL. Valid + # values are 'permit', 'deny', or 'remark'. + # + # @option entry addr [String] The IP address to permit or deny. + # + # @option entry prefixlen [String] The prefixlen for the IP address. + # + # @option entry log [Boolean] Triggers an informational log message # to the console about the matching packet. # - # @return [String] returns commands to create an entry + # @return [String] Returns commands to create an entry. def build_entry(entry) cmds = "#{entry[:seqno]} " if entry[:seqno] cmds << "#{entry[:action]} #{entry[:srcaddr]}/#{entry[:srcprefixlen]}" @@ -269,20 +274,26 @@ def build_entry(entry) # update_entry will update an entry, identified by the seqno # in the ACL specified by name, with the passed in parameters. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The ACL name to update on the node. - # @param [Hash] :opts the options for the entry - # @option :opts [String] :seqno The sequence number of the entry in + # @param name [String] The ACL name to update on the node. + # + # @param entry [Hash] the options for the entry. + # + # @option entry seqno [String] The sequence number of the entry in # the ACL to update. - # @option :opts [String] :action The action triggered by the ACL. Valid - # values are 'permit', 'deny', or 'remark' - # @option :opts [String] :addr The IP address to permit or deny. - # @option :opts [String] :prefixlen The prefixlen for the IP address. - # @option :opts [Boolean] :log Triggers an informational log message + # + # @option entry action [String] The action triggered by the ACL. Valid + # values are 'permit', 'deny', or 'remark'. + # + # @option entry addr [String] The IP address to permit or deny. + # + # @option entry prefixlen [String] The prefixlen for the IP address. + # + # @option entry log [Boolean] Triggers an informational log message # to the console about the matching packet. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def update_entry(name, entry) cmds = ["ip access-list standard #{name}"] cmds << "no #{entry[:seqno]}" @@ -295,18 +306,23 @@ def update_entry(name, entry) # add_entry will add an entry to the specified ACL with the # passed in parameters. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M + # + # @param name [String] The ACL name to add an entry to on the node. + # + # @param entry [Hash] the options for the entry. # - # @param [String] :name The ACL name to add an entry to on the node. - # @param [Hash] :opts the options for the entry - # @option :opts [String] :action The action triggered by the ACL. Valid - # values are 'permit', 'deny', or 'remark' - # @option :opts [String] :addr The IP address to permit or deny. - # @option :opts [String] :prefixlen The prefixlen for the IP address. - # @option :opts [Boolean] :log Triggers an informational log message + # @option entry action [String] The action triggered by the ACL. Valid + # values are 'permit', 'deny', or 'remark'. + # + # @option entry addr [String] The IP address to permit or deny. + # + # @option entry prefixlen [String] The prefixlen for the IP address. + # + # @option entry log [Boolean] Triggers an informational log message # to the console about the matching packet. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def add_entry(name, entry) cmds = ["ip access-list standard #{name}"] cmds << build_entry(entry) @@ -318,13 +334,14 @@ def add_entry(name, entry) # remove_entry will remove the entry specified by the seqno for # the ACL specified by name. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M + # + # @param name [String] The ACL name to update on the node. # - # @param [String] :name The ACL name to update on the node. - # @param [String] :seqno The sequence number of the entry in + # @param seqno [String] The sequence number of the entry in # the ACL to remove. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def remove_entry(name, seqno) cmds = ["ip access-list standard #{name}", "no #{seqno}", 'exit'] configure(cmds) diff --git a/lib/rbeapi/api/bgp.rb b/lib/rbeapi/api/bgp.rb index 67d3a63..25d11b9 100644 --- a/lib/rbeapi/api/bgp.rb +++ b/lib/rbeapi/api/bgp.rb @@ -32,13 +32,13 @@ require 'rbeapi/api' ## -# Eos is the toplevel namespace for working with Arista EOS nodes +# Eos is the toplevel namespace for working with Arista EOS nodes. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## - # The Bgp class implements global BGP router configuration + # The Bgp class implements global BGP router configuration. class Bgp < Entity attr_reader :neighbors @@ -115,9 +115,9 @@ def get # AS number. Defined as a class method. Used by the BgpNeighbors # class below. # - # @param [String] :config The switch config. + # @param config [String] The switch config. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def self.parse_bgp_as(config) value = config.scan(/^router bgp (\d+)/).first { bgp_as: value[0] } @@ -129,9 +129,9 @@ def self.parse_bgp_as(config) # # @api private # - # @param [String] :config The switch config. + # @param config [String] The switch config. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_router_id(config) value = config.scan(/router-id ([^\s]+)/).first value = value ? value[0] : nil @@ -145,7 +145,7 @@ def parse_router_id(config) # # @api private # - # @param [String] :config The switch config. + # @param config [String] The switch config. # # @return [Hash] resource hash attribute. Returns # true if shutdown, false otherwise. @@ -161,9 +161,9 @@ def parse_shutdown(config) # # @api private # - # @param [String] :config The switch config. + # @param config [String] The switch config. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_maximum_paths(config) values = config.scan(/maximum-paths\s+(\d+)\s+ecmp\s+(\d+)/).first { maximum_paths: values[0].to_i, maximum_ecmp_paths: values[1].to_i } @@ -176,10 +176,9 @@ def parse_maximum_paths(config) # # @api private # - # @param [String] :config The switch config. + # @param config [String] The switch config. # - # @return [Hash] resource hash attribute - # @return [Array] Single element hash with Array of network hashes + # @return [Array] Single element hash with Array of network hashes. def parse_networks(config) networks = [] lines = config.scan(%r{network (.+)/(\d+)(?: route-map (\w+))*}) @@ -196,16 +195,15 @@ def parse_networks(config) # Optional parameters can be passed in to initialize BGP specific # settings. # - # @commands + # commands # router bgp # - # @param [String] :bgp_as The BGP autonomous system number to be + # @param bgp_as [String] The BGP autonomous system number to be # configured for the local BGP routing instance. # + # @param opts [hash] Optional keyword arguments. # - # @param [hash] :opts Optional keyword arguments - # - # @option :opts [String] :router_id The BGP routing process router-id + # @option opts router_id [String] The BGP routing process router-id # value. When no ID has been specified (i.e. value not set), the # local router ID is set to the following: # * The loopback IP address when a single loopback interface is @@ -215,17 +213,17 @@ def parse_networks(config) # * The highest IP address on a physical interface when no loopback # interfaces are configure # - # @option :opts [Integer] :maximum_paths Maximum number of equal cost + # @option opts maximum_paths [Integer] Maximum number of equal cost # paths. # - # @option :opts [Integer] :maximum_ecmp_paths Maximum number of installed + # @option opts maximum_ecmp_paths [Integer] Maximum number of installed # ECMP routes. The maximum_paths option must be set if # maximum_ecmp_paths is set. # - # @option :opts [Boolean] :enable If true then the BGP router is enabled. + # @option opts enable [Boolean] If true then the BGP router is enabled. # If false then the BGP router is disabled. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] returns true if the command completed successfully. def create(bgp_as, opts = {}) if opts[:maximum_ecmp_paths] && !opts[:maximum_paths] message = 'maximum_paths must be set if maximum_ecmp_paths is set' @@ -249,10 +247,10 @@ def create(bgp_as, opts = {}) ## # delete will delete the BGP routing instance from the node. # - # @commands + # commands # no router bgp # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete config = get return true unless config @@ -264,7 +262,7 @@ def delete # keyword. This command has the same effect as deleting the BGP # routine instance from the nodes running configuration. # - # @commands + # commands # default router bgp # # @return [Boolean] returns true if the command complete successfully @@ -281,9 +279,9 @@ def default # # @api private # - # @param [String] :cmd Command to run under BGP mode + # @param cmd [String] Command to run under BGP mode. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def configure_bgp(cmd) config = get_block('^router bgp .*') fail 'BGP router is not configured' unless config @@ -296,14 +294,14 @@ def configure_bgp(cmd) ## # set_router_id sets the router_id for the BGP routing instance. # - # @commands + # commands # router bgp # {no | default} router-id # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments # - # @option :opts [String] :value The BGP routing process router-id - # value. When no ID has been specified (i.e. value not set), the + # @option opts value [String] The BGP routing process router-id + # value. When no ID has been specified (i.e. value not set), the # local router ID is set to the following: # * The loopback IP address when a single loopback interface is # configured. @@ -312,13 +310,13 @@ def configure_bgp(cmd) # * The highest IP address on a physical interface when no loopback # interfaces are configure # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the router-id using - # the default keyword + # @option opts default [Boolean] Configure the router-id using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_router_id(opts = {}) configure_bgp(command_builder('router-id', opts)) end @@ -327,21 +325,21 @@ def set_router_id(opts = {}) # set_shutdown configures the administrative state for the global # BGP routing process. The value option is not used by this method. # - # @commands + # commands # router bgp # {no | default} shutdown # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If enable is true then the BGP + # @option opts enable [Boolean] If enable is true then the BGP # routing process is administratively enabled and if enable is # False then the BGP routing process is administratively # disabled. # - # @option :opts [Boolean] :default Configure the router-id using - # the default keyword + # @option opts default [Boolean] Configure the router-id using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_shutdown(opts = {}) fail 'set_shutdown has the value option set' if opts[:value] # Shutdown semantics are opposite of enable semantics so invert enable @@ -354,25 +352,25 @@ def set_shutdown(opts = {}) # set_maximum_paths sets the maximum number of equal cost paths and # the maximum number of installed ECMP routes. # - # @commands + # commands # router bgp # {no | default} # maximum-paths [ecmp ] # - # @param [Integer] :maximum_paths Maximum number of equal cost paths. + # @param maximum_paths [Integer] Maximum number of equal cost paths. # - # @param [Integer] :maximum_ecmp_paths Maximum number of installed ECMP + # @param maximum_ecmp_paths [Integer] Maximum number of installed ECMP # routes. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the maximum paths using - # the default keyword + # @option opts default [Boolean] Configure the maximum paths using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_maximum_paths(maximum_paths, maximum_ecmp_paths, opts = {}) enable = opts.fetch(:enable, true) default = opts[:default] || false @@ -393,19 +391,21 @@ def set_maximum_paths(maximum_paths, maximum_ecmp_paths, opts = {}) ## # add_network creates a new instance of a BGP network on the node. # - # @commands + # commands # router bgp # network / # route-map # - # @param [String] :prefix The IPv4 prefix to configure as part of - # the network statement. The value must be a valid IPv4 prefix. - # @param [String] :masklen The IPv4 subnet mask length in bits. + # @param prefix [String] The IPv4 prefix to configure as part of + # the network statement. The value must be a valid IPv4 prefix. + # + # @param masklen [String] The IPv4 subnet mask length in bits. # The masklen must be in the valid range of 1 to 32. - # @param [String] :route_map The route-map name to apply to the + # + # @param route_map [String] The route-map name to apply to the # network statement when configured. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def add_network(prefix, masklen, route_map = nil) cmd = "network #{prefix}/#{masklen}" cmd << " route-map #{route_map}" if route_map @@ -415,18 +415,20 @@ def add_network(prefix, masklen, route_map = nil) ## # remove_network removes the instance of a BGP network on the node. # - # @commands + # commands # router bgp # {no} shutdown # - # @param [String] :prefix The IPv4 prefix to configure as part of + # @param prefix [String] The IPv4 prefix to configure as part of # the network statement. The value must be a valid IPv4 prefix. - # @param [String] :masklen The IPv4 subnet mask length in bits. + # + # @param masklen [String] The IPv4 subnet mask length in bits. # The masklen must be in the valid range of 1 to 32. - # @param [String] :route_map The route-map name to apply to the + # + # @param route_map [String] The route-map name to apply to the # network statement when configured. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def remove_network(prefix, masklen, route_map = nil) cmd = "no network #{prefix}/#{masklen}" cmd << " route-map #{route_map}" if route_map @@ -453,7 +455,7 @@ class BgpNeighbors < Entity # route_map_out: # } # - # @param [String] :name The name of the BGP neighbor to manage. + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # @@ -525,12 +527,13 @@ def getall # # @api private # - # @param [String] :config The switch config. - # @param [String] :name The name of the BGP neighbor to manage. + # @param config [String] The switch config. + # + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_peer_group(config, name) value = config.scan(/neighbor #{name} peer-group ([^\s]+)/) peer_group = value[0] ? value[0][0] : nil @@ -544,12 +547,13 @@ def parse_peer_group(config, name) # # @api private # - # @param [String] :config The switch config. - # @param [String] :name The name of the BGP neighbor to manage. + # @param config [String] The switch config. + # + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute def parse_remote_as(config, name) value = config.scan(/neighbor #{name} remote-as (\d+)/) remote_as = value[0] ? value[0][0] : nil @@ -563,12 +567,13 @@ def parse_remote_as(config, name) # # @api private # - # @param [String] :config The switch config. - # @param [String] :name The name of the BGP neighbor to manage. + # @param config [String] The switch config. + # + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_send_community(config, name) value = config.scan(/no neighbor #{name} send-community/) enabled = value[0] ? false : true @@ -582,13 +587,14 @@ def parse_send_community(config, name) # # @api private # - # @param [String] :config The switch config. - # @param [String] :name The name of the BGP neighbor to manage. + # @param config [String] The switch config. + # + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Hash] resource hash attribute. Returns - # true if shutdown, false otherwise. + # @return [Hash] Resource hash attribute. Returns + # true if shutdown, false otherwise. def parse_shutdown(config, name) value = config.scan(/no neighbor #{name} shutdown/) shutdown = value[0] ? false : true @@ -602,12 +608,14 @@ def parse_shutdown(config, name) # # @api private # - # @param [String] :config The switch config. - # @param [String] :name The name of the BGP neighbor to manage. + # @param config [String] The switch config. + # + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash + # attribute. def parse_description(config, name) value = config.scan(/neighbor #{name} description (.*)$/) description = value[0] ? value[0][0] : nil @@ -621,12 +629,13 @@ def parse_description(config, name) # # @api private # - # @param [String] :config The switch config. - # @param [String] :name The name of the BGP neighbor to manage. + # @param config [String] The switch config. + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash + # attribute. def parse_next_hop_self(config, name) value = config.scan(/no neighbor #{name} next-hop-self/) enabled = value[0] ? false : true @@ -640,12 +649,14 @@ def parse_next_hop_self(config, name) # # @api private # - # @param [String] :config The switch config. - # @param [String] :name The name of the BGP neighbor to manage. + # @param config [String] The switch config. + # + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash + # attribute. def parse_route_map_in(config, name) value = config.scan(/neighbor #{name} route-map ([^\s]+) in/) route_map_in = value[0] ? value[0][0] : nil @@ -659,12 +670,14 @@ def parse_route_map_in(config, name) # # @api private # - # @param [String] :config The switch config. - # @param [String] :name The name of the BGP neighbor to manage. + # @param config [String] The switch config. + # + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash + # attribute. def parse_route_map_out(config, name) value = config.scan(/neighbor #{name} route-map ([^\s]+) out/) route_map_out = value[0] ? value[0][0] : nil @@ -679,9 +692,9 @@ def parse_route_map_out(config, name) # # @api private # - # @param [String] :cmd Command to run under BGP mode + # @param cmd [String] Command to run under BGP mode. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def configure_bgp(cmd) config = get_block('^router bgp .*') fail 'BGP router is not configured' unless config @@ -695,11 +708,11 @@ def configure_bgp(cmd) # create will create a new instance of a BGP neighbor on the node. # The neighbor is created in the shutdown state and then enabled. # - # @param [String] :name The name of the BGP neighbor to manage. + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(name) set_shutdown(name, enable: false) end @@ -707,16 +720,16 @@ def create(name) ## # delete will delete the BGP neighbor from the node. # - # @commands + # commands # no neighbor # or # no neighbor peer-group # - # @param [String] :name The name of the BGP neighbor to manage. + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete(name) cmd = "no neighbor #{name}" response = configure_bgp(cmd) @@ -728,21 +741,23 @@ def delete(name) end ## - # neigh_command_builder for neighbors which calls command_builder + # neigh_command_builder for neighbors which calls command_builder. + # + # @param name [String] The name of the BGP neighbor to manage. # - # @param [String] :name The name of the BGP neighbor to manage. - # @param [String] :cmd The command portion of the neighbor command. - # @param [hash] :opts Optional keyword arguments + # @param cmd [String] The command portion of the neighbor command. # - # @option :opts [String] :value Value being set. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] Value being set. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the command using + # @option opts default [Boolean] Configure the command using # the default keyword. # - # @return [String] Returns built command string + # @return [String] Returns built command string. def neigh_command_builder(name, cmd, opts) command_builder("neighbor #{name} #{cmd}", opts) end @@ -750,22 +765,23 @@ def neigh_command_builder(name, cmd, opts) ## # set_peer_group creates a BGP static peer group name. # - # @commands + # commands # router bgp # {no | default} neighbor peer-group # - # @param [String] :name The IP address of the neighbor - # @param [hash] :opts Optional keyword arguments + # @param name [String] The IP address of the neighbor. + # + # @param opts [hash] Optional keyword arguments. # - # @option :opts [String] :value The group name. + # @option opts value [String] The group name. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the peer group using - # the default keyword + # @option opts default [Boolean] Configure the peer group using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_peer_group(name, opts = {}) configure_bgp(neigh_command_builder(name, 'peer-group', opts)) end @@ -774,22 +790,23 @@ def set_peer_group(name, opts = {}) # set_remote_as configures the expected AS number for a neighbor # (peer). # - # @commands + # commands # router bgp # {no | default} neighbor remote-as # - # @param [String] :name The IP address or name of the peer group. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The IP address or name of the peer group. # - # @option :opts [String] :value The remote as-id. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] The remote as-id. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the peer group using - # the default keyword + # @option opts default [Boolean] Configure the peer group using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_remote_as(name, opts = {}) configure_bgp(neigh_command_builder(name, 'remote-as', opts)) end @@ -798,23 +815,24 @@ def set_remote_as(name, opts = {}) # set_shutdown disables the specified neighbor. The value option is # not used by this method. # - # @commands + # commands # router bgp # {no | default} neighbor shutdown # - # @param [String] :name The IP address or name of the peer group. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The IP address or name of the peer group. # - # @option :opts [String] :enable True enables the specified neighbor. + # @param opts [hash] Optional keyword arguments. + # + # @option opts enable [String] True enables the specified neighbor. # False disables the specified neighbor. # - # @option :opts [Boolean] :default Configure the peer group using - # the default keyword + # @option opts default [Boolean] Configure the peer group using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_shutdown(name, opts = {}) fail 'set_shutdown has value option set' if opts[:value] - # Shutdown semantics are opposite of enable semantics so invert enable + # Shutdown semantics are opposite of enable semantics so invert enable. value = !opts[:enable] opts.merge!(enable: value) configure_bgp(neigh_command_builder(name, 'shutdown', opts)) @@ -825,20 +843,21 @@ def set_shutdown(name, opts = {}) # attributes to the specified BGP neighbor. The value option is # not used by this method. # - # @commands + # commands # router bgp # {no | default} neighbor send-community # - # @param [String] :name The IP address or name of the peer group. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The IP address or name of the peer group. + # + # @param opts [hash] Optional keyword arguments. # - # @option :opts [String] :enable True enables the feature. False + # @option opts enable [String] True enables the feature. False # disables the feature. # - # @option :opts [Boolean] :default Configure the peer group using - # the default keyword + # @option opts default [Boolean] Configure the peer group using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_send_community(name, opts = {}) fail 'send_community has the value option set' if opts[:value] configure_bgp(neigh_command_builder(name, 'send-community', opts)) @@ -850,20 +869,21 @@ def set_send_community(name, opts = {}) # BGP-speaking neighbor or neighbors in the specified peer group. # The value option is not used by this method. # - # @commands + # commands # router bgp # {no | default} neighbor next-hop-self # - # @param [String] :name The IP address or name of the peer group. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The IP address or name of the peer group. + # + # @param opts [hash] Optional keyword arguments. # - # @option :opts [String] :enable True enables the feature. False + # @option opts enable [String] True enables the feature. False # disables the feature. # - # @option :opts [Boolean] :default Configure the peer group using - # the default keyword + # @option opts default [Boolean] Configure the peer group using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_next_hop_self(name, opts = {}) fail 'set_next_hop_self has the value option set' if opts[:value] configure_bgp(neigh_command_builder(name, 'next-hop-self', opts)) @@ -873,22 +893,23 @@ def set_next_hop_self(name, opts = {}) # set_route_map_in command applies a route map to inbound BGP # routes. # - # @commands + # commands # router bgp # {no | default} neighbor route-map in # - # @param [String] :name The IP address or name of the peer group. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The IP address or name of the peer group. # - # @option :opts [String] :value Name of a route map. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] Name of a route map. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the peer group using - # the default keyword + # @option opts default [Boolean] Configure the peer group using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_route_map_in(name, opts = {}) cmd = neigh_command_builder(name, 'route-map', opts) + ' in' configure_bgp(cmd) @@ -898,22 +919,23 @@ def set_route_map_in(name, opts = {}) # set_route_map_out command applies a route map to outbound BGP # routes. # - # @commands + # commands # router bgp # {no | default} neighbor route-map out # - # @param [String] :name The IP address or name of the peer group. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The IP address or name of the peer group. # - # @option :opts [String] :value Name of a route map. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] Name of a route map. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the peer group using - # the default keyword + # @option opts default [Boolean] Configure the peer group using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_route_map_out(name, opts = {}) cmd = neigh_command_builder(name, 'route-map', opts) + ' out' configure_bgp(cmd) @@ -923,22 +945,23 @@ def set_route_map_out(name, opts = {}) # set_description associates descriptive text with the specified # peer or peer group. # - # @commands + # commands # router bgp # {no | default} neighbor description # - # @param [String] :name The IP address or name of the peer group. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The IP address or name of the peer group. # - # @option :opts [String] :value The description string. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] The description string. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the peer group using - # the default keyword + # @option opts default [Boolean] Configure the peer group using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_description(name, opts = {}) configure_bgp(neigh_command_builder(name, 'description', opts)) end diff --git a/lib/rbeapi/api/dns.rb b/lib/rbeapi/api/dns.rb index f3777cb..2072ccf 100644 --- a/lib/rbeapi/api/dns.rb +++ b/lib/rbeapi/api/dns.rb @@ -32,16 +32,16 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Dns class manages DNS settings on an EOS node. class Dns < Entity ## - # get returns the DNS resource + # get returns the DNS resource. # # @example # { @@ -50,7 +50,7 @@ class Dns < Entity # "domain_list": array # } # - # @return [Hash] A Ruby hash object that provides the SNMP settings as + # @return [Hash] A Ruby hash object that provides the SNMP settings as # key / value pairs. def get response = {} @@ -61,11 +61,11 @@ def get end ## - # parse_domain_name parses the domain-name from config + # parse_domain_name parses the domain-name from config. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_domain_name mdata = /ip domain-name ([\w.]+)/.match(config) { domain_name: mdata.nil? ? '' : mdata[1] } @@ -74,11 +74,11 @@ def parse_domain_name ## # parse_name_servers parses the name-server values from - # config + # config. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_name_servers servers = config.scan(/(?:ip name-server vrf )(?:\w+)\s(.+)/) values = servers.each_with_object([]) { |srv, arry| arry << srv.first } @@ -87,11 +87,11 @@ def parse_name_servers private :parse_name_servers ## - # parse_domain_list parses the domain-list from config + # parse_domain_list parses the domain-list from config. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_domain_list search = config.scan(/(?<=^ip\sdomain-list\s).+$/) { domain_list: search } @@ -99,15 +99,18 @@ def parse_domain_list private :parse_domain_list ## - # Configure the domain-name value in the running-config + # Configure the domain-name value in the running-config. # - # @param [Hash] opts The configuration parameters - # @option opts [string] :value The value to set the domain-name to - # @option :opts [Boolean] :enable If false then the command is + # @param opts [Hash] The configuration parameters. + # + # @option opts value [string] The value to set the domain-name to. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default # - # @return [Boolean] returns true if the command completed successfully + # @option opts default [Boolean] The value should be set to default. + # + # @return [Boolean] Returns true if the command completed successfully. def set_domain_name(opts = {}) cmds = command_builder('ip domain-name', opts) configure(cmds) @@ -118,26 +121,29 @@ def set_domain_name(opts = {}) # to resolve dns queries. If the enable option is false, then the # name-server list will be configured using the no keyword. If the # default option is specified, then the name server list will be - # configured using the default keyword. If both options are provided the - # keyword option will take precedence + # configured using the default keyword. If both options are provided the + # keyword option will take precedence. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # ip name-server # no ip name-server # default ip name-server # - # @param [Hash] opts The configuration parameters - # @option opts [string] :value The set of name servers to configure on the - # node. The list of name servers will be replace in the nodes running - # configuration by the list provided in value - # @option :opts [Boolean] :enable If false then the command is + # @param [Hash] opts The configuration parameters. + # + # @option opts value [string] The set of name servers to configure on the + # node. The list of name servers will be replace in the nodes running + # configuration by the list provided in value. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option [Boolean] :default Configures the ip name-servers using the + # + # @option default [Boolean] Configures the ip name-servers using the # default keyword argument. Default takes precedence over enable. # - # @return [Boolean] returns true if the commands completed successfully + # @return [Boolean] Returns true if the commands completed successfully. def set_name_servers(opts = {}) value = opts[:value] enable = opts.fetch(:enable, true) @@ -160,9 +166,9 @@ def set_name_servers(opts = {}) ## # add_name_server adds an ip name-server. # - # @param [String] :server The name of the ip name-server to create + # @param server [String] The name of the ip name-server to create. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_name_server(server) configure "ip name-server #{server}" end @@ -170,36 +176,36 @@ def add_name_server(server) ## # remove_name_server removes the specified ip name-server. # - # @param [String] :server The name of the ip name-server to remove + # @param server [String] The name of the ip name-server to remove. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def remove_name_server(server) configure "no ip name-server #{server}" end ## # set_domain_list configures the set of domain names to search when - # making dns queries for the FQDN. If the enable option is set to false, + # making dns queries for the FQDN. If the enable option is set to false, # then the domain-list will be configured using the no keyword. If the # default option is specified, then the domain list will be configured - # using the default keyword. If both options are provided the default + # using the default keyword. If both options are provided the default # keyword option will take precedence. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # ip domain-list # no ip domain-list # default ip domain-list # - # @option [Array] :value The set of domain names to configure on the - # node. The list of domain names will be replace in the nodes running - # configuration by the list provided in value + # @option value [Array] The set of domain names to configure on the + # node. The list of domain names will be replace in the nodes running + # configuration by the list provided in value. # - # @option [Boolean] :default Configures the ip domain-list using the - # default keyword argument + # @option default [Boolean] Configures the ip domain-list using the + # default keyword argument. # - # @return [Boolean] returns true if the commands completed successfully + # @return [Boolean] Returns true if the commands completed successfully. def set_domain_list(opts = {}) value = opts[:value] enable = opts.fetch(:enable, true) @@ -227,9 +233,9 @@ def set_domain_list(opts = {}) ## # add_domain_list adds an ip domain-list. # - # @param [String] :name The name of the ip domain-list to add + # @param name [String] The name of the ip domain-list to add. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_domain_list(name) configure "ip domain-list #{name}" end @@ -237,9 +243,9 @@ def add_domain_list(name) ## # remove_domain_list removes a specified ip domain-list. # - # @param [String] :name The name of the ip domain-list to remove + # @param name [String] The name of the ip domain-list to remove. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def remove_domain_list(name) configure "no ip domain-list #{name}" end diff --git a/lib/rbeapi/api/interfaces.rb b/lib/rbeapi/api/interfaces.rb index f2e2de3..9efc667 100644 --- a/lib/rbeapi/api/interfaces.rb +++ b/lib/rbeapi/api/interfaces.rb @@ -33,10 +33,10 @@ require 'rbeapi/utils' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Interfaces class manages all physical and logical interfaces on an @@ -48,7 +48,7 @@ def initialize(node) end ## - # get returns a hash of interface configurations for the given name + # get returns a hash of interface configurations for the given name. # # @example # { @@ -58,18 +58,18 @@ def initialize(node) # shutdown: # } # - # @param [String] :name The interface name to return a resource for from - # the nodes configuration + # @param name [String] The interface name to return a resource for from + # the nodes configuration. # # @return [nil, Hash] Returns the interface resource as a # Hash. If the specified name is not found in the nodes current - # configuration a nil object is returned + # configuration a nil object is returned. def get(name) get_instance(name).get(name) end ## - # getall returns a hash of interface configurations + # getall returns a hash of interface configurations. # # @example # { @@ -91,8 +91,8 @@ def get(name) # } # # @return [Hash] Returns the interface resources as a - # Hash. If none exist in the nodes current - # configuration an empty hash is returned + # Hash. If none exist in the nodes current configuration an empty + # hash is returned. def getall interfaces = config.scan(/(?<=^interface\s).+$/) @@ -103,12 +103,11 @@ def getall end ## - # get_instance returns an interface instance for the given name + # get_instance returns an interface instance for the given name. # - # @param [String] :name The interface name to return an instance for + # @param name [String] The interface name to return an instance for. # - # @return [Object] Returns the interface instance as an - # Object. + # @return [Object] Returns the interface instance as an Object. def get_instance(name) name = name[0, 2].upcase case name @@ -148,9 +147,9 @@ class BaseInterface < Entity ## # get returns the specified interface resource hash that represents the - # node's current interface configuration. The BaseInterface class + # node's current interface configuration. The BaseInterface class # provides all the set of attributes that are common to all interfaces - # in EOS. This method will return an interface type of generic + # in EOS. This method will return an interface type of generic. # # @example # { @@ -160,12 +159,12 @@ class BaseInterface < Entity # shutdown: [true, false] # } # - # @param [String] :name The name of the interface to return from the - # running-configuration + # @param name [String] The name of the interface to return from the + # running-configuration. # # @return [nil, Hash] Returns a hash of the interface # properties if the interface name was found in the running - # configuration. If the interface was not found, nil is returned + # configuration. If the interface was not found, nil is returned. def get(name) config = get_block("^interface #{name}") return nil unless config @@ -185,7 +184,10 @@ def get(name) # # @api private # - # @return [Hash] resource hash attribute + # @param config [String] The configuration block retrieved from the + # nodes current running configuration. + # + # @return [Hash] Returns the resource hash attribute. def parse_description(config) mdata = /^\s{3}description\s(.+)$/.match(config) { description: mdata.nil? ? DEFAULT_INTF_DESCRIPTION : mdata[1] } @@ -201,7 +203,10 @@ def parse_description(config) # # @api private # - # @return [Hash] resource hash attribute + # @param config [String] The configuration block retrieved from the + # nodes current running configuration. + # + # @return [Hash] Returns the resource hash attribute. def parse_shutdown(config) value = /no shutdown/ =~ config { shutdown: value.nil? } @@ -210,80 +215,80 @@ def parse_shutdown(config) ## # create will create a new interface resource in the node's current - # configuration with the specified interface name. If the create + # configuration with the specified interface name. If the create # method is called and the interface already exists, this method will - # return successful + # return successful. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :value The interface name to create on the node. The + # @param value [String] The interface name to create on the node. The # interface name must be the full interface identifier (ie Loopback, - # not Lo) + # not Lo). # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(value) configure("interface #{value}") end ## # delete will delete an existing interface resource in the node's - # current configuration with the specified interface name. If the + # current configuration with the specified interface name. If the # delete method is called and interface does not exist, this method - # will return successful + # will return successful. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :value The interface name to delete from the node. + # @param value [String] The interface name to delete from the node. # The interface name must be the full interface identifier - # (ie Loopback, no Lo) + # (ie Loopback, no Lo). # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete(value) configure("no interface #{value}") end ## - # default will configure the interface using the default keyword. For + # default will configure the interface using the default keyword. For # virtual interfaces this is equivalent to deleting the interface. For # physical interfaces, the entire interface configuration will be set # to defaults. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :value The interface name to default in the node. The + # @param value [String] The interface name to default in the node. The # interface name must be the full interface identifier (ie Loopback, - # not Lo) + # not Lo). # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def default(value) configure("default interface #{value}") end ## # set_description configures the description value for the specified - # interface name in the nodes running configuration. If the enable + # interface name in the nodes running configuration. If the enable # keyword is false then the description value is negated using the no - # keyword. If the default keyword is set to true, then the description - # value is defaulted using the default keyword. The default keyword takes + # keyword. If the default keyword is set to true, then the description + # value is defaulted using the default keyword. The default keyword takes # precedence over the enable keyword if both are provided. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # to. The name value must be the full interface identifier + # @param name [String] The interface name to apply the configuration + # to. The name value must be the full interface identifier. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the description + # @option opts value [String] The value to configure the description # to in the node's configuration. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the interface description - # using the default keyword + # @option opts default [Boolean] Configure the interface description + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_description(name, opts = {}) commands = command_builder('description', opts) configure_interface(name, commands) @@ -291,31 +296,31 @@ def set_description(name, opts = {}) ## # set_shutdown configures the administrative state of the specified - # interface in the node. If the enable keyword is false, then the - # interface is administratively disabled. If the enable keyword is - # true, then the interface is administratively enabled. If the default + # interface in the node. If the enable keyword is false, then the + # interface is administratively disabled. If the enable keyword is + # true, then the interface is administratively enabled. If the default # keyword is set to true, then the interface shutdown value is configured - # using the default keyword. The default keyword takes precedence + # using the default keyword. The default keyword takes precedence # over the enable keyword if both are provided. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # to. The name value must be the full interface identifier + # @param name [String] The interface name to apply the configuration + # to. The name value must be the full interface identifier. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable True if the interface should be + # @option opts enable [Boolean] True if the interface should be # administratively enabled or false if the interface should be # administratively disabled. # - # @option :opts [Boolean] :default Configure the interface shutdown - # using the default keyword + # @option opts default [Boolean] Configure the interface shutdown + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_shutdown(name, opts = {}) fail 'set_shutdown has the value option set' if opts[:value] - # Shutdown semantics are opposite of enable semantics so invert enable + # Shutdown semantics are opposite of enable semantics so invert enable. value = !opts[:enable] opts.merge!(enable: value) commands = command_builder('shutdown', opts) @@ -349,12 +354,12 @@ class EthernetInterface < BaseInterface # flowcontrol_receive: # } # - # @param [String] :name The interface name to return a resource hash - # for from the node's running configuration + # @param name [String] The interface name to return a resource hash + # for from the node's running configuration. # # @return [nil, Hash] Returns the interface resource as - # a hash. If the specified interface name is not found in the node's - # configuration a nil object is returned + # a hash. If the specified interface name is not found in the node's + # configuration a nil object is returned. def get(name) config = get_block("^interface #{name}") return nil unless config @@ -372,12 +377,14 @@ def get(name) ## # parse_speed scans the provided configuration block and parses the speed # value. If the speed value is not found in the interface configuration - # block provided, DEFAULT_SPEED and DEFAULT_FORCED are used. The - # returned hash is intended to be merged into the interface resource hash + # block provided, DEFAULT_SPEED and DEFAULT_FORCED are used. The + # returned hash is intended to be merged into the interface resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @param config [String] The configuration block to parse. + # + # @return [Hash] Returns the resource hash attribute. def parse_speed(config) value = config.scan(/speed (forced)?[ ]?(\w+)/).first return { speed: DEFAULT_SPEED, forced: DEFAULT_FORCED } unless value @@ -388,13 +395,15 @@ def parse_speed(config) ## # parse_sflow scans the provided configuration block and parse the - # sflow value. The sflow values true if sflow is enabled on the - # interface or returns false if it is not enabled. The hash returned + # sflow value. The sflow values true if sflow is enabled on the + # interface or returns false if it is not enabled. The hash returned # is intended to be merged into the interface hash. # # @api private # - # @return [Hash] resource hash attribute + # @param config [String] The configuration block to parse. + # + # @return [Hash] Returns the resource hash attribute. def parse_sflow(config) value = /no sflow enable/ =~ config { sflow: value.nil? } @@ -403,14 +412,16 @@ def parse_sflow(config) ## # parse_flowcontrol_send scans the provided configuration block and - # parses the flowcontrol send value. If the interface flowcontrol value + # parses the flowcontrol send value. If the interface flowcontrol value # is not configured, then this method will return the value of - # DEFAULT_ETH_FLOWC_TX. The hash returned is intended to be merged into + # DEFAULT_ETH_FLOWC_TX. The hash returned is intended to be merged into # the interface resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @param config [String] The configuration block to parse. + # + # @return [Hash] Returns the resource hash attribute. def parse_flowcontrol_send(config) mdata = /flowcontrol send (\w+)$/.match(config) { flowcontrol_send: mdata.nil? ? DEFAULT_ETH_FLOWC_TX : mdata[1] } @@ -419,14 +430,16 @@ def parse_flowcontrol_send(config) ## # parse_flowcontrol_receive scans the provided configuration block and - # parse the flowcontrol receive value. If the interface flowcontrol + # parse the flowcontrol receive value. If the interface flowcontrol # value is not configured, then this method will return the value of - # DEFAULT_ETH_FLOWC_RX. The hash returned is intended to be merged into + # DEFAULT_ETH_FLOWC_RX. The hash returned is intended to be merged into # the interface resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @param config [String] The configuration block to parse. + # + # @return [Hash] Returns the resource hash attribute. def parse_flowcontrol_receive(config) mdata = /flowcontrol receive (\w+)$/.match(config) { flowcontrol_receive: mdata.nil? ? DEFAULT_ETH_FLOWC_RX : mdata[1] } @@ -437,10 +450,10 @@ def parse_flowcontrol_receive(config) # create overrides the create method from the BaseInterface and raises # an exception because Ethernet interface creation is not supported. # - # @param [String] :name The name of the interface + # @param _name [String] The name of the interface. # # @raise [NotImplementedError] Creation of physical Ethernet interfaces - # is not supported + # is not supported. def create(_name) fail NotImplementedError, 'creating Ethernet interfaces is '\ 'not supported' @@ -451,10 +464,10 @@ def create(_name) # raises an exception because Ethernet interface deletion is not # supported. # - # @param [String] :name The name of the interface + # @param _name [String] The name of the interface. # # @raise [NotImplementedError] Deletion of physical Ethernet interfaces - # is not supported + # is not supported. def delete(_name) fail NotImplementedError, 'deleting Ethernet interfaces is '\ 'not supported' @@ -462,32 +475,32 @@ def delete(_name) ## # set_speed configures the interface speed and negotiation values on the - # specified interface. If the enable option is false the speed - # setting is configured using the no keyword. If the default options is + # specified interface. If the enable option is false the speed + # setting is configured using the no keyword. If the default options is # set to true, then the speed setting is configured using the default - # keyword. If both options are specified, the default keyword takes + # keyword. If both options are specified, the default keyword takes # precedence. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # values to. The name must be the full interface identifier. + # @param name [String] The interface name to apply the configuration + # values to. The name must be the full interface identifier. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option [String] :value The value to configure the speed setting to in - # the nodes running configuration + # @option opts value [String] The value to configure the speed setting to + # in the nodes running configuration. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option [Boolean] :forced Specifies if auto negotiation should be - # enabled (true) or disabled (false) + # @option opts forced [Boolean] Specifies if auto negotiation should be + # enabled (true) or disabled (false). # - # @option :opts [Boolean] :default Configures the sflow value on the - # interface using the default keyword + # @option opts default [Boolean] Configures the sflow value on the + # interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_speed(name, opts = {}) value = opts[:value] forced = opts.fetch(:forced, false) @@ -509,26 +522,26 @@ def set_speed(name, opts = {}) ## # set_sflow configures the administrative state of sflow on the - # interface. Setting the enable keyword to true enables sflow on the + # interface. Setting the enable keyword to true enables sflow on the # interface and setting enable to false disables sflow on the interface. # If the default keyword is set to true, then the sflow value is - # defaulted using the default keyword. The default keyword takes + # defaulted using the default keyword. The default keyword takes # precedence over the enable keyword # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # values to. The name must be the full interface identifier. + # @param name [String] The interface name to apply the configuration + # values to. The name must be the full interface identifier. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable Enables sflow if the value is true or + # @option opts enable [Boolean] Enables sflow if the value is true or # disables sflow on the interface if false. Default is true. # - # @option :opts [Boolean] :default Configures the sflow value on the - # interface using the default keyword + # @option opts default [Boolean] Configures the sflow value on the + # interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_sflow(name, opts = {}) commands = command_builder('sflow enable', opts) configure_interface(name, commands) @@ -537,31 +550,31 @@ def set_sflow(name, opts = {}) ## # set_flowcontrol configures the flowcontrol value either on or off for # the for the specified interface in the specified direction (either send - # or receive). If the enable keyword is false then the configuration is - # negated using the no keyword. If the default keyword is set to true, - # then the state value is defaulted using the default keyword. The + # or receive). If the enable keyword is false then the configuration is + # negated using the no keyword. If the default keyword is set to true, + # then the state value is defaulted using the default keyword. The # default keyword takes precedence over the enable keyword # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # values to. The name must be the full interface identifier. + # @param name [String] The interface name to apply the configuration + # values to. The name must be the full interface identifier. # - # @param [String] :direction Specifies the flowcontrol direction to - # configure. Valid values include send and receive. + # @param direction [String] Specifies the flowcontrol direction to + # configure. Valid values include send and receive. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value Specifies the value to configure the - # flowcontrol setting for. Valid values include on or off + # @option opts value [String] Specifies the value to configure the + # flowcontrol setting for. Valid values include on or off. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configures the flowcontrol value on - # the interface using the default keyword + # @option opts default [Boolean] Configures the flowcontrol value on + # the interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_flowcontrol(name, direction, opts = {}) commands = command_builder("flowcontrol #{direction}", opts) configure_interface(name, commands) @@ -573,50 +586,50 @@ def set_flowcontrol(name, direction, opts = {}) # # @see set_flowcontrol # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # values to. The name must be the full interface identifier. + # @param name [String] The interface name to apply the configuration + # values to. The name must be the full interface identifier. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value Specifies the value to configure the - # flowcontrol setting for. Valid values include on or off + # @option opts value [String] Specifies the value to configure the + # flowcontrol setting for. Valid values include on or off. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configures the flowcontrol value on - # the interface using the default keyword + # @option opts default [Boolean] Configures the flowcontrol value on + # the interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_flowcontrol_send(name, opts = {}) set_flowcontrol(name, 'send', opts) end ## - # set_flowcontrol_receive is a convenience function for configuring th e - # value of interface flowcontrol + # set_flowcontrol_receive is a convenience function for configuring the + # value of interface flowcontrol. # # @see set_flowcontrol # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # values to. The name must be the full interface identifier. + # @param name [String] The interface name to apply the configuration + # values to. The name must be the full interface identifier. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value Specifies the value to configure the - # flowcontrol setting for. Valid values include on or off + # @option opts value [String] Specifies the value to configure the + # flowcontrol setting for. Valid values include on or off. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configures the flowcontrol value on - # the interface using the default keyword + # @option opts default [Boolean] Configures the flowcontrol value on + # the interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_flowcontrol_receive(name, opts = {}) set_flowcontrol(name, 'receive', opts) end @@ -632,7 +645,7 @@ class PortchannelInterface < BaseInterface ## # get returns the specified port-channel interface configuration from - # the nodes running configuration as a resource hash. The resource + # the nodes running configuration as a resource hash. The resource # hash returned extends the BaseInterface resource hash, sets the type # value to portchannel and adds the portchannel specific attributes # @@ -650,13 +663,13 @@ class PortchannelInterface < BaseInterface # # @see BaseInterface Interface get example # - # @param [String] :name The name of the portchannel interface to return - # a resource hash for. The name must be the full interface name of + # @param name [String] The name of the portchannel interface to return + # a resource hash for. The name must be the full interface name of # the desired interface. # - # @return [nil, Hash] returns the interface resource as - # a hash object. If the specified interface does not exist in the - # running configuration, a nil object is returned + # @return [nil, Hash] Returns the interface resource as + # a hash object. If the specified interface does not exist in the + # running configuration, a nil object is returned. def get(name) config = get_block("^interface #{name}") return nil unless config @@ -672,17 +685,17 @@ def get(name) ## # parse_members scans the nodes running config and returns all of the - # Ethernet members for the port-channel interface specified. If the + # Ethernet members for the port-channel interface specified. If the # port-channel interface has no members configured, then this method will - # assign an empty array as the value for members. The hash returned is - # intended to be merged into the interface resource hash + # assign an empty array as the value for members. The hash returned is + # intended to be merged into the interface resource hash. # # @api private # - # @param [String] :name The name of the portchannel interface to extract - # the members for + # @param name [String] The name of the portchannel interface to extract + # the members for. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_members(name) grpid = name.scan(/(?<=Port-Channel)\d+/)[0] command = "show port-channel #{grpid} all-ports" @@ -694,17 +707,17 @@ def parse_members(name) ## # parse_lacp_mode scans the member interfaces and returns the configured - # lacp mode. The lacp mode value must be common across every member - # in the port channel interface. If no members are configured, the value - # for lacp_mode will be set using DEFAULT_LACP_MODE. The hash returned is + # lacp mode. The lacp mode value must be common across every member + # in the port channel interface. If no members are configured, the value + # for lacp_mode will be set using DEFAULT_LACP_MODE. The hash returned is # intended to be merged into the interface resource hash # # @api private # - # @param [String] :name The name of the portchannel interface to extract - # the members from in order to get the configured lacp_mode + # @param name [String] The name of the portchannel interface to extract + # the members from in order to get the configured lacp_mode. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_lacp_mode(name) members = parse_members(name)[:members] return { lacp_mode: DEFAULT_LACP_MODE } unless members @@ -716,17 +729,17 @@ def parse_lacp_mode(name) ## # parse_minimum_links scans the port-channel configuration and returns - # the value for port-channel minimum-links. If the value is not found + # the value for port-channel minimum-links. If the value is not found # in the interface configuration, then DEFAULT_MIN_LINKS value is used. # The hash returned is intended to be merged into the interface - # resource hash + # resource hash. # # @api private # - # @param [String] :config The interface configuration block to extract - # the minimum links value from + # @param config [String] The interface configuration block to extract + # the minimum links value from. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_minimum_links(config) mdata = /port-channel min-links (\d+)$/.match(config) { minimum_links: mdata ? mdata[1] : DEFAULT_MIN_LINKS } @@ -735,17 +748,17 @@ def parse_minimum_links(config) ## # parse_lacp_fallback scans the interface config block and returns the - # configured value of the lacp fallback attribute. If the value is not + # configured value of the lacp fallback attribute. If the value is not # configured, then the method will return the value of - # DEFAULT_LACP_FALLBACK. The hash returned is intended to be merged into - # the interface resource hash + # DEFAULT_LACP_FALLBACK. The hash returned is intended to be merged into + # the interface resource hash. # # @api private # - # @param [String] :config The interface configuration block to extract - # the lacp fallback value from + # @param config [String] The interface configuration block to extract + # the lacp fallback value from. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_lacp_fallback(config) mdata = /lacp fallback (static|individual)/.match(config) { lacp_fallback: mdata ? mdata[1] : DEFAULT_LACP_FALLBACK } @@ -754,16 +767,16 @@ def parse_lacp_fallback(config) ## # parse_lacp_timeout scans the interface config block and returns the - # value of the lacp fallback timeout value. The value is expected to be - # found in the interface configuration block. The hash returned is - # intended to be merged into the interface resource hash + # value of the lacp fallback timeout value. The value is expected to be + # found in the interface configuration block. The hash returned is + # intended to be merged into the interface resource hash. # # @api private # - # @param [String] :config The interface configuration block to extract - # the lacp timeout value from + # @param config [String] The interface configuration block to extract + # the lacp timeout value from. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_lacp_timeout(config) mdata = /lacp fallback timeout (\d+)$/.match(config) { lacp_timeout: mdata[1] } @@ -772,31 +785,31 @@ def parse_lacp_timeout(config) ## # set_minimum_links configures the minimum physical links up required to - # consider the logical portchannel interface operationally up. If the + # consider the logical portchannel interface operationally up. If the # enable keyword is false then the minimum-links is configured using the - # no keyword argument. If the default keyword argument is provided and + # no keyword argument. If the default keyword argument is provided and # set to true, the minimum-links value is defaulted using the default - # keyword. The default keyword takes precedence over the enable keyword + # keyword. The default keyword takes precedence over the enable keyword # argument if both are provided. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration + # @param name [String] The interface name to apply the configuration # values to. The name must be the full interface identifier. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String, Integer] :value Specifies the value to - # configure the minimum-links to in the configuration. Valid values + # @option opts value [String, Integer] Specifies the value to + # configure the minimum-links to in the configuration. Valid values # are in the range of 1 to 16. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configures the minimum links value on - # the interface using the default keyword + # @option opts default [Boolean] Configures the minimum links value on + # the interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_minimum_links(name, opts = {}) commands = command_builder('port-channel min-links', opts) configure_interface(name, commands) @@ -804,22 +817,23 @@ def set_minimum_links(name, opts = {}) ## # set_members configures the set of physical interfaces that comprise the - # logical port-channel interface. The members value passed should be an + # logical port-channel interface. The members value passed should be an # array of physical interface names that comprise the port-channel - # interface. This method will add and remove individual members as - # required to sync the provided members array + # interface. This method will add and remove individual members as + # required to sync the provided members array. + # + # @see add_member Adds member links to the port-channel interface. # - # @see add_member Adds member links to the port-channel interface - # @see remove_member Removes member links from the port-channel interface + # @see remove_member Removes member links from the port-channel interface. # - # @param [String] :name The name of the port-channel interface to apply - # the members to. If the port-channel interface does not already exist - # it will be created + # @param name [String] The name of the port-channel interface to apply + # the members to. If the port-channel interface does not already exist + # it will be created. # - # @param [Array] :members The array of physical interface members to add + # @param members [Array] The array of physical interface members to add # to the port-channel logical interface. # - # @param [str] :mode The LACP mode to configure the member interfaces to. + # @param mode [str] The LACP mode to configure the member interfaces to. # Valid values are 'on, 'passive', 'active'. When there are # existing channel-group members and their lacp mode differs # from this attribute, all of those members will be removed and @@ -827,7 +841,7 @@ def set_minimum_links(name, opts = {}) # is omitted, the existing lacp mode will be used for new # member additions. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_members(name, members, mode = nil) current_members = Set.new parse_members(name)[:members] members = Set.new members @@ -841,13 +855,13 @@ def set_members(name, members, mode = nil) cmds = [] grpid = /(\d+)/.match(name)[0] - # remove members from the current port-channel interface + # remove members from the current port-channel interface. current_members.difference(members).each do |intf| cmds << "interface #{intf}" cmds << "no channel-group #{grpid}" end - # add new member interfaces to the port-channel + # add new member interfaces to the port-channel. members.difference(current_members).each do |intf| cmds << "interface #{intf}" cmds << "channel-group #{grpid} mode #{lacp_mode}" @@ -858,18 +872,18 @@ def set_members(name, members, mode = nil) ## # add_member adds the interface specified in member to the port-channel - # interface specified by name in the nodes running-configuration. If + # interface specified by name in the nodes running-configuration. If # the port-channel interface does not already exist, it will be created. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The name of the port-channel interface to apply + # @param name [String] The name of the port-channel interface to apply # the configuration to. # - # @param [String] :member The name of the physical Ethernet interface to + # @param member [String] The name of the physical Ethernet interface to # add to the logical port-channel interface. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_member(name, member) lacp = parse_lacp_mode(name)[:lacp_mode] grpid = /(\d+)/.match(name)[0] @@ -881,15 +895,15 @@ def add_member(name, member) # port-channel interface specified by name in the nodes # running-configuration. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The name of the port-channel interface to apply + # @param name [String] The name of the port-channel interface to apply # the configuration to. # - # @param [String] :member The name of the physical Ethernet interface to + # @param member [String] The name of the physical Ethernet interface to # remove from the logical port-channel interface. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def remove_member(name, member) grpid = /(\d+)/.match(name)[0] configure_interface(member, "no channel-group #{grpid}") @@ -897,20 +911,20 @@ def remove_member(name, member) ## # set_lacp_mode configures the lacp mode on the port-channel interface - # by configuring the lacp mode value for each member interface. This + # by configuring the lacp mode value for each member interface. This # method will find all member interfaces for a port-channel and # reconfigure them using the mode argument. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # values to. The name must be the full interface identifier. + # @param name [String] The interface name to apply the configuration + # values to. The name must be the full interface identifier. # - # @param [String] :mode The lacp mode to configure on the member - # interfaces for the port-channel. Valid values include active, - # passive or on + # @param mode [String] The lacp mode to configure on the member + # interfaces for the port-channel. Valid values include active, + # passive or on. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_lacp_mode(name, mode) return false unless %w(on passive active).include?(mode) grpid = /(\d+)/.match(name)[0] @@ -930,29 +944,29 @@ def set_lacp_mode(name, mode) ## # set_lacp_fallback configures the lacp fallback mode for the # port-channel interface. If the enable keyword is false, lacp fallback - # is configured using the no keyword argument. If the default option is + # is configured using the no keyword argument. If the default option is # specified and set to true, the lacp fallback value is configured using - # the default keyword. The default keyword takes precedence over the + # the default keyword. The default keyword takes precedence over the # enable keyword if both options are provided. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # values to. The name must be the full interface identifier. + # @param name [String] The interface name to apply the configuration + # values to. The name must be the full interface identifier. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value Specifies the value to configure for - # the port-channel lacp fallback. Valid values are individual and - # static + # @option opts value [String] Specifies the value to configure for + # the port-channel lacp fallback. Valid values are individual and + # static. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configures the lacp fallback value on - # the interface using the default keyword + # @option opts default [Boolean] Configures the lacp fallback value on + # the interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_lacp_fallback(name, opts = {}) commands = command_builder('port-channel lacp fallback', opts) configure_interface(name, commands) @@ -960,29 +974,29 @@ def set_lacp_fallback(name, opts = {}) ## # set_lacp_timeout configures the lacp fallback timeout for the - # port-channel interface. If the enable keyword is false, lacp fallback - # timeout is configured using the no keyword argument. If the default + # port-channel interface. If the enable keyword is false, lacp fallback + # timeout is configured using the no keyword argument. If the default # option is specified and set to true, the lacp fallback timeout value is - # configured using the default keyword. The default keyword takes + # configured using the default keyword. The default keyword takes # precedence over the enable keyword if both options are provided. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # values to. The name must be the full interface identifier. + # @param name [String] The interface name to apply the configuration + # values to. The name must be the full interface identifier. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value Specifies the value to configure for + # @option opts value [String] Specifies the value to configure for # the port-channel lacp fallback timeout. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configures the lacp fallback timeout - # value on the interface using the default keyword + # @option opts default [Boolean] Configures the lacp fallback timeout + # value on the interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_lacp_timeout(name, opts = {}) commands = command_builder('port-channel lacp fallback timeout', opts) configure_interface(name, commands) @@ -999,7 +1013,7 @@ class VxlanInterface < BaseInterface # Returns the Vxlan interface configuration as a Ruby hash of key/value # pairs from the nodes running configuration. This method extends the # BaseInterface get method and adds the Vxlan specific attributes to - # the hash + # the hash. # # @example # { @@ -1014,12 +1028,12 @@ class VxlanInterface < BaseInterface # vlans: # } # - # @param [String] :name The interface name to return from the nodes - # configuration. This optional parameter defaults to Vxlan1 + # @param name [String] The interface name to return from the nodes + # configuration. This optional parameter defaults to Vxlan1. # # @return [nil, Hash] Returns the interface configuration - # as a Ruby hash object. If the provided interface name is not found - # then this method will return nil + # as a Ruby hash object. If the provided interface name is not found + # then this method will return nil. def get(name = 'Vxlan1') config = get_block("interface #{name}") return nil unless config @@ -1036,14 +1050,14 @@ def get(name = 'Vxlan1') ## # parse_source_interface scans the interface config block and returns the - # value of the vxlan source-interface. If the source-interface is not - # configured then the value of DEFAULT_SRC_INTF is used. The hash + # value of the vxlan source-interface. If the source-interface is not + # configured then the value of DEFAULT_SRC_INTF is used. The hash # returned is intended to be merged into the interface resource hash # # @api private # - # @param [String] :config The interface configuration block to extract - # the vxlan source-interface value from + # @param config [String] The interface configuration block to extract + # the vxlan source-interface value from. # # @return [Hash] def parse_source_interface(config) @@ -1054,14 +1068,14 @@ def parse_source_interface(config) ## # parse_multicast_group scans the interface config block and returns the - # value of the vxlan multicast-group. If the multicast-group is not - # configured then the value of DEFAULT_MCAST_GRP is used. The hash - # returned is intended to be merged into the interface resource hash + # value of the vxlan multicast-group. If the multicast-group is not + # configured then the value of DEFAULT_MCAST_GRP is used. The hash + # returned is intended to be merged into the interface resource hash. # # @api private # - # @param [String] :config The interface configuration block to extract - # the vxlan multicast-group value from + # @param config [String] The interface configuration block to extract + # the vxlan multicast-group value from. # # @return [Hash] def parse_multicast_group(config) @@ -1072,14 +1086,14 @@ def parse_multicast_group(config) ## # parse_udp_port scans the interface config block and returns the value - # of the vxlan udp-port setting. The vxlan udp-port value is expected to - # always be present in the configuration. The returned value is intended - # to be merged into the interface resource Hash + # of the vxlan udp-port setting. The vxlan udp-port value is expected to + # always be present in the configuration. The returned value is intended + # to be merged into the interface resource Hash. # # @api private # - # @param [String] :config The interface configuration block to parse the - # vxlan udp-port value from + # @param config [String] The interface configuration block to parse the + # vxlan udp-port value from. # # @return [Hash] def parse_udp_port(config) @@ -1090,15 +1104,15 @@ def parse_udp_port(config) ## # parse_flood_list scans the interface config block and returns the list - # of configured VTEPs that comprise the flood list. If there are no + # of configured VTEPs that comprise the flood list. If there are no # flood list values configured, the value will return DEFAULT_FLOOD_LIST. # The returned value is intended to be merged into the interface resource # Hash. # # @api private # - # @param [String] :config The interface configuration block to parse the - # vxlan flood list values from + # @param config [String] The interface configuration block to parse the + # vxlan flood list values from. # # @return [Hash] def parse_flood_list(config) @@ -1110,13 +1124,13 @@ def parse_flood_list(config) ## # parse_vlans scans the interface config block and returns the set of - # configured vlan to vni mappings. If there are no vlans configured, the - # value will return an empty Hash + # configured vlan to vni mappings. If there are no vlans configured, the + # value will return an empty Hash. # # @api private # - # @param [String] :config The interface configuration block to parse the - # vxlan flood list values from + # @param config [String] The interface configuration block to parse the + # vxlan flood list values from. # # @return [Hash] def parse_vlans(config) @@ -1129,26 +1143,26 @@ def parse_vlans(config) private :parse_vlans ## - # Configures the vxlan source-interface to the specified value. This + # Configures the vxlan source-interface to the specified value. This # parameter should be the interface identifier of the interface to act - # as the source for all Vxlan traffic + # as the source for all Vxlan traffic. # - # @param [String] :name The name of the interface to apply the - # configuration values to + # @param name [String] The name of the interface to apply the + # configuration values to. # - # @param [Hash] :opt Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value Configures the vxlan source-interface to - # the specified value + # @option opts value [String] Configures the vxlan source-interface to + # the specified value. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Specifies whether or not the - # multicast-group command is configured as default. The value of this - # option has a higher precedence than :enable + # @option opts default [Boolean] Specifies whether or not the + # multicast-group command is configured as default. The value of this + # option has a higher precedence than :enable. # - # @return [Boolean] Returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def set_source_interface(name = 'Vxlan1', opts = {}) commands = command_builder('vxlan source-interface', opts) configure_interface(name, commands) @@ -1156,24 +1170,24 @@ def set_source_interface(name = 'Vxlan1', opts = {}) ## # Configures the vxlan multicast-group flood address to the specified - # value. The value should be a valid multicast address + # value. The value should be a valid multicast address. # - # @param [String] :name The name of the interface to apply the - # configuration values to + # @param name [String] The name of the interface to apply the + # configuration values to. # - # @param [Hash] :opt Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value Configures the multicast-group flood + # @option opts value [String] Configures the multicast-group flood # address to the specified value. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Specifies whether or not the - # multicast-group command is configured as default. The value of this - # option has a higher precedence than :value + # @option opts default [Boolean] Specifies whether or not the + # multicast-group command is configured as default. The value of this + # option has a higher precedence than :value. # - # @return [Boolean] Returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def set_multicast_group(name = 'Vxlan1', opts = {}) commands = command_builder('vxlan multicast-group', opts) configure_interface(name, commands) @@ -1181,28 +1195,28 @@ def set_multicast_group(name = 'Vxlan1', opts = {}) ## # set_udp_port configures the Vxlan udp-port value in EOS for the - # specified interface name. If the enable keyword is false then the - # no keyword is used to configure the value. If the default option is - # provided and set to true, then the default keyword is used. If both + # specified interface name. If the enable keyword is false then the + # no keyword is used to configure the value. If the default option is + # provided and set to true, then the default keyword is used. If both # options are provided, the default keyword will take precedence. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The name of the vxlan interface to configure + # @param name [String] The name of the vxlan interface to configure. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value Specifies the value to configure the - # udp-port setting to. Valid values are in the range of 1024 to - # 65535 + # @option opts value [String] Specifies the value to configure the + # udp-port setting to. Valid values are in the range of 1024 to + # 65535. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configures the udp-port value on - # the interface using the default keyword + # @option opts default [Boolean] Configures the udp-port value on + # the interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_udp_port(name, opts = {}) commands = command_builder('vxlan udp-port', opts) configure_interface(name, commands) @@ -1210,47 +1224,49 @@ def set_udp_port(name, opts = {}) ## # add_vtep adds a new VTEP endpoint to the global flood list for the - # specified interface. If the VTEP endpoint is already configured, this + # specified interface. If the VTEP endpoint is already configured, this # method will still return successfully. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M + # + # @param name [String] The name of the interface to configure. # - # @param [String] :name The name of the interface to configure - # @param [String] :vtep The IP address of the remote VTEP endpoint + # @param vtep [String] The IP address of the remote VTEP endpoint. # - # @return [Boolean] Returns true if the commands completed successfully + # @return [Boolean] Returns true if the commands completed successfully. def add_vtep(name, vtep) configure_interface(name, "vxlan flood vtep add #{vtep}") end ## # remove_vtep deletes a VTEP endpoint from the global flood list for the - # specified interface. If the VTEP endpoint specified is not configured, + # specified interface. If the VTEP endpoint specified is not configured, # this method will still return successfully. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M + # + # @param name [String] The name of the interface to configure. # - # @param [String] :name The name of the interface to configure - # @param [String] :vtep The IP address of the remote VTEP endpoint + # @param vtep [String] The IP address of the remote VTEP endpoint. # - # @return [Boolean] Returns true if the commands completed successfully + # @return [Boolean] Returns true if the commands completed successfully. def remove_vtep(name, vtep) configure_interface(name, "vxlan flood vtep remove #{vtep}") end ## # update_vlan creates a new vlan to vni mapping for the specified - # interface in the nodes current configuration + # interface in the nodes current configuration. # - # @eos_verson 4.13.7M + # @since eos_verson 4.13.7M # - # @param [String] :name The name of the interface to configure + # @param name [String] The name of the interface to configure. # - # @param [Fixnum] :vlan The VLAN ID to configure. + # @param vlan [Fixnum] The VLAN ID to configure. # - # @param [Fixnum] :vni The VNI value to map the VLAN into + # @param vni [Fixnum] The VNI value to map the VLAN into. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def update_vlan(name, vlan, vni) configure_interface(name, "vxlan vlan #{vlan} vni #{vni}") end @@ -1259,15 +1275,15 @@ def update_vlan(name, vlan, vni) # remove_vlan deletes a previously configured VLAN to VNI mapping on the # specified interface. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name the name of the interface to configure + # @param name [String] the name of the interface to configure. # - # @param [Fixnum] :vlan The VLAN ID to remove from the configuration. If + # @param vlan [Fixnum] The VLAN ID to remove from the configuration. If # the VLAN ID does not exist, this method will still return - # successfully + # successfully. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def remove_vlan(name, vlan) configure_interface(name, "no vxlan vlan #{vlan} vni") end diff --git a/lib/rbeapi/api/ipinterfaces.rb b/lib/rbeapi/api/ipinterfaces.rb index ddeb80c..7b270a4 100644 --- a/lib/rbeapi/api/ipinterfaces.rb +++ b/lib/rbeapi/api/ipinterfaces.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api # # The Ipinterface class provides an instance for managing logical @@ -49,17 +49,17 @@ class Ipinterfaces < Entity # # @example # { - # address: - # mtu: + # address: , + # mtu: , # helper_addresses: array # } # - # @param [String] :name The full interface identifier of the interface to - # return the resource configuration hash for. The name must be the - # full name (Ethernet, not Et) + # @param name [String] The full interface identifier of the interface to + # return the resource configuration hash for. The name must be the + # full name (Ethernet, not Et). # - # @return [nil, Hash] returns the ip interface - # configuration as a hash. If the provided interface name is not a + # @return [nil, Hash] Returns the ip interface + # configuration as a hash. If the provided interface name is not a # configured ip address, nil is returned. def get(name) config = get_block("interface #{name}") @@ -80,13 +80,13 @@ def get(name) # @example # { # : { - # address: - # mtu: + # address: , + # mtu: , # helper_addresses: array # }, # : { - # address: - # mtu: + # address: , + # mtu: , # helper_addresses: array # }, # ... @@ -94,9 +94,9 @@ def get(name) # # @see get Ipaddress resource example # - # @return [Hash] returns a hash object that - # represents all of the configured IP addresses found. If no IP - # addresses are configured, then an empty hash is returned + # @return [Hash] Returns a hash object that + # represents all of the configured IP addresses found. If no IP + # addresses are configured, then an empty hash is returned. def getall interfaces = config.scan(/(?<=^interface\s).+/) interfaces.each_with_object({}) do |name, hsh| @@ -107,17 +107,17 @@ def getall ## # parse_address scans the provided configuration block and extracts - # the interface address, if configured, and returns it. If there is + # the interface address, if configured, and returns it. If there is # no IP address configured, then this method will return the - # DEFAULT_ADDRESS. The return value is intended to be merged into the + # DEFAULT_ADDRESS. The return value is intended to be merged into the # ipaddress resource hash. # # @api private # - # @param [String] :config The IP interface configuration block returned - # from the node's running configuration + # @param config [String] The IP interface configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_address(config) mdata = /(?<=^\s{3}ip\saddress\s)(.+)$/.match(config) { address: mdata.nil? ? DEFAULT_ADDRESS : mdata[1] } @@ -126,16 +126,16 @@ def parse_address(config) ## # parse_mtu scans the provided configuration block and extracts the IP - # interface MTU value. The MTU value is expected to always be present in - # the configuration blcok. The return value is intended to be merged - # into the ipaddress resource hash + # interface MTU value. The MTU value is expected to always be present in + # the configuration blcok. The return value is intended to be merged + # into the ipaddress resource hash. # # @api private # - # @param [String] :config The IP interface configuration block returned - # from the node's running configuration + # @param config [String] The IP interface configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_mtu(config) mdata = /(?<=mtu\s)(\d+)$/.match(config) { mtu: mdata.nil? ? '' : mdata[1] } @@ -144,18 +144,18 @@ def parse_mtu(config) ## # parse_helper_addresses scans the provided configuration block and - # extracts any configured IP helper address values. The interface could - # be configured with one or more helper addresses. If no helper + # extracts any configured IP helper address values. The interface could + # be configured with one or more helper addresses. If no helper # addresses are configured, then an empty array is set in the return - # hash. The return value is intended to be merged into the ipaddress - # resource hash + # hash. The return value is intended to be merged into the ipaddress + # resource hash. # # @api private # - # @param [String] :config The IP interface configuration block returned - # from the node's running configuration + # @param config [String] The IP interface configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_helper_addresses(config) helpers = config.scan(/(?<=\s{3}ip\shelper-address\s).+$/) { helper_addresses: helpers } @@ -163,80 +163,80 @@ def parse_helper_addresses(config) private :parse_helper_addresses ## - # create will create a new IP interface on the node. If the ip interface + # create will create a new IP interface on the node. If the ip interface # already exists in the configuration, this method will still return - # successful. This method will cause an existing layer 2 interface + # successful. This method will cause an existing layer 2 interface # (switchport) to be deleted if it exists in the node's configuration. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # no switchport # - # @param [String] :name The full interface name of the port to create the - # logical interface on. The name must be the full interface - # identifier + # @param name [String] The full interface name of the port to create the + # logical interface on. The name must be the full interface + # identifier. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def create(name) configure(["interface #{name}", 'no switchport']) end ## # delete will delete an existing IP interface in the node's current - # configuration. If the IP interface does not exist on the specified - # interface, this method will still return success. This command will + # configuration. If the IP interface does not exist on the specified + # interface, this method will still return success. This command will # default the interface back to being a switchport. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # no ip address # switchport # - # @param [String] :name The full interface name of the port to delete the - # logical interface from. The name must be the full interface name + # @param name [String] The full interface name of the port to delete the + # logical interface from. The name must be the full interface name # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def delete(name) configure(["interface #{name}", 'no ip address', 'switchport']) end ## # set_address configures a logical IP interface with an address. - # The address value must be in the form of A.B.C.D/E. If the enable + # The address value must be in the form of A.B.C.D/E. If the enable # keyword is false, then the interface address is negated using the - # config no keyword. If the default option is set to true, then the - # ip address # value is defaulted using the default keyword. The + # config no keyword. If the default option is set to true, then the + # ip address # value is defaulted using the default keyword. The # default keyword has precedence over the enable keyword if both - # options are specified + # options are specified. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # ip address # no ip address # default ip address # - # @param [String] :name The name of the interface to configure the - # address in the node. The name must be the full interface name. + # @param name [String] The name of the interface to configure the + # address in the node. The name must be the full interface name. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the address to - # for the specified interface name. The value must be in the form - # of A.B.C.D/E + # @option opts value [String] The value to configure the address to + # for the specified interface name. The value must be in the form + # of A.B.C.D/E. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the ip address value using - # the default keyword + # @option opts default [Boolean] Configure the ip address value using + # the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns True if the command completed successfully. def set_address(name, opts = {}) cmds = command_builder('ip address', opts) configure_interface(name, cmds) @@ -244,36 +244,36 @@ def set_address(name, opts = {}) ## # set_mtu configures the IP mtu value of the ip interface in the nodes - # configuration. If the enable option is false, then the ip mtu value is - # configured using the no keyword. If the default keyword option is + # configuration. If the enable option is false, then the ip mtu value is + # configured using the no keyword. If the default keyword option is # provided and set to true then the ip mtu value is configured using the - # default keyword. The default keyword has precedence over the enable + # default keyword. The default keyword has precedence over the enable # keyword if both options are specified. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # mtu # no mtu # default mtu # - # @param [String] :name The name of the interface to configure the - # address in the node. The name must be the full interface name. + # @param name [String] The name of the interface to configure the + # address in the node. The name must be the full interface name. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the IP MTU to in - # the nodes configuration. Valid values are in the range of 68 to 9214 - # bytes. The default is 1500 bytes + # @option opts value [String] The value to configure the IP MTU to in + # the nodes configuration. Valid values are in the range of 68 to 9214 + # bytes. The default is 1500 bytes. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the ip mtu value using - # the default keyword + # @option opts default [Boolean] Configure the ip mtu value using + # the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_mtu(name, opts = {}) cmds = command_builder('mtu', opts) configure_interface(name, cmds) @@ -281,31 +281,31 @@ def set_mtu(name, opts = {}) ## # set_helper_addresses configures the list of helper addresses on the ip - # interface. An IP interface can have one or more helper addresses - # configured. If no value is provided, the helper address configuration - # is set using the no keyword. If the default option is specified and + # interface. An IP interface can have one or more helper addresses + # configured. If no value is provided, the helper address configuration + # is set using the no keyword. If the default option is specified and # set to true, then the helper address values are defaulted using the # default keyword. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # ip helper-address # no ip helper-address # default ip helper-address # - # @param [String] :name The name of the interface to configure the - # address in the node. The name must be the full interface name. + # @param name [String] The name of the interface to configure the + # address in the node. The name must be the full interface name. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [Array] :value The list of IP addresses to configure as - # helper address on the interface. The helper addresses must be valid + # @option opts value [Array] The list of IP addresses to configure as + # helper address on the interface. The helper addresses must be valid # addresses in the main interface's subnet. # - # @option :opts [Boolean] :default Configure the ip helper address values - # using the default keyword + # @option opts default [Boolean] Configure the ip helper address values + # using the default keyword. # def set_helper_addresses(name, opts = {}) value = opts[:value] diff --git a/lib/rbeapi/api/logging.rb b/lib/rbeapi/api/logging.rb index f5b18c1..1c09a9a 100644 --- a/lib/rbeapi/api/logging.rb +++ b/lib/rbeapi/api/logging.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Logging class manages logging settings on an EOS node. @@ -50,8 +50,8 @@ class Logging < Entity # hosts: array # } # - # @return [Hash] returns the logging resource as a hash - # object from the nodes current configuration + # @return [Hash] Returns the logging resource as a hash + # object from the nodes current configuration. def get response = {} response.merge!(parse_enable) @@ -61,14 +61,14 @@ def get ## # parse_enable scans the nodes current running configuration and extracts - # the current enabled state of the logging facility. The logging enable - # command is expected to always be in the node's configuration. This + # the current enabled state of the logging facility. The logging enable + # command is expected to always be in the node's configuration. This # methods return value is intended to be merged into the logging resource # hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_enable value = /no logging on/ !~ config { enable: value } @@ -76,14 +76,14 @@ def parse_enable ## # parse_hosts scans the nodes current running configuration and extracts - # the configured logging host destinations if any are configured. If no + # the configured logging host destinations if any are configured. If no # logging hosts are configured, then the value for hosts will be an empty - # array. The return value is intended to be merged into the logging + # array. The return value is intended to be merged into the logging # resource hash # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_hosts hosts = config.scan(/(?<=^logging\shost\s)[^\s]+/) { hosts: hosts } @@ -92,28 +92,28 @@ def parse_hosts ## # set_enable configures the global logging instance on the node as either - # enabled or disabled. If the enable keyword is set to true then logging - # is globally enabled and if set to false, it is globally disabled. If + # enabled or disabled. If the enable keyword is set to true then logging + # is globally enabled and if set to false, it is globally disabled. If # the default keyword is specified and set to true, then the configuration - # is defaulted using the default keyword. The default keyword option + # is defaulted using the default keyword. The default keyword option # takes precedence over the enable keyword if both options are specified. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # logging on # no logging on # default logging on # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments # - # @option :opts [Boolean] :enable Enables logging globally if value is - # true or disabled logging globally if value is false + # @option opts enable [Boolean] Enables logging globally if value is + # true or disabled logging globally if value is false. # - # @option :opts [Boolean] :default Configure the ip address value using - # the default keyword + # @option opts default [Boolean] Configure the ip address value using + # the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_enable(opts = {}) cmd = command_builder('logging on', opts) configure cmd @@ -121,36 +121,36 @@ def set_enable(opts = {}) ## # add_host configures a new logging destination host address or hostname - # to the list of logging destinations. If the host is already configured + # to the list of logging destinations. If the host is already configured # in the list of destinations, this method will return successfully. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # logging host # - # @param [String] :name The host name or ip address of the destination + # @param name [String] The host name or ip address of the destination # node to send logging information to. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_host(name) configure "logging host #{name}" end ## # remove_host deletes a logging destination host name or address form the - # list of logging destinations. If the host is not in the list of + # list of logging destinations. If the host is not in the list of # configured hosts, this method will still return successfully. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # no logging host # - # @param [String] :name The host name or ip address of the destination - # host to remove from the nodes current configuration + # @param name [String] The host name or ip address of the destination + # host to remove from the nodes current configuration. # - # @return [Boolean] returns true if the commands completed successfully + # @return [Boolean] Returns true if the commands completed successfully. def remove_host(name) configure "no logging host #{name}" end diff --git a/lib/rbeapi/api/mlag.rb b/lib/rbeapi/api/mlag.rb index e88a67f..b57ccd0 100644 --- a/lib/rbeapi/api/mlag.rb +++ b/lib/rbeapi/api/mlag.rb @@ -32,14 +32,14 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Mlag class provides a configuration instance for working with - # the global MLAG configuration of the node + # the global MLAG configuration of the node. class Mlag < Entity DEFAULT_DOMAIN_ID = '' DEFAULT_LOCAL_INTF = '' @@ -73,8 +73,8 @@ class Mlag < Entity # @see parse_interfaces # # @return [nil, Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_domain_id(config) mdata = /(?<=\s{3}domain-id\s)(.+)$/.match(config) { domain_id: mdata.nil? ? DEFAULT_DOMAIN_ID : mdata[1] } @@ -108,16 +108,16 @@ def parse_domain_id(config) ## # parse_local_interface scans the current nodes running configuration and - # extracts the mlag local-interface value. If the mlag local-interface + # extracts the mlag local-interface value. If the mlag local-interface # has not been configured, this method will return DEFAULT_LOCAL_INTF. - # The return value is intended to be merged into the resource hash + # The return value is intended to be merged into the resource hash. # # @api private # - # @param [String] :config The mlag configuration block retrieved from the + # @param config [String] The mlag configuration block retrieved from the # nodes current running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_local_interface(config) mdata = /(?<=\s{3}local-interface\s)(.+)$/.match(config) { local_interface: mdata.nil? ? DEFAULT_LOCAL_INTF : mdata[1] } @@ -126,16 +126,16 @@ def parse_local_interface(config) ## # parse_peer_address scans the current nodes running configuration and - # extracts the mlag peer-address value. If the mlag peer-address has not - # been configured, this method will return DEFAULT_PEER_ADDR. The return + # extracts the mlag peer-address value. If the mlag peer-address has not + # been configured, this method will return DEFAULT_PEER_ADDR. The return # value is intended to be merged into the resource hash. # # @api private # - # @param [String] :config The mlag configuration block retrieved from the + # @param config [String] The mlag configuration block retrieved from the # nodes current running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_peer_address(config) mdata = /(?<=\s{3}peer-address\s)(.+)$/.match(config) { peer_address: mdata.nil? ? DEFAULT_PEER_ADDR : mdata[1] } @@ -144,16 +144,16 @@ def parse_peer_address(config) ## # parse_peer_link scans the current nodes running configuration and - # extracts the mlag peer-link value. If the mlag peer-link hash not been - # configure, this method will return DEFAULT_PEER_LINK. The return value + # extracts the mlag peer-link value. If the mlag peer-link hash not been + # configure, this method will return DEFAULT_PEER_LINK. The return value # is intended to be merged into the resource hash. # # @api private # - # @param [String] :config The mlag configuration block retrieved from the + # @param config [String] The mlag configuration block retrieved from the # nodes current running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute def parse_peer_link(config) mdata = /(?<=\s{3}peer-link\s)(.+)$/.match(config) { peer_link: mdata.nil? ? DEFAULT_PEER_LINK : mdata[1] } @@ -162,16 +162,16 @@ def parse_peer_link(config) ## # parse_shutdown scans the current nodes mlag configuration and extracts - # the mlag shutdown value. The mlag configuration should always return - # the value of shutdown from the configuration block. Ths return value + # the mlag shutdown value. The mlag configuration should always return + # the value of shutdown from the configuration block. The return value # is intended to be merged into the resource hash. # # @api private # - # @param [String] :config The mlag configuration block retrieved from the + # @param config [String] The mlag configuration block retrieved from the # nodes current running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_shutdown(config) value = /\s{3}no shutdown/ !~ config { shutdown: value } @@ -180,16 +180,16 @@ def parse_shutdown(config) ## # parse_interfaces scans the global configuration and returns all of the - # configured MLAG interfaces. Each interface returns the configured MLAG - # identifier for establishing a MLAG peer. The return value is intended - # to be merged into the resource Hash + # configured MLAG interfaces. Each interface returns the configured MLAG + # identifier for establishing a MLAG peer. The return value is intended + # to be merged into the resource Hash. # # The resource Hash attribute returned contains: - # * mlag_id: (Fixnum) The configured MLAG identifier + # * mlag_id: (Fixnum) The configured MLAG identifier. # # @api private # - # @return [Hash] resource Hash attribute + # @return [Hash] Returns the resource Hash attribute. def parse_interfaces names = config.scan(/(?<=^interface\s)Po.+/) names.each_with_object({}) do |name, hsh| @@ -204,31 +204,31 @@ def parse_interfaces ## # set_domain_id configures the mlag domain-id value in the current nodes # running configuration. If the enable keyword is false, the the - # domain-id is configured with the no keyword. If the default keyword + # domain-id is configured with the no keyword. If the default keyword # is provided, the configuration is defaulted using the default keyword. # The default keyword takes precedence over the enable keyword if both - # options are specified + # options are specified. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # mlag configuration # domain-id # no domain-id # default domain-id # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments # - # @option :opts [String] :value The value to configure the mlag + # @option opts value [String] The value to configure the mlag # domain-id to. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the domain-id value using - # the default keyword + # @option opts default [Boolean] Configure the domain-id value using + # the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_domain_id(opts = {}) cmd = command_builder('domain-id', opts) cmds = ['mlag configuration', cmd] @@ -238,32 +238,32 @@ def set_domain_id(opts = {}) ## # set_local_interface configures the mlag local-interface value in the # current nodes running configuration. If the enable keyword is false, - # the local-interface is configured with the no keyword. If + # the local-interface is configured with the no keyword. If # the default keyword is provided, the configuration is defaulted using - # the default keyword. The default keyword takes precedence over the + # the default keyword. The default keyword takes precedence over the # enable keyword if both options are specified # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # mlag configuration # local-interface # no local-interface # default local-interface # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments # - # @option :opts [String] :value The value to configure the mlag - # local-interface to. The local-interface accepts full interface + # @option opts value [String] The value to configure the mlag + # local-interface to. The local-interface accepts full interface # identifiers and expects a Vlan interface # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the local-interface value - # using the default keyword + # @option opts default [Boolean] Configure the local-interface value + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_local_interface(opts = {}) cmd = command_builder('local-interface', opts) cmds = ['mlag configuration', cmd] @@ -273,32 +273,32 @@ def set_local_interface(opts = {}) ## # set_peer_link configures the mlag peer-link value in the current nodes # running configuration. If enable keyword is false, then the - # peer-link is configured with the no keyword. If the default keyword + # peer-link is configured with the no keyword. If the default keyword # is provided, the configuration is defaulted using the default keyword. # The default keyword takes precedence over the enable keyword if both - # options are specified + # options are specified. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # mlag configuration # peer-link # no peer-link # default peer-link # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the mlag - # peer-link to. The peer-link accepts full interface identifiers - # and expects an Ethernet or Port-Channel interface + # @option opts value [String] The value to configure the mlag + # peer-link to. The peer-link accepts full interface identifiers + # and expects an Ethernet or Port-Channel interface. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the peer-link using the - # default keyword + # @option opts default [Boolean] Configure the peer-link using the + # default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_peer_link(opts = {}) cmd = command_builder('peer-link', opts) cmds = ['mlag configuration', cmd] @@ -308,32 +308,32 @@ def set_peer_link(opts = {}) ## # set_peer_address configures the mlag peer-address value in the current # nodes running configuration. If the enable keyword is false, then the - # peer-address is configured with the no keyword. If the default keyword + # peer-address is configured with the no keyword. If the default keyword # is provided, the configuration is defaulted using the default keyword. # The default keyword takes precedence over the enable keyword if both # options are specified # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # mlag configuration # peer-address # no peer-address # default peer-address # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the mlag - # peer-address to. The peer-address accepts an IP address in the form - # of A.B.C.D/E + # @option opts value [String] The value to configure the mlag + # peer-address to. The peer-address accepts an IP address in the form + # of A.B.C.D/E. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the peer-address using the - # default keyword + # @option opts default [Boolean] Configure the peer-address using the + # default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_peer_address(opts = {}) cmd = command_builder('peer-address', opts) cmds = ['mlag configuration', cmd] @@ -342,30 +342,30 @@ def set_peer_address(opts = {}) ## # set_shutdown configures the administrative state of the mlag process on - # the current node. If the enable keyword is true, then mlag is enabled + # the current node. If the enable keyword is true, then mlag is enabled # and if the enable keyword is false, then mlag is disabled. If the # default keyword is provided, the configuration is defaulted using # the default keyword. The default keyword takes precedence over the # enable keyword if both options are specified # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # mlag configuration # shutdown # no shutdown # default shutdown # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable True if the interface should be + # @option opts enable [Boolean] True if the interface should be # administratively enabled or false if the interface should be # administratively disabled. # - # @option :opts [Boolean] :default Configure the shutdown value using the - # default keyword + # @option opts default [Boolean] Configure the shutdown value using the + # default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_shutdown(opts = {}) fail 'set_shutdown has the value option set' if opts[:value] # Shutdown semantics are opposite of enable semantics so invert enable @@ -378,36 +378,36 @@ def set_shutdown(opts = {}) ## # set_mlag_id configures the mlag id on the interface in the nodes - # current running configuration. If the enable keyword is false, then the - # interface mlag id is configured using the no keyword. If the default + # current running configuration. If the enable keyword is false, then the + # interface mlag id is configured using the no keyword. If the default # keyword is provided and set to true, the interface mlag id is - # configured using the default keyword. The default keyword takes + # configured using the default keyword. The default keyword takes # precedence over the enable keyword if both options are specified # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # mlag # no mlag # default mlag # - # @param [String] :name The full interface identifier of the interface + # @param name [String] The full interface identifier of the interface # to configure th mlag id for. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String, Integer] :value The value to configure the - # interface mlag to. The mlag id should be in the valid range of 1 to - # 2000 + # @option opts value [String, Integer] The value to configure the + # interface mlag to. The mlag id should be in the valid range of 1 to + # 2000. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the mlag value using the - # default keyword + # @option opts default [Boolean] Configure the mlag value using the + # default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_mlag_id(name, opts = {}) cmd = command_builder('mlag', opts) configure_interface(name, cmd) diff --git a/lib/rbeapi/api/ntp.rb b/lib/rbeapi/api/ntp.rb index 2b1e78d..4ae0058 100644 --- a/lib/rbeapi/api/ntp.rb +++ b/lib/rbeapi/api/ntp.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Ntp class provides an instance for working with the nodes @@ -44,7 +44,7 @@ class Ntp < Entity DEFAULT_SRC_INTF = '' ## - # get returns the nodes current ntp configure as a resource hash + # get returns the nodes current ntp configure as a resource hash. # # @example # { @@ -65,13 +65,13 @@ def get ## # parse_source_interface scans the nodes configurations and parses - # the ntp source interface if configured. If the source interface + # the ntp source interface if configured. If the source interface # is not configured, this method will return DEFAULT_SRC_INTF as the - # value. The return hash is intended to be merged into the resource hash + # value. The return hash is intended to be merged into the resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_source_interface mdata = /(?<=^ntp\ssource\s)(.+)$/.match(config) { source_interface: mdata.nil? ? DEFAULT_SRC_INTF : mdata[1] } @@ -80,14 +80,14 @@ def parse_source_interface ## # parse_servers scans the nodes configuration and parses the configured - # ntp server host names and/or addresses. This method will also return - # the value of prefer. If no servers are configured, the value will be - # set to an empty array. The return hash is intended to be merged into - # the resource hash + # ntp server host names and/or addresses. This method will also return + # the value of prefer. If no servers are configured, the value will be + # set to an empty array. The return hash is intended to be merged into + # the resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_servers servers = config.scan(/(?:ntp server\s)([^\s]+)\s(prefer)?/) values = servers.each_with_object({}) do |(srv, prefer), hsh| @@ -99,31 +99,31 @@ def parse_servers ## # set_source_interface configures the ntp source value in the nodes - # running configuration. If the enable keyword is false, then - # the ntp source is configured with the no keyword argument. If the + # running configuration. If the enable keyword is false, then + # the ntp source is configured with the no keyword argument. If the # default keyword argument is provided and set to true, the value is - # configured used the default keyword. The default keyword takes + # configured used the default keyword. The default keyword takes # precedence over the enable keyword if both options are specified. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # ntp source # no ntp source # default ntp source # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the ntp source - # in the nodes configuration + # @option opts value [String] The value to configure the ntp source + # in the nodes configuration. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the ntp source value using - # the default keyword + # @option opts default [Boolean] Configure the ntp source value using + # the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_source_interface(opts = {}) cmd = command_builder('ntp source', opts) configure(cmd) @@ -131,17 +131,17 @@ def set_source_interface(opts = {}) ## # add_server configures a new ntp server destination hostname or ip - # address to the list of ntp destinations. The optional prefer argument + # address to the list of ntp destinations. The optional prefer argument # configures the server as a preferred (true) or not (false) ntp # destination. # - # @param [String] :server The IP address or FQDN of the NTP server to - # be removed from the configuration + # @param server [String] The IP address or FQDN of the NTP server to + # be removed from the configuration. # - # @param [Boolean] :prefer Appends the prefer keyword argument to the - # command if this value is true + # @param prefer [Boolean] Appends the prefer keyword argument to the + # command if this value is true. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_server(server, prefer = false) cmd = "ntp server #{server}" cmd << ' prefer' if prefer @@ -150,13 +150,13 @@ def add_server(server, prefer = false) ## # remove_server deletes the provided server destination from the list of - # ntp server destinations. If the ntp server does not exist in the list + # ntp server destinations. If the ntp server does not exist in the list # of servers, this method will return successful # - # @param [String] :server The IP address or FQDN of the NTP server to - # be removed from the configuration + # @param server [String] The IP address or FQDN of the NTP server to + # be removed from the configuration. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def remove_server(server) configure("no ntp server #{server}") end @@ -166,20 +166,20 @@ def remove_server(server) # If the server does not already exist in the configuration, it will be # added and the prefer keyword will be set. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # ntp server prefer # no ntp server prefer # - # @param [String] :srv The IP address or hostname of the ntp server to - # configure with the prefer value + # @param srv [String] The IP address or hostname of the ntp server to + # configure with the prefer value. # - # @param [Boolean] :value The value to configure for prefer. If true + # @param value [Boolean] The value to configure for prefer. If true # the prefer value is configured for the server. If false, then the # prefer value is removed. # - # @return [Boolean] returns true if the commands completed successfully + # @return [Boolean] Returns true if the commands completed successfully. def set_prefer(srv, value) case value when true diff --git a/lib/rbeapi/api/ospf.rb b/lib/rbeapi/api/ospf.rb index 8f4fea4..9e21c70 100644 --- a/lib/rbeapi/api/ospf.rb +++ b/lib/rbeapi/api/ospf.rb @@ -32,17 +32,17 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Ospf class is a global class that provides an instance for working - # with the node's OSPF configuration + # with the node's OSPF configuration. class Ospf < Entity ## - # Returns the global OSPF configuration from the node + # Returns the global OSPF configuration from the node. # # rubocop:disable Metrics/MethodLength # @@ -55,9 +55,9 @@ class Ospf < Entity # redistribute: {} # } # - # @param [String] :inst The ospf instance name + # @param inst [String] The ospf instance name. # - # @return [Hash] A Ruby hash object that provides the OSPF settings as + # @return [Hash] A Ruby hash object that provides the OSPF settings as # key / value pairs. def get(inst) config = get_block("router ospf #{inst}") @@ -88,19 +88,19 @@ def get(inst) end ## - # Returns the OSPF configuration from the node as a Ruby hash + # Returns the OSPF configuration from the node as a Ruby hash. # # @example - # { - # : { - # router_id: , - # areas: {}, - # redistribute: {} - # }, - # interfaces: {} - # } + # { + # : { + # router_id: , + # areas: {}, + # redistribute: {} + # }, + # interfaces: {} + # } # - # @return [Hash] A Ruby hash object that provides the OSPF settings as + # @return [Hash] A Ruby hash object that provides the OSPF settings as # key / value pairs. def getall instances = config.scan(/(?<=^router\sospf\s)\d+$/) @@ -118,38 +118,38 @@ def interfaces end ## - # create will create a router ospf with the specified pid + # create will create a router ospf with the specified pid. # - # @param [String] :pid The router ospf to create + # @param pid [String] The router ospf to create. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(pid) configure "router ospf #{pid}" end ## - # delete will remove the specified router ospf + # delete will remove the specified router ospf. # - # @param [String] :pid The router ospf to remove + # @param pid [String] The router ospf to remove. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete(pid) configure "no router ospf #{pid}" end ## - # set_router_id sets router ospf router-id with pid and options + # set_router_id sets router ospf router-id with pid and options. # - # @param [String] :pid The router ospf name + # @param pid [String] The router ospf name. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the router-id to default. + # @option opts default [Boolean] Configure the router-id to default. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_router_id(pid, opts = {}) cmd = command_builder('router-id', opts) cmds = ["router ospf #{pid}", cmd] @@ -159,13 +159,13 @@ def set_router_id(pid, opts = {}) ## # add_network adds network settings for router ospf and network area. # - # @param [String] :pid The pid for router ospf + # @param pid [String] The pid for router ospf. # - # @param [String] :net The network name + # @param net [String] The network name. # - # @param [String] :area The network area name + # @param area [String] The network area name. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_network(pid, net, area) configure ["router ospf #{pid}", "network #{net} area #{area}"] end @@ -174,34 +174,34 @@ def add_network(pid, net, area) # remove_network removes network settings for router ospf and network # area. # - # @param [String] :pid The pid for router ospf + # @param pid [String] The pid for router ospf. # - # @param [String] :net The network name + # @param net [String] The network name. # - # @param [String] :area The network area name + # @param area [String] The network area name. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def remove_network(pid, net, area) configure ["router ospf #{pid}", "no network #{net} area #{area}"] end ## - # set_redistribute sets router ospf router-id with pid and options + # set_redistribute sets router ospf router-id with pid and options. # - # @param [String] :pid The router ospf name + # @param pid [String] The router ospf name. # - # @param [String] :proto The redistribute value + # @param proto [String] The redistribute value. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [String] :routemap The route-map value + # @option opts routemap [String] The route-map value. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the router-id to default. + # @option opts default [Boolean] Configure the router-id to default. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_redistribute(pid, proto, opts = {}) routemap = opts[:routemap] cmds = ["router ospf #{pid}", "redistribute #{proto}"] @@ -212,21 +212,21 @@ def set_redistribute(pid, proto, opts = {}) ## # The OspfInterfaces class is a global class that provides an instance - # for working with the node's OSPF interface configuration + # for working with the node's OSPF interface configuration. class OspfInterfaces < Entity ## - # Returns a single MLAG interface configuration + # Returns a single MLAG interface configuration. # # Example # { # network_type: # } # - # @param [String] :name The interface name to return the configuration - # values for. This must be the full interface identifier. + # @param name [String] The interface name to return the configuration + # values for. This must be the full interface identifier. # # @return [nil, Hash] A Ruby hash that represents the - # MLAG interface configuration. A nil object is returned if the + # MLAG interface configuration. A nil object is returned if the # specified interface is not configured def get(name) config = get_block("interface #{name}") @@ -241,7 +241,7 @@ def get(name) ## # Returns the collection of MLAG interfaces as a hash index by the - # interface name + # interface name. # # Example # { @@ -255,7 +255,7 @@ def get(name) # } # # @return [nil, Hash] A Ruby hash that represents the - # MLAG interface configuration. A nil object is returned if no + # MLAG interface configuration. A nil object is returned if no # interfaces are configured. def getall interfaces = config.scan(/(?<=interface\s)[Et|Po|Lo|Vl].+/) @@ -266,21 +266,21 @@ def getall end ## - # set_network_type sets network type with options + # set_network_type sets network type with options. # - # @param [String] :name The name of the interface + # @param name [String] The name of the interface. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [String] :value The point-to-point value + # @option opts value [String] The point-to-point value. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the ip ospf network + # @option opts default [Boolean] Configure the ip ospf network # to default. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_network_type(name, opts = {}) value = opts[:value] return false unless [nil, 'point-to-point'].include?(value) diff --git a/lib/rbeapi/api/prefixlists.rb b/lib/rbeapi/api/prefixlists.rb index 0a2435d..d0583aa 100644 --- a/lib/rbeapi/api/prefixlists.rb +++ b/lib/rbeapi/api/prefixlists.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Prefixlists class provides a configuration instance for working @@ -43,7 +43,7 @@ module Api # class Prefixlists < Entity ## - # Returns the static routes configured on the node + # Returns the static routes configured on the node. # # @example # { @@ -53,12 +53,12 @@ class Prefixlists < Entity # } # } # - # @param [String] :name The name of the prefix-list to return + # @param name [String] The name of the prefix-list to return. # - # @returns [Hash The method will return all of the - # configured static routes on the node as a Ruby hash object. If + # @return [Hash The method will return all of the + # configured static routes on the node as a Ruby hash object. If # there are no static routes configured, this method will return - # an empty hash + # an empty hash. def get(name) config = get_block("ip prefix-list #{name}") return nil unless config @@ -71,7 +71,7 @@ def get(name) end ## - # Returns the static routes configured on the node + # Returns the static routes configured on the node. # # @example # { @@ -81,10 +81,10 @@ def get(name) # } # } # - # @returns [Hash The method will return all of the - # configured static routes on the node as a Ruby hash object. If + # @return [Hash The method will return all of the + # configured static routes on the node as a Ruby hash object. If # there are no static routes configured, this method will return - # an empty hash + # an empty hash. def getall lists = config.scan(/(?<=^ip\sprefix-list\s).+/) lists.each_with_object({}) do |name, hsh| @@ -96,9 +96,9 @@ def getall ## # create will create a new ip prefix-list with designated name. # - # @param [String] :name The name of the ip prefix-list + # @param name [String] The name of the ip prefix-list. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(name) configure "ip prefix-list #{name}" end @@ -107,15 +107,15 @@ def create(name) # add_rule will create an ip prefix-list with the designated name, # seqno, action and prefix. # - # @param [String] :name The name of the ip prefix-list + # @param name [String] The name of the ip prefix-list. # - # @param [String] :seq The seq value + # @param seq [String] The seq value. # - # @param [String] :action The action value + # @param action [String] The action value. # - # @param [String] :prefix The prefix value + # @param prefix [String] The prefix value. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_rule(name, action, prefix, seq = nil) cmd = "ip prefix-list #{name}" cmd << " seq #{seq}" if seq @@ -124,13 +124,13 @@ def add_rule(name, action, prefix, seq = nil) end ## - # delete will remove the designated prefix-list + # delete will remove the designated prefix-list. # - # @param [String] :name The name of the ip prefix-list + # @param name [String] The name of the ip prefix-list. # - # @param [String] :seq The seq value + # @param seq [String] The seq value. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete(name, seq = nil) cmd = "no ip prefix-list #{name}" cmd << " seq #{seq}" if seq diff --git a/lib/rbeapi/api/radius.rb b/lib/rbeapi/api/radius.rb index 33b449a..c2e73f7 100644 --- a/lib/rbeapi/api/radius.rb +++ b/lib/rbeapi/api/radius.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # Radius provides instance methods to retrieve and set radius configuration @@ -70,7 +70,7 @@ class Radius < Entity # servers: # } # - # @return [Array] Single element Array of resource hashes + # @return [Array] Single element Array of resource hashes. def get global = {} global.merge!(parse_global_timeout) @@ -82,12 +82,12 @@ def get ## # parse_time scans the nodes current configuration and parse the - # radius-server timeout value. The timeout value is expected to always - # be present in the config + # radius-server timeout value. The timeout value is expected to always + # be present in the config. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_global_timeout value = config.scan(/radius-server timeout (\d+)/).first { timeout: value.first.to_i } @@ -96,12 +96,12 @@ def parse_global_timeout ## # parse_retransmit scans the cnodes current configuration and parses the - # radius-server retransmit value. the retransmit value is expected to - # always be present in the config + # radius-server retransmit value. The retransmit value is expected to + # always be present in the config. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_global_retransmit value = config.scan(/radius-server retransmit (\d+)/).first { retransmit: value.first.to_i } @@ -110,13 +110,13 @@ def parse_global_retransmit ## # parse_key scans the current nodes running configuration and parse the - # global radius-server key and format value. If the key is not + # global radius-server key and format value. If the key is not # configured this method will return DEFAULT_KEY and DEFAULT_KEY_FORMAT # for the resource hash values. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_global_key rsrc_hsh = {} (key_format, key) = config.scan(/radius-server key (\d+) (\w+)/).first @@ -127,9 +127,9 @@ def parse_global_key private :parse_global_key ## - # parse_servers returns an Array of radius server resource hashes. Each + # parse_servers returns an Array of radius server resource hashes. Each # hash describes the current state of the radius server and is intended - # to be merged into the radius resource hash + # to be merged into the radius resource hash. # # The resource hash returned contains the following information: # * hostname: hostname or ip address @@ -145,7 +145,7 @@ def parse_global_key # # @api private # - # @return [Array>] Array of resource hashes + # @return [Array>] Array of resource hashes. def parse_servers tuples = config.scan(SERVER_REGEXP) tuples.map do |(host, vrf, authp, acctp, tout, tries, keyfm, key)| @@ -164,33 +164,33 @@ def parse_servers private :parse_servers ## - # set_global_key configures the global radius-server key. If the enable + # set_global_key configures the global radius-server key. If the enable # option is false, radius-server key is configured using the no # keyword. If the default option is specified, radius-server key is # configured using the default keyword. If both options are specified, # the default keyword option takes precedence. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # radius-server key # no radius-server key # default radius-server key # - # @option [String] :value The value to configure the radius-server key to - # in the nodes running configuration + # @option value [String] The value to configure the radius-server key to + # in the nodes running configuration. # - # @option [Fixnum] :key_format The format of the key to be passed to the - # nodes running configuration. Valid values are 0 (clear text) or 7 - # (encrypted). The default value is 0 if format is not provided. + # @option key_format [Fixnum] The format of the key to be passed to the + # nodes running configuration. Valid values are 0 (clear text) or 7 + # (encrypted). The default value is 0 if format is not provided. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option [Boolean] :default Configures the radius-server key using the - # default keyword argument + # @option default [Boolean] Configures the radius-server key using the + # default keyword argument. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def set_global_key(opts = {}) value = opts[:value] enable = opts.fetch(:enable, true) @@ -211,30 +211,30 @@ def set_global_key(opts = {}) end ## - # set_global_timeout configures the radius-server timeout value. If the + # set_global_timeout configures the radius-server timeout value. If the # enable option is false, then radius-server timeout is configured - # using the no keyword. If the default option is specified, radius-server - # timeout is configured using the default keyword. If both options are + # using the no keyword. If the default option is specified, radius-server + # timeout is configured using the default keyword. If both options are # specified then the default keyword takes precedence. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # radius-server timeout # no radius-server timeout # default radius-server timeout # - # @option [String, Fixnum] :value The value to set the global - # radius-server timeout value to. This value should be in the range of - # 1 to 1000 + # @option value [String, Fixnum] The value to set the global + # radius-server timeout value to. This value should be in the range of + # 1 to 1000. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option [Boolean] :default Configures the radius-server timeout value + # @option default [Boolean] Configures the radius-server timeout value # using the default keyword. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def set_global_timeout(opts = {}) cmd = command_builder('radius-server timeout', opts) configure cmd @@ -246,26 +246,26 @@ def set_global_timeout(opts = {}) # value is configured using the no keyword. If the default option is # specified, the radius-server retransmit value is configured using the # default keyword. If both options are specified then the default keyword - # takes precedence + # takes precedence. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # radius-server retransmit # no radius-server retransmit # default radius-server retransmit # - # @option [String, Fixnum] :value The value to set the global - # radius-server retransmit value to. This value should be in the range + # @option value [String, Fixnum] The value to set the global + # radius-server retransmit value to. This value should be in the range # of 1 to 100 # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option [Boolean] :default Configures the radius-server retransmit - # value using the default keyword + # @option default [Boolean] Configures the radius-server retransmit + # value using the default keyword. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def set_global_retransmit(opts = {}) cmd = command_builder('radius-server retransmit', opts) configure cmd @@ -275,11 +275,29 @@ def set_global_retransmit(opts = {}) # update_server configures a radius server resource on the target device. # This API method maps to the `radius server host` command, e.g. # `radius-server host 10.11.12.13 auth-port 1024 acct-port 2048 timeout - # 30 retransmit 5 key 7 011204070A5955` + # 30 retransmit 5 key 7 011204070A5955`. # # @api public # - # @return [Boolean] true if there are no errors + # @param opts [Hash] The configuration options. + # + # @option opts key_format [Integer] The key format value. + # + # @option opts hostname [String] The host value. + # + # @option opts vrf [String] The vrf value. + # + # @option opts auth_port [String] The auth-port value. + # + # @option opts acct_port [String] The acct-port value. + # + # @option opts timeout [String] The timeout value. + # + # @option opts retransmit [String] The retransmit value. + # + # @option opts key [String] The key value. + # + # @return [Boolean] Returns true if there are no errors. def update_server(opts = {}) # beware: order of cli keyword options counts key_format = opts[:key_format] || 7 @@ -299,7 +317,17 @@ def update_server(opts = {}) # # @api public # - # @return [Boolean] true if no errors + # @param opts [Hash] The configuration options. + # + # @option opts hostname [String] The host value. + # + # @option opts vrf [String] The vrf value. + # + # @option opts auth_port [String] The auth-port value. + # + # @option opts acct_port [String] The acct-port value. + # + # @return [Boolean] Returns true if there are no errors. def remove_server(opts = {}) cmd = "no radius-server host #{opts[:hostname]}" cmd << " vrf #{opts[:vrf]}" if opts[:vrf] diff --git a/lib/rbeapi/api/routemaps.rb b/lib/rbeapi/api/routemaps.rb index 7be95b3..9f75b43 100644 --- a/lib/rbeapi/api/routemaps.rb +++ b/lib/rbeapi/api/routemaps.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Routemaps class manages routemaps. A route map is a list of rules @@ -47,7 +47,7 @@ module Api # class Routemaps < Entity ## - # get returns a hash of routemap configurations for the given name + # get returns a hash of routemap configurations for the given name. # # @example # { @@ -81,12 +81,12 @@ class Routemaps < Entity # } # } # - # @param [String] :name The routemap name to return a resource for from - # the nodes configuration + # @param name [String] The routemap name to return a resource for from + # the nodes configuration. # # @return [nil, Hash] Returns the routemap resource as a # Hash. If the specified name is not found in the nodes current - # configuration a nil object is returned + # configuration a nil object is returned. def get(name) parse_entries(name) end @@ -160,8 +160,8 @@ def get(name) # } # } # - # @return [nil, Hash] returns a hash that represents the - # entire routemap collection from the nodes running configuration. If + # @return [nil, Hash] Returns a hash that represents the + # entire routemap collection from the nodes running configuration. If # there are no routemap names configured, this method will return nil. def getall routemaps = config.scan(/(?<=^route-map\s)[^\s]+/) @@ -176,8 +176,10 @@ def getall # # @api private # - # @return [nil, Hash] returns a hash that represents the - # rules for routemaps from the nodes running configuration. If + # @param name [String] The routemap name. + # + # @return [nil, Hash] Returns a hash that represents the + # rules for routemaps from the nodes running configuration. If # there are no routemaps configured, this method will return nil. def parse_entries(name) entries = config.scan(/^route-map\s#{name}\s.+$/) @@ -199,10 +201,20 @@ def parse_entries(name) # # @api private # - # @return [Hash] returns a hash that represents the - # rules for routemaps from the nodes running configuration. If + # @param rules [Hash] Rules configuration options. + # + # @option rules match [Array] The match options. + # + # @option rules set [Array] The set options. + # + # @option rules continue [String] The continue value. + # + # @option rules description [String] The description value. + # + # @return [Hash] Returns a hash that represents the + # rules for routemaps from the nodes running configuration. If # there are no routemaps configured, this method will return an empty - # hash. + # hash. def parse_rules(rules) rules.split("\n").each_with_object({}) do |rule, rule_hsh| mdata = /\s{3}(\w+)\s/.match(rule) @@ -225,7 +237,21 @@ def parse_rules(rules) private :parse_rules ## - # name_commands is utilized to initially prepare the routemap + # name_commands is utilized to initially prepare the routemap. + # + # @param name [String] The routemap name. + # + # @param action [String] The action value. + # + # @param seqno [String] The seqno value. + # + # @param opts [Hash] The configuration options. + # + # @option opts default [Boolean] The default value. + # + # @option opts enable [Boolean] The enable value. + # + # @return [Array] Returns the prepared eos command. def name_commands(name, action, seqno, opts = {}) if opts[:default] == true cmd = "default route-map #{name}" @@ -245,35 +271,35 @@ def name_commands(name, action, seqno, opts = {}) # # rubocop:disable Metrics/MethodLength # - # @commands + # commands # route-map action seqno description # match set continue # - # @param [String] :name The name of the routemap to create + # @param name [String] The name of the routemap to create. # - # @param [String] :action Either permit or deny + # @param action [String] Either permit or deny. # - # @param [Integer] :seqno The sequence number + # @param seqno [Integer] The sequence number value. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :default Set routemap to default + # @option opts default [Boolean] Set routemap to default. # - # @option :opts [String] :description A description for the routemap + # @option opts description [String] A description for the routemap. # - # @option :opts [Array] :match routemap match rule + # @option opts match [Array] routemap match rule. # - # @option :opts [String] :set Sets route attribute + # @option opts set [String] Sets route attribute. # - # @option :opts [String] :continue The routemap sequence number to + # @option opts continue [String] The routemap sequence number to # continue on. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the routemap to default. + # @option opts default [Boolean] Configure the routemap to default. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(name, action, seqno, opts = {}) if opts.empty? cmds = name_commands(name, action, seqno) @@ -306,6 +332,16 @@ def create(name, action, seqno, opts = {}) ## # remove_match_statemements removes all match rules for the # specified routemap + # + # @param name [String] The routemap name. + # + # @param action [String] The action value. + # + # @param seqno [String] The seqno value. + # + # @param cmds [Array] Array of eos commands. + # + # @return [Boolean] Returns true if the command completed successfully. def remove_match_statements(name, action, seqno, cmds) entries = parse_entries(name) return nil unless entries @@ -322,6 +358,16 @@ def remove_match_statements(name, action, seqno, cmds) ## # remove_set_statemements removes all set rules for the # specified routemap + # + # @param name [String] The routemap name. + # + # @param action [String] The action value. + # + # @param seqno [String] The seqno value. + # + # @param cmds [Array] Array of eos commands. + # + # @return [Boolean] Returns true if the command completed successfully. def remove_set_statements(name, action, seqno, cmds) entries = parse_entries(name) return nil unless entries @@ -340,16 +386,16 @@ def remove_set_statements(name, action, seqno, cmds) # running configuration. If the delete method is called and the # routemap name does not exist, this method will succeed. # - # @commands + # commands # no route-map # - # @param [String] :name The routemap name to delete from the node. + # @param name [String] The routemap name to delete from the node. # - # @param [String] :action Either permit or deny + # @param action [String] Either permit or deny. # - # @param [Integer] :seqno The sequence number + # @param seqno [Integer] The sequence number. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete(name, action, seqno) configure(["no route-map #{name} #{action} #{seqno}"]) end @@ -358,20 +404,20 @@ def delete(name, action, seqno) # This method will attempt to default the routemap from the nodes # operational config. Since routemaps do not exist by default, # the default action is essentially a negation and the result will - # be the removal of the routemap clause. - # If the routemap does not exist then this - # method will not perform any changes but still return True + # be the removal of the routemap clause. If the routemap does not + # exist then this method will not perform any changes but still + # return True. # - # @commands + # commands # no route-map # - # @param [String] :name The routemap name to set to default. + # @param name [String] The routemap name to set to default. # - # @param [String] :action Either permit or deny + # @param action [String] Either permit or deny. # - # @param [Integer] :seqno The sequence number + # @param seqno [Integer] The sequence number. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def default(name, action, seqno) configure(["default route-map #{name} #{action} #{seqno}"]) end @@ -380,18 +426,18 @@ def default(name, action, seqno) # set_match_statements will set the match values for a specified routemap. # If the specified routemap does not exist, it will be created. # - # @commands + # commands # route-map action seqno match # - # @param [String] :name The name of the routemap to create + # @param name [String] The name of the routemap to create. # - # @param [String] :action Either permit or deny + # @param action [String] Either permit or deny. # - # @param [Integer] :seqno The sequence number + # @param seqno [Integer] The sequence number. # - # @param [Array] :value The routemap match rules + # @param value [Array] The routemap match rules. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_match_statements(name, action, seqno, value) cmds = ["route-map #{name} #{action} #{seqno}"] remove_match_statements(name, action, seqno, cmds) @@ -405,18 +451,18 @@ def set_match_statements(name, action, seqno, value) # set_set_statements will set the set values for a specified routemap. # If the specified routemap does not exist, it will be created. # - # @commands + # commands # route-map action seqno set # - # @param [String] :name The name of the routemap to create + # @param name [String] The name of the routemap to create. # - # @param [String] :action Either permit or deny + # @param action [String] Either permit or deny. # - # @param [Integer] :seqno The sequence number + # @param seqno [Integer] The sequence number. # - # @param [Array] :value The routemap set rules + # @param value [Array] The routemap set rules. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_set_statements(name, action, seqno, value) cmds = ["route-map #{name} #{action} #{seqno}"] remove_set_statements(name, action, seqno, cmds) @@ -430,18 +476,18 @@ def set_set_statements(name, action, seqno, value) # set_continue will set the continue value for a specified routemap. # If the specified routemap does not exist, it will be created. # - # @commands + # commands # route-map action seqno continue # - # @param [String] :name The name of the routemap to create + # @param name [String] The name of the routemap to create. # - # @param [String] :action Either permit or deny + # @param action [String] Either permit or deny. # - # @param [Integer] :seqno The sequence number + # @param seqno [Integer] The sequence number. # - # @param [Integer] :value The continue value + # @param value [Integer] The continue value. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_continue(name, action, seqno, value) cmds = ["route-map #{name} #{action} #{seqno}"] cmds << 'no continue' @@ -453,18 +499,18 @@ def set_continue(name, action, seqno, value) # set_description will set the description for a specified routemap. # If the specified routemap does not exist, it will be created. # - # @commands + # commands # route-map action seqno description # - # @param [String] :name The name of the routemap to create + # @param name [String] The name of the routemap to create. # - # @param [String] :action Either permit or deny + # @param action [String] Either permit or deny. # - # @param [Integer] :seqno The sequence number + # @param seqno [Integer] The sequence number. # - # @param [String] :value The description value + # @param value [String] The description value. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_description(name, action, seqno, value) cmds = ["route-map #{name} #{action} #{seqno}"] cmds << 'no description' diff --git a/lib/rbeapi/api/snmp.rb b/lib/rbeapi/api/snmp.rb index 3006260..f4d38fe 100644 --- a/lib/rbeapi/api/snmp.rb +++ b/lib/rbeapi/api/snmp.rb @@ -32,17 +32,17 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Snmp class provides a class implementation for working with the - # nodes SNMP configuration entity. This class presents an abstraction + # nodes SNMP configuration entity. This class presents an abstraction # of the node's snmp configuration from the running config. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M class Snmp < Entity DEFAULT_SNMP_LOCATION = '' DEFAULT_SNMP_CONTACT = '' @@ -63,7 +63,7 @@ class Snmp < Entity # source_interface: # } # - # @return[Hash] Returns the snmp resource as a Hash + # @return[Hash] Returns the snmp resource as a Hash. def get response = {} response.merge!(parse_location) @@ -77,14 +77,14 @@ def get ## # parse_location scans the running config from the node and parses - # the snmp location value if it exists in the configuration. If the + # the snmp location value if it exists in the configuration. If the # snmp location is not configure, then the DEFAULT_SNMP_LOCATION string - # is returned. The Hash returned by this method is merged into the + # is returned. The Hash returned by this method is merged into the # snmp resource Hash returned by the get method. # # @api private # - # @return [Hash] resource Hash attribute + # @return [Hash] Returns the resource Hash attribute. def parse_location mdata = /snmp-server location (.+)$/.match(config) { location: mdata.nil? ? DEFAULT_SNMP_LOCATION : mdata[1] } @@ -93,14 +93,14 @@ def parse_location ## # parse_contact scans the running config form the node and parses - # the snmp contact value if it exists in the configuration. If the + # the snmp contact value if it exists in the configuration. If the # snmp contact is not configured, then the DEFAULT_SNMP_CONTACT value - # is returned. The Hash returned by this method is merged into the + # is returned. The Hash returned by this method is merged into the # snmp resource Hash returned by the get method. # # @api private # - # @return [Hash] resource Hash attribute + # @return [Hash] Returns the resource Hash attribute. def parse_chassis_id mdata = /snmp-server chassis-id (.+)$/.match(config) { chassis_id: mdata.nil? ? DEFAULT_SNMP_CHASSIS_ID : mdata[1] } @@ -126,14 +126,14 @@ def parse_chassis_id ## # parse_source_interface scans the running config from the node and # parses the snmp source interface value if it exists in the - # configuration. If the snmp source interface is not configured, then - # the DEFAULT_SNMP_SOURCE_INTERFACE value is returned. The Hash + # configuration. If the snmp source interface is not configured, then + # the DEFAULT_SNMP_SOURCE_INTERFACE value is returned. The Hash # returned by this method is intended to be merged into the snmmp - # resource Hash + # resource Hash. # # @api private # - # @return [Hash] resource Hash attribute + # @return [Hash] Returns the resource Hash attribute. def parse_source_interface mdata = /snmp-server source-interface (.+)$/.match(config) { source_interface: mdata.nil? ? '' : mdata[1] } @@ -142,14 +142,14 @@ def parse_source_interface ## # parse_communities scans the running config from the node and parses all - # of the configure snmp community strings. If there are no configured + # of the configure snmp community strings. If there are no configured # snmp community strings, the community value is set to an empty array. # The returned hash is intended to be merged into the global snmp - # resource hash + # resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_communities values = config.scan(/snmp-server community (\w+) (ro|rw)[ ]?(.+)?$/) communities = values.each_with_object({}) do |value, hsh| @@ -162,9 +162,9 @@ def parse_communities ## # parse_notifications scans the running configuration and parses all of - # the snmp trap notifications configuration. It is expected the trap - # configuration is in the running config. The returned hash is intended - # to be merged into the resource hash + # the snmp trap notifications configuration. It is expected the trap + # configuration is in the running config. The returned hash is intended + # to be merged into the resource hash. def parse_notifications traps = config.scan(/(default|no)?[ ]?snmp-server enable traps (.+)$/) all = config.scan(/(default|no)?[ ]?snmp-server enable traps$/).first @@ -180,24 +180,26 @@ def parse_notifications ## # set_notification configures the snmp trap notification for the - # specified trap. The name option accepts the snmp trap name to + # specified trap. The name option accepts the snmp trap name to # configure or the keyword all to globally enable or disable - # notifications. If the optional state argument is not provided then the + # notifications. If the optional state argument is not provided then the # default state is default. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # snmp-server enable traps # no snmp-server enable traps # default snmp-server enable traps # - # @param [String] :name The name of the trap to configure or the keyword - # all. If this option is not specified, then the value of 'all' is - # used as the default. + # @param opts [Hash] The configuration parameters. # - # @param [String] :state The state to configure the trap notification. - # Valid values include 'on', 'off' or 'default' + # @option opts name [String] The name of the trap to configure or the + # keyword all. If this option is not specified, then the value of + # 'all' is used as the default. + # + # @option opts state [String] The state to configure the trap + # notification. Valid values include 'on', 'off' or 'default'. def set_notification(opts = {}) name = opts[:name] name = nil if name == 'all' @@ -208,29 +210,29 @@ def set_notification(opts = {}) ## # set_location updates the snmp location value in the nodes running - # configuration. If enable is false, then the snmp location value is - # negated using the no keyword. If the default keyword is set to true, + # configuration. If enable is false, then the snmp location value is + # negated using the no keyword. If the default keyword is set to true, # then the snmp location value is defaulted using the default keyword. # The default parameter takes precedence over the enable keyword. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # snmp-server location # no snmp-server location # default snmp-server location # - # @param [Hash] opts The configuration parameters + # @param opts [Hash] The configuration parameters. # - # @option opts [string] :value The snmp location value to configure + # @option opts value [string] The snmp location value to configure. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option opts [Boolean] :default Configure the snmp location value - # using the default keyword + # @option opts default [Boolean] Configure the snmp location value + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_location(opts = {}) cmd = command_builder('snmp-server location', opts) configure(cmd) @@ -238,30 +240,30 @@ def set_location(opts = {}) ## # set_contact updates the snmp contact value in the nodes running - # configuration. If enable is false in the opts Hash then - # the snmp contact value is negated using the no keyword. If the + # configuration. If enable is false in the opts Hash then + # the snmp contact value is negated using the no keyword. If the # default keyword is set to true, then the snmp contact value is - # defaulted using the default keyword. The default parameter takes + # defaulted using the default keyword. The default parameter takes # precedence over the enable keyword. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # snmp-server contact # no snmp-server contact # default snmp-server contact # - # @param [Hash] opts The configuration parameters + # @param opts [Hash] The configuration parameters. # - # @option opts [string] :value The snmp contact value to configure + # @option opts value [string] The snmp contact value to configure. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option opts [Boolean] :default Configures the snmp contact value - # using the default keyword + # @option opts default [Boolean] Configures the snmp contact value + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_contact(opts = {}) cmd = command_builder('snmp-server contact', opts) configure(cmd) @@ -269,30 +271,30 @@ def set_contact(opts = {}) ## # set_chassis_id updates the snmp chassis id value in the nodes - # running configuration. If enable is false in the opts + # running configuration. If enable is false in the opts # Hash then the snmp chassis id value is negated using the no - # keyword. If the default keyword is set to true, then the snmp - # chassis id value is defaulted using the default keyword. The default + # keyword. If the default keyword is set to true, then the snmp + # chassis id value is defaulted using the default keyword. The default # keyword takes precedence over the enable keyword. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # snmp-server chassis-id # no snmp-server chassis-id # default snmp-server chassis-id # - # @param [Hash] opts The configuration parameters + # @param opts [Hash] The configuration parameters # - # @option opts [string] :value The snmp chassis id value to configure + # @option opts value [string] The snmp chassis id value to configure # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option opts [Boolean] :default Configures the snmp chassis id value - # using the default keyword + # @option opts default [Boolean] Configures the snmp chassis id value + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_chassis_id(opts = {}) cmd = command_builder('snmp-server chassis-id', opts) configure(cmd) @@ -300,30 +302,30 @@ def set_chassis_id(opts = {}) ## # set_source_interface updates the snmp source interface value in the - # nodes running configuration. If enable is false in the opts + # nodes running configuration. If enable is false in the opts # Hash then the snmp source interface is negated using the no keyword. # If the default keyword is set to true, then the snmp source interface - # value is defaulted using the default keyword. The default keyword + # value is defaulted using the default keyword. The default keyword # takes precedence over the enable keyword. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # snmp-server source-interface # no snmp-server source-interface # default snmp-server source-interface # - # @param [Hash] opts The configuration parameters + # @param opts [Hash] The configuration parameters. # - # @option opts [string] :value The snmp source interface value to - # configure. This method will not ensure the interface is present - # in the configuration - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [string] The snmp source interface value to + # configure. This method will not ensure the interface is present + # in the configuration. + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default Configures the snmp source interface - # value using the default keyword + # @option opts default [Boolean] Configures the snmp source interface + # value using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_source_interface(opts = {}) cmd = command_builder('snmp-server source-interface', opts) configure(cmd) @@ -331,65 +333,67 @@ def set_source_interface(opts = {}) ## # add_community adds a new snmp community to the nodes running - # configuration. This function is a convenience function that passes the + # configuration. This function is a convenience function that passes the # message to set_community_access. # # @see set_community_access # - # @param [String] :name The name of the snmp community to add to the + # @param name [String] The name of the snmp community to add to the # nodes running configuration. # - # @param [String] :access Specifies the access level to assign to the - # new snmp community. Valid values are 'rw' or 'ro' + # @param access [String] Specifies the access level to assign to the + # new snmp community. Valid values are 'rw' or 'ro'. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_community(name, access = 'ro') set_community_access(name, access) end ## # remove_community removes the specified community from the nodes running - # configuration. If the specified name is not configured, this method + # configuration. If the specified name is not configured, this method # will still return successfully. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # no snmp-server community # - # @param [String] :name The name of the snmp community to add to the + # @param name [String] The name of the snmp community to add to the # nodes running configuration. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def remove_community(name) configure "no snmp-server community #{name}" end ## # set_community_acl configures the acl to apply to the specified - # community name. When enable is true, it will remove the + # community name. When enable is true, it will remove the # the named community and then add the new acl entry. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # no snmp-server [ro|rw] # snmp-server [ro|rw] # - # @param [String] :name The name of the snmp community to add to the + # @param name [String] The name of the snmp community to add to the # nodes running configuration. # - # @param [Hash] opts The configuration parameters + # @param opts [Hash] The configuration parameters. # - # @option opts [String] :value The name of the acl to apply to the snmp + # @option opts value [String] The name of the acl to apply to the snmp # community in the nodes config. If nil, then the community name # allows access to all objects. - # @option opts [Boolean] :enable If false then the command is + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default Configure the snmp community name + # + # @option opts default [Boolean] Configure the snmp community name # using the default keyword. Default takes precedence over enable. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_community_acl(name, opts = {}) value = opts[:value] enable = opts.fetch(:enable, true) @@ -407,11 +411,11 @@ def set_community_acl(name, opts = {}) # set_community_access configures snmp-server community with designated # name and access values. # - # @param [String] :name The snmp-server community name value + # @param name [String] The snmp-server community name value. # - # @param [String] :access The snmp-server community access value + # @param access [String] The snmp-server community access value. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_community_access(name, access) configure "snmp-server community #{name} #{access}" end diff --git a/lib/rbeapi/api/staticroutes.rb b/lib/rbeapi/api/staticroutes.rb index 1efe459..313b0a7 100644 --- a/lib/rbeapi/api/staticroutes.rb +++ b/lib/rbeapi/api/staticroutes.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Staticroutes class provides a configuration instance for working @@ -43,7 +43,7 @@ module Api # class Staticroutes < Entity ## - # Returns the static routes configured on the node + # Returns the static routes configured on the node. # # @example # { @@ -59,9 +59,9 @@ class Staticroutes < Entity # ] # } # - # @returns [Array] The method will return all of the + # @return [Array] The method will return all of the # configured static routes on the node as a Ruby array object - # containing a list of hashes with each hash describing a route. If + # containing a list of hashes with each hash describing a route. If # there are no static routes configured, this method will return # an empty array. def getall @@ -88,22 +88,28 @@ def getall ## # Creates a static route in EOS. May add or overwrite an existing route. # - # @commands + # commands # ip route [router_ip] [distance] [tag ] # [name ] # - # @param [String] :destination The destination and prefix matching the + # @param destination [String] The destination and prefix matching the # route(s). Ex '192.168.0.2/24'. - # @param [String] :nexthop The nexthop for this entry, which may an IP + # + # @param nexthop [String] The nexthop for this entry, which may an IP # address or interface name. - # @param [Hash] :opts Additional options for the route entry. - # @option :opts [String] :router_ip If nexthop is an egress interface, - # router_ip specifies the router to which traffic will be forwarded - # @option :opts [String] :distance The administrative distance (metric) - # @option :opts [String] :tag The route tag - # @option :opts [String] :name A route name # - # @return [Boolean] returns true on success + # @param opts [Hash] Additional options for the route entry. + # + # @option opts router_ip [String] If nexthop is an egress interface, + # router_ip specifies the router to which traffic will be forwarded. + # + # @option opts distance [String] The administrative distance (metric). + # + # @option opts tag [String] The route tag. + # + # @option opts name [String] A route name. + # + # @return [Boolean] Returns True on success, otherwise False. def create(destination, nexthop, opts = {}) cmd = "ip route #{destination} #{nexthop}" cmd << " #{opts[:router_ip]}" if opts[:router_ip] @@ -114,18 +120,19 @@ def create(destination, nexthop, opts = {}) end ## - # Removes a given route from EOS. May remove multiple routes if nexthop + # Removes a given route from EOS. May remove multiple routes if nexthop # is not specified. # - # @commands + # commands # no ip route [nexthop] # - # @param [String] :destination The destination and prefix matching the + # @param destination [String] The destination and prefix matching the # route(s). Ex '192.168.0.2/24'. - # @param [String] :nexthop The nexthop for this entry, which may an IP + # + # @param nexthop [String] The nexthop for this entry, which may an IP # address or interface name. # - # @return [Boolean] returns true on success + # @return [Boolean] Returns True on success, otherwise False. def delete(destination, nexthop = nil) cmd = "no ip route #{destination}" cmd << " #{nexthop}" if nexthop diff --git a/lib/rbeapi/api/stp.rb b/lib/rbeapi/api/stp.rb index bd2a25f..20e5b9c 100644 --- a/lib/rbeapi/api/stp.rb +++ b/lib/rbeapi/api/stp.rb @@ -31,14 +31,14 @@ # ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Stp class provides a base class instance for working with - # the EOS spanning-tree configuration + # the EOS spanning-tree configuration. # class Stp < Entity ## @@ -62,7 +62,7 @@ class Stp < Entity # } # } # - # @return [Hash] returns a Hash of attributes derived from eAPI + # @return [Hash] returns a Hash of attributes derived from eAPI. def get response = {} response.merge!(parse_mode) @@ -73,13 +73,13 @@ def get ## # parse_mode scans the nodes running configuration and extracts the - # value of the spanning-tree mode. The spanning tree mode is - # expected to be always be available in the running config. The return - # value is intended to be merged into the stp resource hash + # value of the spanning-tree mode. The spanning tree mode is + # expected to be always be available in the running config. The return + # value is intended to be merged into the stp resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Resource hash attribute. def parse_mode mdata = /(?<=spanning-tree\smode\s)(\w+)$/.match(config) { mode: mdata[1] } @@ -89,7 +89,7 @@ def parse_mode # instances returns a memoized instance of StpInstances for configuring # individual stp instances. # - # @return [StpInstances] an instance of StpInstances class + # @return [StpInstances] an instance of StpInstances class. def instances return @instances if @instances @instances = StpInstances.new(node) @@ -98,9 +98,9 @@ def instances ## # interfaces returns a memoized instance of StpInterfaces for - # configuring individual stp interfaces + # configuring individual stp interfaces. # - # @return [StpInterfaces] an instance of StpInterfaces class + # @return [StpInterfaces] an instance of StpInterfaces class. def interfaces return @interfaces if @interfaces @interfaces = StpInterfaces.new(node) @@ -113,27 +113,27 @@ def interfaces # mode is configured with the no keyword argument. If the default option # is specified then the mode is configured with the default keyword # argument. The default keyword argument takes precedence over the enable - # option if both are provided + # option if both are provided. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # spanning-tree mode # no spanning-tree mode # default spanning-tree mode # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the stp mode to - # in the nodes current running configuration + # @option opts value [String] The value to configure the stp mode to + # in the nodes current running configuration. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the stp mode value using - # the default keyword + # @option opts default [Boolean] Configure the stp mode value using + # the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] returns true if the command completed successfully. # def set_mode(opts = {}) cmd = command_builder('spanning-tree mode', opts) @@ -157,11 +157,11 @@ class StpInstances < Entity # priority: # } # - # @param [String] :inst The named stp instance to return + # @param inst [String] The named stp instance to return. # - # @return [nil, Hash] returns all configured stp instances - # found in the nodes running configuration + # @return [Hash] Returns all configured stp instances + # found in the nodes running configuration. def getall parse_instances.each_with_object({}) do |inst, hsh| values = get(inst) @@ -196,12 +196,12 @@ def getall ## # parse_instances will scan the nodes current configuration and extract - # the list of configured mst instances. If no instances are configured - # then this method will return an empty array + # the list of configured mst instances. If no instances are configured + # then this method will return an empty array. # # @api private # - # @return [Array] returns an Array of configured stp instances + # @return [Array] Returns an Array of configured stp instances. def parse_instances config = get_block('spanning-tree mst configuration') config.scan(/(?<=^\s{3}instance\s)\d+/) @@ -210,14 +210,14 @@ def parse_instances ## # parse_priority will scan the nodes current configuration and extract - # the stp priority value for the given stp instance. If the stp + # the stp priority value for the given stp instance. If the stp # instance priority is not configured, the priority value will be set - # using DEFAULT_STP_PRIORITY. The returned hash is intended to be merged - # into the resource hash + # using DEFAULT_STP_PRIORITY. The returned hash is intended to be merged + # into the resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Resource hash attribute. def parse_priority(inst) priority_re = /(?<=^spanning-tree\smst\s#{inst}\spriority\s)(.+$)/x mdata = priority_re.match(config) @@ -226,27 +226,31 @@ def parse_priority(inst) private :parse_priority ## - # Deletes a configured MST instance + # Deletes a configured MST instance. # - # @param [String] inst The MST instance to delete + # @param inst [String] The MST instance to delete. # - # @return [Boolean] True if the commands succeed otherwise False + # @return [Boolean] True if the commands succeed otherwise False. def delete(inst) configure ['spanning-tree mst configuration', "no instance #{inst}", 'exit'] end ## - # Configures the spanning-tree MST priority + # Configures the spanning-tree MST priority. # - # @param [String] inst The MST instance to configure - # @param [Hash] opts The configuration parameters for the priority - # @option opts [string] :value The value to set the priority to - # @option :opts [Boolean] :enable If false then the command is + # @param inst [String] The MST instance to configure. + # + # @param opts [Hash] The configuration parameters for the priority. + # + # @option opts value [string] The value to set the priority to. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default # - # @return [Boolean] True if the commands succeed otherwise False + # @option opts default [Boolean] The value should be set to default. + # + # @return [Boolean] True if the commands succeed otherwise False. def set_priority(inst, opts = {}) value = opts[:value] enable = opts.fetch(:enable, true) @@ -268,13 +272,13 @@ def set_priority(inst, opts = {}) ## # The StpInterfaces class provides a class instance for working with - # spanning-tree interfaces in EOS + # spanning-tree interfaces in EOS. # class StpInterfaces < Entity ## # get returns the configured stp interfaces from the nodes running - # configuration as a resource hash. If the specified interface is not - # configured as a switchport then this method will return nil + # configuration as a resource hash. If the specified interface is not + # configured as a switchport then this method will return nil. # # @example # { @@ -283,11 +287,11 @@ class StpInterfaces < Entity # bpduguard: # } # - # @param [String] :name The interface name to return a resource for from - # the nodes configuration + # @param name [String] The interface name to return a resource for from + # the nodes configuration. # - # @return [nil, Hash] returns the stp interface as a - # resource hash + # @return [nil, Hash] Returns the stp interface as a + # resource hash. def get(name) config = get_block("interface #{name}") return nil unless config @@ -301,8 +305,8 @@ def get(name) ## # getall returns all of the configured stp interfaces parsed from the - # nodes current running configuration. The returned hash is keyed by the - # interface name + # nodes current running configuration. The returned hash is keyed by the + # interface name. # # @example # { @@ -319,8 +323,8 @@ def get(name) # ... # } # - # @return [Hash] returns the stp interfaces config as a - # resource hash from the nodes running configuration + # @return [Hash] Returns the stp interfaces config as a + # resource hash from the nodes running configuration. def getall interfaces = config.scan(/(?<=^interface\s)[Et|Po].+/) resp = interfaces.each_with_object({}) do |name, hsh| @@ -332,12 +336,12 @@ def getall ## # parse_portfast scans the supplied interface configuration block and - # parses the value stp portfast. The value of portfast is either enabled - # (true) or disabled (false) + # parses the value stp portfast. The value of portfast is either enabled + # (true) or disabled (false). # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Resource hash attribute. def parse_portfast(config) val = /no spanning-tree portfast/ =~ config { portfast: val.nil? } @@ -346,12 +350,12 @@ def parse_portfast(config) ## # parse_portfast_type scans the supplied interface configuration block - # and parses the value stp portfast type. The value of portfast type + # and parses the value stp portfast type. The value of portfast type # is either not set which implies normal (default), edge, or network. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Resource hash attribute. def parse_portfast_type(config) if /spanning-tree portfast network/ =~ config value = 'network' @@ -366,12 +370,12 @@ def parse_portfast_type(config) ## # parse_bpduguard scans the supplied interface configuration block and - # parses the value of stp bpduguard. The value of bpduguard is either - # disabled (false) or enabled (true) + # parses the value of stp bpduguard. The value of bpduguard is either + # disabled (false) or enabled (true). # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Resource hash attribute. def parse_bpduguard(config) val = /spanning-tree bpduguard enable/ =~ config { bpduguard: !val.nil? } @@ -379,16 +383,20 @@ def parse_bpduguard(config) private :parse_bpduguard ## - # Configures the interface portfast value + # Configures the interface portfast value. # - # @param [String] name The name of the interface to configure - # @param [Hash] opts The configuration parameters for portfast - # @option opts [Boolean] :value The value to set portfast - # @option :opts [Boolean] :enable If false then the command is + # @param name [String] The name of the interface to configure. + # + # @param opts [Hash] The configuration parameters for portfast. + # + # @option opts value [Boolean] The value to set portfast. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default # - # @return [Boolean] True if the commands succeed otherwise False + # @option opts default [Boolean] The value should be set to default. + # + # @return [Boolean] True if the commands succeed otherwise False. def set_portfast(name, opts = {}) cmd = command_builder('spanning-tree portfast', opts) configure_interface(name, cmd) @@ -397,15 +405,19 @@ def set_portfast(name, opts = {}) ## # Configures the interface portfast type value # - # @param [String] name The name of the interface to configure - # @param [Hash] opts The configuration parameters for portfast type - # @option opts [String] :value The value to set portfast type to. + # @param name [String] The name of the interface to configure. + # + # @param opts [Hash] The configuration parameters for portfast type. + # + # @option opts value [String] The value to set portfast type to. # The value must be set for calls to this method. - # @option opts [Boolean] :enable If false then the command is + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default # - # @return [Boolean] True if the commands succeed otherwise False + # @option opts default [Boolean] The value should be set to default. + # + # @return [Boolean] True if the commands succeed otherwise False. def set_portfast_type(name, opts = {}) value = opts[:value] fail ArgumentError, 'value must be set' unless value @@ -428,14 +440,18 @@ def set_portfast_type(name, opts = {}) ## # Configures the interface bpdu guard value # - # @param [String] name The name of the interface to configure - # @param [Hash] opts The configuration parameters for bpduguard - # @option opts [Boolean] :value The value to set bpduguard - # @option opts [Boolean] :enable If false then the bpduguard is + # @param name [String] The name of the interface to configure. + # + # @param opts [Hash] The configuration parameters for bpduguard. + # + # @option opts value [Boolean] The value to set bpduguard. + # + # @option opts enable [Boolean] If false then the bpduguard is # disabled. If true then the bpduguard is enabled. Default is true. - # @option opts [Boolean] :default The value should be set to default # - # @return [Boolean] True if the commands succeed otherwise False + # @option opts default [Boolean] The value should be set to default. + # + # @return [Boolean] True if the commands succeed otherwise False. def set_bpduguard(name, opts = {}) enable = opts.fetch(:enable, true) default = opts[:default] || false diff --git a/lib/rbeapi/api/switchports.rb b/lib/rbeapi/api/switchports.rb index dba8c8e..45c9b15 100644 --- a/lib/rbeapi/api/switchports.rb +++ b/lib/rbeapi/api/switchports.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Switchport class provides a base class instance for working with @@ -44,7 +44,7 @@ module Api class Switchports < Entity ## # Retrieves the properties for a logical switchport from the - # running-config using eAPI + # running-config using eAPI. # # Example # { @@ -56,10 +56,10 @@ class Switchports < Entity # "trunk_groups": array # } # - # @param [String] :name The full name of the interface to get. The - # interface name must be the full interface (ie Ethernet, not Et) + # @param name [String] The full name of the interface to get. The + # interface name must be the full interface (ie Ethernet, not Et). # - # @return [Hash] a hash that includes the switchport properties + # @return [Hash] Returns a hash that includes the switchport properties. def get(name) config = get_block("interface #{name}") return nil unless config @@ -75,14 +75,14 @@ def get(name) end ## - # parse_mode parses switchport mode from the provided config + # parse_mode parses switchport mode from the provided config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_mode(config) mdata = /(?<=\s{3}switchport\smode\s)(.+)$/.match(config) { mode: mdata[1] } @@ -91,14 +91,14 @@ def parse_mode(config) ## # parse_access_vlan parses access vlan from the provided - # config + # config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_access_vlan(config) mdata = /(?<=access\svlan\s)(.+)$/.match(config) { access_vlan: mdata[1] } @@ -107,14 +107,14 @@ def parse_access_vlan(config) ## # parse_trunk_native_vlan parses trunk native vlan from - # the provided config + # the provided config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_trunk_native_vlan(config) mdata = /(?<=trunk\snative\svlan\s)(.+)$/.match(config) { trunk_native_vlan: mdata[1] } @@ -123,14 +123,14 @@ def parse_trunk_native_vlan(config) ## # parse_trunk_allowed_vlans parses trunk allowed vlan from - # the provided config + # the provided config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_trunk_allowed_vlans(config) mdata = /(?<=trunk\sallowed\svlan\s)(.+)$/.match(config) return { trunk_allowed_vlans: [] } unless mdata[1] != 'none' @@ -149,14 +149,14 @@ def parse_trunk_allowed_vlans(config) ## # parse_trunk_groups parses trunk group values from the - # provided config + # provided config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_trunk_groups(config) mdata = config.scan(/(?<=trunk\sgroup\s)(.+)$/) mdata = mdata.flatten if mdata.length > 0 @@ -165,7 +165,7 @@ def parse_trunk_groups(config) private :parse_trunk_groups ## - # Retrieves all switchport interfaces from the running-config + # Retrieves all switchport interfaces from the running-config. # # @example # { @@ -186,7 +186,7 @@ def parse_trunk_groups(config) # ... # } # - # @return [Array] an array of switchport hashes + # @return [Array] Returns an array of switchport hashes. def getall interfaces = config.scan(/(?<=^interface\s)([Et|Po].+)$/) interfaces.each_with_object({}) do |port, hsh| @@ -196,31 +196,31 @@ def getall end ## - # Creates a new logical switchport interface in EOS + # Creates a new logical switchport interface in EOS. # - # @param [String] name The name of the logical interface + # @param name [String] The name of the logical interface. # - # @return [Boolean] True if it succeeds otherwise False + # @return [Boolean] Returns True if it succeeds otherwise False. def create(name) configure ["interface #{name}", 'no ip address', 'switchport'] end ## - # Deletes a logical switchport interface from the running-config + # Deletes a logical switchport interface from the running-config. # - # @param [String] name The name of the logical interface + # @param name [String] The name of the logical interface. # - # @return [Boolean] True if it succeeds otherwise False + # @return [Boolean] Returns True if it succeeds otherwise False. def delete(name) configure ["interface #{name}", 'no switchport'] end ## - # Defaults a logical switchport interface in the running-config + # Defaults a logical switchport interface in the running-config. # - # @param [String] name The name of the logical interface + # @param name [String] The name of the logical interface. # - # @return [Boolean] True if it succeeds otherwise False + # @return [Boolean] Returns True if it succeeds otherwise False. def default(name) configure ["interface #{name}", 'default switchport'] end @@ -228,14 +228,18 @@ def default(name) ## # Configures the switchport mode for the specified interface. # - # @param [String] name The name of the interface to configure - # @param [Hash] opts The configuration parameters for the interface - # @option opts [string] :value The value to set the mode to - # @option opts [Boolean] :enable If false then the command is + # @param name [String] The name of the interface to configure. + # + # @param opts [Hash] The configuration parameters for the interface. + # + # @option opts value [string] The value to set the mode to. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default # - # @return [Boolean] True if the commands succeed otherwise False + # @option opts default [Boolean] The value should be set to default. + # + # @return [Boolean] Returns True if the commands succeed otherwise False. def set_mode(name, opts = {}) cmd = command_builder('switchport mode', opts) configure_interface(name, cmd) @@ -243,31 +247,35 @@ def set_mode(name, opts = {}) ## # set_trunk_allowed_vlans configures the list of vlan ids that are - # allowed on the specified trunk port. If the enable option is set to + # allowed on the specified trunk port. If the enable option is set to # false, then the allowed trunks is configured using the no keyword. # If the default keyword is provided then the allowed trunks is configured - # using the default keyword The default option takes precedence over the - # enable option if both are specified + # using the default keyword. The default option takes precedence over the + # enable option if both are specified. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # switchport trunk allowed vlan add # no switchport trunk allowed vlan # default switchport trunk allowed vlan # - # @param [String] name The name of the interface to configure - # @param [Hash] opts The configuration parameters for the interface - # @option pts [Array] :value The list of vlan ids to configure on the - # switchport to be allowed. This value must be an array of valid vlan - # ids - # @option opts [Boolean] :enable If false then the command is + # @param name [String] The name of the interface to configure. + # + # @param opts [Hash] The configuration parameters for the interface. + # + # @option ots value [Array] The list of vlan ids to configure on the + # switchport to be allowed. This value must be an array of valid vlan + # ids. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option [Boolean] :default Configures the switchport trunk allowed + # + # @option default [Boolean] Configures the switchport trunk allowed # vlans command using the default keyword. Default takes precedence # over enable. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def set_trunk_allowed_vlans(name, opts = {}) value = opts[:value] enable = opts.fetch(:enable, true) @@ -297,15 +305,19 @@ def set_trunk_allowed_vlans(name, opts = {}) # This value is only valid if the switchport mode is configure as # trunk. # - # @param [String] name The name of the interface to configure - # @param [Hash] opts The configuration parameters for the interface - # @option opts [string] :value The value of the trunk native vlan - # @option :opts [Boolean] :enable If false then the command is + # @param name [String] The name of the interface to configure. + # + # @param opts [Hash] The configuration parameters for the interface. + # + # @option opts value [string] The value of the trunk native vlan. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default. + # + # @option opts default [Boolean] The value should be set to default. # Default takes precedence over enable. # - # @return [Boolean] True if the commands succeed otherwise False + # @return [Boolean] Returns True if the commands succeed otherwise False. def set_trunk_native_vlan(name, opts = {}) cmd = command_builder('switchport trunk native vlan', opts) configure_interface(name, cmd) @@ -316,15 +328,19 @@ def set_trunk_native_vlan(name, opts = {}) # This value is only valid if the switchport mode is configure # in access mode. # - # @param [String] name The name of the interface to configure - # @param [Hash] opts The configuration parameters for the interface - # @option opts [string] :value The value of the access vlan - # @option opts [Boolean] :enable If false then the command is + # @param name [String] The name of the interface to configure. + # + # @param opts [Hash] The configuration parameters for the interface. + # + # @option opts value [string] The value of the access vlan. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default + # + # @option opts default [Boolean] The value should be set to default # Default takes precedence over enable. # - # @return [Boolean] True if the commands succeed otherwise False + # @return [Boolean] Returns True if the commands succeed otherwise False. def set_access_vlan(name, opts = {}) cmd = command_builder('switchport access vlan', opts) configure_interface(name, cmd) @@ -335,15 +351,19 @@ def set_access_vlan(name, opts = {}) # Trunk groups not currently set are added and trunk groups # currently configured but not in the passed in value array are removed. # - # @param [String] name The name of the interface to configure - # @param [Hash] opts The configuration parameters for the interface - # @option opts [string] :value Set of values to configure the trunk group - # @option opts [Boolean] :enable If false then the command is + # @param name [String] The name of the interface to configure. + # + # @param opts [Hash] The configuration parameters for the interface. + # + # @option opts value [string] Set of values to configure the trunk group. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default + # + # @option opts default [Boolean] The value should be set to default # Default takes precedence over enable. # - # @return [Boolean] True if the commands succeed otherwise False + # @return [Boolean] Returns True if the commands succeed otherwise False. def set_trunk_groups(name, opts = {}) default = opts.fetch(:default, false) if default @@ -362,12 +382,12 @@ def set_trunk_groups(name, opts = {}) current_value = Set.new get(name)[:trunk_groups] cmds = [] - # Add trunk groups that are not currently in the list + # Add trunk groups that are not currently in the list. value.difference(current_value).each do |group| cmds << "switchport trunk group #{group}" end - # Remove trunk groups that are not in the new list + # Remove trunk groups that are not in the new list. current_value.difference(value).each do |group| cmds << "no switchport trunk group #{group}" end diff --git a/lib/rbeapi/api/tacacs.rb b/lib/rbeapi/api/tacacs.rb index 4b34ae5..308376b 100644 --- a/lib/rbeapi/api/tacacs.rb +++ b/lib/rbeapi/api/tacacs.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # Tacacs provides instance methods to retrieve and set tacacs configuration @@ -45,7 +45,7 @@ class Tacacs < Entity DEFAULT_KEY = nil # Regular expression to extract a tacacs server's attributes from the - # running-configuration text. The explicit [ ] spaces enable line + # running-configuration text. The explicit [ ] spaces enable line # wrapping and indentation with the /x flag. SERVER_REGEXP = /tacacs-server[ ]host[ ]([^\s]+) (?:[ ](single-connection))? @@ -72,7 +72,7 @@ class Tacacs < Entity # timeout: # } # - # @return [Array] Single element Array of resource hashes + # @return [Array] Single element Array of resource hashes. def get global = {} global.merge!(parse_global_timeout) @@ -84,15 +84,13 @@ def get ## # parse_global_key takes a running configuration as a string and # parses out the radius global key and global key format if it exists in - # the configuration. An empty Hash is returned if there is no global key - # configured. The intent of the Hash is to be merged into a property + # the configuration. An empty Hash is returned if there is no global key + # configured. The intent of the Hash is to be merged into a property # hash. # - # @param [String] config The running configuration as a single string. - # # @api private # - # @return [Hash] resource hash attributes + # @return [Hash] Returns the resource hash attributes. def parse_global_key rsrc_hsh = {} (key_format, key) = config.scan(/tacacs-server key (\d+) (\w+)/).first @@ -105,15 +103,13 @@ def parse_global_key ## # parse_global_timeout takes a running configuration as a string # and parses out the tacacs global timeout if it exists in the - # configuration. An empty Hash is returned if there is no global timeout - # value configured. The intent of the Hash is to be merged into a + # configuration. An empty Hash is returned if there is no global timeout + # value configured. The intent of the Hash is to be merged into a # property hash. # - # @param [String] config The running configuration as a single string. - # # @api private # - # @return [Hash] resource hash attributes + # @return [Hash] Returns the resource hash attributes. def parse_global_timeout timeout = config.scan(/tacacs-server timeout (\d+)/).first { timeout: timeout.first.to_i } @@ -127,17 +123,17 @@ def parse_global_timeout # # The resource hash returned contains the following information: # - # * hostname: hostname or ip address, part of the identifier - # * port: (Fixnum) TCP port of the server, part of the identifier - # * key: (String) the key either in plain text or hashed format - # * key_format: (Fixnum) e.g. 0 or 7 - # * timeout: (Fixnum) seconds before the timeout period ends + # * hostname: hostname or ip address, part of the identifier. + # * port: (Fixnum) TCP port of the server, part of the identifier. + # * key: (String) the key either in plain text or hashed format. + # * key_format: (Fixnum) e.g. 0 or 7. + # * timeout: (Fixnum) seconds before the timeout period ends. # * multiplex: (Boolean) true when configured to make requests through a - # single connection + # single connection. # # @api public # - # @return [Array>] Array of resource hashes + # @return [Array>] Array of resource hashes. def servers tuples = config.scan(SERVER_REGEXP) tuples.map do |(host, mplex, vrf, port, tout, keyfm, key)| @@ -154,19 +150,19 @@ def servers end ## - # set_global_key configures the tacacs default key. This method maps to + # set_global_key configures the tacacs default key. This method maps to # the `tacacs-server key` EOS configuration command, e.g. `tacacs-server # key 7 070E234F1F5B4A`. # - # @option opts [String] :key ('070E234F1F5B4A') The key value + # @option opts key [String] ('070E234F1F5B4A') The key value. # - # @option opts [Fixnum] :key_format (7) The key format, 0 for plain text - # and 7 for a hashed value. 7 will be assumed if this option is not + # @option opts key_format [Fixnum] (7) The key format, 0 for plain text + # and 7 for a hashed value. 7 will be assumed if this option is not # provided. # # @api public # - # @return [Boolean] true if no errors + # @return [Boolean] Returns true if no errors. def set_global_key(opts = {}) format = opts[:key_format] key = opts[:key] @@ -176,18 +172,21 @@ def set_global_key(opts = {}) end ## - # set_timeout configures the tacacs default timeout. This method maps to + # set_timeout configures the tacacs default timeout. This method maps to # the `tacacs-server timeout` setting. # - # @param [Hash] opts The configuration parameters - # @option opts [string] :value The value to set the timeout to - # @option :opts [Boolean] :enable If false then the command is + # @param opts [Hash] The configuration parameters. + # + # @option opts value [string] The value to set the timeout to. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default + # + # @option opts default [Boolean] The value should be set to default. # # @api public # - # @return [Boolean] true if no errors + # @return [Boolean] Returns true if no errors. def set_global_timeout(opts = {}) cmd = command_builder('tacacs-server timeout', opts) configure cmd @@ -197,11 +196,25 @@ def set_global_timeout(opts = {}) # update_server configures a tacacs server resource on the target device. # This API method maps to the `tacacs server host` command, e.g. # `tacacs-server host 1.2.3.4 single-connection port 4949 timeout 6 key 7 - # 06070D221D1C5A` + # 06070D221D1C5A`. # # @api public # - # @return [Boolean] true if there are no errors + # @param opts [Hash] The configuration parameters. + # + # @option opts key_format [Integer] The format for the key. + # + # @option opts hostname [String] The host value. + # + # @option opts multiplex [String] Defines single-connection. + # + # @option opts port [String] The port value. + # + # @option opts timeout [String] The timeout value. + # + # @option opts key [String] The key value. + # + # @return [Boolean] Returns true if there are no errors. def update_server(opts = {}) key_format = opts[:key_format] || 7 cmd = "tacacs-server host #{opts[:hostname]}" @@ -218,7 +231,13 @@ def update_server(opts = {}) # # @api public # - # @return [Boolean] true if no errors + # @param opts [Hash] The configuration parameters. + # + # @option hostname [String] The host value. + # + # @option port [String] The port value. + # + # @return [Boolean] Returns true if there are no errors. def remove_server(opts = {}) cmd = "no tacacs-server host #{opts[:hostname]}" cmd << " port #{opts[:port]}" if opts[:port] diff --git a/lib/rbeapi/api/users.rb b/lib/rbeapi/api/users.rb index 593157e..ca0f8d1 100644 --- a/lib/rbeapi/api/users.rb +++ b/lib/rbeapi/api/users.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Users class provides configuration of local user resources for @@ -63,7 +63,7 @@ def initialize(node) end ## - # get returns the local user configuration + # get returns the local user configuration. # # @example # { @@ -76,12 +76,12 @@ def initialize(node) # sshkey: # } # - # @param [String] :name The user name to return a resource for from the + # @param name [String] The user name to return a resource for from the # nodes configuration # # @return [nil, Hash] Returns the user resource as a # Hash. If the specified user name is not found in the nodes current - # configuration a nil object is returned + # configuration a nil object is returned. def get(name) # The regex used here parses the running configuration to find one # username entry. @@ -100,7 +100,7 @@ def get(name) ## # getall returns a collection of user resource hashes from the nodes - # running configuration. The user resource collection hash is keyed + # running configuration. The user resource collection hash is keyed # by the unique user name. # # @example @@ -126,7 +126,7 @@ def get(name) # ... # ] # - # @return [Hash] returns a hash that represents the + # @return [Hash] Returns a hash that represents the # entire user collection from the nodes running configuration. If # there are no user names configured, this method will return an empty # hash. @@ -144,10 +144,10 @@ def getall # # @api private # - # @param [Array] :user An array of values returned from the regular + # @param user [Array] An array of values returned from the regular # expression scan of the nodes configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_user_entry(user) hsh = {} hsh[:name] = user[0] @@ -178,34 +178,34 @@ def parse_user_entry(user) # Optional parameters can be passed in to initialize user name specific # settings. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # username nopassword privilege role # username secret [0,5,sha512] ... # - # @param [String] :name The name of the user to create + # @param name [String] The name of the user to create. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :nopassword Configures the user to be able to - # authenticate without a password challenge + # @option opts nopassword [Boolean] Configures the user to be able to + # authenticate without a password challenge. # - # @option :opts [String] :secret The secret (password) to assign to this - # user + # @option opts secret [String] The secret (password) to assign to this + # user. # - # @option :opts [String] :encryption Specifies how the secret is encoded. + # @option opts encryption [String] Specifies how the secret is encoded. # Valid values are "cleartext", "md5", "sha512". The default is - # "cleartext" + # "cleartext". # - # @option :opts [String] :privilege The privilege value to assign to - # the user + # @option opts privilege [String] The privilege value to assign to + # the user. # - # @option :opts [String] :role The role value to assign to the user + # @option opts role [String] The role value to assign to the user. # - # @option :opts [String] :sshkey The sshkey value to assign to the user + # @option opts sshkey [String] The sshkey value to assign to the user. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(name, opts = {}) cmd = "username #{name}" cmd << " privilege #{opts[:privilege]}" if opts[:privilege] @@ -234,134 +234,134 @@ def create(name, opts = {}) ## # delete will delete an existing user name from the nodes current - # running configuration. If the delete method is called and the user + # running configuration. If the delete method is called and the user # name does not exist, this method will succeed. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # no username # - # @param [String] :name The user name to delete from the node. + # @param name [String] The user name to delete from the node. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete(name) configure("no username #{name}") end ## - # default will configure the user name using the default keyword. This + # default will configure the user name using the default keyword. This # command has the same effect as deleting the user name from the nodes # running configuration. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # default username # - # @param [String] :name The user name to default in the nodes + # @param name [String] The user name to default in the nodes # configuration. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def default(name) configure("default username #{name}") end ## # set_privilege configures the user privilege value for the specified user - # name in the nodes running configuration. If enable is false in the + # name in the nodes running configuration. If enable is false in the # opts keyword Hash then the name value is negated using the no # keyword. If the default keyword is set to true, then the privilege value - # is defaulted using the default keyword. The default keyword takes + # is defaulted using the default keyword. The default keyword takes # precedence over the enable keyword # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # username privilege # no username privilege # default username privilege # - # @param [String] :name The user name to default in the nodes + # @param name [String] The user name to default in the nodes # configuration. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The privilege value to assign to the user + # @option opts value [String] The privilege value to assign to the user. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the user privilege value - # using the default keyword + # @option opts default [Boolean] Configure the user privilege value + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_privilege(name, opts = {}) configure(command_builder("username #{name} privilege", opts)) end ## # set_role configures the user role value for the specified user - # name in the nodes running configuration. If enable is false in the + # name in the nodes running configuration. If enable is false in the # opts keyword Hash then the name value is negated using the no # keyword. If the default keyword is set to true, then the role value - # is defaulted using the default keyword. The default keyword takes + # is defaulted using the default keyword. The default keyword takes # precedence over the enable keyword # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # username role # no username role # default username role # - # @param [String] :name The user name to default in the nodes + # @param name [String] The user name to default in the nodes # configuration. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The role value to assign to the user + # @option opts value [String] The role value to assign to the user. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the user role value - # using the default keyword + # @option opts default [Boolean] Configure the user role value + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_role(name, opts = {}) configure(command_builder("username #{name} role", opts)) end ## # set_sshkey configures the user sshkey value for the specified user - # name in the nodes running configuration. If enable is false in the + # name in the nodes running configuration. If enable is false in the # opts keyword Hash then the name value is negated using the no # keyword. If the default keyword is set to true, then the sshkey value - # is defaulted using the default keyword. The default keyword takes - # precedence over the enable keyword + # is defaulted using the default keyword. The default keyword takes + # precedence over the enable keyword. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # username sshkey # no username sshkey # default username sshkey # - # @param [String] :name The user name to default in the nodes + # @param name [String] The user name to default in the nodes # configuration. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments # - # @option :opts [String] :value The sshkey value to assign to the user + # @option opts value [String] The sshkey value to assign to the user # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the user sshkey value - # using the default keyword + # @option opts default [Boolean] Configure the user sshkey value + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_sshkey(name, opts = {}) configure(command_builder("username #{name} sshkey", opts)) end diff --git a/lib/rbeapi/api/varp.rb b/lib/rbeapi/api/varp.rb index 45a4dcd..69b6292 100644 --- a/lib/rbeapi/api/varp.rb +++ b/lib/rbeapi/api/varp.rb @@ -32,17 +32,17 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Varp class provides an instance for working with the global - # VARP configuration of the node + # VARP configuration of the node. class Varp < Entity ## - # Returns the global VARP configuration from the node + # Returns the global VARP configuration from the node. # # @example # { @@ -58,7 +58,7 @@ class Varp < Entity # } # } # - # @return [Hash] A Ruby hash object that provides the Varp settings as + # @return [Hash] A Ruby hash object that provides the Varp settings as # key / value pairs. def get response = {} @@ -68,17 +68,17 @@ def get end ## - # parse_mac_address parses mac-address values from the provided config + # parse_mac_address parses mac-address values from the provided config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_mac_address(config) # ip virtual-router mac-address value will always - # be stored in aa:bb:cc:dd:ee:ff format + # be stored in aa:bb:cc:dd:ee:ff format. regex = /mac-address ((?:[a-f0-9]{2}:){5}[a-f0-9]{2})$/ mdata = regex.match(config) { mac_address: mdata.nil? ? '' : mdata[1] } @@ -92,15 +92,18 @@ def interfaces end ## - # Configure the VARP virtual-router mac-address value + # Configure the VARP virtual-router mac-address value. # - # @param [Hash] opts The configuration parameters - # @option opts [string] :value The value to set the mac-address to - # @option opts [Boolean] :enable If false then the command is + # @param opts [Hash] The configuration parameters. + # + # @option opts value [string] The value to set the mac-address to. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default # - # @return [Boolean] returns true if the command completed successfully + # @option opts default [Boolean] The value should be set to default. + # + # @return [Boolean] Returns true if the command completed successfully. def set_mac_address(opts = {}) cmd = command_builder('ip virtual-router mac-address', opts) configure(cmd) @@ -109,21 +112,21 @@ def set_mac_address(opts = {}) ## # The VarpInterfaces class provides an instance for working with the global - # VARP interface configuration of the node + # VARP interface configuration of the node. class VarpInterfaces < Entity ## - # Returns a single VARP interface configuration + # Returns a single VARP interface configuration. # # @example # { # "addresses": array # } # - # @param [String] :name The interface name to return the configuration - # values for. This must be the full interface identifier. + # @param name [String] The interface name to return the configuration + # values for. This must be the full interface identifier. # # @return [nil, Hash] A Ruby hash that represents the - # VARP interface configuration. A nil object is returned if the + # VARP interface configuration. A nil object is returned if the # specified interface is not configured def get(name) config = get_block("^interface #{name}") @@ -134,7 +137,7 @@ def get(name) ## # Returns the collection of MLAG interfaces as a hash index by the - # interface name + # interface name. # # @example # { @@ -148,7 +151,7 @@ def get(name) # } # # @return [nil, Hash] A Ruby hash that represents the - # MLAG interface configuration. A nil object is returned if no + # MLAG interface configuration. A nil object is returned if no # interfaces are configured. def getall interfaces = config.scan(/(?<=^interface\s)(Vl.+)$/) @@ -162,14 +165,14 @@ def getall ## # parse_addresses parses ip virtual-router address from the provided - # config + # config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_addresses(config) addrs = config.scan(/(?<=\s{3}ip\svirtual-router\saddress\s).+$/) { addresses: addrs } @@ -181,17 +184,21 @@ def parse_addresses(config) # to the specified VLAN interface. All existing addresses are # removed before the ones in value are added. # - # @param [String] :name The name of the interface. The - # name argument must be the full interface name. Valid interfaces - # are restricted to VLAN interfaces - # @param [Hash] opts The configuration parameters - # @option opts [Array] :value Array of IPv4 addresses to add to + # @param name [String] The name of the interface. The + # name argument must be the full interface name. Valid interfaces + # are restricted to VLAN interfaces. + # + # @param opts [Hash] The configuration parameters. + # + # @option opts value [Array] Array of IPv4 addresses to add to # the virtual router. - # @option opts [Boolean] :enable If false then the command is + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default # - # @return [Boolean] True if the commands succeeds otherwise False + # @option opts default [Boolean] The value should be set to default. + # + # @return [Boolean] True if the commands succeeds otherwise False. def set_addresses(name, opts = {}) value = opts[:value] enable = opts.fetch(:enable, true) @@ -215,27 +222,29 @@ def set_addresses(name, opts = {}) end ## - # The add_address method assigns one virtual IPv4 address + # The add_address method assigns one virtual IPv4 address. # - # @param [String] :name The name of the interface. The - # name argument must be the full interface name. Valid interfaces - # are restricted to VLAN interfaces - # @param [string] :address The virtual router address to add + # @param name [String] The name of the interface. The + # name argument must be the full interface name. Valid interfaces + # are restricted to VLAN interfaces. # - # @return [Boolean] True if the commands succeeds otherwise False + # @param value [string] The virtual router address to add. + # + # @return [Boolean] True if the commands succeeds otherwise False. def add_address(name, value) configure(["interface #{name}", "ip virtual-router address #{value}"]) end ## - # The remove_address method removes one virtual IPv4 address + # The remove_address method removes one virtual IPv4 address. + # + # @param name [String] The name of the interface. The + # name argument must be the full interface name. Valid interfaces + # are restricted to VLAN interfaces. # - # @param [String] :name The name of the interface. The - # name argument must be the full interface name. Valid interfaces - # are restricted to VLAN interfaces - # @param [string] :address The virtual router address to remove + # @param value [string] The virtual router address to remove. # - # @return [Boolean] True if the commands succeeds otherwise False + # @return [Boolean] True if the commands succeeds otherwise False. def remove_address(name, value) configure(["interface #{name}", "no ip virtual-router address #{value}"]) diff --git a/lib/rbeapi/api/vlans.rb b/lib/rbeapi/api/vlans.rb index 5567030..ef02a23 100644 --- a/lib/rbeapi/api/vlans.rb +++ b/lib/rbeapi/api/vlans.rb @@ -32,17 +32,17 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Vlan class provides a class implementation for working with the - # collection of Vlans on the node. This class presents an abstraction + # collection of Vlans on the node. This class presents an abstraction # of the nodes configured vlan id's from the running configuration. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M class Vlans < Entity ## # get returns the specified vlan resource Hash that represents the @@ -55,12 +55,12 @@ class Vlans < Entity # trunk_groups: array[] Returns the vlan resource as a - # Hash. If the specified vlan id is not found in the nodes current - # configuration a nil object is returned + # Hash. If the specified vlan id is not found in the nodes current + # configuration a nil object is returned. def get(id) config = get_block("vlan #{id}") return nil unless config @@ -73,8 +73,8 @@ def get(id) ## # getall returns the collection of vlan resources from the nodes - # running configuration as a hash. The vlan resource collection - # hash is keyed by the unique vlan id + # running configuration as a hash. The vlan resource collection + # hash is keyed by the unique vlan id. # # @example # { @@ -93,10 +93,10 @@ def get(id) # # @see get Vlan resource example # - # @return [Hash] returns a hash that represents the - # entire vlan collection from the nodes running configuration. If + # @return [Hash] Returns a hash that represents the + # entire vlan collection from the nodes running configuration. If # there are no vlans configured, this method will return an empty - # hash + # hash. def getall vlans = config.scan(/(?<=^vlan\s)\d+$/) vlans.each_with_object({}) do |vid, hsh| @@ -107,13 +107,13 @@ def getall ## # parse_name scans the provided configuration block and parses the - # vlan name value. The vlan name should always return a value - # from the running configuration. The return value is intended to - # be merged into the resource hash + # vlan name value. The vlan name should always return a value + # from the running configuration. The return value is intended to + # be merged into the resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_name(config) mdata = /name ([^\s]+)$/.match(config) { name: mdata[1] } @@ -123,12 +123,12 @@ def parse_name(config) ## # parse_state scans the provided configuration block and parses the # vlan state value. The vlan state should always return a value from - # the nodes running configuration. The return hash is intended to be - # merged into the resource hash + # the nodes running configuration. The return hash is intended to be + # merged into the resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_state(config) mdata = /state (\w+)$/.match(config) { state: mdata[1] } @@ -137,13 +137,13 @@ def parse_state(config) ## # parse_trunk_groups scans the provided configuration block and parses - # the trunk groups. If no trunk groups are found in the nodes + # the trunk groups. If no trunk groups are found in the nodes # running configuration then an empty array is returned as the value. # The return hash is intended to be merged into the resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_trunk_groups(config) values = config.scan(/trunk group (.+)$/).first values = [] unless values @@ -153,92 +153,92 @@ def parse_trunk_groups(config) ## # create will create a new vlan resource in the nodes current - # configuration with the specified vlan id. If the create method + # configuration with the specified vlan id. If the create method # is called and the vlan id already exists, this method will still # return true. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # vlan # - # @param [String, Integer] :id The vlan id to create on the node. The - # vlan id must be in the valid range of 1 to 4094 + # @param id [String, Integer] The vlan id to create on the node. The + # vlan id must be in the valid range of 1 to 4094. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(id) configure("vlan #{id}") end ## # delete will delete an existing vlan resource from the nodes current - # running configuration. If the delete method is called and the vlan + # running configuration. If the delete method is called and the vlan # id does not exist, this method will succeed. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # no vlan # - # @param [String, Integer] :id The vlan id to delete from the node. The - # id value should be in the valid range of 1 to 4094 + # @param id [String, Integer] The vlan id to delete from the node. The + # id value should be in the valid range of 1 to 4094. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete(id) configure("no vlan #{id}") end ## - # default will configure the vlan using the default keyword. This + # default will configure the vlan using the default keyword. This # command has the same effect as deleting the vlan from the nodes # running configuration. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # default vlan # - # @param [String, Integer] :id The vlan id to default in the nodes - # configuration. Ths vid value should be in the valid range of 1 - # to 4094 + # @param id [String, Integer] The vlan id to default in the nodes + # configuration. Ths vid value should be in the valid range of 1 + # to 4094. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def default(id) configure("default vlan #{id}") end ## # set_name configures the name value for the specified vlan id in the - # nodes running configuration. If enable is false in the + # nodes running configuration. If enable is false in the # opts keyword Hash then the name value is negated using the no - # keyword. If the default keyword is set to true, then the name value - # is defaulted using the default keyword. The default keyword takes - # precedence over the enable keyword + # keyword. If the default keyword is set to true, then the name value + # is defaulted using the default keyword. The default keyword takes + # precedence over the enable keyword. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # vlan # name # no name # default name # - # @param [String, Integer] :id The vlan id to apply the configuration - # to. The id value should be in the valid range of 1 to 4094 + # @param id [String, Integer] The vlan id to apply the configuration + # to. The id value should be in the valid range of 1 to 4094. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the vlan name - # to in the node configuration. The name parameter accepts a-z, 0-9 + # @option opts value [String] The value to configure the vlan name + # to in the node configuration. The name parameter accepts a-z, 0-9 # and _. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the vlan name value using - # the default keyword + # @option opts default [Boolean] Configure the vlan name value using + # the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_name(id, opts = {}) cmd = command_builder('name', opts) cmds = ["vlan #{id}", cmd] @@ -247,39 +247,39 @@ def set_name(id, opts = {}) ## # set_state configures the state value for the specified vlan id in - # the nodes running configuration. If enable is set to false in + # the nodes running configuration. If enable is set to false in # the opts keyword Hash then the state value is negated using the no # keyword. If the default keyword is set to true, then the state - # value is defaulted using the default keyword. The default keyword + # value is defaulted using the default keyword. The default keyword # takes precedence over the enable keyword # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # vlan # state [active, suspend] # no state # default state # - # @param [String, Integer] :id The vlan id to apply the configuration - # to. The id value should be in the valid range of 1 to 4094 + # @param id [String, Integer] The vlan id to apply the configuration + # to. The id value should be in the valid range of 1 to 4094. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the vlan state - # to in the node's configuration. Accepted values are 'active' or - # 'suspend' + # @option opts value [String] The value to configure the vlan state + # to in the node's configuration. Accepted values are 'active' or + # 'suspend'. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the vlan state value using - # the default keyword + # @option opts default [Boolean] Configure the vlan state value using + # the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. # # @raise [ArgumentError] if the value is not in the accept list of - # values + # values. def set_state(id, opts = {}) value = opts[:value] unless ['active', 'suspend', nil].include?(value) @@ -294,41 +294,41 @@ def set_state(id, opts = {}) ## # add_trunk_group adds a new trunk group value to the specified vlan # id in the nodes running configuration. The trunk group name value - # accepts a-z 0-9 and _ + # accepts a-z 0-9 and _. # - # @version 4.13.7M + # @since version 4.13.7M # - # @commands + # commands # vlan # trunk group # - # @param [String, Integer] :id The vlan id to apply the configuration - # to. the id value should be in the range of 1 to 4094 + # @param id [String, Integer] The vlan id to apply the configuration + # to. the id value should be in the range of 1 to 4094 # - # @param [String] :value The value to add to the vlan id configuration + # @param value [String] The value to add to the vlan id configuration # on the node. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_trunk_group(id, value) configure(["vlan #{id}", "trunk group #{value}"]) end ## # remove_trunk_group removes the specified trunk group value from the - # specified vlan id in the node's configuration. If the trunk group + # specified vlan id in the node's configuration. If the trunk group # name does not exist, this method will return success # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # vlan # no trunk group # - # @param [String, Integer] :id The vlan id to apply the configuration - # to. the id value should be in the range of 1 to 4094 + # @param id [String, Integer] The vlan id to apply the configuration + # to. the id value should be in the range of 1 to 4094. # - # @param [String] :value The value to remove from the list of trunk - # group names configured for the specified vlan + # @param value [String] The value to remove from the list of trunk + # group names configured for the specified vlan. # def remove_trunk_group(id, value) configure(["vlan #{id}", "no trunk group #{value}"]) diff --git a/lib/rbeapi/api/vrrp.rb b/lib/rbeapi/api/vrrp.rb index 69cf370..90d3fa0 100644 --- a/lib/rbeapi/api/vrrp.rb +++ b/lib/rbeapi/api/vrrp.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Eos is the toplevel namespace for working with Arista EOS nodes +# Eos is the toplevel namespace for working with Arista EOS nodes. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Vrrp class manages the set of virtual routers. @@ -74,7 +74,7 @@ def initialize(node) # } # } # - # @param [String] :name The layer 3 interface name. + # @param name [String] The layer 3 interface name. # # @return [nil, Hash] Returns the VRRP resource as a # Hash with the virtual router ID as the key. If the interface name @@ -128,7 +128,7 @@ def get(name) # # @return [nil, Hash] Returns a hash that represents # the entire virtual router IPs collection for all the layer 3 - # interfaces from the nodes running configuration. If there are no + # interfaces from the nodes running configuration. If there are no # virtual routers configured, this method will return an empty hash. def getall interfaces = config.scan(/(?<=^interface\s).+$/) @@ -144,8 +144,9 @@ def getall # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [Hash<'primary_ip', String>] Where string is the IPv4 # address or nil if the value is not set. @@ -166,8 +167,9 @@ def parse_primary_ip(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [Hash<'priority', Integer>] The priority is between # <1-255> or nil if the value is not set. @@ -188,8 +190,9 @@ def parse_priority(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [nil, Hash<'timers_advertise', Integer>] The timers_advertise # is between <1-255> or nil if the value is not set. @@ -210,8 +213,9 @@ def parse_timers_advertise(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [nil, Hash<'preempt', Integer>] The preempt is # between <1-255> or nil if the value is not set. @@ -232,8 +236,9 @@ def parse_preempt(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [Hash<'enable', Boolean>] def parse_enable(config, vrid) @@ -253,8 +258,9 @@ def parse_enable(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [nil, Hash<'secondary_ip', Array>] Returns an empty # array if the value is not set. @@ -275,8 +281,9 @@ def parse_secondary_ip(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [nil, Hash<'secondary_ip', String>] Returns nil if the # value is not set. @@ -297,8 +304,9 @@ def parse_description(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [Hash<'track', Array] Returns an empty array if the # value is not set. An example array of hashes follows: @@ -325,8 +333,9 @@ def parse_track(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [Hash<'ip_version', Integer>] Returns nil if the # value is not set. @@ -348,8 +357,9 @@ def parse_ip_version(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [Hash<'mac_addr_adv_interval', Integer>] Returns nil if the # value is not set. @@ -368,12 +378,13 @@ def parse_mac_addr_adv_interval(config, vrid) ## # parse_preempt_delay_min scans the nodes configurations for the given - # virtual router id and extracts the preempt delay minimum value.. + # virtual router id and extracts the preempt delay minimum value. # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [Hash<'preempt_delay_min', Integer>] Returns nil if the # value is not set. @@ -394,8 +405,9 @@ def parse_preempt_delay_min(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [Hash<'preempt_delay_reload', Integer>] Returns nil if the # value is not set. @@ -416,10 +428,11 @@ def parse_preempt_delay_reload(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # - # @return [Hash<'delay_reload', Integer>] Returns empty hash if the + # @return [Hash<'delay_reload', Integer>] Returns empty hash if the # value is not set. def parse_delay_reload(config, vrid) match = config.scan(/^\s+vrrp #{vrid} delay reload (\d+)$/) @@ -434,69 +447,69 @@ def parse_delay_reload(config, vrid) ## # create will create a new virtual router ID resource for the interface - # in the nodes current. If the create method is called and the virtual + # in the nodes current. If the create method is called and the virtual # router ID already exists for the interface, this method will still - # return true. Create takes optional parameters, but at least one + # return true. Create takes optional parameters, but at least one # parameter needs to be set or the command will fail. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # vrrp ... # - # @param [String] :name The layer 3 interface name. + # @param name [String] The layer 3 interface name. # - # @param [String] :vrid The virtual router id. + # @param vrid [String] The virtual router id. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable Enable the virtual router. + # @option opts enable [Boolean] Enable the virtual router. # - # @option :opts [String] :primary_ip The primary IPv4 address. + # @option opts primary_ip [String] The primary IPv4 address. # - # @option :opts [Integer] :priority The priority setting for a virtual + # @option opts priority [Integer] The priority setting for a virtual # router. # - # @option :opts [String] :description Associates a text string to a + # @option opts description [String] Associates a text string to a # virtual router. # - # @option :opts [Array] :secondary_ip The secondary IPv4 + # @option opts secondary_ip [Array] The secondary IPv4 # address to the specified virtual router. # - # @option :opts [Integer] :ip_version Configures the VRRP version for + # @option opts ip_version [Integer] Configures the VRRP version for # the VRRP router. # - # @option :opts [Integer] :timers_advertise The interval between + # @option opts timers_advertise [Integer] The interval between # successive advertisement messages that the switch sends to routers # in the specified virtual router ID. # - # @option :opts [Integer] :mac_addr_adv_interval Specifies interval in + # @option opts mac_addr_adv_interval [Integer] Specifies interval in # seconds between advertisement packets sent to VRRP group members. # - # @option :opts [Boolean] :preempt A virtual router preempt mode + # @option opts preempt [Boolean] A virtual router preempt mode # setting. When preempt mode is enabled, if the switch has a higher # priority it will preempt the current master virtual router. When # preempt mode is disabled, the switch can become the master virtual # router only when a master virtual router is not present on the # subnet, regardless of priority settings. # - # @option :opts [Integer] :preempt_delay_min Interval in seconds between + # @option opts preempt_delay_min [Integer] Interval in seconds between # VRRP preempt event and takeover. Minimum delays takeover when VRRP # is fully implemented. # - # @option :opts [Integer] :preempt_delay_reload Interval in seconds + # @option opts preempt_delay_reload [Integer] Interval in seconds # between VRRP preempt event and takeover. Reload delays takeover # after initialization following a switch reload. # - # @option :opts [Integer] :delay_reload Delay between system reboot and + # @option opts delay_reload [Integer] Delay between system reboot and # VRRP initialization. # - # @option :opts [Array] :track The track hash contains the + # @option opts track [Array] The track hash contains the # name of an interface to track, the action to take on state-change # of the tracked interface, and the amount to decrement the priority. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(name, vrid, opts = {}) fail ArgumentError, 'create has no options set' if opts.empty? cmds = [] @@ -555,16 +568,17 @@ def create(name, vrid, opts = {}) # and the virtual router id does not exist on the interface, this # method will succeed. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # no vrrp # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. + # @param name [String] The layer 3 interface name. # - # @return [Boolean] returns true if the command completed successfully + # @param vrid [Integer] The virtual router ID. + # + # @return [Boolean] Returns true if the command completed successfully. def delete(name, vrid) configure_interface(name, "no vrrp #{vrid}") end @@ -577,16 +591,17 @@ def delete(name, vrid) # virtual router id does not exist on the interface, this method will # succeed. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # default vrrp # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def default(name, vrid) configure_interface(name, "default vrrp #{vrid}") end @@ -594,26 +609,28 @@ def default(name, vrid) ## # set_shutdown enables and disables the virtual router. # - # @commands + # commands # interface # {no | default} vrrp shutdown # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. # - # @option :opts [Boolean] :enable If enable is true then the virtual + # @param vrid [Integer] The virtual router ID. + # + # @param opts [hash] Optional keyword arguments. + # + # @option opts enable [Boolean] If enable is true then the virtual # router is administratively enabled for the interface and if enable # is false then the virtual router is administratively disabled # for the interface. Default is true. # - # @option :opts [Boolean] :default Configure shutdown using + # @option opts default [Boolean] Configure shutdown using # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_shutdown(name, vrid, opts = {}) fail 'set_shutdown has the value option set' if opts[:value] - # Shutdown semantics are opposite of enable semantics so invert enable + # Shutdown semantics are opposite of enable semantics so invert enable. enable = opts.fetch(:enable, true) opts.merge!(enable: !enable) cmd = "vrrp #{vrid} shutdown" @@ -623,23 +640,25 @@ def set_shutdown(name, vrid, opts = {}) ## # set_primary_ip sets the primary IP address for the virtual router. # - # @commands + # commands # interface # {no | default} vrrp ip # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. + # + # @param opts [hash] Optional keyword arguments. # - # @option :opts [String] :value The primary IPv4 address. + # @option opts value [String] The primary IPv4 address. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the primary IP address using + # @option opts default [Boolean] Configure the primary IP address using # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_primary_ip(name, vrid, opts = {}) cmd = "vrrp #{vrid} ip" configure_interface(name, command_builder(cmd, opts)) @@ -648,23 +667,25 @@ def set_primary_ip(name, vrid, opts = {}) ## # set_priority sets the priority for a virtual router. # - # @commands + # commands # interface # {no | default} vrrp priority # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. # - # @option :opts [String] :value The priority value. + # @param vrid [Integer] The virtual router ID. # - # @option :opts [Boolean] :enable If false then the command is + # @param opts [hash] Optional keyword arguments. + # + # @option opts value [String] The priority value. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the priority using + # @option opts default [Boolean] Configure the priority using # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_priority(name, vrid, opts = {}) cmd = "vrrp #{vrid} priority" configure_interface(name, command_builder(cmd, opts)) @@ -673,23 +694,25 @@ def set_priority(name, vrid, opts = {}) ## # set_description sets the description for a virtual router. # - # @commands + # commands # interface # {no | default} vrrp description # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. # - # @option :opts [String] :value The description value. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] The description value. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the description using + # @option opts default [Boolean] Configure the description using # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_description(name, vrid, opts = {}) cmd = "vrrp #{vrid} description" configure_interface(name, command_builder(cmd, opts)) @@ -702,11 +725,11 @@ def set_description(name, vrid, opts = {}) # # @api private # - # @param [String] :name The layer 3 interface name. + # @param name [String] The layer 3 interface name. # - # @param [Integer] :vrid The virtual router ID. + # @param vrid [Integer] The virtual router ID. # - # @param [Array] :ip_addrs Array of secondary IPv4 address. + # @param ip_addrs [Array] Array of secondary IPv4 address. # An empty array will remove all secondary IPv4 addresses set for # the virtual router on the specified layer 3 interface. # @@ -744,27 +767,27 @@ def build_secondary_ip_cmd(name, vrid, ip_addrs) private :build_secondary_ip_cmd # set_secondary_ips configures the set of secondary IP addresses - # associated with the virtual router. The ip_addrs value passed - # should be an array of IP Addresses. This method will remove + # associated with the virtual router. The ip_addrs value passed + # should be an array of IP Addresses. This method will remove # secondary IP addresses that are currently set for the virtual # router but not included in the ip_addrs array value passed in. # The method will then add secondary IP addresses that are not # currently set for the virtual router but are included in the # ip_addrs array value passed in. # - # @commands + # commands # interface # {no} vrrp ip secondary # - # @param [String] :name The layer 3 interface name. + # @param name [String] The layer 3 interface name. # - # @param [Integer] :vrid The virtual router ID. + # @param vrid [Integer] The virtual router ID. # - # @param [Array] :ip_addrs Array of secondary IPv4 address. + # @param ip_addrs [Array] Array of secondary IPv4 address. # An empty array will remove all secondary IPv4 addresses set for # the virtual router on the specified layer 3 interface. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_secondary_ip(name, vrid, ip_addrs) cmds = build_secondary_ip_cmd(name, vrid, ip_addrs) return true if cmds.empty? @@ -774,23 +797,25 @@ def set_secondary_ip(name, vrid, ip_addrs) ## # set_ip_version sets the VRRP version for a virtual router. # - # @commands + # commands # interface # {no | default} vrrp ip version # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. # - # @option :opts [String] :value The VRRP version. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] The VRRP version. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the VRRP version using + # @option opts default [Boolean] Configure the VRRP version using # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_ip_version(name, vrid, opts = {}) cmd = "vrrp #{vrid} ip version" configure_interface(name, command_builder(cmd, opts)) @@ -801,23 +826,25 @@ def set_ip_version(name, vrid, opts = {}) # advertisement messages that the switch sends to routers in the # specified virtual router ID. # - # @commands + # commands # interface # {no | default} vrrp timers advertise # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. + # + # @param opts [hash] Optional keyword arguments. # - # @option :opts [String] :value The timer value in seconds. + # @option opts value [String] The timer value in seconds. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the timer advertise value + # @option opts default [Boolean] Configure the timer advertise value # using the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_timers_advertise(name, vrid, opts = {}) cmd = "vrrp #{vrid} timers advertise" configure_interface(name, command_builder(cmd, opts)) @@ -828,24 +855,26 @@ def set_timers_advertise(name, vrid, opts = {}) # advertisement packets sent to VRRP group members for the # specified virtual router ID. # - # @commands + # commands # interface # {no | default} vrrp mac-address advertisement-interval # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. + # + # @param opts [hash] Optional keyword arguments # - # @option :opts [String] :value The mac address advertisement interval + # @option opts value [String] The mac address advertisement interval # value in seconds. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the timer advertise value + # @option opts default [Boolean] Configure the timer advertise value # using the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_mac_addr_adv_interval(name, vrid, opts = {}) cmd = "vrrp #{vrid} mac-address advertisement-interval" configure_interface(name, command_builder(cmd, opts)) @@ -859,23 +888,25 @@ def set_mac_addr_adv_interval(name, vrid, opts = {}) # when a master virtual router is not present on the subnet, # regardless of priority settings. # - # @commands + # commands # interface # {no | default} vrrp preempt # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. # - # @option :opts [Boolean] :enable If enable is true then the virtual + # @param vrid [Integer] The virtual router ID. + # + # @param opts [hash] Optional keyword arguments. + # + # @option opts enable [Boolean] If enable is true then the virtual # router preempt mode is administratively enabled for the interface # and if enable is false then the virtual router preempt mode is # administratively disabled for the interface. Default is true. # - # @option :opts [Boolean] :default Configure the timer advertise value + # @option opts default [Boolean] Configure the timer advertise value # using the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_preempt(name, vrid, opts = {}) fail 'set_preempt has the value option set' if opts[:value] cmd = "vrrp #{vrid} preempt" @@ -886,23 +917,25 @@ def set_preempt(name, vrid, opts = {}) # set_preempt_delay_min sets the minimum time in seconds for the # virtual router to wait before taking over the active role. # - # @commands + # commands # interface # {no | default} vrrp preempt delay minimum # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. # - # @option :opts [String] :value The preempt delay minimum value. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] The preempt delay minimum value. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the preempt delay minimum + # @option opts default [Boolean] Configure the preempt delay minimum # value using the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_preempt_delay_min(name, vrid, opts = {}) cmd = "vrrp #{vrid} preempt delay minimum" configure_interface(name, command_builder(cmd, opts)) @@ -913,23 +946,25 @@ def set_preempt_delay_min(name, vrid, opts = {}) # only. This delay period applies only to the first interface-up # event after the virtual router has reloaded. # - # @commands + # commands # interface # {no | default} vrrp preempt delay reload # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. # - # @option :opts [String] :value The preempt delay reload value. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] The preempt delay reload value. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the preempt delay reload - # value using the default keyword. + # @option opts default [Boolean] :default Configure the preempt delay + # reload value using the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_preempt_delay_reload(name, vrid, opts = {}) cmd = "vrrp #{vrid} preempt delay reload" configure_interface(name, command_builder(cmd, opts)) @@ -939,23 +974,25 @@ def set_preempt_delay_reload(name, vrid, opts = {}) # set_delay_reload sets the delay between system reboot and VRRP # initialization for the virtual router. # - # @commands + # commands # interface # {no | default} vrrp delay reload # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. + # + # @param opts [hash] Optional keyword arguments # - # @option :opts [String] :value The delay reload value. + # @option opts value [String] The delay reload value. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the delay reload + # @option opts default [Boolean] Configure the delay reload # value using the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_delay_reload(name, vrid, opts = {}) cmd = "vrrp #{vrid} delay reload" configure_interface(name, command_builder(cmd, opts)) @@ -968,11 +1005,11 @@ def set_delay_reload(name, vrid, opts = {}) # # @api private # - # @param [String] :name The layer 3 interface name. + # @param name [String] The layer 3 interface name. # - # @param [Integer] :vrid The virtual router ID. + # @param vrid [Integer] The virtual router ID. # - # @param [Array] :tracks Array of a hash of track information. + # @param tracks [Array] Array of a hash of track information. # Hash format: { name: 'Eth2', action: 'decrement', amount: 33 }, # The name and action key are required. The amount key should only # be specified if the action is shutdown. The valid actions are @@ -1010,7 +1047,7 @@ def build_tracks_cmd(name, vrid, tracks) tracks = Set.new tracks - # Get the current tracks set for the virtual router + # Get the current tracks set for the virtual router. # A return of nil means that nothing has been configured for # the virtual router. vrrp = get(name) @@ -1041,27 +1078,27 @@ def build_tracks_cmd(name, vrid, tracks) private :build_tracks_cmd # set_tracks configures the set of track settings associated with - # the virtual router. The tracks value passed should be an array of - # hashes, each hash containing a track entry. This method will remove + # the virtual router. The tracks value passed should be an array of + # hashes, each hash containing a track entry. This method will remove # tracks that are currently set for the virtual router but not included - # in the tracks array value passed in. The method will then add + # in the tracks array value passed in. The method will then add # tracks that are not currently set for the virtual router but are # included in the tracks array value passed in. # - # @commands + # commands # interface # {no} vrrp track [] # - # @param [String] :name The layer 3 interface name. + # @param name [String] The layer 3 interface name. # - # @param [Integer] :vrid The virtual router ID. + # @param vrid [Integer] The virtual router ID. # - # @param [Array] :tracks Array of a hash of track information. + # @param tracks [Array] Array of a hash of track information. # Hash format: { name: 'Eth2', action: 'decrement', amount: 33 }, # An empty array will remove all tracks set for # the virtual router on the specified layer 3 interface. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_tracks(name, vrid, tracks) cmds = build_tracks_cmd(name, vrid, tracks) return true if cmds.empty? diff --git a/lib/rbeapi/utils.rb b/lib/rbeapi/utils.rb index d5337ab..663b001 100644 --- a/lib/rbeapi/utils.rb +++ b/lib/rbeapi/utils.rb @@ -33,19 +33,19 @@ require 'syslog' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Utils module + # Utils module. module Utils ## # Iterates through a hash structure and converts all of the keys # to symbols. # - # @param [Hash] :value The hash structure to convert the keys + # @param value [Hash] The hash structure to convert the keys. # # @return [Hash] An updated hash structure with all keys converted to - # symboles + # symboles. def self.transform_keys_to_symbols(value) return value unless value.is_a?(Hash) hash = value.each_with_object({}) do |(k, v), hsh| @@ -56,11 +56,11 @@ def self.transform_keys_to_symbols(value) end ## - # Returns a class object from a string capable of being instatiated + # Returns a class object from a string capable of being instatiated. # - # @param [String] :name The name of the class to return a constant for + # @param name [String] The name of the class to return a constant for. # - # @return [Object] Returns a a class object that can be instatiated + # @return [Object] Returns a a class object that can be instatiated. def self.class_from_string(name) name.split('::').inject(Object) do |mod, cls| mod.const_get(cls) @@ -70,7 +70,7 @@ def self.class_from_string(name) ## # Syslogs a warning message. # - # @param [String] :message The message to log. + # @param message [String] The message to log. def self.syslog_warning(message) Syslog.open('rbeapi', Syslog::LOG_PID) { |s| s.warning message } end diff --git a/lib/rbeapi/version.rb b/lib/rbeapi/version.rb index d179c37..f09e1db 100644 --- a/lib/rbeapi/version.rb +++ b/lib/rbeapi/version.rb @@ -31,7 +31,7 @@ # # # -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi VERSION = '0.4.0' end From 14437b37ca61814c0c2fbf6782465678bee7f9a1 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Tue, 19 Jan 2016 17:10:38 -0700 Subject: [PATCH 048/110] Update doc. --- lib/rbeapi/api/system.rb | 77 +++++++------ lib/rbeapi/client.rb | 233 ++++++++++++++++++++++----------------- lib/rbeapi/eapilib.rb | 125 ++++++++++++--------- 3 files changed, 243 insertions(+), 192 deletions(-) diff --git a/lib/rbeapi/api/system.rb b/lib/rbeapi/api/system.rb index 1d9abfd..db775f4 100644 --- a/lib/rbeapi/api/system.rb +++ b/lib/rbeapi/api/system.rb @@ -35,11 +35,11 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The System class configures the node system services such as - # hostname and domain name + # hostname and domain name. class System < Entity def initialize(node) super(node) @@ -47,7 +47,7 @@ def initialize(node) end ## - # Returns the system settings for hostname, iprouting, and banners + # Returns the system settings for hostname, iprouting, and banners. # # @example # { @@ -57,7 +57,7 @@ def initialize(node) # banner_login: # } # - # @return [Hash] A Ruby hash object that provides the system settings as + # @return [Hash] A Ruby hash object that provides the system settings as # key/value pairs. def get response = {} @@ -68,14 +68,14 @@ def get end ## - # parse_hostname parses hostname values from the provided config + # parse_hostname parses hostname values from the provided config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] The resource hash attribute. def parse_hostname(config) mdata = /(?<=^hostname\s)(.+)$/.match(config) { hostname: mdata.nil? ? '' : mdata[1] } @@ -83,14 +83,14 @@ def parse_hostname(config) private :parse_hostname ## - # parse_iprouting parses ip routing from the provided config + # parse_iprouting parses ip routing from the provided config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] The resource hash attribute. def parse_iprouting(config) mdata = /no\sip\srouting/.match(config) { iprouting: mdata.nil? ? true : false } @@ -103,10 +103,10 @@ def parse_iprouting(config) # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute. If the + # @return [Hash] The resource hash attribute. If the # banner is not set it will return a value of None for that key. def parse_banners(config) motd_value = login_value = '' @@ -123,49 +123,58 @@ def parse_banners(config) private :parse_banners ## - # Configures the system hostname value in the running-config + # Configures the system hostname value in the running-config. # - # @param [Hash] opts The configuration parameters - # @option opts [string] :value The value to set the hostname to - # @option :opts [Boolean] :enable If false then the command is + # @param opts [Hash] The configuration parameters. + # + # @option opts value [string] The value to set the hostname to. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option :opts [Boolean] :default If true configure the command using + # + # @option opts default [Boolean] If true configure the command using # the default keyword. Default is false. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_hostname(opts = {}) cmd = command_builder('hostname', opts) configure(cmd) end ## - # Configures the state of global ip routing + # Configures the state of global ip routing. # - # @param [Hash] opts The configuration parameters - # @option :opts [Boolean] :enable True if ip routing should be enabled + # @param opts [Hash] The configuration parameters. + # + # @option opts enable [Boolean] True if ip routing should be enabled # or False if ip routing should be disabled. Default is true. - # @option :opts [Boolean] :default If true configure the command using + # + # @option opts default [Boolean] If true configure the command using # the default keyword. Default is false. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_iprouting(opts = {}) cmd = command_builder('ip routing', opts) configure(cmd) end ## - # Configures system banners + # Configures system banners. # - # @param [String] :banner_type banner to be changed (likely either - # login or motd) - # @param [Hash] opts The configuration parameters - # @option opts [string] :value The value to set for the banner. - # @option :opts [Boolean] :enable If false then the command is + # @param banner_type [String] Banner to be changed (likely either + # login or motd). + # + # @param opts [Hash] The configuration parameters. + # + # @option opts value [string] The value to set for the banner. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option :opts [Boolean] :default If true configure the command using + # + # @option opts default [Boolean] If true configure the command using # the default keyword. Default is false. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_banner(banner_type, opts = {}) value = opts[:value] cmd_string = "banner #{banner_type}" diff --git a/lib/rbeapi/client.rb b/lib/rbeapi/client.rb index e11c53a..fe5ebb8 100644 --- a/lib/rbeapi/client.rb +++ b/lib/rbeapi/client.rb @@ -50,12 +50,12 @@ class << self 'socket' => 'Rbeapi::Eapilib::SocketEapiConnection' } ## - # Returns the currently loaded config object. This function will + # Returns the currently loaded config object. This function will # create a new instance of the config object if one doesn't already - # exist + # exist. # # @return [Config] Returns an instance of Config used for working - # with the eapi.conf file + # with the eapi.conf file. def config return @config if @config @config = Config.new @@ -64,11 +64,11 @@ def config ## # load_config overrides the default conf file loaded in the config - # instances using the supplied conf argument as the conf file. This + # instances using the supplied conf argument as the conf file. This # method will clear out an previously loaded configuration and replace # all entries with the contents of the supplied file. # - # @param [String] :conf The full path to the conf file to load into + # @param conf [String] The full path to the conf file to load into # the config instance. def load_config(conf) config.read(conf) @@ -76,15 +76,15 @@ def load_config(conf) ## # Returns the configuration options for the named connection from - # the loaded configuration. The configuration name is specified as + # the loaded configuration. The configuration name is specified as # the string right of the colon in the section name. # - # @param [String] :name The connection name to return from the loaded - # configuration + # @param name [String] The connection name to return from the loaded + # configuration. # # @return [Hash, nil] This method will return the configuration hash for - # the named configuration if found. If the name is not found, then - # nil is returned + # the named configuration if found. If the name is not found, then + # nil is returned. def config_for(name) config.get_connection(name) end @@ -93,11 +93,11 @@ def config_for(name) # Retrieves the node config from the loaded configuration file and # returns a Rbeapi::Node instance for working with the remote node. # - # @param [String] :name The named configuration to use for creating the - # connection to the remote node + # @param name [String] The named configuration to use for creating the + # connection to the remote node. # - # @return [Rbeapi::Node, nil] Returns an instance of Rbeapi::Node. If - # the named configuration is not found then nil is returned + # @return [Rbeapi::Node, nil] Returns an instance of Rbeapi::Node. If + # the named configuration is not found then nil is returned. def connect_to(name) config_entry = config_for(name) return nil unless config_entry @@ -114,26 +114,32 @@ def connect_to(name) ## # Builds a connection object to a remote node using the specified - # options and return an instance of Rbeapi::Connection. All + # options and return an instance of Rbeapi::Connection. All # configuration options can be passed via the :opts param. # - # @param [Hash] :opts the options to create a message with - # @option :opts [String] :host The IP address or hostname of the remote - # eAPI endpoint - # @option :opts [String] :username The username to use to authenticate - # the eAPI connection with - # @option :opts [String] :password The password to use to authenticate - # the eAPI connection with - # @option :opts [String] :enablepwd The enable password (if defined) to - # pass to the remote node to enter privilege mode - # @option :opts [String] :use_ssl Specifies whether or not to use the - # HTTP or HTTPS protocol - # @option :opts [String] :port The port to connect to. If not specified + # @param opts [Hash] the options to create a message with. + # + # @option opts host [String] The IP address or hostname of the remote + # eAPI endpoint. + # + # @option opts username [String] The username to use to authenticate + # the eAPI connection with. + # + # @option opts password [String] The password to use to authenticate + # the eAPI connection with. + # + # @option opts enablepwd [String] The enable password (if defined) to + # pass to the remote node to enter privilege mode. + # + # @option opts use_ssl [String] Specifies whether or not to use the + # HTTP or HTTPS protocol. + # + # @option opts port [String] The port to connect to. If not specified # The port is automatically determined based on the protocol used - # (443 for https, 80 for http) + # (443 for https, 80 for http). # # @return [Rbeapi::Connection] Returns an instance of Rbeapi::Connection - # using the specified configuration options + # using the specified configuration options. def connect(opts = {}) transport = opts.fetch(:transport, DEFAULT_TRANSPORT) make_connection(transport, opts) @@ -143,10 +149,11 @@ def connect(opts = {}) # Creates a connection instance that can either be used directly or # passed to a Node instance. # - # @params [String] :transport The name of the transport to create. - # @params [Hash] :opts The options used to create the transport + # @param transport [String] The name of the transport to create. # - # @return [Rbeapi::EapiConnection] A instance of a connection object + # @param opts [Hash] The options used to create the transport. + # + # @return [Rbeapi::EapiConnection] A instance of a connection object. def make_connection(transport, opts = {}) klass = TRANSPORTS.fetch(transport) cls = Rbeapi::Utils.class_from_string(klass) @@ -155,7 +162,7 @@ def make_connection(transport, opts = {}) end ## - # The Config class holds the loaded configuration file data. It is a + # The Config class holds the loaded configuration file data. It is a # subclass of IniFile. class Config < IniFile CONFIG_SEARCH_PATH = ['/mnt/flash/eapi.conf'] @@ -164,7 +171,9 @@ class Config < IniFile # The Config class will automatically search for a filename to load # (if none provided) and load the data when the object is instantiated. # - # @param [String] :filename The full path to the filename to load. If + # @param opts [Hash] The initialization parameters. + # + # @option opts filename [String] The full path to the filename to load. If # the filename is not provided, then this class will attempt to find # a valid conf file using the CONFIG_SEARCH_PATH. def initialize(opts = {}) @@ -175,13 +184,14 @@ def initialize(opts = {}) ## # This private method automatically finds and loads the conf file - # into the instance using the class variable CONFIG_SEARCH_PATH. The - # connections should be retrieved using the get_connection method + # into the instance using the class variable CONFIG_SEARCH_PATH. The + # connections should be retrieved using the get_connection method. + # + # @param opts [Hash] The options for specifying the message. # - # @param [Hash] :opts The options for specifying the message - # @option :opts [String] :filename The full path to the filename - # to load. Using this option eliminates the use of the - # search path + # @option opts filename [String] The full path to the filename + # to load. Using this option eliminates the use of the + # search path. def autoload(opts = {}) search_path = CONFIG_SEARCH_PATH.dup # Add the home directory path if the HOME environement var is defined. @@ -202,10 +212,10 @@ def autoload(opts = {}) ## # This method will read the specified filename and load its contents - # into the instance. It will also add the default localhost entry - # if it doesn't exist in the conf file + # into the instance. It will also add the default localhost entry + # if it doesn't exist in the conf file. # - # @param [String] :filename The full path to the filename to load + # @param filename [String] The full path to the filename to load. def read(filename) begin super(filename: filename) @@ -215,7 +225,7 @@ def read(filename) end # For each section, if the host parameter is omitted then the - # connection name is used + # connection name is used. sections.each do |name| if name.start_with?('connection:') conn = self["#{name}"] @@ -228,13 +238,14 @@ def read(filename) end ## - # This method will cause the config to be loaded. The process of + # This method will cause the config to be loaded. The process of # finding the configuration will be repeated so it is possible a # different conf file could be chosen if the original file was - # removed or a new file added higher on the search priority list + # removed or a new file added higher on the search priority list. # - # @param [Hash] :opts The options for specifying the message - # @opton :opts [String] :filename The full path to the file to load + # @param opts [Hash] The options for specifying the message. + # + # @option opts filename [String] The full path to the file to load. def reload(opts = {}) autoload opts end @@ -244,12 +255,12 @@ def reload(opts = {}) # connection is not found matching the name and if a default # connection has been specified then return the default connection. # - # @param [String] :name The name of the connection to return from - # the configuration. This should be the string right of the : - # in the config section header + # @param name [String] The name of the connection to return from + # the configuration. This should be the string right of the : + # in the config section header. # # @return [nil, Hash Returns a hash of the connection - # properties from the loaded config. This method will return nil + # properties from the loaded config. This method will return nil # if the connection name is not found. def get_connection(name) return self["connection:#{name}"] \ @@ -259,11 +270,12 @@ def get_connection(name) end ## - # Adds a new connection section to the current configuration + # Adds a new connection section to the current configuration. # - # @param [String] :name The name of the connection to add to the + # @param name [String] The name of the connection to add to the # configuration. - # @param [Hash] :values The properties for the connection + # + # @param values [Hash] The properties for the connection. def add_connection(name, values) self["connection:#{name}"] = values nil @@ -273,7 +285,7 @@ def add_connection(name, values) ## # The Node object provides an instance for sending and receiving messages # with a specific EOS device. The methods provided in this class allow - # for handling both enable mode and config mode commands + # for handling both enable mode and config mode commands. class Node attr_reader :connection attr_accessor :dry_run @@ -281,7 +293,7 @@ class Node ## # Save the connection and set autorefresh to true. # - # @param [Rbeapi::Eapilib::EapiConnection] :connection An instance of + # @param connection [Rbeapi::Eapilib::EapiConnection] An instance of # EapiConnection used to send and receive eAPI formatted messages def initialize(connection) @connection = connection @@ -291,55 +303,58 @@ def initialize(connection) ## # Provides access the nodes running-configuration. This is a lazily - # loaded memoized property for working with the node configuration + # loaded memoized property for working with the node configuration. # - # @return [String] The node's running-config as a string + # @return [String] The node's running-config as a string. def running_config return @running_config if @running_config @running_config = get_config(params: 'all', as_string: true) end ## - # Provides access to the nodes startup-configuration. This is a lazily - # loaded memoized property for working with the nodes startup config + # Provides access to the nodes startup-configuration. This is a lazily + # loaded memoized property for working with the nodes startup config. # - # @return [String] The node's startup-config as a string + # @return [String] The node's startup-config as a string. def startup_config return @startup_config if @startup_config @startup_config = get_config(config: 'startup-config', as_string: true) end ## - # Configures the node instance to use an enable password. EOS can be + # Configures the node instance to use an enable password. EOS can be # configured to require a second layer of authentication when putting - # the session into enable mode. The password supplied will be used to + # the session into enable mode. The password supplied will be used to # authenticate the session to enable mode if necessary. # - # @param [String] :password The value of the enable password + # @param password [String] The value of the enable password. def enable_authentication(password) @enablepwd = password end ## # The config method is a convenience method that will handling putting - # the switch into config mode prior to executing commands. The method + # the switch into config mode prior to executing commands. The method # will insert 'config' at the top of the command stack and then pop # the empty hash from the response output before return the array - # to the caller + # to the caller. # - # @param [Array] :commands An ordered list of commands to + # @param commands [Array] An ordered list of commands to # execute. A string in the list is an eapi command. A Hash entry in the # array consists of the following key value pairs: # { cmd: 'eapi command', input: 'text passed into stdin for command' } - # @option :opts [String] :encoding The encoding scheme to use for sending - # and receive eAPI messages. Valid values are json and text. The - # default value is json - # @option :opts [Float] :open_timeout Number of seconds to wait for the + # + # @option opts encoding [String] The encoding scheme to use for sending + # and receive eAPI messages. Valid values are json and text. The + # default value is json. + # + # @option opts open_timeout [Float] Number of seconds to wait for the # eAPI connection to open. - # @option :opts [Float] :read_timeout Number of seconds to wait for one + # + # @option opts read_timeout [Float] Number of seconds to wait for one # block of eAPI results to be read (via one read(2) call). # - # @return [Array] ordered list of output from commands + # @return [Array] Ordered list of output from commands. def config(commands, opts = {}) commands = [*commands] unless commands.respond_to?('each') @@ -364,19 +379,22 @@ def config(commands, opts = {}) # # rubocop:disable Metrics/MethodLength # - # @param [Array] :commands An ordered list of commands to + # @param commands [Array] An ordered list of commands to # execute. A string in the list is an eapi command. A Hash entry in the # array consists of the following key value pairs: # { cmd: 'eapi command', input: 'text passed into stdin for command' } - # @option :opts [String] :encoding The encoding scheme to use for sending - # and receive eAPI messages. Valid values are json and text. The - # default value is json - # @option :opts [Float] :open_timeout Number of seconds to wait for the + # + # @option opts encoding [String] The encoding scheme to use for sending + # and receive eAPI messages. Valid values are json and text. The + # default value is json. + # + # @option opts open_timeout [Float] Number of seconds to wait for the # eAPI connection to open. - # @option :opts [Float] :read_timeout Number of seconds to wait for one + # + # @option opts read_timeout [Float] Number of seconds to wait for one # block of eAPI results to be read (via one read(2) call). # - # @return [Array] ordered list of output from commands + # @return [Array] Ordered list of output from commands. def enable(commands, opts = {}) commands = [*commands] unless commands.respond_to?('each') @@ -407,16 +425,18 @@ def enable(commands, opts = {}) end ## - # Returns a response object from a call to the enable method. This + # Returns a response object from a call to the enable method. This # private method is an internal method to ensure consistency in the - # return message format + # return message format. + # + # @param command [String] The command send to the node. # - # @param [String] :command The command send to the node - # @param [Hash] :response The response returned from the eAPI call - # @param [String] :encoding The encoding scheme used in the response - # which should be either json or text + # @param result [Hash] The response returned from the eAPI call. # - # @return [Hash] A Ruby hash object + # @param encoding [String] The encoding scheme used in the response + # which should be either json or text. + # + # @return [Hash] A Ruby hash object. def make_response(command, result, encoding) { command: command, result: result, encoding: encoding } end @@ -424,17 +444,20 @@ def make_response(command, result, encoding) ## # This method will send the ordered list of commands to the destination - # node using the transport. It is also response for inserting enable - # onto the command stack and popping the enable result on the response + # node using the transport. It is also response for inserting enable + # onto the command stack and popping the enable result on the response. # - # @param [Array] :commands The ordered list of commands to send to the + # @param commands [Array] The ordered list of commands to send to the # destination node. - # @option :opts [String] :encoding The encoding scheme to use for - # sending and receive eAPI requests. This argument is optional. - # Valid values include json or text. The default is json - # @option :opts [Float] :open_timeout Number of seconds to wait for the + # + # @option opts encoding [String] The encoding scheme to use for + # sending and receive eAPI requests. This argument is optional. + # Valid values include json or text. The default is json. + # + # @option opts open_timeout [Float] Number of seconds to wait for the # eAPI connection to open. - # @option :opts [Float] :read_timeout Number of seconds to wait for one + # + # @option opts read_timeout [Float] Number of seconds to wait for one # block of eAPI results to be read (via one read(2) call). def run_commands(commands, opts = {}) encoding = opts.fetch(:encoding, 'json') @@ -458,12 +481,14 @@ def run_commands(commands, opts = {}) # and return it in full text. # # @param [Hash] opts the options to create a message with - # @option :opts [String] :config The configuration instance to return from - # the node. Valid values are 'running-config' and 'startup-config'. If - # no value is specified, then 'running-config' is used - # @ :opts [String] :param Additional parameters to append to the - # retrieving the configuration. Valid values depend on the config - # file requested + # + # @option opts config [String] The configuration instance to return from + # the node. Valid values are 'running-config' and 'startup-config'. If + # no value is specified, then 'running-config' is used. + # + # @option opts param [String] Additional parameters to append to the + # retrieving the configuration. Valid values depend on the config + # file requested. # # running-config params # all Configuration with defaults @@ -478,7 +503,7 @@ def run_commands(commands, opts = {}) # interfaces Filter config to include only the given interfaces # section Display sections containing matching commands # - # @return [String] the specified configuration as text + # @return [String] The specified configuration as text. def get_config(opts = {}) config = opts.fetch(:config, 'running-config') params = opts.fetch(:params, '') @@ -490,7 +515,7 @@ def get_config(opts = {}) ## # Returns an API module for working with the active configuration - # of the node + # of the node. def api(name, opts = {}) path = opts.fetch(:path, 'rbeapi/api') namespace = opts.fetch(:namespace, 'Rbeapi::Api') diff --git a/lib/rbeapi/eapilib.rb b/lib/rbeapi/eapilib.rb index 701411e..e548887 100644 --- a/lib/rbeapi/eapilib.rb +++ b/lib/rbeapi/eapilib.rb @@ -58,8 +58,8 @@ class EapiError < StandardError # The EapiError class provides one property for holding the set of # commands issued when the error was generated. # - # @param [String] :message The error message to return from raising - # the exception + # @param message [String] The error message to return from raising + # the exception. def initalize(message) @message = message @commands = nil @@ -77,12 +77,14 @@ class CommandError < EapiError ## # The exception contains the eAPI error code and error text. # - # @param [String] :message The error message to return from raising - # this exception - # @param [Integer] :code The error code associated with the error - # message to be raised - # @param [Array] :commands The list of commands that were used in the - # eAPI request message + # @param message [String] The error message to return from raising + # this exception. + # + # @param code [Integer] The error code associated with the error + # message to be raised. + # + # @param commands [Array] The list of commands that were used in the + # eAPI request message. def initialize(message, code, commands = nil) @error_code = code @error_text = message @@ -101,12 +103,14 @@ class ConnectionError < EapiError ## # The exception contains the eAPI error code and error text. # - # @param [String] :message The error message to return from raising - # this exception - # @param [String] :connection_type The optional connection_type of - # the instance - # @param [Array] :commands The list of commands that were used in the - # eAPI request message + # @param message [String] The error message to return from raising + # this exception. + # + # @param connection_type [String] The optional connection_type of + # the instance. + # + # @param commands [Array] The list of commands that were used in the + # eAPI request message. def initialize(message, connection_type = nil, commands = nil) @connection_type = connection_type @commands = commands @@ -117,8 +121,8 @@ def initialize(message, connection_type = nil, commands = nil) ## # The EapiConnection provides a base class for building eAPI connection # instances with a specific transport for connecting to Arista EOS - # devices. This class handles sending and receiving eAPI calls using - # JSON-RPC. This class should not need to be directly instantiated. + # devices. This class handles sending and receiving eAPI calls using + # JSON-RPC. This class should not need to be directly instantiated. class EapiConnection attr_reader :error attr_reader :open_timeout @@ -127,8 +131,8 @@ class EapiConnection ## # The connection contains the transport. # - # @param [Net::HTTP] :transport The HTTP transport to use for sending - # and receive eAPI request and response messages + # @param transport [Net::HTTP] The HTTP transport to use for sending + # and receive eAPI request and response messages. def initialize(transport) @transport = transport @error = nil @@ -136,13 +140,16 @@ def initialize(transport) ## # Configures the connection authentication values (username and - # password). The authentication values are used to authenticate - # the eAPI connection. Using authentication is only required for - # connections that use Http or Https transports + # password). The authentication values are used to authenticate + # the eAPI connection. Using authentication is only required for + # connections that use Http or Https transports. # - # @options :opts [String] :username The username to use to + # @param opts [Hash] The authentication parameters. + # + # @option opts username [String] The username to use to # authenticate with eAPI. Default is 'admin'. - # @options :opts [String] :password The password to use to + # + # @option opts password [String] The password to use to # authenticate with eAPI. Default is ''. def authentication(opts = {}) @username = opts.fetch(:username, 'admin') @@ -151,12 +158,13 @@ def authentication(opts = {}) ## # Configures the connection timeout values (open_timeout and - # read_timeout). The timeout values are used for the eAPI + # read_timeout). The timeout values are used for the eAPI # connection. # - # @option :opts [Float] :open_timeout Number of seconds to wait for the + # @option opts open_timeout [Float] Number of seconds to wait for the # eAPI connection to open. Default is DEFAULT_HTTP_OPEN_TIMEOUT. - # @option :opts [Float] :read_timeout Number of seconds to wait for one + # + # @option opts read_timeout [Float] Number of seconds to wait for one # block of eAPI results to be read (via one read(2) call). Default # is DEFAULT_HTTP_READ_TIMEOUT. def timeouts(opts = {}) @@ -181,18 +189,21 @@ def timeouts(opts = {}) # "id": # } # - # @param [Array] :commands The ordered set of commands that should - # be included in the eAPI request - # @param [Hash] :opts Optional keyword arguments - # @option :opts [String] :id The value to use for the eAPI request - # id. If not provided,the object_id for the connection instance - # will be used - # @option :opts [String] :format The encoding formation to pass in - # the eAPI request. Valid values are json or text. The default - # value is json + # @param commands [Array] The ordered set of commands that should + # be included in the eAPI request. + # + # @param opts [Hash] Optional keyword arguments. + # + # @option opts id [String] The value to use for the eAPI request + # id. If not provided,the object_id for the connection instance + # will be used. + # + # @option opts format [String] The encoding formation to pass in + # the eAPI request. Valid values are json or text. The default + # value is json. # # @return [Hash] Returns a Ruby hash of the request message that is - # suitable to be JSON encoded and sent to the destination node + # suitable to be JSON encoded and sent to the destination node. def request(commands, opts = {}) id = opts.fetch(:reqid, object_id) format = opts.fetch(:format, 'json') @@ -205,7 +216,7 @@ def request(commands, opts = {}) ## # This method will send the request to the node over the specified # transport and return a response message with the contents from - # the eAPI response. eAPI responds to request messages with either + # the eAPI response. eAPI responds to request messages with either # a success message or failure message. # # @example eAPI Response - success @@ -242,16 +253,18 @@ def request(commands, opts = {}) # "id": # } # - # @param [Hash] :data A hash containing the body of the request - # message. This should be a valid eAPI request message. - # @option :opts [Float] :open_timeout Number of seconds to wait for the + # @param data [Hash] A hash containing the body of the request + # message. This should be a valid eAPI request message. + # + # @option opts open_timeout [Float] Number of seconds to wait for the # eAPI connection to open. - # @option :opts [Float] :read_timeout Number of seconds to wait for one + # + # @option opts read_timeout [Float] Number of seconds to wait for one # block of eAPI results to be read (via one read(2) call). # - # @return [Hash] returns the response message as a Ruby hash object + # @return [Hash] Returns the response message as a Ruby hash object. # - # @raises [CommandError] Raised if an eAPI failure response is return + # @raise [CommandError] Raised if an eAPI failure response is return # from the destination node. def send(data, opts) request = Net::HTTP::Post.new('/command-api') @@ -283,24 +296,28 @@ def send(data, opts) # Executes the commands on the destination node and returns the # response from the node. # - # @param [Array] :commands The ordered list of commands to execute + # @param commands [Array] The ordered list of commands to execute # on the destination node. - # @param [Hash] :opts Optional keyword arguments - # @option :opts [String] :encoding Used to specify the encoding to be - # used for the response. Valid encoding values are json or text - # @option :opts [Float] :open_timeout Number of seconds to wait for the + # + # @param opts [Hash] Optional keyword arguments. + # + # @option opts encoding [String] Used to specify the encoding to be + # used for the response. Valid encoding values are json or text. + # + # @option opts open_timeout [Float] Number of seconds to wait for the # eAPI connection to open. - # @option :opts [Float] :read_timeout Number of seconds to wait for one + # + # @option opts read_timeout [Float] Number of seconds to wait for one # block of eAPI results to be read (via one read(2) call). # - # @returns [Array] This method will return the array of responses + # @return [Array] This method will return the array of responses # for each command executed on the node. # - # @raises [CommandError] Raises a CommandError if rescued from the - # send method and adds the list of commands to the exception message + # @raise [CommandError] Raises a CommandError if rescued from the + # send method and adds the list of commands to the exception message. # - # @raises [ConnectionError] Raises a ConnectionError if rescued and - # adds the list of commands to the exception message + # @raise [ConnectionError] Raises a ConnectionError if rescued and + # adds the list of commands to the exception message. def execute(commands, opts = {}) @error = nil request = request(commands, opts) From 0adf955210037dafea9d0517ad5259e79d91dd01 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Fri, 22 Jan 2016 18:11:07 -0700 Subject: [PATCH 049/110] Update documentation. --- guide/api.rst | 5894 ++++++++++++++++++++++++++++++++ guide/contributing.rst | 6 + guide/cookbook.rst | 4 - guide/developing.rst | 4 - guide/faq.rst | 4 - guide/getting-started.rst | 134 + guide/index.rst | 8 +- guide/installation.rst | 57 +- guide/license.rst | 15 +- guide/overview.rst | 7 +- guide/quickstart.rst | 4 - guide/testing.rst | 6 +- guide/troubleshooting.rst | 1 - guide/upgrading.rst | 10 + lib/rbeapi/api/aaa.rb | 6 +- lib/rbeapi/api/acl.rb | 6 +- lib/rbeapi/api/bgp.rb | 34 +- lib/rbeapi/api/dns.rb | 4 +- lib/rbeapi/api/ipinterfaces.rb | 10 +- lib/rbeapi/api/logging.rb | 6 +- lib/rbeapi/api/mlag.rb | 12 +- lib/rbeapi/api/ntp.rb | 4 +- lib/rbeapi/api/radius.rb | 6 +- lib/rbeapi/api/routemaps.rb | 14 +- lib/rbeapi/api/snmp.rb | 14 +- lib/rbeapi/api/staticroutes.rb | 4 +- lib/rbeapi/api/stp.rb | 2 +- lib/rbeapi/api/switchports.rb | 2 +- lib/rbeapi/api/users.rb | 12 +- lib/rbeapi/api/vlans.rb | 14 +- lib/rbeapi/api/vrrp.rb | 32 +- 31 files changed, 6214 insertions(+), 122 deletions(-) create mode 100644 guide/api.rst create mode 100644 guide/contributing.rst delete mode 100644 guide/cookbook.rst delete mode 100644 guide/developing.rst delete mode 100644 guide/faq.rst create mode 100644 guide/getting-started.rst delete mode 100644 guide/quickstart.rst delete mode 100644 guide/troubleshooting.rst create mode 100644 guide/upgrading.rst diff --git a/guide/api.rst b/guide/api.rst new file mode 100644 index 0000000..ef1f8dd --- /dev/null +++ b/guide/api.rst @@ -0,0 +1,5894 @@ +Copyright (c) 2014, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Aaa class manages Authorization, Authentication and Accounting (AAA) +on an EOS node. + +get returns a hash of all Aaa resources. + +@example { : { : { type: , servers: }, : { type: , servers: } } } + +@return [Hash] Returns the Aaa resources as a Hash. If +no Aaa resources are found, an empty hash is returned. + +Returns an object node for working with AaaGroups class. + +The AaaGroups class manages the server groups on an EOS node. Regular +expression that parses the radius servers from the aaa group server +radius configuration block. Regular expression that parses the tacacs +servers from the aaa group server tacacs+ configuration block. + +get returns the aaa server group resource hash that describes the +current configuration for the specified server group name. + +@example { type: , servers: } + +@param name [String] The server group name to return from the nodes +current running configuration. If the name is not configured a nil +object is returned. + +@return [nil, Hash] Returns the resource hash for the +specified name. If the name does not exist, a nil object is returned. +block = get\_block("aaa group server ([^\\s]+) {name}") + +getall returns a aaa server groups hash. + +@example { : { type: , servers: }, : { type: , servers: } } + +@return [Hash] Returns the resource hashes for +configured aaa groups. If none exist, a nil object is returned. + +parse\_type scans the specified configuration block and returns the +server group type as either 'tacacs' or 'radius'. The type value is +expected to always be present in the config. + +@api private + +@param config [String] The aaa server group block configuration for the +group name to parse. + +@return [Hash] Resource hash attribute. + +parse\_servers scans the specified configuraiton block and returns the +list of servers configured for the group. If there are no servers +configured for the group the servers value will return an empty array. + +@api private + +@see parse\_radius\_server @see parse\_tacacs\_server + +@param config [String] The aaa server group block configuration for the +group name to parse. + +@param type [String] The aaa server block type. Valid values are either +radius or tacacs+. + +@return [Hash] Resource hash attribute + +parse\_radius\_server scans the provide configuration block and returns +the list of servers configured. The configuration block is expected to +be a radius configuration block. If there are no servers configured for +the group the servers value will return an empty array. + +@api private + +@param config [String] The aaa server group block configuration for the +group name to parse + +@return [Hash] resource hash attribute + +parse\_tacacs\_server scans the provided configuration block and returns +the list of configured servers. The configuration block is expected to +be a tacacs configuration block. If there are no servers configured for +the group the servers value will return an empty array. + +@api private + +@param config [String] The aaa server group block configuration for the +group name to parse. + +@return [Hash] Resource hash attribute. + +find\_type is a utility method to find the type of aaa server group for +the specified name. This method will scan the current running +configuration on the node and return the server group type as either +'radius' or 'tacacs+'. If the server group is not configured, then nil +will be returned. + +@api private + +@param name [String] The aaa server group name to find in the config and +return the type value for. + +@return [nil, String] Returns either the type name as 'radius' or +'tacacs+' or nil if the server group is not configured. mdata = /aaa +group server ([^\\s]+) {name}/.match(config) + +create adds a new aaa group server to the nodes current configuration. +If the specified name and type are already created then this method will +return successfully. If the name is configured but the type is +different, this method will not return successfully (returns false). + +@since eos\_version 4.13.7M + +commands aaa group server + +@param name [String] The name of the aaa group server to create in the +nodes running configuration + +@param type [String] The type of aaa group server to create in the nodes +running configuration. Valid values include 'radius' or 'tacacs+' + +@return [Boolean] returns true if the commands complete successfully +configure ["aaa group server {type} {name}", 'exit'] + +delete removes a current aaa server group from the nodes current +configuration. This method will automatically determine the server group +type based on the name. If the name is not configured in the nodes +current configuration, this method will return successfully. + +@since eos\_version 4.13.7M + +commands no aaa group server [radius \| tacacs+] + +@param name [String] The name of the aaa group server to create in the +nodes running configuration. + +@return [Boolean] Returns true if the commands complete successfully. +configure "no aaa group server {type} {name}" + +set\_servers configures the set of servers for a specified aaa server +group. This is an atomic operation that first removes all current +servers and then adds the new servers back. If any of the servers failes +to be removed or added, this method will return unsuccessfully. + +@see remove\_server @see add\_server + +@param name [String] The name of the aaa group server to add the new +server configuration to. + +@param servers [String] The IP address or host name of the server to add +to the configuration + +@return [Boolean] Returns true if the commands complete successfully + +add\_server adds a new server to the specified aaa server group. If the +server is already configured in the list of servers, this method will +still return successfully. + +@see add\_radius\_server @see add\_tacacs\_server + +@param name [String] The name of the aaa group server to add the new +server configuration to. + +@param server [String] The IP address or host name of the server to add +to the configuration. + +@param opts [Hash] Optional configuration parameters. + +@return [Boolean] Returns true if the commands complete successfully. + +add\_radius\_server adds a new radius server to the nodes current +configuration. If the server already exists in the specified group name +this method will still return successfully. + +@since eos\_version 4.13.7M + +commmands aaa group server radius server [acct-port ] [auth-port ] [vrf +] + +@param name [String] The name of the aaa group server to add the new +server configuration to. + +@param server [String] The IP address or host name of the server to add +to the configuration. + +@param opts [Hash] Optional configuration parameters. + +@return [Boolean] Returns true if the commands complete successfully. +order of command options matter here! server = "server {server} " server +<< "auth-port {opts[:auth\_port]} " if opts[:auth\_port] server << +"acct-port {opts[:acct\_port]} " if opts[:acct\_port] server << "vrf +{opts[:vrf]}" if opts[:vrf] configure ["aaa group server radius {name}", +server, 'exit'] + +add\_tacacs\_server adds a new tacacs server to the nodes current +configuration. If the server already exists in the specified group name +this method will still return successfully. + +@since eos\_version 4.13.7M + +commmands aaa group server tacacs+ server [acct-port ] [auth-port ] [vrf +] + +@param name [String] The name of the aaa group server to add the new +server configuration to. + +@param server [String] The IP address or host name of the server to add +to the configuration. + +@param opts [Hash] Optional configuration parameters. + +@return [Boolean] Returns true if the commands complete successfully. +order of command options matter here! server = "server {server} " server +<< "vrf {opts[:vrf]} " if opts[:vrf] server << "port {opts[:port]} " if +opts[:port] configure ["aaa group server tacacs+ {name}", server, +'exit'] + +remove\_server deletes an existing server from the specified aaa server +group. If the specified server is not configured in the specified server +group, this method will still return true. + +eos\_version 4.13.7M + +commands aaa group server [radius \| tacacs+] no server + +@param name [String] The name of the aaa group server to remove. + +@param server [String] The IP address or host name of the server. + +@param opts [Hash] Optional configuration parameters. + +@return [Boolean] returns true if the commands complete successfully. +server = "no server {server} " server << "vrf {opts[:vrf]}" if +opts[:vrf] configure ["aaa group server {type} {name}", server, 'exit'] + +Copyright (c) 2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Acl class manages the set of standard ACLs. + +get returns the specified ACL from the nodes current configuration. + +@example { : { seqno: , action: , srcaddr: , srcprefixle: , log: }, : { +seqno: , action: , srcaddr: , srcprefixle: , log: }, ... } + +@param name [String] The ACL name. + +@return [nil, Hash] Returns the ACL resource as a Hash. +Returns nil if name does not exist. config = get\_block("ip access-list +standard {name}") + +getall returns the collection of ACLs from the nodes running +configuration as a hash. The ACL resource collection hash is keyed by +the ACL name. + +@example { : { : { seqno: , action: , srcaddr: , srcprefixle: , log: }, +: { seqno: , action: , srcaddr: , srcprefixle: , log: }, ... }, : { : { +seqno: , action: , srcaddr: , srcprefixle: , log: }, : { seqno: , +action: , srcaddr: , srcprefixle: , log: }, ... }, ... } + +@return [nil, Hash] Returns a hash that represents the +entire ACL collection from the nodes running configuration. If there are +no ACLs configured, this method will return an empty hash. + +mask\_to\_prefixlen converts a subnet mask from dotted decimal to bit +length. + +@param mask [String] The dotted decimal subnet mask to convert. + +@return [String] The subnet mask as a valid prefix length. + +parse\_entries scans the nodes configurations and parses the entries +within an ACL. + +@api private + +@param config [String] The switch config. + +@return [Hash] Returns the resource hash attribute. + +create will create a new ACL resource in the nodes current configuration +with the specified name. If the create method is called and the ACL +already exists, this method will still return true. The ACL will not +have any entries. Use add\_entry to add entries to the ACL. + +@since eos\_version 4.13.7M + +commands ip access-list standard + +@param name [String] The ACL name to create on the node. Must begin with +an alphabetic character. Cannot contain spaces or quotation marks. + +@return [Boolean] Returns true if the command completed successfully. +configure("ip access-list standard {name}") + +delete will delete an existing ACL resource from the nodes current +running configuration. If the delete method is called and the ACL does +not exist, this method will succeed. + +@since eos\_version 4.13.7M + +commands no ip access-list standard + +@param name [String] The ACL name to delete on the node. + +@return [Boolean] Returns true if the command completed successfully. +configure("no ip access-list standard {name}") + +default will configure the ACL using the default keyword. This command +has the same effect as deleting the ACL from the nodes running +configuration. + +@since eos\_version 4.13.7M + +commands default no ip access-list standard + +@param name [String] The ACL name to set to the default value on the +node. + +@return [Boolean] Returns true if the command complete successfully +configure("default ip access-list standard {name}") + +build\_entry will build the commands to add an entry. + +@api private + +@param entry [Hash] the options for the entry. + +@option entry seqno [String] The sequence number of the entry in the ACL +to add. Default is nil, will be assigned. + +@option entry action [String] The action triggered by the ACL. Valid +values are 'permit', 'deny', or 'remark'. + +@option entry addr [String] The IP address to permit or deny. + +@option entry prefixlen [String] The prefixlen for the IP address. + +@option entry log [Boolean] Triggers an informational log message to the +console about the matching packet. + +@return [String] Returns commands to create an entry. cmds = +"{entry[:seqno]} " if entry[:seqno] cmds << "{entry[:action]} +{entry[:srcaddr]}/{entry[:srcprefixlen]}" + +update\_entry will update an entry, identified by the seqno in the ACL +specified by name, with the passed in parameters. + +@since eos\_version 4.13.7M + +@param name [String] The ACL name to update on the node. + +@param entry [Hash] the options for the entry. + +@option entry seqno [String] The sequence number of the entry in the ACL +to update. + +@option entry action [String] The action triggered by the ACL. Valid +values are 'permit', 'deny', or 'remark'. + +@option entry addr [String] The IP address to permit or deny. + +@option entry prefixlen [String] The prefixlen for the IP address. + +@option entry log [Boolean] Triggers an informational log message to the +console about the matching packet. + +@return [Boolean] Returns true if the command complete successfully. +cmds = ["ip access-list standard {name}"] cmds << "no {entry[:seqno]}" + +add\_entry will add an entry to the specified ACL with the passed in +parameters. + +@since eos\_version 4.13.7M + +@param name [String] The ACL name to add an entry to on the node. + +@param entry [Hash] the options for the entry. + +@option entry action [String] The action triggered by the ACL. Valid +values are 'permit', 'deny', or 'remark'. + +@option entry addr [String] The IP address to permit or deny. + +@option entry prefixlen [String] The prefixlen for the IP address. + +@option entry log [Boolean] Triggers an informational log message to the +console about the matching packet. + +@return [Boolean] Returns true if the command complete successfully. +cmds = ["ip access-list standard {name}"] + +remove\_entry will remove the entry specified by the seqno for the ACL +specified by name. + +@since eos\_version 4.13.7M + +@param name [String] The ACL name to update on the node. + +@param seqno [String] The sequence number of the entry in the ACL to +remove. + +@return [Boolean] Returns true if the command complete successfully. +cmds = ["ip access-list standard {name}", "no {seqno}", 'exit'] + +Copyright (c) 2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Eos is the toplevel namespace for working with Arista EOS nodes. + +Api is module namespace for working with the EOS command API. + +The Bgp class implements global BGP router configuration. + +get returns the BGP routing configuration from the nodes current +configuration. + +@example { bgp\_as: , router\_id: , shutdown: , maximum\_paths: , +maximum\_ecmp\_paths: networks: [ { prefix: , masklen: , route\_map: }, +{ prefix: , masklen: , route\_map: } ], neighbors: { name: { +peer\_group: , remote\_as: , send\_community: , shutdown: , description: +, next\_hop\_selp: , route\_map\_in: , route\_map\_out: }, name: { +peer\_group: , remote\_as: , send\_community: , shutdown: , description: +, next\_hop\_selp: , route\_map\_in: , route\_map\_out: }, ... } } + +@return [nil, Hash] Returns the BGP resource as a Hash. + +parse\_bgp\_as scans the BGP routing configuration for the AS number. +Defined as a class method. Used by the BgpNeighbors class below. + +@param config [String] The switch config. + +@return [Hash] Returns the resource hash attribute. + +parse\_router\_id scans the BGP routing configuration for the router ID. + +@api private + +@param config [String] The switch config. + +@return [Hash] Returns the resource hash attribute. + +parse\_shutdown scans the BGP routing configuration for the shutdown +status. + +@api private + +@param config [String] The switch config. + +@return [Hash] resource hash attribute. Returns true if +shutdown, false otherwise. + +parse\_maximum\_paths scans the BGP routing configuration for the +maximum paths and maximum ecmp paths. + +@api private + +@param config [String] The switch config. + +@return [Hash] Returns the resource hash attribute. + +parse\_networks scans the BGP routing configuration for all the network +entries. + +@api private + +@param config [String] The switch config. + +@return [Array] Single element hash with Array of network hashes. + +create will create a new instance of BGP routing on the node. Optional +parameters can be passed in to initialize BGP specific settings. + +commands router bgp + +@param bgp\_as [String] The BGP autonomous system number to be +configured for the local BGP routing instance. + +@param opts [hash] Optional keyword arguments. + +@option opts router\_id [String] The BGP routing process router-id +value. When no ID has been specified (i.e. value not set), the local +router ID is set to the following: \* The loopback IP address when a +single loopback interface is configured. \* The loopback with the +highest IP address when multiple loopback interfaces are configured. \* +The highest IP address on a physical interface when no loopback +interfaces are configure + +@option opts maximum\_paths [Integer] Maximum number of equal cost +paths. + +@option opts maximum\_ecmp\_paths [Integer] Maximum number of installed +ECMP routes. The maximum\_paths option must be set if +maximum\_ecmp\_paths is set. + +@option opts enable [Boolean] If true then the BGP router is enabled. If +false then the BGP router is disabled. + +@return [Boolean] returns true if the command completed successfully. +cmds = ["router bgp {bgp\_as}"] cmds << "router-id {opts[:router\_id]}" +if opts.key?(:router\_id) cmd = "maximum-paths {opts[:maximum\_paths]}" +cmd << " ecmp {opts[:maximum\_ecmp\_paths]}" + +delete will delete the BGP routing instance from the node. + +commands no router bgp + +@return [Boolean] Returns true if the command completed successfully. +configure("no router bgp {config[:bgp\_as]}") + +default will configure the BGP routing using the default keyword. This +command has the same effect as deleting the BGP routine instance from +the nodes running configuration. + +commands default router bgp + +@return [Boolean] returns true if the command complete successfully +configure("default router bgp {config[:bgp\_as]}") + +configure\_bgp adds the command to go to BGP config mode. Then it adds +the passed in command. The commands are then passed on to configure. + +@api private + +@param cmd [String] Command to run under BGP mode. + +@return [Boolean] Returns true if the command complete successfully. +cmds = ["router bgp {bgp\_as[:bgp\_as]}", cmd] + +set\_router\_id sets the router\_id for the BGP routing instance. + +commands router bgp {no \| default} router-id + +@param opts [hash] Optional keyword arguments + +@option opts value [String] The BGP routing process router-id value. +When no ID has been specified (i.e. value not set), the local router ID +is set to the following: \* The loopback IP address when a single +loopback interface is configured. \* The loopback with the highest IP +address when multiple loopback interfaces are configured. \* The highest +IP address on a physical interface when no loopback interfaces are +configure + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the router-id using the default +keyword. + +@return [Boolean] Returns true if the command complete successfully. + +set\_shutdown configures the administrative state for the global BGP +routing process. The value option is not used by this method. + +commands router bgp {no \| default} shutdown + +@param opts [hash] Optional keyword arguments. + +@option opts enable [Boolean] If enable is true then the BGP routing +process is administratively enabled and if enable is False then the BGP +routing process is administratively disabled. + +@option opts default [Boolean] Configure the router-id using the default +keyword. + +@return [Boolean] Returns true if the command complete successfully. +Shutdown semantics are opposite of enable semantics so invert enable + +set\_maximum\_paths sets the maximum number of equal cost paths and the +maximum number of installed ECMP routes. + +commands router bgp {no \| default} maximum-paths [ecmp ] + +@param maximum\_paths [Integer] Maximum number of equal cost paths. + +@param maximum\_ecmp\_paths [Integer] Maximum number of installed ECMP +routes. + +@param opts [hash] Optional keyword arguments + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the maximum paths using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "maximum-paths {maximum\_paths} ecmp {maximum\_ecmp\_paths}" + +add\_network creates a new instance of a BGP network on the node. + +commands router bgp network / route-map + +@param prefix [String] The IPv4 prefix to configure as part of the +network statement. The value must be a valid IPv4 prefix. + +@param masklen [String] The IPv4 subnet mask length in bits. The masklen +must be in the valid range of 1 to 32. + +@param route\_map [String] The route-map name to apply to the network +statement when configured. + +@return [Boolean] Returns true if the command complete successfully. cmd += "network {prefix}/{masklen}" cmd << " route-map {route\_map}" if +route\_map + +remove\_network removes the instance of a BGP network on the node. + +commands router bgp {no} shutdown + +@param prefix [String] The IPv4 prefix to configure as part of the +network statement. The value must be a valid IPv4 prefix. + +@param masklen [String] The IPv4 subnet mask length in bits. The masklen +must be in the valid range of 1 to 32. + +@param route\_map [String] The route-map name to apply to the network +statement when configured. + +@return [Boolean] Returns true if the command complete successfully. cmd += "no network {prefix}/{masklen}" cmd << " route-map {route\_map}" if +route\_map + +The BgpNeighbors class implements BGP neighbor configuration + +get returns a single BGP neighbor entry from the nodes current +configuration. + +@example { peer\_group: , remote\_as: , send\_community: , shutdown: , +description: next\_hop\_self: route\_map\_in: route\_map\_out: } + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [nil, Hash] Returns the BGP neighbor resource as +a Hash. + +getall returns the collection of all neighbor entries for the BGP router +instance. + +@example { : { peer\_group: , remote\_as: , send\_community: , shutdown: +, description: next\_hop\_self: route\_map\_in: route\_map\_out: }, : { +peer\_group: , remote\_as: , send\_community: , shutdown: , description: +next\_hop\_self: route\_map\_in: route\_map\_out: }, ... } + +@return [nil, Hash] Returns a hash that represents the +entire BGP neighbor collection from the nodes running configuration. If +there a BGP router is not configured or contains no neighbor entries +then this method will return an empty hash. + +parse\_peer\_group scans the BGP neighbor entries for the peer group. + +@api private + +@param config [String] The switch config. + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Hash] Returns the resource hash attribute. +value = config.scan(/neighbor {name} peer-group ([^\\s]+)/) + +parse\_remote\_as scans the BGP neighbor entries for the remote AS. + +@api private + +@param config [String] The switch config. + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Hash] Returns the resource hash attribute value += config.scan(/neighbor {name} remote-as (:raw-latex:`\d`+)/) + +parse\_send\_community scans the BGP neighbor entries for the remote AS. + +@api private + +@param config [String] The switch config. + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Hash] Returns the resource hash attribute. +value = config.scan(/no neighbor {name} send-community/) + +parse\_shutdown scans the BGP neighbor entries for the remote AS. + +@api private + +@param config [String] The switch config. + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Hash] Resource hash attribute. Returns true if +shutdown, false otherwise. value = config.scan(/no neighbor {name} +shutdown/) + +parse\_description scans the BGP neighbor entries for the description. + +@api private + +@param config [String] The switch config. + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Hash] Returns the resource hash attribute. +value = config.scan(/neighbor {name} description (.\*)$/) + +parse\_next\_hop\_self scans the BGP neighbor entries for the next hop +self. + +@api private + +@param config [String] The switch config. @param name [String] The name +of the BGP neighbor to manage. This value can be either an IPv4 address +or string (in the case of managing a peer group). + +@return [Hash] Returns the resource hash attribute. +value = config.scan(/no neighbor {name} next-hop-self/) + +parse\_route\_map\_in scans the BGP neighbor entries for the route map +in. + +@api private + +@param config [String] The switch config. + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Hash] Returns the resource hash attribute. +value = config.scan(/neighbor {name} route-map ([^\\s]+) in/) + +parse\_route\_map\_out scans the BGP neighbor entries for the route map +in. + +@api private + +@param config [String] The switch config. + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Hash] Returns the resource hash attribute. +value = config.scan(/neighbor {name} route-map ([^\\s]+) out/) + +configure\_bgp adds the command to go to BGP config mode. Then it adds +the passed in command. The commands are then passed on to configure. + +@api private + +@param cmd [String] Command to run under BGP mode. + +@return [Boolean] Returns true if the command complete successfully. +cmds = ["router bgp {bgp\_as[:bgp\_as]}", cmd] + +create will create a new instance of a BGP neighbor on the node. The +neighbor is created in the shutdown state and then enabled. + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Boolean] Returns true if the command completed successfully. + +delete will delete the BGP neighbor from the node. + +commands no neighbor or no neighbor peer-group + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Boolean] Returns true if the command completed successfully. +cmd = "no neighbor {name}" cmd = "no neighbor {name} peer-group" + +neigh\_command\_builder for neighbors which calls command\_builder. + +@param name [String] The name of the BGP neighbor to manage. + +@param cmd [String] The command portion of the neighbor command. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] Value being set. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the command using the default +keyword. + +@return [String] Returns built command string. +command\_builder("neighbor {name} {cmd}", opts) + +set\_peer\_group creates a BGP static peer group name. + +commands router bgp {no \| default} neighbor peer-group + +@param name [String] The IP address of the neighbor. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The group name. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the peer group using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. + +set\_remote\_as configures the expected AS number for a neighbor (peer). + +commands router bgp {no \| default} neighbor remote-as + +@param name [String] The IP address or name of the peer group. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The remote as-id. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the peer group using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. + +set\_shutdown disables the specified neighbor. The value option is not +used by this method. + +commands router bgp {no \| default} neighbor shutdown + +@param name [String] The IP address or name of the peer group. + +@param opts [hash] Optional keyword arguments. + +@option opts enable [String] True enables the specified neighbor. False +disables the specified neighbor. + +@option opts default [Boolean] Configure the peer group using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. +Shutdown semantics are opposite of enable semantics so invert enable. + +set\_send\_community configures the switch to send community attributes +to the specified BGP neighbor. The value option is not used by this +method. + +commands router bgp {no \| default} neighbor send-community + +@param name [String] The IP address or name of the peer group. + +@param opts [hash] Optional keyword arguments. + +@option opts enable [String] True enables the feature. False disables +the feature. + +@option opts default [Boolean] Configure the peer group using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. + +set\_next\_hop\_self configures the switch to list its address as the +next hop in routes that it advertises to the specified BGP-speaking +neighbor or neighbors in the specified peer group. The value option is +not used by this method. + +commands router bgp {no \| default} neighbor next-hop-self + +@param name [String] The IP address or name of the peer group. + +@param opts [hash] Optional keyword arguments. + +@option opts enable [String] True enables the feature. False disables +the feature. + +@option opts default [Boolean] Configure the peer group using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. + +set\_route\_map\_in command applies a route map to inbound BGP routes. + +commands router bgp {no \| default} neighbor route-map in + +@param name [String] The IP address or name of the peer group. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] Name of a route map. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the peer group using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. + +set\_route\_map\_out command applies a route map to outbound BGP routes. + +commands router bgp {no \| default} neighbor route-map out + +@param name [String] The IP address or name of the peer group. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] Name of a route map. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the peer group using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. + +set\_description associates descriptive text with the specified peer or +peer group. + +commands router bgp {no \| default} neighbor description + +@param name [String] The IP address or name of the peer group. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The description string. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the peer group using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Dns class manages DNS settings on an EOS node. + +get returns the DNS resource. + +@example { "domain\_name": , "name\_servers": array, "domain\_list": +array } + +@return [Hash] A Ruby hash object that provides the SNMP settings as key +/ value pairs. + +parse\_domain\_name parses the domain-name from config. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_name\_servers parses the name-server values from config. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_domain\_list parses the domain-list from config. + +@api private + +@return [Hash] Returns the resource hash attribute. + +Configure the domain-name value in the running-config. + +@param opts [Hash] The configuration parameters. + +@option opts value [string] The value to set the domain-name to. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. + +@return [Boolean] Returns true if the command completed successfully. + +set\_name\_servers configures the set of name servers that eos will use +to resolve dns queries. If the enable option is false, then the +name-server list will be configured using the no keyword. If the default +option is specified, then the name server list will be configured using +the default keyword. If both options are provided the keyword option +will take precedence. + +@since eos\_version 4.13.7M + +commands ip name-server no ip name-server default ip name-server + +@param [Hash] opts The configuration parameters. + +@option opts value [string] The set of name servers to configure on the +node. The list of name servers will be replace in the nodes running +configuration by the list provided in value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option default [Boolean] Configures the ip name-servers using the +default keyword argument. Default takes precedence over enable. + +@return [Boolean] Returns true if the commands completed successfully. +cmds << "ip name-server {srv}" + +add\_name\_server adds an ip name-server. + +@param server [String] The name of the ip name-server to create. + +@return [Boolean] Returns true if the command completed successfully. +configure "ip name-server {server}" + +remove\_name\_server removes the specified ip name-server. + +@param server [String] The name of the ip name-server to remove. + +@return [Boolean] Returns true if the command completed successfully. +configure "no ip name-server {server}" + +set\_domain\_list configures the set of domain names to search when +making dns queries for the FQDN. If the enable option is set to false, +then the domain-list will be configured using the no keyword. If the +default option is specified, then the domain list will be configured +using the default keyword. If both options are provided the default +keyword option will take precedence. + +@since eos\_version 4.13.7M + +commands ip domain-list no ip domain-list default ip domain-list + +@option value [Array] The set of domain names to configure on the node. +The list of domain names will be replace in the nodes running +configuration by the list provided in value. + +@option default [Boolean] Configures the ip domain-list using the +default keyword argument. + +@return [Boolean] Returns true if the commands completed successfully. +cmds << "default ip domain-list {name}" cmds << "no ip domain-list +{name}" cmds << "ip domain-list {name}" + +add\_domain\_list adds an ip domain-list. + +@param name [String] The name of the ip domain-list to add. + +@return [Boolean] Returns true if the command completed successfully. +configure "ip domain-list {name}" + +remove\_domain\_list removes a specified ip domain-list. + +@param name [String] The name of the ip domain-list to remove. + +@return [Boolean] Returns true if the command completed successfully. +configure "no ip domain-list {name}" + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Interfaces class manages all physical and logical interfaces on an +EOS node. + +get returns a hash of interface configurations for the given name. + +@example { name: , type: , description: , shutdown: } + +@param name [String] The interface name to return a resource for from +the nodes configuration. + +@return [nil, Hash] Returns the interface resource as a +Hash. If the specified name is not found in the nodes current +configuration a nil object is returned. + +getall returns a hash of interface configurations. + +@example { : { name: , type: , description: , shutdown: , ... }, : { +name: , type: , description: , shutdown: , ... }, ... } + +@return [Hash] Returns the interface resources as a +Hash. If none exist in the nodes current configuration an empty hash is +returned. + +get\_instance returns an interface instance for the given name. + +@param name [String] The interface name to return an instance for. + +@return [Object] Returns the interface instance as an Object. + +The BaseInterface class extends Entity and provides an implementation +that is common to all interfaces configured in EOS. + +get returns the specified interface resource hash that represents the +node's current interface configuration. The BaseInterface class provides +all the set of attributes that are common to all interfaces in EOS. This +method will return an interface type of generic. + +@example { name: type: 'generic' description: shutdown: [true, false] } + +@param name [String] The name of the interface to return from the +running-configuration. + +@return [nil, Hash] Returns a hash of the interface +properties if the interface name was found in the running configuration. +If the interface was not found, nil is returned. config = +get\_block("^interface {name}") + +parse\_description scans the provided configuration block and parses the +description value if it exists in the configuration. If the description +value is not configured, then the DEFALT\_INTF\_DESCRIPTION value is +returned. The hash returned by this method is intended to be merged into +the interface resource hash returned by the get method. + +@api private + +@param config [String] The configuration block retrieved from the nodes +current running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_shutdown scans the provided configuration block and parses the +shutdown value. If the shutdown value is configured then true is +returned as its value otherwise false is returned. The hash returned by +this method is intended to be merged into the interface resource hash +returned by the get method. + +@api private + +@param config [String] The configuration block retrieved from the nodes +current running configuration. + +@return [Hash] Returns the resource hash attribute. + +create will create a new interface resource in the node's current +configuration with the specified interface name. If the create method is +called and the interface already exists, this method will return +successful. + +@since eos\_version 4.13.7M + +@param value [String] The interface name to create on the node. The +interface name must be the full interface identifier (ie Loopback, not +Lo). + +@return [Boolean] Returns true if the command completed successfully. +configure("interface {value}") + +delete will delete an existing interface resource in the node's current +configuration with the specified interface name. If the delete method is +called and interface does not exist, this method will return successful. + +@since eos\_version 4.13.7M + +@param value [String] The interface name to delete from the node. The +interface name must be the full interface identifier (ie Loopback, no +Lo). + +@return [Boolean] Returns true if the command completed successfully. +configure("no interface {value}") + +default will configure the interface using the default keyword. For +virtual interfaces this is equivalent to deleting the interface. For +physical interfaces, the entire interface configuration will be set to +defaults. + +@since eos\_version 4.13.7M + +@param value [String] The interface name to default in the node. The +interface name must be the full interface identifier (ie Loopback, not +Lo). + +@return [Boolean] Returns true if the command completed successfully. +configure("default interface {value}") + +set\_description configures the description value for the specified +interface name in the nodes running configuration. If the enable keyword +is false then the description value is negated using the no keyword. If +the default keyword is set to true, then the description value is +defaulted using the default keyword. The default keyword takes +precedence over the enable keyword if both are provided. + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration to. +The name value must be the full interface identifier. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The value to configure the description to in +the node's configuration. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the interface description using +the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_shutdown configures the administrative state of the specified +interface in the node. If the enable keyword is false, then the +interface is administratively disabled. If the enable keyword is true, +then the interface is administratively enabled. If the default keyword +is set to true, then the interface shutdown value is configured using +the default keyword. The default keyword takes precedence over the +enable keyword if both are provided. + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration to. +The name value must be the full interface identifier. + +@param opts [hash] Optional keyword arguments. + +@option opts enable [Boolean] True if the interface should be +administratively enabled or false if the interface should be +administratively disabled. + +@option opts default [Boolean] Configure the interface shutdown using +the default keyword. + +@return [Boolean] Returns true if the command completed successfully. +Shutdown semantics are opposite of enable semantics so invert enable. + +The EthernetInterface class manages all Ethernet interfaces on an EOS +node. + +get returns the specified Ethernet interface resource hash that +represents the interface's current configuration in the node. + +@example { name: , type: , description: , shutdown: , speed: , forced: , +sflow: , flowcontrol\_send: , flowcontrol\_receive: } + +@param name [String] The interface name to return a resource hash for +from the node's running configuration. + +@return [nil, Hash] Returns the interface resource as a +hash. If the specified interface name is not found in the node's +configuration a nil object is returned. config = get\_block("^interface +{name}") + +parse\_speed scans the provided configuration block and parses the speed +value. If the speed value is not found in the interface configuration +block provided, DEFAULT\_SPEED and DEFAULT\_FORCED are used. The +returned hash is intended to be merged into the interface resource hash. + +@api private + +@param config [String] The configuration block to parse. + +@return [Hash] Returns the resource hash attribute. + +parse\_sflow scans the provided configuration block and parse the sflow +value. The sflow values true if sflow is enabled on the interface or +returns false if it is not enabled. The hash returned is intended to be +merged into the interface hash. + +@api private + +@param config [String] The configuration block to parse. + +@return [Hash] Returns the resource hash attribute. + +parse\_flowcontrol\_send scans the provided configuration block and +parses the flowcontrol send value. If the interface flowcontrol value is +not configured, then this method will return the value of +DEFAULT\_ETH\_FLOWC\_TX. The hash returned is intended to be merged into +the interface resource hash. + +@api private + +@param config [String] The configuration block to parse. + +@return [Hash] Returns the resource hash attribute. + +parse\_flowcontrol\_receive scans the provided configuration block and +parse the flowcontrol receive value. If the interface flowcontrol value +is not configured, then this method will return the value of +DEFAULT\_ETH\_FLOWC\_RX. The hash returned is intended to be merged into +the interface resource hash. + +@api private + +@param config [String] The configuration block to parse. + +@return [Hash] Returns the resource hash attribute. + +create overrides the create method from the BaseInterface and raises an +exception because Ethernet interface creation is not supported. + +@param \_name [String] The name of the interface. + +@raise [NotImplementedError] Creation of physical Ethernet interfaces is +not supported. + +delete overrides the delete method fro the BaseInterface instance and +raises an exception because Ethernet interface deletion is not +supported. + +@param \_name [String] The name of the interface. + +@raise [NotImplementedError] Deletion of physical Ethernet interfaces is +not supported. + +set\_speed configures the interface speed and negotiation values on the +specified interface. If the enable option is false the speed setting is +configured using the no keyword. If the default options is set to true, +then the speed setting is configured using the default keyword. If both +options are specified, the default keyword takes precedence. + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the speed setting to +in the nodes running configuration. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts forced [Boolean] Specifies if auto negotiation should be +enabled (true) or disabled (false). + +@option opts default [Boolean] Configures the sflow value on the +interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. +cmds = ["interface {name}"] cmds << enable ? "speed {forced} {value}" : +'no speed' + +set\_sflow configures the administrative state of sflow on the +interface. Setting the enable keyword to true enables sflow on the +interface and setting enable to false disables sflow on the interface. +If the default keyword is set to true, then the sflow value is defaulted +using the default keyword. The default keyword takes precedence over the +enable keyword + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param opts [Hash] Optional keyword arguments. + +@option opts enable [Boolean] Enables sflow if the value is true or +disables sflow on the interface if false. Default is true. + +@option opts default [Boolean] Configures the sflow value on the +interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_flowcontrol configures the flowcontrol value either on or off for +the for the specified interface in the specified direction (either send +or receive). If the enable keyword is false then the configuration is +negated using the no keyword. If the default keyword is set to true, +then the state value is defaulted using the default keyword. The default +keyword takes precedence over the enable keyword + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param direction [String] Specifies the flowcontrol direction to +configure. Valid values include send and receive. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] Specifies the value to configure the +flowcontrol setting for. Valid values include on or off. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the flowcontrol value on the +interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. +commands = command\_builder("flowcontrol {direction}", opts) + +set\_flowcontrol\_send is a convenience function for configuring the +value of interface flowcontrol. + +@see set\_flowcontrol + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] Specifies the value to configure the +flowcontrol setting for. Valid values include on or off. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the flowcontrol value on the +interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_flowcontrol\_receive is a convenience function for configuring the +value of interface flowcontrol. + +@see set\_flowcontrol + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] Specifies the value to configure the +flowcontrol setting for. Valid values include on or off. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the flowcontrol value on the +interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +The PortchannelInterface class manages all port channel interfaces on an +EOS node. + +get returns the specified port-channel interface configuration from the +nodes running configuration as a resource hash. The resource hash +returned extends the BaseInterface resource hash, sets the type value to +portchannel and adds the portchannel specific attributes + +@example { type: 'portchannel' description: shutdown: [true, false] +members: array[] lacp\_mode: [active, passive, on] minimum\_links: +lacp\_timeout: lacp\_fallback: [static, individual, disabled] } + +@see BaseInterface Interface get example + +@param name [String] The name of the portchannel interface to return a +resource hash for. The name must be the full interface name of the +desired interface. + +@return [nil, Hash] Returns the interface resource as a +hash object. If the specified interface does not exist in the running +configuration, a nil object is returned. config = get\_block("^interface +{name}") + +parse\_members scans the nodes running config and returns all of the +Ethernet members for the port-channel interface specified. If the +port-channel interface has no members configured, then this method will +assign an empty array as the value for members. The hash returned is +intended to be merged into the interface resource hash. + +@api private + +@param name [String] The name of the portchannel interface to extract +the members for. + +@return [Hash] Returns the resource hash attribute. +command = "show port-channel {grpid} all-ports" + +parse\_lacp\_mode scans the member interfaces and returns the configured +lacp mode. The lacp mode value must be common across every member in the +port channel interface. If no members are configured, the value for +lacp\_mode will be set using DEFAULT\_LACP\_MODE. The hash returned is +intended to be merged into the interface resource hash + +@api private + +@param name [String] The name of the portchannel interface to extract +the members from in order to get the configured lacp\_mode. + +@return [Hash] Returns the resource hash attribute. +config = get\_block("interface {members.first}") + +parse\_minimum\_links scans the port-channel configuration and returns +the value for port-channel minimum-links. If the value is not found in +the interface configuration, then DEFAULT\_MIN\_LINKS value is used. The +hash returned is intended to be merged into the interface resource hash. + +@api private + +@param config [String] The interface configuration block to extract the +minimum links value from. + +@return [Hash] Returns the resource hash attribute. + +parse\_lacp\_fallback scans the interface config block and returns the +configured value of the lacp fallback attribute. If the value is not +configured, then the method will return the value of +DEFAULT\_LACP\_FALLBACK. The hash returned is intended to be merged into +the interface resource hash. + +@api private + +@param config [String] The interface configuration block to extract the +lacp fallback value from. + +@return [Hash] Returns the resource hash attribute. + +parse\_lacp\_timeout scans the interface config block and returns the +value of the lacp fallback timeout value. The value is expected to be +found in the interface configuration block. The hash returned is +intended to be merged into the interface resource hash. + +@api private + +@param config [String] The interface configuration block to extract the +lacp timeout value from. + +@return [Hash] Returns the resource hash attribute. + +set\_minimum\_links configures the minimum physical links up required to +consider the logical portchannel interface operationally up. If the +enable keyword is false then the minimum-links is configured using the +no keyword argument. If the default keyword argument is provided and set +to true, the minimum-links value is defaulted using the default keyword. +The default keyword takes precedence over the enable keyword argument if +both are provided. + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String, Integer] Specifies the value to configure +the minimum-links to in the configuration. Valid values are in the range +of 1 to 16. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the minimum links value on the +interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_members configures the set of physical interfaces that comprise the +logical port-channel interface. The members value passed should be an +array of physical interface names that comprise the port-channel +interface. This method will add and remove individual members as +required to sync the provided members array. + +@see add\_member Adds member links to the port-channel interface. + +@see remove\_member Removes member links from the port-channel +interface. + +@param name [String] The name of the port-channel interface to apply the +members to. If the port-channel interface does not already exist it will +be created. + +@param members [Array] The array of physical interface members to add to +the port-channel logical interface. + +@param mode [str] The LACP mode to configure the member interfaces to. +Valid values are 'on, 'passive', 'active'. When there are existing +channel-group members and their lacp mode differs from this attribute, +all of those members will be removed and then re-added using the +specified lacp mode. If this attribute is omitted, the existing lacp +mode will be used for new member additions. + +@return [Boolean] Returns true if the command completed successfully. +remove members from the current port-channel interface. cmds << +"interface {intf}" cmds << "no channel-group {grpid}" add new member +interfaces to the port-channel. cmds << "interface {intf}" cmds << +"channel-group {grpid} mode {lacp\_mode}" + +add\_member adds the interface specified in member to the port-channel +interface specified by name in the nodes running-configuration. If the +port-channel interface does not already exist, it will be created. + +@since eos\_version 4.13.7M + +@param name [String] The name of the port-channel interface to apply the +configuration to. + +@param member [String] The name of the physical Ethernet interface to +add to the logical port-channel interface. + +@return [Boolean] Returns true if the command completed successfully. +configure\_interface(member, "channel-group {grpid} mode {lacp}") + +remove\_member removes the interface specified in member from the +port-channel interface specified by name in the nodes +running-configuration. + +@since eos\_version 4.13.7M + +@param name [String] The name of the port-channel interface to apply the +configuration to. + +@param member [String] The name of the physical Ethernet interface to +remove from the logical port-channel interface. + +@return [Boolean] Returns true if the command completed successfully. +configure\_interface(member, "no channel-group {grpid}") + +set\_lacp\_mode configures the lacp mode on the port-channel interface +by configuring the lacp mode value for each member interface. This +method will find all member interfaces for a port-channel and +reconfigure them using the mode argument. + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param mode [String] The lacp mode to configure on the member interfaces +for the port-channel. Valid values include active, passive or on. + +@return [Boolean] Returns true if the command completed successfully. +remove\_commands << "interface {member}" remove\_commands << "no +channel-group {grpid}" add\_commands << "interface {member}" +add\_commands << "channel-group {grpid} mode {mode}" + +set\_lacp\_fallback configures the lacp fallback mode for the +port-channel interface. If the enable keyword is false, lacp fallback is +configured using the no keyword argument. If the default option is +specified and set to true, the lacp fallback value is configured using +the default keyword. The default keyword takes precedence over the +enable keyword if both options are provided. + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] Specifies the value to configure for the +port-channel lacp fallback. Valid values are individual and static. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the lacp fallback value on the +interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_lacp\_timeout configures the lacp fallback timeout for the +port-channel interface. If the enable keyword is false, lacp fallback +timeout is configured using the no keyword argument. If the default +option is specified and set to true, the lacp fallback timeout value is +configured using the default keyword. The default keyword takes +precedence over the enable keyword if both options are provided. + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] Specifies the value to configure for the +port-channel lacp fallback timeout. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the lacp fallback timeout +value on the interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +The VxlanInterface class manages all Vxlan interfaces on an EOS node. + +Returns the Vxlan interface configuration as a Ruby hash of key/value +pairs from the nodes running configuration. This method extends the +BaseInterface get method and adds the Vxlan specific attributes to the +hash. + +@example { name: , type: , description: , shutdown: , source\_interface: +, multicast\_group: , udp\_port: , flood\_list: , vlans: } + +@param name [String] The interface name to return from the nodes +configuration. This optional parameter defaults to Vxlan1. + +@return [nil, Hash] Returns the interface configuration +as a Ruby hash object. If the provided interface name is not found then +this method will return nil. config = get\_block("interface {name}") + +parse\_source\_interface scans the interface config block and returns +the value of the vxlan source-interface. If the source-interface is not +configured then the value of DEFAULT\_SRC\_INTF is used. The hash +returned is intended to be merged into the interface resource hash + +@api private + +@param config [String] The interface configuration block to extract the +vxlan source-interface value from. + +@return [Hash] + +parse\_multicast\_group scans the interface config block and returns the +value of the vxlan multicast-group. If the multicast-group is not +configured then the value of DEFAULT\_MCAST\_GRP is used. The hash +returned is intended to be merged into the interface resource hash. + +@api private + +@param config [String] The interface configuration block to extract the +vxlan multicast-group value from. + +@return [Hash] + +parse\_udp\_port scans the interface config block and returns the value +of the vxlan udp-port setting. The vxlan udp-port value is expected to +always be present in the configuration. The returned value is intended +to be merged into the interface resource Hash. + +@api private + +@param config [String] The interface configuration block to parse the +vxlan udp-port value from. + +@return [Hash] + +parse\_flood\_list scans the interface config block and returns the list +of configured VTEPs that comprise the flood list. If there are no flood +list values configured, the value will return DEFAULT\_FLOOD\_LIST. The +returned value is intended to be merged into the interface resource +Hash. + +@api private + +@param config [String] The interface configuration block to parse the +vxlan flood list values from. + +@return [Hash] + +parse\_vlans scans the interface config block and returns the set of +configured vlan to vni mappings. If there are no vlans configured, the +value will return an empty Hash. + +@api private + +@param config [String] The interface configuration block to parse the +vxlan flood list values from. + +@return [Hash] + +Configures the vxlan source-interface to the specified value. This +parameter should be the interface identifier of the interface to act as +the source for all Vxlan traffic. + +@param name [String] The name of the interface to apply the +configuration values to. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] Configures the vxlan source-interface to the +specified value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Specifies whether or not the +multicast-group command is configured as default. The value of this +option has a higher precedence than :enable. + +@return [Boolean] Returns true if the commands complete successfully. + +Configures the vxlan multicast-group flood address to the specified +value. The value should be a valid multicast address. + +@param name [String] The name of the interface to apply the +configuration values to. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] Configures the multicast-group flood address +to the specified value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Specifies whether or not the +multicast-group command is configured as default. The value of this +option has a higher precedence than :value. + +@return [Boolean] Returns true if the commands complete successfully. + +set\_udp\_port configures the Vxlan udp-port value in EOS for the +specified interface name. If the enable keyword is false then the no +keyword is used to configure the value. If the default option is +provided and set to true, then the default keyword is used. If both +options are provided, the default keyword will take precedence. + +@since eos\_version 4.13.7M + +@param name [String] The name of the vxlan interface to configure. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] Specifies the value to configure the +udp-port setting to. Valid values are in the range of 1024 to 65535. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the udp-port value on the +interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +add\_vtep adds a new VTEP endpoint to the global flood list for the +specified interface. If the VTEP endpoint is already configured, this +method will still return successfully. + +@since eos\_version 4.13.7M + +@param name [String] The name of the interface to configure. + +@param vtep [String] The IP address of the remote VTEP endpoint. + +@return [Boolean] Returns true if the commands completed successfully. +configure\_interface(name, "vxlan flood vtep add {vtep}") + +remove\_vtep deletes a VTEP endpoint from the global flood list for the +specified interface. If the VTEP endpoint specified is not configured, +this method will still return successfully. + +@since eos\_version 4.13.7M + +@param name [String] The name of the interface to configure. + +@param vtep [String] The IP address of the remote VTEP endpoint. + +@return [Boolean] Returns true if the commands completed successfully. +configure\_interface(name, "vxlan flood vtep remove {vtep}") + +update\_vlan creates a new vlan to vni mapping for the specified +interface in the nodes current configuration. + +@since eos\_verson 4.13.7M + +@param name [String] The name of the interface to configure. + +@param vlan [Fixnum] The VLAN ID to configure. + +@param vni [Fixnum] The VNI value to map the VLAN into. + +@return [Boolean] Returns true if the command completed successfully. +configure\_interface(name, "vxlan vlan {vlan} vni {vni}") + +remove\_vlan deletes a previously configured VLAN to VNI mapping on the +specified interface. + +@since eos\_version 4.13.7M + +@param name [String] the name of the interface to configure. + +@param vlan [Fixnum] The VLAN ID to remove from the configuration. If +the VLAN ID does not exist, this method will still return successfully. + +@return [Boolean] Returns true if the command completed successfully. +configure\_interface(name, "no vxlan vlan {vlan} vni") + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Ipinterface class provides an instance for managing logical IP +interfaces configured using eAPI. + +get returns a resource hash that represents the configuration of the IP +interface from the nodes running configuration. + +@example { address: , mtu: , helper\_addresses: array } + +@param name [String] The full interface identifier of the interface to +return the resource configuration hash for. The name must be the full +name (Ethernet, not Et). + +@return [nil, Hash] Returns the ip interface +configuration as a hash. If the provided interface name is not a +configured ip address, nil is returned. config = get\_block("interface +{name}") + +getall returns a hash object that represents all ip interfaces +configured on the node from the current running configuration. + +@example { : { address: , mtu: , helper\_addresses: array }, : { +address: , mtu: , helper\_addresses: array }, ... } + +@see get Ipaddress resource example + +@return [Hash] Returns a hash object that represents all +of the configured IP addresses found. If no IP addresses are configured, +then an empty hash is returned. + +parse\_address scans the provided configuration block and extracts the +interface address, if configured, and returns it. If there is no IP +address configured, then this method will return the DEFAULT\_ADDRESS. +The return value is intended to be merged into the ipaddress resource +hash. + +@api private + +@param config [String] The IP interface configuration block returned +from the node's running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_mtu scans the provided configuration block and extracts the IP +interface MTU value. The MTU value is expected to always be present in +the configuration blcok. The return value is intended to be merged into +the ipaddress resource hash. + +@api private + +@param config [String] The IP interface configuration block returned +from the node's running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_helper\_addresses scans the provided configuration block and +extracts any configured IP helper address values. The interface could be +configured with one or more helper addresses. If no helper addresses are +configured, then an empty array is set in the return hash. The return +value is intended to be merged into the ipaddress resource hash. + +@api private + +@param config [String] The IP interface configuration block returned +from the node's running configuration. + +@return [Hash] Returns the resource hash attribute. + +create will create a new IP interface on the node. If the ip interface +already exists in the configuration, this method will still return +successful. This method will cause an existing layer 2 interface +(switchport) to be deleted if it exists in the node's configuration. + +@since eos\_version 4.13.7M + +commands interface no switchport + +@param name [String] The full interface name of the port to create the +logical interface on. The name must be the full interface identifier. + +@return [Boolean] Returns true if the commands complete successfully. +configure(["interface {name}", 'no switchport']) + +delete will delete an existing IP interface in the node's current +configuration. If the IP interface does not exist on the specified +interface, this method will still return success. This command will +default the interface back to being a switchport. + +@since eos\_version 4.13.7M + +commands interface no ip address switchport + +@param name [String] The full interface name of the port to delete the +logical interface from. The name must be the full interface name + +@return [Boolean] Returns true if the commands complete successfully. +configure(["interface {name}", 'no ip address', 'switchport']) + +set\_address configures a logical IP interface with an address. The +address value must be in the form of A.B.C.D/E. If the enable keyword is +false, then the interface address is negated using the config no +keyword. If the default option is set to true, then the ip address value +is defaulted using the default keyword. The default keyword has +precedence over the enable keyword if both options are specified. + +@since eos\_version 4.13.7M + +commands interface ip address no ip address default ip address + +@param name [String] The name of the interface to configure the address +in the node. The name must be the full interface name. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the address to for +the specified interface name. The value must be in the form of +A.B.C.D/E. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the ip address value using the +default keyword. + +@return [Boolean] Returns True if the command completed successfully. + +set\_mtu configures the IP mtu value of the ip interface in the nodes +configuration. If the enable option is false, then the ip mtu value is +configured using the no keyword. If the default keyword option is +provided and set to true then the ip mtu value is configured using the +default keyword. The default keyword has precedence over the enable +keyword if both options are specified. + +@since eos\_version 4.13.7M + +commands interface mtu no mtu default mtu + +@param name [String] The name of the interface to configure the address +in the node. The name must be the full interface name. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the IP MTU to in the +nodes configuration. Valid values are in the range of 68 to 9214 bytes. +The default is 1500 bytes. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the ip mtu value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_helper\_addresses configures the list of helper addresses on the ip +interface. An IP interface can have one or more helper addresses +configured. If no value is provided, the helper address configuration is +set using the no keyword. If the default option is specified and set to +true, then the helper address values are defaulted using the default +keyword. + +@since eos\_version 4.13.7M + +commands interface ip helper-address no ip helper-address default ip +helper-address + +@param name [String] The name of the interface to configure the address +in the node. The name must be the full interface name. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [Array] The list of IP addresses to configure as +helper address on the interface. The helper addresses must be valid +addresses in the main interface's subnet. + +@option opts default [Boolean] Configure the ip helper address values +using the default keyword. + +value.each { \|addr\| cmds << "ip helper-address {addr}" } if enable + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Logging class manages logging settings on an EOS node. + +get returns the current logging configuration hash extracted from the +nodes running configuration. + +@example { enable: [true, false], hosts: array } + +@return [Hash] Returns the logging resource as a hash +object from the nodes current configuration. + +parse\_enable scans the nodes current running configuration and extracts +the current enabled state of the logging facility. The logging enable +command is expected to always be in the node's configuration. This +methods return value is intended to be merged into the logging resource +hash. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_hosts scans the nodes current running configuration and extracts +the configured logging host destinations if any are configured. If no +logging hosts are configured, then the value for hosts will be an empty +array. The return value is intended to be merged into the logging +resource hash + +@api private + +@return [Hash] Returns the resource hash attribute. + +set\_enable configures the global logging instance on the node as either +enabled or disabled. If the enable keyword is set to true then logging +is globally enabled and if set to false, it is globally disabled. If the +default keyword is specified and set to true, then the configuration is +defaulted using the default keyword. The default keyword option takes +precedence over the enable keyword if both options are specified. + +@since eos\_version 4.13.7M + +commands logging on no logging on default logging on + +@param opts [Hash] Optional keyword arguments + +@option opts enable [Boolean] Enables logging globally if value is true +or disabled logging globally if value is false. + +@option opts default [Boolean] Configure the ip address value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +add\_host configures a new logging destination host address or hostname +to the list of logging destinations. If the host is already configured +in the list of destinations, this method will return successfully. + +@since eos\_version 4.13.7M + +commands logging host + +@param name [String] The host name or ip address of the destination node +to send logging information to. + +@return [Boolean] Returns true if the command completed successfully. +configure "logging host {name}" + +remove\_host deletes a logging destination host name or address form the +list of logging destinations. If the host is not in the list of +configured hosts, this method will still return successfully. + +@since eos\_version 4.13.7M + +commands no logging host + +@param name [String] The host name or ip address of the destination host +to remove from the nodes current configuration. + +@return [Boolean] Returns true if the commands completed successfully. +configure "no logging host {name}" + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Mlag class provides a configuration instance for working with the +global MLAG configuration of the node. + +get scans the current nodes configuration and returns the values as a +Hash describing the current state. + +@example { global: { domain\_id: , local\_interface: , peer\_address: , +peer\_link: , shutdown: }, interfaces: { : { mlag\_id: }, : { mlag\_id: +}, ... } } + +@see parse\_interfaces + +@return [nil, Hash] Returns the resource hash attribute. + +parse\_local\_interface scans the current nodes running configuration +and extracts the mlag local-interface value. If the mlag local-interface +has not been configured, this method will return DEFAULT\_LOCAL\_INTF. +The return value is intended to be merged into the resource hash. + +@api private + +@param config [String] The mlag configuration block retrieved from the +nodes current running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_peer\_address scans the current nodes running configuration and +extracts the mlag peer-address value. If the mlag peer-address has not +been configured, this method will return DEFAULT\_PEER\_ADDR. The return +value is intended to be merged into the resource hash. + +@api private + +@param config [String] The mlag configuration block retrieved from the +nodes current running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_peer\_link scans the current nodes running configuration and +extracts the mlag peer-link value. If the mlag peer-link hash not been +configure, this method will return DEFAULT\_PEER\_LINK. The return value +is intended to be merged into the resource hash. + +@api private + +@param config [String] The mlag configuration block retrieved from the +nodes current running configuration. + +@return [Hash] Returns the resource hash attribute + +parse\_shutdown scans the current nodes mlag configuration and extracts +the mlag shutdown value. The mlag configuration should always return the +value of shutdown from the configuration block. The return value is +intended to be merged into the resource hash. + +@api private + +@param config [String] The mlag configuration block retrieved from the +nodes current running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_interfaces scans the global configuration and returns all of the +configured MLAG interfaces. Each interface returns the configured MLAG +identifier for establishing a MLAG peer. The return value is intended to +be merged into the resource Hash. + +The resource Hash attribute returned contains: \* mlag\_id: (Fixnum) The +configured MLAG identifier. + +@api private + +@return [Hash] Returns the resource Hash attribute. +config = get\_block("^interface {name}") + +set\_domain\_id configures the mlag domain-id value in the current nodes +running configuration. If the enable keyword is false, the the domain-id +is configured with the no keyword. If the default keyword is provided, +the configuration is defaulted using the default keyword. The default +keyword takes precedence over the enable keyword if both options are +specified. + +@since eos\_version 4.13.7M + +commands mlag configuration domain-id no domain-id default domain-id + +@param opts [Hash] Optional keyword arguments + +@option opts value [String] The value to configure the mlag domain-id +to. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the domain-id value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_local\_interface configures the mlag local-interface value in the +current nodes running configuration. If the enable keyword is false, the +local-interface is configured with the no keyword. If the default +keyword is provided, the configuration is defaulted using the default +keyword. The default keyword takes precedence over the enable keyword if +both options are specified + +@since eos\_version 4.13.7M + +commands mlag configuration local-interface no local-interface default +local-interface + +@param opts [Hash] Optional keyword arguments + +@option opts value [String] The value to configure the mlag +local-interface to. The local-interface accepts full interface +identifiers and expects a Vlan interface + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the local-interface value using +the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_peer\_link configures the mlag peer-link value in the current nodes +running configuration. If enable keyword is false, then the peer-link is +configured with the no keyword. If the default keyword is provided, the +configuration is defaulted using the default keyword. The default +keyword takes precedence over the enable keyword if both options are +specified. + +@since eos\_version 4.13.7M + +commands mlag configuration peer-link no peer-link default peer-link + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the mlag peer-link +to. The peer-link accepts full interface identifiers and expects an +Ethernet or Port-Channel interface. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the peer-link using the default +keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_peer\_address configures the mlag peer-address value in the current +nodes running configuration. If the enable keyword is false, then the +peer-address is configured with the no keyword. If the default keyword +is provided, the configuration is defaulted using the default keyword. +The default keyword takes precedence over the enable keyword if both +options are specified + +@since eos\_version 4.13.7M + +commands mlag configuration peer-address no peer-address default +peer-address + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the mlag peer-address +to. The peer-address accepts an IP address in the form of A.B.C.D/E. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the peer-address using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_shutdown configures the administrative state of the mlag process on +the current node. If the enable keyword is true, then mlag is enabled +and if the enable keyword is false, then mlag is disabled. If the +default keyword is provided, the configuration is defaulted using the +default keyword. The default keyword takes precedence over the enable +keyword if both options are specified + +@since eos\_version 4.13.7M + +commands mlag configuration shutdown no shutdown default shutdown + +@param opts [Hash] Optional keyword arguments. + +@option opts enable [Boolean] True if the interface should be +administratively enabled or false if the interface should be +administratively disabled. + +@option opts default [Boolean] Configure the shutdown value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. +Shutdown semantics are opposite of enable semantics so invert enable + +set\_mlag\_id configures the mlag id on the interface in the nodes +current running configuration. If the enable keyword is false, then the +interface mlag id is configured using the no keyword. If the default +keyword is provided and set to true, the interface mlag id is configured +using the default keyword. The default keyword takes precedence over the +enable keyword if both options are specified + +@since eos\_version 4.13.7M + +commands interface mlag no mlag default mlag + +@param name [String] The full interface identifier of the interface to +configure th mlag id for. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String, Integer] The value to configure the +interface mlag to. The mlag id should be in the valid range of 1 to +2000. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the mlag value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Ntp class provides an instance for working with the nodes NTP +configuration. + +get returns the nodes current ntp configure as a resource hash. + +@example { source\_interface: , servers: { prefer: [true, false] } } + +@return [nil, Hash] Returns the ntp resource as a Hash. + +parse\_source\_interface scans the nodes configurations and parses the +ntp source interface if configured. If the source interface is not +configured, this method will return DEFAULT\_SRC\_INTF as the value. The +return hash is intended to be merged into the resource hash. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_servers scans the nodes configuration and parses the configured +ntp server host names and/or addresses. This method will also return the +value of prefer. If no servers are configured, the value will be set to +an empty array. The return hash is intended to be merged into the +resource hash. + +@api private + +@return [Hash] Returns the resource hash attribute. + +set\_source\_interface configures the ntp source value in the nodes +running configuration. If the enable keyword is false, then the ntp +source is configured with the no keyword argument. If the default +keyword argument is provided and set to true, the value is configured +used the default keyword. The default keyword takes precedence over the +enable keyword if both options are specified. + +@since eos\_version 4.13.7M + +commands ntp source no ntp source default ntp source + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the ntp source in the +nodes configuration. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the ntp source value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +add\_server configures a new ntp server destination hostname or ip +address to the list of ntp destinations. The optional prefer argument +configures the server as a preferred (true) or not (false) ntp +destination. + +@param server [String] The IP address or FQDN of the NTP server to be +removed from the configuration. + +@param prefer [Boolean] Appends the prefer keyword argument to the +command if this value is true. + +@return [Boolean] Returns true if the command completed successfully. +cmd = "ntp server {server}" + +remove\_server deletes the provided server destination from the list of +ntp server destinations. If the ntp server does not exist in the list of +servers, this method will return successful + +@param server [String] The IP address or FQDN of the NTP server to be +removed from the configuration. + +@return [Boolean] Returns true if the command completed successfully. +configure("no ntp server {server}") + +set\_prefer will set the prefer keyword for the specified ntp server. If +the server does not already exist in the configuration, it will be added +and the prefer keyword will be set. + +@since eos\_version 4.13.7M + +commands ntp server prefer no ntp server prefer + +@param srv [String] The IP address or hostname of the ntp server to +configure with the prefer value. + +@param value [Boolean] The value to configure for prefer. If true the +prefer value is configured for the server. If false, then the prefer +value is removed. + +@return [Boolean] Returns true if the commands completed successfully. +cmds = "ntp server {srv} prefer" cmds = ["no ntp server {srv} prefer", +"ntp server {srv}"] + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Ospf class is a global class that provides an instance for working +with the node's OSPF configuration. + +Returns the global OSPF configuration from the node. + +rubocop:disable Metrics/MethodLength + +@example { router\_id: areas: { : array }, redistribute: {} } + +@param inst [String] The ospf instance name. + +@return [Hash] A Ruby hash object that provides the OSPF settings as key +/ value pairs. config = get\_block("router ospf {inst}") + +Returns the OSPF configuration from the node as a Ruby hash. + +@example { : { router\_id: , areas: {}, redistribute: {} }, interfaces: +{} } + +@return [Hash] A Ruby hash object that provides the OSPF settings as key +/ value pairs. + +create will create a router ospf with the specified pid. + +@param pid [String] The router ospf to create. + +@return [Boolean] Returns true if the command completed successfully. +configure "router ospf {pid}" + +delete will remove the specified router ospf. + +@param pid [String] The router ospf to remove. + +@return [Boolean] Returns true if the command completed successfully. +configure "no router ospf {pid}" + +set\_router\_id sets router ospf router-id with pid and options. + +@param pid [String] The router ospf name. + +@param opts [hash] Optional keyword arguments. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the router-id to default. + +@return [Boolean] Returns true if the command completed successfully. +cmds = ["router ospf {pid}", cmd] + +add\_network adds network settings for router ospf and network area. + +@param pid [String] The pid for router ospf. + +@param net [String] The network name. + +@param area [String] The network area name. + +@return [Boolean] Returns true if the command completed successfully. +configure ["router ospf {pid}", "network {net} area {area}"] + +remove\_network removes network settings for router ospf and network +area. + +@param pid [String] The pid for router ospf. + +@param net [String] The network name. + +@param area [String] The network area name. + +@return [Boolean] Returns true if the command completed successfully. +configure ["router ospf {pid}", "no network {net} area {area}"] + +set\_redistribute sets router ospf router-id with pid and options. + +@param pid [String] The router ospf name. + +@param proto [String] The redistribute value. + +@param opts [hash] Optional keyword arguments. + +@option opts routemap [String] The route-map value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the router-id to default. + +@return [Boolean] Returns true if the command completed successfully. +cmds = ["router ospf {pid}", "redistribute {proto}"] cmds[1] << " +route-map {routemap}" if routemap + +The OspfInterfaces class is a global class that provides an instance for +working with the node's OSPF interface configuration. + +Returns a single MLAG interface configuration. + +Example { network\_type: } + +@param name [String] The interface name to return the configuration +values for. This must be the full interface identifier. + +@return [nil, Hash] A Ruby hash that represents the MLAG +interface configuration. A nil object is returned if the specified +interface is not configured config = get\_block("interface {name}") + +Returns the collection of MLAG interfaces as a hash index by the +interface name. + +Example { : { network\_type: }, : { network\_type: }, ... } + +@return [nil, Hash] A Ruby hash that represents the MLAG +interface configuration. A nil object is returned if no interfaces are +configured. + +set\_network\_type sets network type with options. + +@param name [String] The name of the interface. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The point-to-point value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the ip ospf network to default. + +@return [Boolean] Returns true if the command completed successfully. + +Copyright (c) 2014, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Prefixlists class provides a configuration instance for working with +static routes in EOS. + +Returns the static routes configured on the node. + +@example { : { next\_hop: , name: } } + +@param name [String] The name of the prefix-list to return. + +@return [Hash The method will return all of the configured static routes +on the node as a Ruby hash object. If there are no static routes +configured, this method will return an empty hash. config = +get\_block("ip prefix-list {name}") + +Returns the static routes configured on the node. + +@example { : { next\_hop: , name: } } + +@return [Hash The method will return all of the configured static routes +on the node as a Ruby hash object. If there are no static routes +configured, this method will return an empty hash. + +create will create a new ip prefix-list with designated name. + +@param name [String] The name of the ip prefix-list. + +@return [Boolean] Returns true if the command completed successfully. +configure "ip prefix-list {name}" + +add\_rule will create an ip prefix-list with the designated name, seqno, +action and prefix. + +@param name [String] The name of the ip prefix-list. + +@param seq [String] The seq value. + +@param action [String] The action value. + +@param prefix [String] The prefix value. + +@return [Boolean] Returns true if the command completed successfully. +cmd = "ip prefix-list {name}" cmd << " seq {seq}" if seq cmd << " +{action} {prefix}" + +delete will remove the designated prefix-list. + +@param name [String] The name of the ip prefix-list. + +@param seq [String] The seq value. + +@return [Boolean] Returns true if the command completed successfully. +cmd = "no ip prefix-list {name}" cmd << " seq {seq}" if seq + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +Radius provides instance methods to retrieve and set radius +configuration values. Regular expression to extract a radius server's +attributes from the running-configuration text. The explicit [ ] spaces +enable line wrapping and indentation with the /x flag. + +get Returns an Array with a single resource Hash describing the current +state of the global radius configuration on the target device. This +method is intended to be used by a provider's instances class method. + +@example { key: , key\_format: , timeout: , retransmit: , servers: } + +@return [Array] Single element Array of resource hashes. + +parse\_time scans the nodes current configuration and parse the +radius-server timeout value. The timeout value is expected to always be +present in the config. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_retransmit scans the cnodes current configuration and parses the +radius-server retransmit value. The retransmit value is expected to +always be present in the config. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_key scans the current nodes running configuration and parse the +global radius-server key and format value. If the key is not configured +this method will return DEFAULT\_KEY and DEFAULT\_KEY\_FORMAT for the +resource hash values. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_servers returns an Array of radius server resource hashes. Each +hash describes the current state of the radius server and is intended to +be merged into the radius resource hash. + +The resource hash returned contains the following information: \* +hostname: hostname or ip address \* vrf: (String) vrf name \* key: +(String) the key either in plain text or hashed format \* key\_format: +(Fixnum) e.g. 0 or 7 \* timeout: (Fixnum) seconds before the timeout +period ends \* retransmit: (Integer), e.g. 3, attempts after first +timeout expiry. \* group: (String) Server group associated with this +server. \* acct\_port: (Fixnum) Port number to use for accounting. \* +accounting\_only: (Boolean) Enable this server for accounting only. \* +auth\_port: (Fixnum) Port number to use for authentication + +@api private + +@return [Array>] Array of resource hashes. + +set\_global\_key configures the global radius-server key. If the enable +option is false, radius-server key is configured using the no keyword. +If the default option is specified, radius-server key is configured +using the default keyword. If both options are specified, the default +keyword option takes precedence. + +@since eos\_version 4.13.7M + +commands radius-server key no radius-server key default radius-server +key + +@option value [String] The value to configure the radius-server key to +in the nodes running configuration. + +@option key\_format [Fixnum] The format of the key to be passed to the +nodes running configuration. Valid values are 0 (clear text) or 7 +(encrypted). The default value is 0 if format is not provided. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option default [Boolean] Configures the radius-server key using the +default keyword argument. + +@return [Boolean] Returns true if the commands complete successfully. +cmds = "radius-server key {key\_format} {value}" + +set\_global\_timeout configures the radius-server timeout value. If the +enable option is false, then radius-server timeout is configured using +the no keyword. If the default option is specified, radius-server +timeout is configured using the default keyword. If both options are +specified then the default keyword takes precedence. + +@since eos\_version 4.13.7M + +commands radius-server timeout no radius-server timeout default +radius-server timeout + +@option value [String, Fixnum] The value to set the global radius-server +timeout value to. This value should be in the range of 1 to 1000. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option default [Boolean] Configures the radius-server timeout value +using the default keyword. + +@return [Boolean] Returns true if the commands complete successfully. + +set\_global\_retransmit configures the global radius-server retransmit +value. If the enable option is false, then the radius-server retransmit +value is configured using the no keyword. If the default option is +specified, the radius-server retransmit value is configured using the +default keyword. If both options are specified then the default keyword +takes precedence. + +@since eos\_version 4.13.7M + +commands radius-server retransmit no radius-server retransmit default +radius-server retransmit + +@option value [String, Fixnum] The value to set the global radius-server +retransmit value to. This value should be in the range of 1 to 100 + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option default [Boolean] Configures the radius-server retransmit value +using the default keyword. + +@return [Boolean] Returns true if the commands complete successfully. + +update\_server configures a radius server resource on the target device. +This API method maps to the ``radius server host`` command, e.g. +``radius-server host 10.11.12.13 auth-port 1024 acct-port 2048 timeout 30 retransmit 5 key 7 011204070A5955``. + +@api public + +@param opts [Hash] The configuration options. + +@option opts key\_format [Integer] The key format value. + +@option opts hostname [String] The host value. + +@option opts vrf [String] The vrf value. + +@option opts auth\_port [String] The auth-port value. + +@option opts acct\_port [String] The acct-port value. + +@option opts timeout [String] The timeout value. + +@option opts retransmit [String] The retransmit value. + +@option opts key [String] The key value. + +@return [Boolean] Returns true if there are no errors. beware: order of +cli keyword options counts cmd = "radius-server host {opts[:hostname]}" +cmd << " vrf {opts[:vrf]}" if opts[:vrf] cmd << " auth-port +{opts[:auth\_port]}" if opts[:auth\_port] cmd << " acct-port +{opts[:acct\_port]}" if opts[:acct\_port] cmd << " timeout +{opts[:timeout]}" if opts[:timeout] cmd << " retransmit +{opts[:retransmit]}" if opts[:retransmit] cmd << " key {key\_format} +{opts[:key]}" if opts[:key] + +remove\_server removes the SNMP server identified by the hostname, +auth\_port, and acct\_port attributes. + +@api public + +@param opts [Hash] The configuration options. + +@option opts hostname [String] The host value. + +@option opts vrf [String] The vrf value. + +@option opts auth\_port [String] The auth-port value. + +@option opts acct\_port [String] The acct-port value. + +@return [Boolean] Returns true if there are no errors. cmd = "no +radius-server host {opts[:hostname]}" cmd << " vrf {opts[:vrf]}" if +opts[:vrf] cmd << " auth-port {opts[:auth\_port]}" if opts[:auth\_port] +cmd << " acct-port {opts[:acct\_port]}" if opts[:acct\_port] + +Copyright (c) 2014, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Routemaps class manages routemaps. A route map is a list of rules +that control the redistribution of IP routes into a protocol domain on +the basis of such criteria as route metrics, access control lists, next +hop addresses, and route tags. + +rubocop:disable Metrics/ClassLength + +get returns a hash of routemap configurations for the given name. + +@example { : { : { match: , set: , continue: , description: }, : { +match: , set: , continue: , description: } }, : { : { match: , set: , +continue: , description: }, : { match: , set: , continue: , description: +} } } + +@param name [String] The routemap name to return a resource for from the +nodes configuration. + +@return [nil, Hash] Returns the routemap resource as a +Hash. If the specified name is not found in the nodes current +configuration a nil object is returned. + +getall returns a collection of routemap resource hashes from the nodes +running configuration. The routemap resource collection hash is keyed by +the unique routemap name. + +@example { : { : { : { match: , set: , continue: , description: }, : { +match: , set: , continue: , description: } }, : { : { match: , set: , +continue: , description: }, : { match: , set: , continue: , description: +} } }, : { : { : { match: , set: , continue: , description: }, : { +match: , set: , continue: , description: } }, : { : { match: , set: , +continue: , description: }, : { match: , set: , continue: , description: +} } } } + +@return [nil, Hash] Returns a hash that represents the +entire routemap collection from the nodes running configuration. If +there are no routemap names configured, this method will return nil. + +parse entries is a private method to get the routemap rules. + +@api private + +@param name [String] The routemap name. + +@return [nil, Hash] Returns a hash that represents the +rules for routemaps from the nodes running configuration. If there are +no routemaps configured, this method will return nil. entries = +config.scan(/^route-map:raw-latex:`\s{name}`:raw-latex:`\s`.+$/) + +parse rule is a private method to parse a rule. + +@api private + +@param rules [Hash] Rules configuration options. + +@option rules match [Array] The match options. + +@option rules set [Array] The set options. + +@option rules continue [String] The continue value. + +@option rules description [String] The description value. + +@return [Hash] Returns a hash that represents the rules +for routemaps from the nodes running configuration. If there are no +routemaps configured, this method will return an empty hash. + +name\_commands is utilized to initially prepare the routemap. + +@param name [String] The routemap name. + +@param action [String] The action value. + +@param seqno [String] The seqno value. + +@param opts [Hash] The configuration options. + +@option opts default [Boolean] The default value. + +@option opts enable [Boolean] The enable value. + +@return [Array] Returns the prepared eos command. cmd = "default +route-map {name}" cmd = "no route-map {name}" cmd = "route-map {name}" +cmd << " {action}" cmd << " {seqno}" + +create will create a new routemap with the specified name. + +rubocop:disable Metrics/MethodLength + +commands route-map action seqno description match set continue + +@param name [String] The name of the routemap to create. + +@param action [String] Either permit or deny. + +@param seqno [Integer] The sequence number value. + +@param opts [hash] Optional keyword arguments. + +@option opts default [Boolean] Set routemap to default. + +@option opts description [String] A description for the routemap. + +@option opts match [Array] routemap match rule. + +@option opts set [String] Sets route attribute. + +@option opts continue [String] The routemap sequence number to continue +on. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the routemap to default. + +@return [Boolean] Returns true if the command completed successfully. +cmds << "description {opts[:description]}" cmds << "continue +{opts[:continue]}" cmds << "match {options}" cmds << "set {options}" + +remove\_match\_statemements removes all match rules for the specified +routemap + +@param name [String] The routemap name. + +@param action [String] The action value. + +@param seqno [String] The seqno value. + +@param cmds [Array] Array of eos commands. + +@return [Boolean] Returns true if the command completed successfully. +cmds << "no match {options}" + +remove\_set\_statemements removes all set rules for the specified +routemap + +@param name [String] The routemap name. + +@param action [String] The action value. + +@param seqno [String] The seqno value. + +@param cmds [Array] Array of eos commands. + +@return [Boolean] Returns true if the command completed successfully. +cmds << "no set {options}" + +delete will delete an existing routemap name from the nodes current +running configuration. If the delete method is called and the routemap +name does not exist, this method will succeed. + +commands no route-map + +@param name [String] The routemap name to delete from the node. + +@param action [String] Either permit or deny. + +@param seqno [Integer] The sequence number. + +@return [Boolean] Returns true if the command completed successfully. +configure(["no route-map {name} {action} {seqno}"]) + +This method will attempt to default the routemap from the nodes +operational config. Since routemaps do not exist by default, the default +action is essentially a negation and the result will be the removal of +the routemap clause. If the routemap does not exist then this method +will not perform any changes but still return True. + +commands no route-map + +@param name [String] The routemap name to set to default. + +@param action [String] Either permit or deny. + +@param seqno [Integer] The sequence number. + +@return [Boolean] Returns true if the command completed successfully. +configure(["default route-map {name} {action} {seqno}"]) + +set\_match\_statements will set the match values for a specified +routemap. If the specified routemap does not exist, it will be created. + +commands route-map action seqno match + +@param name [String] The name of the routemap to create. + +@param action [String] Either permit or deny. + +@param seqno [Integer] The sequence number. + +@param value [Array] The routemap match rules. + +@return [Boolean] Returns true if the command completed successfully. +cmds = ["route-map {name} {action} {seqno}"] cmds << "match {options}" + +set\_set\_statements will set the set values for a specified routemap. +If the specified routemap does not exist, it will be created. + +commands route-map action seqno set + +@param name [String] The name of the routemap to create. + +@param action [String] Either permit or deny. + +@param seqno [Integer] The sequence number. + +@param value [Array] The routemap set rules. + +@return [Boolean] Returns true if the command completed successfully. +cmds = ["route-map {name} {action} {seqno}"] cmds << "set {options}" + +set\_continue will set the continue value for a specified routemap. If +the specified routemap does not exist, it will be created. + +commands route-map action seqno continue + +@param name [String] The name of the routemap to create. + +@param action [String] Either permit or deny. + +@param seqno [Integer] The sequence number. + +@param value [Integer] The continue value. + +@return [Boolean] Returns true if the command completed successfully. +cmds = ["route-map {name} {action} {seqno}"] cmds << "continue {value}" + +set\_description will set the description for a specified routemap. If +the specified routemap does not exist, it will be created. + +commands route-map action seqno description + +@param name [String] The name of the routemap to create. + +@param action [String] Either permit or deny. + +@param seqno [Integer] The sequence number. + +@param value [String] The description value. + +@return [Boolean] Returns true if the command completed successfully. +cmds = ["route-map {name} {action} {seqno}"] cmds << "description +{value}" + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Snmp class provides a class implementation for working with the +nodes SNMP configuration entity. This class presents an abstraction of +the node's snmp configuration from the running config. + +@since eos\_version 4.13.7M + +get returns the snmp resource Hash that represents the nodes snmp +configuration abstraction from the running config. + +@example { location: , contact: , chassis\_id: , source\_interface: } + +@return [Hash] Returns the snmp resource as a Hash. + +parse\_location scans the running config from the node and parses the +snmp location value if it exists in the configuration. If the snmp +location is not configure, then the DEFAULT\_SNMP\_LOCATION string is +returned. The Hash returned by this method is merged into the snmp +resource Hash returned by the get method. + +@api private + +@return [Hash] Returns the resource Hash attribute. + +parse\_contact scans the running config form the node and parses the +snmp contact value if it exists in the configuration. If the snmp +contact is not configured, then the DEFAULT\_SNMP\_CONTACT value is +returned. The Hash returned by this method is merged into the snmp +resource Hash returned by the get method. + +@api private + +@return [Hash] Returns the resource Hash attribute. + +parse\_source\_interface scans the running config from the node and +parses the snmp source interface value if it exists in the +configuration. If the snmp source interface is not configured, then the +DEFAULT\_SNMP\_SOURCE\_INTERFACE value is returned. The Hash returned by +this method is intended to be merged into the snmmp resource Hash. + +@api private + +@return [Hash] Returns the resource Hash attribute. + +parse\_communities scans the running config from the node and parses all +of the configure snmp community strings. If there are no configured snmp +community strings, the community value is set to an empty array. The +returned hash is intended to be merged into the global snmp resource +hash. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_notifications scans the running configuration and parses all of +the snmp trap notifications configuration. It is expected the trap +configuration is in the running config. The returned hash is intended to +be merged into the resource hash. + +set\_notification configures the snmp trap notification for the +specified trap. The name option accepts the snmp trap name to configure +or the keyword all to globally enable or disable notifications. If the +optional state argument is not provided then the default state is +default. + +@since eos\_version 4.13.7M + +commands snmp-server enable traps no snmp-server enable traps default +snmp-server enable traps + +@param opts [Hash] The configuration parameters. + +@option opts name [String] The name of the trap to configure or the +keyword all. If this option is not specified, then the value of 'all' is +used as the default. + +@option opts state [String] The state to configure the trap +notification. Valid values include 'on', 'off' or 'default'. configure +"{state} snmp-server enable traps {name}" + +set\_location updates the snmp location value in the nodes running +configuration. If enable is false, then the snmp location value is +negated using the no keyword. If the default keyword is set to true, +then the snmp location value is defaulted using the default keyword. The +default parameter takes precedence over the enable keyword. + +@since eos\_version 4.13.7M + +commands snmp-server location no snmp-server location default +snmp-server location + +@param opts [Hash] The configuration parameters. + +@option opts value [string] The snmp location value to configure. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the snmp location value using +the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_contact updates the snmp contact value in the nodes running +configuration. If enable is false in the opts Hash then the snmp contact +value is negated using the no keyword. If the default keyword is set to +true, then the snmp contact value is defaulted using the default +keyword. The default parameter takes precedence over the enable keyword. + +@since eos\_version 4.13.7M + +commands snmp-server contact no snmp-server contact default snmp-server +contact + +@param opts [Hash] The configuration parameters. + +@option opts value [string] The snmp contact value to configure. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the snmp contact value using +the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_chassis\_id updates the snmp chassis id value in the nodes running +configuration. If enable is false in the opts Hash then the snmp chassis +id value is negated using the no keyword. If the default keyword is set +to true, then the snmp chassis id value is defaulted using the default +keyword. The default keyword takes precedence over the enable keyword. + +@since eos\_version 4.13.7M + +commands snmp-server chassis-id no snmp-server chassis-id default +snmp-server chassis-id + +@param opts [Hash] The configuration parameters + +@option opts value [string] The snmp chassis id value to configure + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the snmp chassis id value +using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_source\_interface updates the snmp source interface value in the +nodes running configuration. If enable is false in the opts Hash then +the snmp source interface is negated using the no keyword. If the +default keyword is set to true, then the snmp source interface value is +defaulted using the default keyword. The default keyword takes +precedence over the enable keyword. + +@since eos\_version 4.13.7M + +commands snmp-server source-interface no snmp-server source-interface +default snmp-server source-interface + +@param opts [Hash] The configuration parameters. + +@option opts value [string] The snmp source interface value to +configure. This method will not ensure the interface is present in the +configuration. @option opts enable [Boolean] If false then the command +is negated. Default is true. @option opts default [Boolean] Configures +the snmp source interface value using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +add\_community adds a new snmp community to the nodes running +configuration. This function is a convenience function that passes the +message to set\_community\_access. + +@see set\_community\_access + +@param name [String] The name of the snmp community to add to the nodes +running configuration. + +@param access [String] Specifies the access level to assign to the new +snmp community. Valid values are 'rw' or 'ro'. + +@return [Boolean] Returns true if the command completed successfully. + +remove\_community removes the specified community from the nodes running +configuration. If the specified name is not configured, this method will +still return successfully. + +@since eos\_version 4.13.7M + +commands no snmp-server community + +@param name [String] The name of the snmp community to add to the nodes +running configuration. + +@return [Boolean] Returns true if the command completed successfully. +configure "no snmp-server community {name}" + +set\_community\_acl configures the acl to apply to the specified +community name. When enable is true, it will remove the the named +community and then add the new acl entry. + +@since eos\_version 4.13.7M + +commands no snmp-server [ro\|rw] snmp-server [ro\|rw] + +@param name [String] The name of the snmp community to add to the nodes +running configuration. + +@param opts [Hash] The configuration parameters. + +@option opts value [String] The name of the acl to apply to the snmp +community in the nodes config. If nil, then the community name allows +access to all objects. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the snmp community name using +the default keyword. Default takes precedence over enable. + +@return [Boolean] Returns true if the command completed successfully. +Default is same as negate for this command cmds = ["no snmp-server +community {name}"] cmds << "snmp-server community {name} {access} +{value}" if enable + +set\_community\_access configures snmp-server community with designated +name and access values. + +@param name [String] The snmp-server community name value. + +@param access [String] The snmp-server community access value. + +@return [Boolean] Returns true if the command completed successfully. +configure "snmp-server community {name} {access}" + +Copyright (c) 2014, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Staticroutes class provides a configuration instance for working +with static routes in EOS. + +Returns the static routes configured on the node. + +@example { [ { destination: , nexthop: next\_hop>, +distance: , tag: , name: }, ... ] } + +@return [Array] The method will return all of the configured +static routes on the node as a Ruby array object containing a list of +hashes with each hash describing a route. If there are no static routes +configured, this method will return an empty array. +([^\\s]+):raw-latex:`\s `capture destination ([^\\s$]+) +capture next hop IP or egress interface `:raw-latex:`\s`\|$ <\d+>`__ +capture metric (distance) +[:raw-latex:`\s`\|$]{1}(?:tag:raw-latex:`\s`(:raw-latex:`\d`+))? catpure +route tag [:raw-latex:`\s`\|$]{1}(?:name:raw-latex:`\s`(.+))? capture +route name + +Creates a static route in EOS. May add or overwrite an existing route. + +commands ip route [router\_ip] [distance] [tag ][name ] + +@param destination [String] The destination and prefix matching the +route(s). Ex '192.168.0.2/24'. + +@param nexthop [String] The nexthop for this entry, which may an IP +address or interface name. + +@param opts [Hash] Additional options for the route entry. + +@option opts router\_ip [String] If nexthop is an egress interface, +router\_ip specifies the router to which traffic will be forwarded. + +@option opts distance [String] The administrative distance (metric). + +@option opts tag [String] The route tag. + +@option opts name [String] A route name. + +@return [Boolean] Returns True on success, otherwise False. cmd = "ip +route {destination} {nexthop}" cmd << " {opts[:router\_ip]}" if +opts[:router\_ip] cmd << " {opts[:distance]}" if opts[:distance] cmd << +" tag {opts[:tag]}" if opts[:tag] cmd << " name {opts[:name]}" if +opts[:name] + +Removes a given route from EOS. May remove multiple routes if nexthop is +not specified. + +commands no ip route [nexthop] + +@param destination [String] The destination and prefix matching the +route(s). Ex '192.168.0.2/24'. + +@param nexthop [String] The nexthop for this entry, which may an IP +address or interface name. + +@return [Boolean] Returns True on success, otherwise False. cmd = "no ip +route {destination}" cmd << " {nexthop}" if nexthop + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Stp class provides a base class instance for working with the EOS +spanning-tree configuration. + +get returns the current stp configuration parsed from the nodes current +running configuration. + +@example { mode: instances: { : { priority: } } interfaces: { : { +portfast: , portfast\_type: , bpduguard: } } } + +@return [Hash] returns a Hash of attributes derived from eAPI. + +parse\_mode scans the nodes running configuration and extracts the value +of the spanning-tree mode. The spanning tree mode is expected to be +always be available in the running config. The return value is intended +to be merged into the stp resource hash. + +@api private + +@return [Hash] Resource hash attribute. + +instances returns a memoized instance of StpInstances for configuring +individual stp instances. + +@return [StpInstances] an instance of StpInstances class. + +interfaces returns a memoized instance of StpInterfaces for configuring +individual stp interfaces. + +@return [StpInterfaces] an instance of StpInterfaces class. + +set\_mode configures the stp mode in the global nodes running +configuration. If the enable option is false, then the stp mode is +configured with the no keyword argument. If the default option is +specified then the mode is configured with the default keyword argument. +The default keyword argument takes precedence over the enable option if +both are provided. + +@since eos\_version 4.13.7M + +commands spanning-tree mode no spanning-tree mode default spanning-tree +mode + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the stp mode to in +the nodes current running configuration. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the stp mode value using the +default keyword. + +@return [Boolean] returns true if the command completed successfully. + +The StpInstances class provides a class instance for working with +spanning-tree instances in EOS + +get returns the specified stp instance config parsed from the nodes +current running configuration. + +@example { priority: } + +@param inst [String] The named stp instance to return. + +@return [nil, Hash] Returns all configured stp instances +found in the nodes running configuration. + +parse\_instances will scan the nodes current configuration and extract +the list of configured mst instances. If no instances are configured +then this method will return an empty array. + +@api private + +@return [Array] Returns an Array of configured stp instances. + +parse\_priority will scan the nodes current configuration and extract +the stp priority value for the given stp instance. If the stp instance +priority is not configured, the priority value will be set using +DEFAULT\_STP\_PRIORITY. The returned hash is intended to be merged into +the resource hash. + +@api private + +@return [Hash] Resource hash attribute. priority\_re = +/(?<=^spanning-tree:raw-latex:`\smst`:raw-latex:`\s{inst}`:raw-latex:`\spriority`:raw-latex:`\s`)(.+$)/x + +Deletes a configured MST instance. + +@param inst [String] The MST instance to delete. + +@return [Boolean] True if the commands succeed otherwise False. +configure ['spanning-tree mst configuration', "no instance {inst}", + +Configures the spanning-tree MST priority. + +@param inst [String] The MST instance to configure. + +@param opts [Hash] The configuration parameters for the priority. + +@option opts value [string] The value to set the priority to. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. + +@return [Boolean] True if the commands succeed otherwise False. cmd = +"default spanning-tree mst {inst} priority" cmd = "spanning-tree mst +{inst} priority {value}" cmd = "no spanning-tree mst {inst} priority" + +The StpInterfaces class provides a class instance for working with +spanning-tree interfaces in EOS. + +get returns the configured stp interfaces from the nodes running +configuration as a resource hash. If the specified interface is not +configured as a switchport then this method will return nil. + +@example { portfast: , portfast\_type: , bpduguard: } + +@param name [String] The interface name to return a resource for from +the nodes configuration. + +@return [nil, Hash] Returns the stp interface as a +resource hash. config = get\_block("interface {name}") + +getall returns all of the configured stp interfaces parsed from the +nodes current running configuration. The returned hash is keyed by the +interface name. + +@example { : { portfast: , portfast\_type: , bpduguard: }, : { portfast: +, portfast\_type: , bpduguard: }, ... } + +@return [Hash] Returns the stp interfaces config as a +resource hash from the nodes running configuration. + +parse\_portfast scans the supplied interface configuration block and +parses the value stp portfast. The value of portfast is either enabled +(true) or disabled (false). + +@api private + +@return [Hash] Resource hash attribute. + +parse\_portfast\_type scans the supplied interface configuration block +and parses the value stp portfast type. The value of portfast type is +either not set which implies normal (default), edge, or network. + +@api private + +@return [Hash] Resource hash attribute. + +parse\_bpduguard scans the supplied interface configuration block and +parses the value of stp bpduguard. The value of bpduguard is either +disabled (false) or enabled (true). + +@api private + +@return [Hash] Resource hash attribute. + +Configures the interface portfast value. + +@param name [String] The name of the interface to configure. + +@param opts [Hash] The configuration parameters for portfast. + +@option opts value [Boolean] The value to set portfast. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. + +@return [Boolean] True if the commands succeed otherwise False. + +Configures the interface portfast type value + +@param name [String] The name of the interface to configure. + +@param opts [Hash] The configuration parameters for portfast type. + +@option opts value [String] The value to set portfast type to. The value +must be set for calls to this method. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. + +@return [Boolean] True if the commands succeed otherwise False. cmds = +"default spanning-tree portfast {value}" cmds = "spanning-tree portfast +{value}" cmds = "no spanning-tree portfast {value}" + +Configures the interface bpdu guard value + +@param name [String] The name of the interface to configure. + +@param opts [Hash] The configuration parameters for bpduguard. + +@option opts value [Boolean] The value to set bpduguard. + +@option opts enable [Boolean] If false then the bpduguard is disabled. +If true then the bpduguard is enabled. Default is true. + +@option opts default [Boolean] The value should be set to default. + +@return [Boolean] True if the commands succeed otherwise False. + +Copyright (c) 2014,2015 Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Switchport class provides a base class instance for working with +logical layer-2 interfaces. + +Retrieves the properties for a logical switchport from the +running-config using eAPI. + +Example { "name": , "mode": [access, trunk], "trunk\_allowed\_vlans": +array "trunk\_native\_vlan": , "access\_vlan": , "trunk\_groups": array +} + +@param name [String] The full name of the interface to get. The +interface name must be the full interface (ie Ethernet, not Et). + +@return [Hash] Returns a hash that includes the switchport properties. +config = get\_block("interface {name}") + +parse\_mode parses switchport mode from the provided config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_access\_vlan parses access vlan from the provided config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_trunk\_native\_vlan parses trunk native vlan from the provided +config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_trunk\_allowed\_vlans parses trunk allowed vlan from the provided +config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_trunk\_groups parses trunk group values from the provided config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] Returns the resource hash attribute. + +Retrieves all switchport interfaces from the running-config. + +@example { : { mode: , access\_vlan: , trunk\_native\_vlan: , +trunk\_allowed\_vlans: , trunk\_groups: }, : { mode: , access\_vlan: , +trunk\_native\_vlan: , trunk\_allowed\_vlans: , trunk\_groups: }, ... } + +@return [Array] Returns an array of switchport hashes. + +Creates a new logical switchport interface in EOS. + +@param name [String] The name of the logical interface. + +@return [Boolean] Returns True if it succeeds otherwise False. configure +["interface {name}", 'no ip address', 'switchport'] + +Deletes a logical switchport interface from the running-config. + +@param name [String] The name of the logical interface. + +@return [Boolean] Returns True if it succeeds otherwise False. configure +["interface {name}", 'no switchport'] + +Defaults a logical switchport interface in the running-config. + +@param name [String] The name of the logical interface. + +@return [Boolean] Returns True if it succeeds otherwise False. configure +["interface {name}", 'default switchport'] + +Configures the switchport mode for the specified interface. + +@param name [String] The name of the interface to configure. + +@param opts [Hash] The configuration parameters for the interface. + +@option opts value [string] The value to set the mode to. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. + +@return [Boolean] Returns True if the commands succeed otherwise False. + +set\_trunk\_allowed\_vlans configures the list of vlan ids that are +allowed on the specified trunk port. If the enable option is set to +false, then the allowed trunks is configured using the no keyword. If +the default keyword is provided then the allowed trunks is configured +using the default keyword. The default option takes precedence over the +enable option if both are specified. + +@since eos\_version 4.13.7M + +commands switchport trunk allowed vlan add no switchport trunk allowed +vlan default switchport trunk allowed vlan + +@param name [String] The name of the interface to configure. + +@param opts [Hash] The configuration parameters for the interface. + +@option ots value [Array] The list of vlan ids to configure on the +switchport to be allowed. This value must be an array of valid vlan ids. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option default [Boolean] Configures the switchport trunk allowed vlans +command using the default keyword. Default takes precedence over enable. + +@return [Boolean] Returns true if the commands complete successfully. +"switchport trunk allowed vlan {value}"] + +Configures the trunk port native vlan for the specified interface. This +value is only valid if the switchport mode is configure as trunk. + +@param name [String] The name of the interface to configure. + +@param opts [Hash] The configuration parameters for the interface. + +@option opts value [string] The value of the trunk native vlan. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. +Default takes precedence over enable. + +@return [Boolean] Returns True if the commands succeed otherwise False. + +Configures the access port vlan for the specified interface. This value +is only valid if the switchport mode is configure in access mode. + +@param name [String] The name of the interface to configure. + +@param opts [Hash] The configuration parameters for the interface. + +@option opts value [string] The value of the access vlan. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default +Default takes precedence over enable. + +@return [Boolean] Returns True if the commands succeed otherwise False. + +Configures the trunk group vlans for the specified interface. Trunk +groups not currently set are added and trunk groups currently configured +but not in the passed in value array are removed. + +@param name [String] The name of the interface to configure. + +@param opts [Hash] The configuration parameters for the interface. + +@option opts value [string] Set of values to configure the trunk group. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default +Default takes precedence over enable. + +@return [Boolean] Returns True if the commands succeed otherwise False. +Add trunk groups that are not currently in the list. cmds << "switchport +trunk group {group}" Remove trunk groups that are not in the new list. +cmds << "no switchport trunk group {group}" + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace + +Api is module namespace for working with the EOS command API. + +The System class configures the node system services such as hostname +and domain name. + +Returns the system settings for hostname, iprouting, and banners. + +@example { hostname: , iprouting: , banner\_motd: , banner\_login: } + +@return [Hash] A Ruby hash object that provides the system settings as +key/value pairs. + +parse\_hostname parses hostname values from the provided config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] The resource hash attribute. + +parse\_iprouting parses ip routing from the provided config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] The resource hash attribute. + +Parses the global config and returns the value for both motd and login +banners. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] The resource hash attribute. If the +banner is not set it will return a value of None for that key. + +Configures the system hostname value in the running-config. + +@param opts [Hash] The configuration parameters. + +@option opts value [string] The value to set the hostname to. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] If true configure the command using the +default keyword. Default is false. + +@return [Boolean] Returns true if the command completed successfully. + +Configures the state of global ip routing. + +@param opts [Hash] The configuration parameters. + +@option opts enable [Boolean] True if ip routing should be enabled or +False if ip routing should be disabled. Default is true. + +@option opts default [Boolean] If true configure the command using the +default keyword. Default is false. + +@return [Boolean] Returns true if the command completed successfully. + +Configures system banners. + +@param banner\_type [String] Banner to be changed (likely either login +or motd). + +@param opts [Hash] The configuration parameters. + +@option opts value [string] The value to set for the banner. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] If true configure the command using the +default keyword. Default is false. + +@return [Boolean] Returns true if the command completed successfully. +cmd\_string = "banner {banner\_type}" + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +Tacacs provides instance methods to retrieve and set tacacs +configuration values. Regular expression to extract a tacacs server's +attributes from the running-configuration text. The explicit [ ] spaces +enable line wrapping and indentation with the /x flag. Default Tacacs +TCP port + +getall Returns an Array with a single resource Hash describing the +current state of the global tacacs configuration on the target device. +This method is intended to be used by a provider's instances class +method. + +@example { name: , enable: , key: , key\_format: , timeout: } + +@return [Array] Single element Array of resource hashes. + +parse\_global\_key takes a running configuration as a string and parses +out the radius global key and global key format if it exists in the +configuration. An empty Hash is returned if there is no global key +configured. The intent of the Hash is to be merged into a property hash. + +@api private + +@return [Hash] Returns the resource hash attributes. + +parse\_global\_timeout takes a running configuration as a string and +parses out the tacacs global timeout if it exists in the configuration. +An empty Hash is returned if there is no global timeout value +configured. The intent of the Hash is to be merged into a property hash. + +@api private + +@return [Hash] Returns the resource hash attributes. + +servers returns an Array of tacacs server resource hashes. Each hash +describes the current state of the tacacs server and is suitable for use +in initializing a tacacs\_server provider. + +The resource hash returned contains the following information: + +- hostname: hostname or ip address, part of the identifier. +- port: (Fixnum) TCP port of the server, part of the identifier. +- key: (String) the key either in plain text or hashed format. +- key\_format: (Fixnum) e.g. 0 or 7. +- timeout: (Fixnum) seconds before the timeout period ends. +- multiplex: (Boolean) true when configured to make requests through a + single connection. + +@api public + +@return [Array>] Array of resource hashes. + +set\_global\_key configures the tacacs default key. This method maps to +the ``tacacs-server key`` EOS configuration command, e.g. +``tacacs-server key 7 070E234F1F5B4A``. + +@option opts key [String] ('070E234F1F5B4A') The key value. + +@option opts key\_format [Fixnum] (7) The key format, 0 for plain text +and 7 for a hashed value. 7 will be assumed if this option is not +provided. + +@api public + +@return [Boolean] Returns true if no errors. result = +api.config("tacacs-server key {format} {key}") + +set\_timeout configures the tacacs default timeout. This method maps to +the ``tacacs-server timeout`` setting. + +@param opts [Hash] The configuration parameters. + +@option opts value [string] The value to set the timeout to. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. + +@api public + +@return [Boolean] Returns true if no errors. + +update\_server configures a tacacs server resource on the target device. +This API method maps to the ``tacacs server host`` command, e.g. +``tacacs-server host 1.2.3.4 single-connection port 4949 timeout 6 key 7 06070D221D1C5A``. + +@api public + +@param opts [Hash] The configuration parameters. + +@option opts key\_format [Integer] The format for the key. + +@option opts hostname [String] The host value. + +@option opts multiplex [String] Defines single-connection. + +@option opts port [String] The port value. + +@option opts timeout [String] The timeout value. + +@option opts key [String] The key value. + +@return [Boolean] Returns true if there are no errors. cmd = +"tacacs-server host {opts[:hostname]}" cmd << " port {opts[:port]}" if +opts[:port] cmd << " timeout {opts[:timeout]}" if opts[:timeout] cmd << +" key {key\_format} {opts[:key]}" if opts[:key] + +remove\_server removes the tacacs server identified by the hostname, and +port attributes. + +@api public + +@param opts [Hash] The configuration parameters. + +@option hostname [String] The host value. + +@option port [String] The port value. + +@return [Boolean] Returns true if there are no errors. cmd = "no +tacacs-server host {opts[:hostname]}" cmd << " port {opts[:port]}" if +opts[:port] + +Copyright (c) 2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Users class provides configuration of local user resources for an +EOS node. The regex used here parses the running configuration to find +all username entries. There is extra logic in the regular expression to +store the username as 'user' and then creates a back reference to find a +following configuration line that might contain the users sshkey. + +get returns the local user configuration. + +@example { name: , privilege: , role: , nopassword: , encryption: +<'cleartext', 'md5', 'sha512'> secret: , sshkey: } + +@param name [String] The user name to return a resource for from the +nodes configuration + +@return [nil, Hash] Returns the user resource as a Hash. +If the specified user name is not found in the nodes current +configuration a nil object is returned. The regex used here parses the +running configuration to find one username entry. user\_re = +Regexp.new(/^username:raw-latex:`\s`+(?{name}):raw-latex:`\s`+ +(username:raw-latex:`\s`+{name}:raw-latex:`\s`+ + +getall returns a collection of user resource hashes from the nodes +running configuration. The user resource collection hash is keyed by the +unique user name. + +@example [ : { name: , privilege: , role: +, nopassword: , encryption: <'cleartext', 'md5', +'sha512'> secret: , sshkey: }, : { name: +, privilege: , role: , nopassword: , +encryption: <'cleartext', 'md5', 'sha512'> secret: , sshkey: + }, ... ] + +@return [Hash] Returns a hash that represents the entire +user collection from the nodes running configuration. If there are no +user names configured, this method will return an empty hash. + +parse\_user\_entry maps the tokens find to the hash entries. + +@api private + +@param user [Array] An array of values returned from the regular +expression scan of the nodes configuration. + +@return [Hash] Returns the resource hash attribute. Map +the encryption value if set, if there is no mapping then just return the +value. + +create will create a new user name resource in the nodes current +configuration with the specified user name. Creating users require +either a secret (password) or the nopassword keyword to be specified. +Optional parameters can be passed in to initialize user name specific +settings. + +@since eos\_version 4.13.7M + +commands username nopassword privilege role username secret [0,5,sha512] +... + +@param name [String] The name of the user to create. + +@param opts [hash] Optional keyword arguments. + +@option opts nopassword [Boolean] Configures the user to be able to +authenticate without a password challenge. + +@option opts secret [String] The secret (password) to assign to this +user. + +@option opts encryption [String] Specifies how the secret is encoded. +Valid values are "cleartext", "md5", "sha512". The default is +"cleartext". + +@option opts privilege [String] The privilege value to assign to the +user. + +@option opts role [String] The role value to assign to the user. + +@option opts sshkey [String] The sshkey value to assign to the user. + +@return [Boolean] Returns true if the command completed successfully. +cmd = "username {name}" cmd << " privilege {opts[:privilege]}" if +opts[:privilege] cmd << " role {opts[:role]}" if opts[:role] Map the +encryption value if set, if there is no mapping then just return the +value. fail ArgumentError, "invalid encryption value: {enc}" cmd << " +secret {enc} {opts[:secret]}" cmds << "username {name} sshkey +{opts[:sshkey]}" if opts[:sshkey] + +delete will delete an existing user name from the nodes current running +configuration. If the delete method is called and the user name does not +exist, this method will succeed. + +@since eos\_version 4.13.7M + +commands no username + +@param name [String] The user name to delete from the node. + +@return [Boolean] Returns true if the command completed successfully. +configure("no username {name}") + +default will configure the user name using the default keyword. This +command has the same effect as deleting the user name from the nodes +running configuration. + +@since eos\_version 4.13.7M + +commands default username + +@param name [String] The user name to default in the nodes +configuration. + +@return [Boolean] Returns true if the command complete successfully. +configure("default username {name}") + +set\_privilege configures the user privilege value for the specified +user name in the nodes running configuration. If enable is false in the +opts keyword Hash then the name value is negated using the no keyword. +If the default keyword is set to true, then the privilege value is +defaulted using the default keyword. The default keyword takes +precedence over the enable keyword + +@since eos\_version 4.13.7M + +commands username privilege no username privilege default username +privilege + +@param name [String] The user name to default in the nodes +configuration. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The privilege value to assign to the user. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the user privilege value using +the default keyword. + +@return [Boolean] Returns true if the command completed successfully. +configure(command\_builder("username {name} privilege", opts)) + +set\_role configures the user role value for the specified user name in +the nodes running configuration. If enable is false in the opts keyword +Hash then the name value is negated using the no keyword. If the default +keyword is set to true, then the role value is defaulted using the +default keyword. The default keyword takes precedence over the enable +keyword + +@since eos\_version 4.13.7M + +commands username role no username role default username role + +@param name [String] The user name to default in the nodes +configuration. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The role value to assign to the user. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the user role value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. +configure(command\_builder("username {name} role", opts)) + +set\_sshkey configures the user sshkey value for the specified user name +in the nodes running configuration. If enable is false in the opts +keyword Hash then the name value is negated using the no keyword. If the +default keyword is set to true, then the sshkey value is defaulted using +the default keyword. The default keyword takes precedence over the +enable keyword. + +@since eos\_version 4.13.7M + +commands username sshkey no username sshkey default username sshkey + +@param name [String] The user name to default in the nodes +configuration. + +@param opts [Hash] Optional keyword arguments + +@option opts value [String] The sshkey value to assign to the user + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the user sshkey value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. +configure(command\_builder("username {name} sshkey", opts)) + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Varp class provides an instance for working with the global VARP +configuration of the node. + +Returns the global VARP configuration from the node. + +@example { mac\_address: , interfaces: { : { addresses: }, : { +addresses: }, ... } } + +@return [Hash] A Ruby hash object that provides the Varp settings as key +/ value pairs. + +parse\_mac\_address parses mac-address values from the provided config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] Returns the resource hash attribute. ip +virtual-router mac-address value will always be stored in +aa:bb:cc:dd:ee:ff format. + +Configure the VARP virtual-router mac-address value. + +@param opts [Hash] The configuration parameters. + +@option opts value [string] The value to set the mac-address to. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. + +@return [Boolean] Returns true if the command completed successfully. + +The VarpInterfaces class provides an instance for working with the +global VARP interface configuration of the node. + +Returns a single VARP interface configuration. + +@example { "addresses": array } + +@param name [String] The interface name to return the configuration +values for. This must be the full interface identifier. + +@return [nil, Hash] A Ruby hash that represents the VARP +interface configuration. A nil object is returned if the specified +interface is not configured config = get\_block("^interface {name}") + +Returns the collection of MLAG interfaces as a hash index by the +interface name. + +@example { : { addresses: }, : { addresses: }, ... } + +@return [nil, Hash] A Ruby hash that represents the MLAG +interface configuration. A nil object is returned if no interfaces are +configured. + +parse\_addresses parses ip virtual-router address from the provided +config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] Returns the resource hash attribute. + +The set\_addresses method assigns one or more virtual IPv4 address to +the specified VLAN interface. All existing addresses are removed before +the ones in value are added. + +@param name [String] The name of the interface. The name argument must +be the full interface name. Valid interfaces are restricted to VLAN +interfaces. + +@param opts [Hash] The configuration parameters. + +@option opts value [Array] Array of IPv4 addresses to add to the virtual +router. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. + +@return [Boolean] True if the commands succeeds otherwise False. cmds = +["interface {name}"] cmds << "ip virtual-router address {addr}" + +The add\_address method assigns one virtual IPv4 address. + +@param name [String] The name of the interface. The name argument must +be the full interface name. Valid interfaces are restricted to VLAN +interfaces. + +@param value [string] The virtual router address to add. + +@return [Boolean] True if the commands succeeds otherwise False. +configure(["interface {name}", "ip virtual-router address {value}"]) + +The remove\_address method removes one virtual IPv4 address. + +@param name [String] The name of the interface. The name argument must +be the full interface name. Valid interfaces are restricted to VLAN +interfaces. + +@param value [string] The virtual router address to remove. + +@return [Boolean] True if the commands succeeds otherwise False. +configure(["interface {name}", "no ip virtual-router address {value}"]) + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Vlan class provides a class implementation for working with the +collection of Vlans on the node. This class presents an abstraction of +the nodes configured vlan id's from the running configuration. + +@since eos\_version 4.13.7M + +get returns the specified vlan resource Hash that represents the nodes +current vlan configuration. + +@example { name: , state: , trunk\_groups: array[] Returns the vlan resource as a Hash. +If the specified vlan id is not found in the nodes current configuration +a nil object is returned. config = get\_block("vlan {id}") + +getall returns the collection of vlan resources from the nodes running +configuration as a hash. The vlan resource collection hash is keyed by +the unique vlan id. + +@example { : { name: , state: , trunk\_groups: array[] Returns a hash that represents the entire +vlan collection from the nodes running configuration. If there are no +vlans configured, this method will return an empty hash. + +parse\_name scans the provided configuration block and parses the vlan +name value. The vlan name should always return a value from the running +configuration. The return value is intended to be merged into the +resource hash. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_state scans the provided configuration block and parses the vlan +state value. The vlan state should always return a value from the nodes +running configuration. The return hash is intended to be merged into the +resource hash. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_trunk\_groups scans the provided configuration block and parses +the trunk groups. If no trunk groups are found in the nodes running +configuration then an empty array is returned as the value. The return +hash is intended to be merged into the resource hash. + +@api private + +@return [Hash] Returns the resource hash attribute. + +create will create a new vlan resource in the nodes current +configuration with the specified vlan id. If the create method is called +and the vlan id already exists, this method will still return true. + +@since eos\_version 4.13.7M + +commands vlan + +@param id [String, Integer] The vlan id to create on the node. The vlan +id must be in the valid range of 1 to 4094. + +@return [Boolean] Returns true if the command completed successfully. +configure("vlan {id}") + +delete will delete an existing vlan resource from the nodes current +running configuration. If the delete method is called and the vlan id +does not exist, this method will succeed. + +@since eos\_version 4.13.7M + +commands no vlan + +@param id [String, Integer] The vlan id to delete from the node. The id +value should be in the valid range of 1 to 4094. + +@return [Boolean] Returns true if the command completed successfully. +configure("no vlan {id}") + +default will configure the vlan using the default keyword. This command +has the same effect as deleting the vlan from the nodes running +configuration. + +@since eos\_version 4.13.7M + +commands default vlan + +@param id [String, Integer] The vlan id to default in the nodes +configuration. Ths vid value should be in the valid range of 1 to 4094. + +@return [Boolean] Returns true if the command complete successfully. +configure("default vlan {id}") + +set\_name configures the name value for the specified vlan id in the +nodes running configuration. If enable is false in the opts keyword Hash +then the name value is negated using the no keyword. If the default +keyword is set to true, then the name value is defaulted using the +default keyword. The default keyword takes precedence over the enable +keyword. + +@since eos\_version 4.13.7M + +commands vlan name no name default name + +@param id [String, Integer] The vlan id to apply the configuration to. +The id value should be in the valid range of 1 to 4094. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the vlan name to in +the node configuration. The name parameter accepts a-z, 0-9 and \_. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the vlan name value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. +cmds = ["vlan {id}", cmd] + +set\_state configures the state value for the specified vlan id in the +nodes running configuration. If enable is set to false in the opts +keyword Hash then the state value is negated using the no keyword. If +the default keyword is set to true, then the state value is defaulted +using the default keyword. The default keyword takes precedence over the +enable keyword + +@since eos\_version 4.13.7M + +commands vlan state [active, suspend] no state default state + +@param id [String, Integer] The vlan id to apply the configuration to. +The id value should be in the valid range of 1 to 4094. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the vlan state to in +the node's configuration. Accepted values are 'active' or 'suspend'. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the vlan state value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +@raise [ArgumentError] if the value is not in the accept list of values. +cmds = ["vlan {id}", cmd] + +add\_trunk\_group adds a new trunk group value to the specified vlan id +in the nodes running configuration. The trunk group name value accepts +a-z 0-9 and \_. + +@since version 4.13.7M + +commands vlan trunk group + +@param id [String, Integer] The vlan id to apply the configuration to. +the id value should be in the range of 1 to 4094 + +@param value [String] The value to add to the vlan id configuration on +the node. + +@return [Boolean] Returns true if the command completed successfully. +configure(["vlan {id}", "trunk group {value}"]) + +remove\_trunk\_group removes the specified trunk group value from the +specified vlan id in the node's configuration. If the trunk group name +does not exist, this method will return success + +@since eos\_version 4.13.7M + +commands vlan no trunk group + +@param id [String, Integer] The vlan id to apply the configuration to. +the id value should be in the range of 1 to 4094. + +@param value [String] The value to remove from the list of trunk group +names configured for the specified vlan. + +configure(["vlan {id}", "no trunk group {value}"]) + +Copyright (c) 2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Eos is the toplevel namespace for working with Arista EOS nodes. + +Api is module namespace for working with the EOS command API. + +The Vrrp class manages the set of virtual routers. rubocop:disable +Metrics/ClassLength + +get returns the all the virtual router IPs for the given layer 3 +interface name from the nodes current configuration. + +rubocop:disable Metrics/MethodLength + +@example { 1: { enable: primary\_ip: priority: description: +secondary\_ip: [ , ] ip\_version: timers\_advertise: +mac\_addr\_adv\_interval: preempt: preempt\_delay\_min: +preempt\_delay\_reload: delay\_reload: track: [ { name: 'Ethernet3', +action: 'decrement', amount: 33 }, { name: 'Ethernet2', action: +'decrement', amount: 22 }, { name: 'Ethernet2', action: 'shutdown' } ] } +} + +@param name [String] The layer 3 interface name. + +@return [nil, Hash] Returns the VRRP resource as a Hash +with the virtual router ID as the key. If the interface name does not +exist then a nil object is returned. config = get\_block("^interface +{name}") Parse the vrrp configuration for the vrid(s) in the list + +getall returns the collection of virtual router IPs for all the layer 3 +interfaces from the nodes running configuration as a hash. The resource +collection hash is keyed by the ACL name. + +@example { 'Vlan100': { 1: { data }, 250: { data }, }, 'Vlan200': { 2: { +data }, 250: { data }, } } + +@return [nil, Hash] Returns a hash that represents the +entire virtual router IPs collection for all the layer 3 interfaces from +the nodes running configuration. If there are no virtual routers +configured, this method will return an empty hash. + +parse\_primary\_ip scans the nodes configurations for the given virtual +router id and extracts the primary IP. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'primary\_ip', String>] Where string is the IPv4 address +or nil if the value is not set. match = +config.scan(/^:raw-latex:`\s`+vrrp {vrid} ip +(:raw-latex:`\d`+.:raw-latex:`\d`+.:raw-latex:`\d`+.:raw-latex:`\d`+)$/) + +parse\_priority scans the nodes configurations for the given virtual +router id and extracts the priority value. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'priority', Integer>] The priority is between <1-255> or +nil if the value is not set. match = config.scan(/^:raw-latex:`\s`+vrrp +{vrid} priority (:raw-latex:`\d`+)$/) + +parse\_timers\_advertise scans the nodes configurations for the given +virtual router id and extracts the timers advertise value. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [nil, Hash<'timers\_advertise', Integer>] The timers\_advertise +is between <1-255> or nil if the value is not set. match = +config.scan(/^:raw-latex:`\s`+vrrp {vrid} timers advertise +(:raw-latex:`\d`+)$/) + +parse\_preempt scans the nodes configurations for the given virtual +router id and extracts the preempt value. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [nil, Hash<'preempt', Integer>] The preempt is between <1-255> +or nil if the value is not set. match = +config.scan(/^:raw-latex:`\s`+vrrp {vrid} preempt$/) + +parse\_enable scans the nodes configurations for the given virtual +router id and extracts the enable value. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'enable', Boolean>] match = +config.scan(/^:raw-latex:`\s`+vrrp {vrid} shutdown$/) + +parse\_secondary\_ip scans the nodes configurations for the given +virtual router id and extracts the secondary\_ip value. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [nil, Hash<'secondary\_ip', Array>] Returns an empty +array if the value is not set. regex = "vrrp {vrid} ip" matches = +config.scan(/^:raw-latex:`\s`+{regex} +(:raw-latex:`\d`+.:raw-latex:`\d`+.:raw-latex:`\d`+.:raw-latex:`\d`+) +secondary$/) + +parse\_description scans the nodes configurations for the given virtual +router id and extracts the description. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [nil, Hash<'secondary\_ip', String>] Returns nil if the value is +not set. match = config.scan(/^:raw-latex:`\s`+vrrp {vrid} +description:raw-latex:`\s`+(.\*):raw-latex:`\s*`$/) + +parse\_track scans the nodes configurations for the given virtual router +id and extracts the track entries. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'track', Array] Returns an empty array if the +value is not set. An example array of hashes follows: { name: +'Ethernet3', action: 'decrement', amount: 33 }, { name: 'Ethernet2', +action: 'decrement', amount: 22 }, { name: 'Ethernet2', action: +'shutdown' } pre = "vrrp {vrid} track " +config.scan(/^:raw-latex:`\s`+{pre}(:raw-latex:`\S`+) +(decrement\|shutdown):raw-latex:`\s*`(?:(:raw-latex:`\d`+\ :math:`|`))/) + +parse\_ip\_version scans the nodes configurations for the given virtual +router id and extracts the IP version. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'ip\_version', Integer>] Returns nil if the value is not +set. match = config.scan(/^:raw-latex:`\s`+vrrp {vrid} ip version +(:raw-latex:`\d`+)$/) + +parse\_mac\_addr\_adv\_interval scans the nodes configurations for the +given virtual router id and extracts the mac address advertisement +interval. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'mac\_addr\_adv\_interval', Integer>] Returns nil if the +value is not set. regex = "vrrp {vrid} mac-address +advertisement-interval" match = config.scan(/^:raw-latex:`\s`+{regex} +(:raw-latex:`\d`+)$/) + +parse\_preempt\_delay\_min scans the nodes configurations for the given +virtual router id and extracts the preempt delay minimum value. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'preempt\_delay\_min', Integer>] Returns nil if the value +is not set. match = config.scan(/^:raw-latex:`\s`+vrrp {vrid} preempt +delay minimum (:raw-latex:`\d`+)$/) + +parse\_preempt\_delay\_reload scans the nodes configurations for the +given virtual router id and extracts the preempt delay reload value. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'preempt\_delay\_reload', Integer>] Returns nil if the +value is not set. match = config.scan(/^:raw-latex:`\s`+vrrp {vrid} +preempt delay reload (:raw-latex:`\d`+)$/) + +parse\_delay\_reload scans the nodes configurations for the given +virtual router id and extracts the delay reload value. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'delay\_reload', Integer>] Returns empty hash if the value +is not set. match = config.scan(/^:raw-latex:`\s`+vrrp {vrid} delay +reload (:raw-latex:`\d`+)$/) + +create will create a new virtual router ID resource for the interface in +the nodes current. If the create method is called and the virtual router +ID already exists for the interface, this method will still return true. +Create takes optional parameters, but at least one parameter needs to be +set or the command will fail. + +@since eos\_version 4.13.7M + +commands interface vrrp ... + +@param name [String] The layer 3 interface name. + +@param vrid [String] The virtual router id. + +@param opts [hash] Optional keyword arguments. + +@option opts enable [Boolean] Enable the virtual router. + +@option opts primary\_ip [String] The primary IPv4 address. + +@option opts priority [Integer] The priority setting for a virtual +router. + +@option opts description [String] Associates a text string to a virtual +router. + +@option opts secondary\_ip [Array] The secondary IPv4 address to the +specified virtual router. + +@option opts ip\_version [Integer] Configures the VRRP version for the +VRRP router. + +@option opts timers\_advertise [Integer] The interval between successive +advertisement messages that the switch sends to routers in the specified +virtual router ID. + +@option opts mac\_addr\_adv\_interval [Integer] Specifies interval in +seconds between advertisement packets sent to VRRP group members. + +@option opts preempt [Boolean] A virtual router preempt mode setting. +When preempt mode is enabled, if the switch has a higher priority it +will preempt the current master virtual router. When preempt mode is +disabled, the switch can become the master virtual router only when a +master virtual router is not present on the subnet, regardless of +priority settings. + +@option opts preempt\_delay\_min [Integer] Interval in seconds between +VRRP preempt event and takeover. Minimum delays takeover when VRRP is +fully implemented. + +@option opts preempt\_delay\_reload [Integer] Interval in seconds +between VRRP preempt event and takeover. Reload delays takeover after +initialization following a switch reload. + +@option opts delay\_reload [Integer] Delay between system reboot and +VRRP initialization. + +@option opts track [Array] The track hash contains the name of an +interface to track, the action to take on state-change of the tracked +interface, and the amount to decrement the priority. + +@return [Boolean] Returns true if the command completed successfully. +cmds << "no vrrp {vrid} shutdown" cmds << "vrrp {vrid} shutdown" cmds << +"vrrp {vrid} ip {opts[:primary\_ip]}" if opts.key?(:primary\_ip) cmds << +"vrrp {vrid} priority {opts[:priority]}" cmds << "vrrp {vrid} +description {opts[:description]}" cmds << "vrrp {vrid} ip version +{opts[:ip\_version]}" cmds << "vrrp {vrid} timers advertise +{opts[:timers\_advertise]}" cmds << "vrrp {vrid} mac-address +advertisement-interval {val}" cmds << "vrrp {vrid} preempt" cmds << "no +vrrp {vrid} preempt" cmds << "vrrp {vrid} preempt delay minimum {val}" +cmds << "vrrp {vrid} preempt delay reload {val}" cmds << "vrrp {vrid} +delay reload {opts[:delay\_reload]}" + +delete will delete the virtual router ID on the interface from the nodes +current running configuration. If the delete method is called and the +virtual router id does not exist on the interface, this method will +succeed. + +@since eos\_version 4.13.7M + +commands interface no vrrp + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@return [Boolean] Returns true if the command completed successfully. +configure\_interface(name, "no vrrp {vrid}") + +default will default the virtual router ID on the interface from the +nodes current running configuration. This command has the same effect as +deleting the virtual router id from the interface in the nodes running +configuration. If the default method is called and the virtual router id +does not exist on the interface, this method will succeed. + +@since eos\_version 4.13.7M + +commands interface default vrrp + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@return [Boolean] Returns true if the command complete successfully. +configure\_interface(name, "default vrrp {vrid}") + +set\_shutdown enables and disables the virtual router. + +commands interface {no \| default} vrrp shutdown + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts enable [Boolean] If enable is true then the virtual router +is administratively enabled for the interface and if enable is false +then the virtual router is administratively disabled for the interface. +Default is true. + +@option opts default [Boolean] Configure shutdown using the default +keyword. + +@return [Boolean] Returns true if the command complete successfully. +Shutdown semantics are opposite of enable semantics so invert enable. +cmd = "vrrp {vrid} shutdown" + +set\_primary\_ip sets the primary IP address for the virtual router. + +commands interface {no \| default} vrrp ip + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The primary IPv4 address. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the primary IP address using +the default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} ip" + +set\_priority sets the priority for a virtual router. + +commands interface {no \| default} vrrp priority + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The priority value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the priority using the default +keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} priority" + +set\_description sets the description for a virtual router. + +commands interface {no \| default} vrrp description + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The description value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the description using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} description" + +build\_secondary\_ip\_cmd builds the array of commands required to +update the secondary IP addresses. This method allows the create methods +to leverage the code in the setter. + +@api private + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param ip\_addrs [Array] Array of secondary IPv4 address. An empty array +will remove all secondary IPv4 addresses set for the virtual router on +the specified layer 3 interface. + +@return [Array] Returns the array of commands. The array could +be empty. Get the current secondary IP address set for the virtual +router A return of nil means that nothing has been configured for the +virtual router. Add commands to delete any secondary IP addresses that +are currently set for the virtual router but not in ip\_addrs. cmds << +"no vrrp {vrid} ip {addr} secondary" Add commands to add any secondary +IP addresses that are not currently set for the virtual router but are +in ip\_addrs. cmds << "vrrp {vrid} ip {addr} secondary" +set\_secondary\_ips configures the set of secondary IP addresses +associated with the virtual router. The ip\_addrs value passed should be +an array of IP Addresses. This method will remove secondary IP addresses +that are currently set for the virtual router but not included in the +ip\_addrs array value passed in. The method will then add secondary IP +addresses that are not currently set for the virtual router but are +included in the ip\_addrs array value passed in. + +commands interface {no} vrrp ip secondary + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param ip\_addrs [Array] Array of secondary IPv4 address. An empty array +will remove all secondary IPv4 addresses set for the virtual router on +the specified layer 3 interface. + +@return [Boolean] Returns true if the command complete successfully. + +set\_ip\_version sets the VRRP version for a virtual router. + +commands interface {no \| default} vrrp ip version + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The VRRP version. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the VRRP version using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} ip version" + +set\_timers\_advertise sets the interval between successive +advertisement messages that the switch sends to routers in the specified +virtual router ID. + +commands interface {no \| default} vrrp timers advertise + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The timer value in seconds. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the timer advertise value using +the default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} timers advertise" + +set\_mac\_addr\_adv\_interval sets the interval in seconds between +advertisement packets sent to VRRP group members for the specified +virtual router ID. + +commands interface {no \| default} vrrp mac-address +advertisement-interval + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments + +@option opts value [String] The mac address advertisement interval value +in seconds. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the timer advertise value using +the default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} mac-address advertisement-interval" + +set\_preempt sets the virtual router's preempt mode setting. When +preempt mode is enabled, if the switch has a higher priority it will +preempt the current master virtual router. When preempt mode is +disabled, the switch can become the master virtual router only when a +master virtual router is not present on the subnet, regardless of +priority settings. + +commands interface {no \| default} vrrp preempt + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts enable [Boolean] If enable is true then the virtual router +preempt mode is administratively enabled for the interface and if enable +is false then the virtual router preempt mode is administratively +disabled for the interface. Default is true. + +@option opts default [Boolean] Configure the timer advertise value using +the default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} preempt" + +set\_preempt\_delay\_min sets the minimum time in seconds for the +virtual router to wait before taking over the active role. + +commands interface {no \| default} vrrp preempt delay minimum + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The preempt delay minimum value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the preempt delay minimum value +using the default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} preempt delay minimum" + +set\_preempt\_delay\_reload sets the preemption delay after a reload +only. This delay period applies only to the first interface-up event +after the virtual router has reloaded. + +commands interface {no \| default} vrrp preempt delay reload + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The preempt delay reload value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] :default Configure the preempt delay +reload value using the default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} preempt delay reload" + +set\_delay\_reload sets the delay between system reboot and VRRP +initialization for the virtual router. + +commands interface {no \| default} vrrp delay reload + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments + +@option opts value [String] The delay reload value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the delay reload value using +the default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} delay reload" + +build\_tracks\_cmd builds the array of commands required to update the +tracks. This method allows the create methods to leverage the code in +the setter. + +@api private + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param tracks [Array] Array of a hash of track information. Hash format: +{ name: 'Eth2', action: 'decrement', amount: 33 }, The name and action +key are required. The amount key should only be specified if the action +is shutdown. The valid actions are 'decrement' and 'shutdown'. An empty +array will remove all tracks set for the virtual router on the specified +layer 3 interface. + +@return [Array] Returns the array of commands. The array could +be empty. Validate the track hash rubocop:disable Style/Next fail +ArgumentError, 'Key: {key} invalid in track hash' Get the current tracks +set for the virtual router. A return of nil means that nothing has been +configured for the virtual router. Add commands to delete any tracks +that are currently set for the virtual router but not in tracks. cmds << +"no vrrp {vrid} track {tk[:name]} {tk[:action]}" Add commands to add any +tracks that are not currently set for the virtual router but are in +tracks. cmd = "vrrp {vrid} track {tk[:name]} {tk[:action]}" cmd << " +{tk[:amount]}" if tk.key?(:amount) set\_tracks configures the set of +track settings associated with the virtual router. The tracks value +passed should be an array of hashes, each hash containing a track entry. +This method will remove tracks that are currently set for the virtual +router but not included in the tracks array value passed in. The method +will then add tracks that are not currently set for the virtual router +but are included in the tracks array value passed in. + +commands interface {no} vrrp track [] + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param tracks [Array] Array of a hash of track information. Hash format: +{ name: 'Eth2', action: 'decrement', amount: 33 }, An empty array will +remove all tracks set for the virtual router on the specified layer 3 +interface. + +@return [Boolean] Returns true if the command complete successfully. diff --git a/guide/contributing.rst b/guide/contributing.rst new file mode 100644 index 0000000..b13d670 --- /dev/null +++ b/guide/contributing.rst @@ -0,0 +1,6 @@ +Contributing +============ + +.. contents:: :local: + +Contributing pull requests are gladly welcomed for this repository. Please note that all contributions that modify the library behavior require corresponding test cases otherwise the pull request will be rejected. \ No newline at end of file diff --git a/guide/cookbook.rst b/guide/cookbook.rst deleted file mode 100644 index c5535bd..0000000 --- a/guide/cookbook.rst +++ /dev/null @@ -1,4 +0,0 @@ -Cookbook -============ - -.. contents:: :local: \ No newline at end of file diff --git a/guide/developing.rst b/guide/developing.rst deleted file mode 100644 index 5e7e5e4..0000000 --- a/guide/developing.rst +++ /dev/null @@ -1,4 +0,0 @@ -Developing -========== - -.. contents:: :local: \ No newline at end of file diff --git a/guide/faq.rst b/guide/faq.rst deleted file mode 100644 index eb5392d..0000000 --- a/guide/faq.rst +++ /dev/null @@ -1,4 +0,0 @@ -FAQ -=== - -.. contents:: :local: \ No newline at end of file diff --git a/guide/getting-started.rst b/guide/getting-started.rst new file mode 100644 index 0000000..8420889 --- /dev/null +++ b/guide/getting-started.rst @@ -0,0 +1,134 @@ +Getting Started +=============== + +.. contents:: :local: + +In order to use rbeapi, the EOS command API must be enabled using management api http-commands configuration mode. This library supports eAPI calls over both HTTP and UNIX Domain Sockets. Once the command API is enabled on the destination node, create a configuration file with the node properities. + +Note: The default search path for the conf file is ~/.eapi.conf followed by /mnt/flash/eapi.conf. This can be overridden by setting EAPI_CONF= in your environment. + +Example eapi.conf File +---------------------- + +Below is an example of an eAPI conf file. The conf file can contain more than one node. Each node section must be prefaced by connection: where is the name of the connection. + +The following configuration options are available for defining node entries: + + host - The IP address or FQDN of the remote device. If the host parameter is omitted then the connection name is used + username - The eAPI username to use for authentication (only required for http or https connections) + password - The eAPI password to use for authentication (only required for http or https connections) + enablepwd - The enable mode password if required by the destination node + transport - Configures the type of transport connection to use. The default value is https. Valid values are: + socket (available in EOS 4.14.5 or later) + http_local (available in EOS 4.14.5 or later) + http + https + port - Configures the port to use for the eAPI connection. A default port is used if this parameter is absent, based on the transport setting using the following values: + transport: http, default port: 80 + transport: https, deafult port: 443 + transport: https_local, default port: 8080 + transport: socket, default port: n/a + open_timeout - The default number of seconds to wait for the eAPI connection to open. Any number may be used, including Floats for fractional seconds. Default value is 10 seconds. + read_timeout - The default number of seconds to wait for one block of eAPI results to be read (via one read(2) call). Any number may be used, including Floats for fractional seconds. Default value is 10 seconds. + +Note: See the EOS User Manual found at arista.com for more details on configuring eAPI values. + +All configuration values are optional. + +[connection:veos01] +username: eapi +password: password +transport: http + +[connection:veos02] +transport: http + +[connection:veos03] +transport: socket + +[connection:veos04] +host: 172.16.10.1 +username: eapi +password: password +enablepwd: itsasecret +port: 1234 +transport: https + +[connection:localhost] +transport: http_local + +The above example shows different ways to define EOS node connections. All configuration options will attempt to use default values if not explicitly defined. If the host parameter is not set for a given entry, then the connection name will be used as the host address. + +Configuring [connection:localhost] +---------------------------------- + +The rbeapi library automatically installs a single default configuration entry for connecting to localhost host using a transport of sockets. If using the rbeapi library locally on an EOS node, simply enable the command API to use sockets and no further configuration is needed for rbeapi to function. If you specify an entry in a conf file with the name [connection:localhost], the values in the conf file will overwrite the default. + +Using rbeapi +------------ + +The Ruby Client for eAPI was designed to be easy to use and implement for writing tools and applications that interface with the Arista EOS management plane. + +Creating a connection and sending commands +------------------------------------------ + +Once EOS is configured properly and the config file created, getting started with a connection to EOS is simple. Below demonstrates a basic connection using rbeapi. For more examples, please see the examples folder. + +# start by importing the library +require 'rbeapi/client' + +# create a node object by specifying the node to work with +node = Rbeapi::Client.connect_to('veos01') + +# send one or more commands to the node +node.enable('show hostname') +node.enable('show hostname') +=> [{:command=>"show hostname", :result=>{"fqdn"=>"veos01.arista.com", "hostname"=>"veos01"}, :encoding=>"json"}] + +# use the config method to send configuration commands +node.config('hostname veos01') +=> [{}] + +# multiple commands can be sent by using a list (works for both enable or config) + +node.config(['interface Ethernet1', 'description foo']) +=> [{}, {}] + +# return the running or startup configuration from the node (output omitted for brevity) + +node.running_config + +node.startup_config + +Using the API +------------- + +The rbeapi library provides both a client for send and receiving commands over eAPI as well as an API for working directly with EOS resources. The API is designed to be easy and straightforward to use yet also extensible. Below is an example of working with the vlans API + +# create a connection to the node +require 'rbeapi/client' +node = Rbeapi::Client.connect_to('veos01') + +# get the instance of the API (in this case vlans) +vlans = node.api('vlans') + +# return all vlans from the node +vlans.getall +=> {"1"=>{:name=>"tester", :state=>"active", :trunk_groups=>[]}, + "4"=>{:name=>"VLAN0004", :state=>"active", :trunk_groups=>[]}, + "100"=>{:name=>"TEST_VLAN_100", :state=>"active", :trunk_groups=>[]}, + "300"=>{:name=>"VLAN0300", :state=>"active", :trunk_groups=>[]}} + +# return a specific vlan from the node +vlans.get(1) +=> {:name=>"tester", :state=>"active", :trunk_groups=>[]} + +# add a new vlan to the node +vlans.create(400) +=> true + +# set the new vlan name +vlans.set_name(100, value: 'foo') +=> true + +All API implementations developed by Arista EOS+ CS are found in the rbeapi/api folder. See the examples folder for additional examples. \ No newline at end of file diff --git a/guide/index.rst b/guide/index.rst index fb21811..29e4770 100644 --- a/guide/index.rst +++ b/guide/index.rst @@ -12,12 +12,10 @@ Contents: :maxdepth: 2 overview - quickstart + getting-started installation - cookbook - troubleshooting - developing + upgrading testing - faq + contributing release-notes license \ No newline at end of file diff --git a/guide/installation.rst b/guide/installation.rst index 3c4aa04..792a678 100644 --- a/guide/installation.rst +++ b/guide/installation.rst @@ -1,4 +1,59 @@ Installation ============ -.. contents:: :local: \ No newline at end of file +.. contents:: :local: + +The source code for rbeapi is provided on Github at http://github.com/arista-eosplus/rbeapi. All current development is done in the develop branch. Stable released versions are tagged in the master branch and uploaded to RubyGems. + + To install the latest stable version of rbeapi, simply run gem install rbeapi + + To install the latest development version from Github, simply clone the develop branch and run + + $ rake build + $ rake install + + To create an RPM, run rake rpm + + To generate a SWIX file for EOS with necessary dependencies, run rake all_rpms then follow the swix create instructions, provided by the build. NOTE: PuppetLabs provides a puppet agent SWIX which includes Ruby 1.9.3 in /opt/puppet/bin/ which is different from where you might otherwise install Ruby. If you have installed the puppet-enterprise 3.x SWIX, then you should build and use the rbeapi-puppet3 swix, below. If you have installed the puppet-enterprise 2015.x SWIX, then you should build and use the rbeapi-puppet-aio swix, below. Otherwise, if you have installed at least Ruby 1.9.3 in the standard system location, then the rbeapi SWIX may be used. + + $ bundle install --path .bundle/gems/ + $ bundle exec rake all_rpms + ... + RPMs are available in rpms/noarch/ + Copy the RPMs to an EOS device then run the 'swix create' command. + Examples: + Puppet Open Source: + cd /mnt/flash; \ + swix create rbeapi-0.4.0-1.swix \ + rubygem-rbeapi-0.4.0-1.eos4.noarch.rpm \ + rubygem-inifile-3.0.0-3.eos4.noarch.rpm \ + rubygem-netaddr-1.5.0-2.eos4.noarch.rpm \ + rubygem-net_http_unix-0.2.1-3.eos4.noarch.rpm + Puppet-enterprise agent (3.x): + cd/mnt/flash; \ + swix create rbeapi-puppet3-0.4.0-1.swix \ + rubygem-rbeapi-puppet3-0.4.0-1.eos4.noarch.rpm \ + rubygem-inifile-puppet3-3.0.0-3.eos4.noarch.rpm \ + rubygem-netaddr-puppet3-1.5.0-2.eos4.noarch.rpm + Puppet-All-in-one agent (2015.x/4.x): + cd/mnt/flash; \ + swix create rbeapi-puppet-aio-0.4.0-1.swix \ + rubygem-rbeapi-puppet-aio-0.4.0-1.eos4.noarch.rpm \ + rubygem-inifile-puppet-aio-3.0.0-3.eos4.noarch.rpm \ + rubygem-netaddr-puppet-aio-1.5.0-2.eos4.noarch.rpm \ + rubygem-net_http_unix-puppet-aio-0.2.1-3.eos4.noarch.rpm + + On EOS: + + Arista# copy flash: + Arista# bash + -bash-4.1# cd /mnt/flash/ + -bash-4.1# swix create rbeapi-puppet3-0.4.0-1.swix \ + rubygem-rbeapi-puppet3-0.4.0-1.eos4.noarch.rpm \ + rubygem-inifile-puppet3-3.0.0-1.eos4.noarch.rpm \ + rubygem-netaddr-puppet3-1.5.0-1.eos4.noarch.rpm + -bash-4.1# exit + Arista# copy flash:rbeapi-puppet3-0.4.0-1.swix extension: + Arista# extension rbeapi-puppet3-0.4.0-1.swix + Arista# copy installed-extensions boot-extensions + diff --git a/guide/license.rst b/guide/license.rst index df32f7b..d1719a2 100644 --- a/guide/license.rst +++ b/guide/license.rst @@ -1,5 +1,16 @@ License ======= -.. include:: ../LICENSE - :literal: \ No newline at end of file +.. contents:: :local: + +Copyright (c) 2015, 2016, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/guide/overview.rst b/guide/overview.rst index d97ec29..088133a 100644 --- a/guide/overview.rst +++ b/guide/overview.rst @@ -3,17 +3,14 @@ Overview .. contents:: :local: -Introduction ------------- - The Ruby Client for eAPI provides a native Ruby implementation for programming Arista EOS network devices using Ruby. The Ruby client provides the ability to build native applications in Ruby that can communicate with EOS either locally via Unix domain sockets (on-box) or remotely over a HTTP/S transport (off-box). It uses a standard INI-style configuration file to specifiy one or more connection profiles. The rbeapi implemenation also provides an API layer for building native Ruby objects that allow for configuration and state extraction of EOS nodes. The API layer provides a consistent implementation for working with EOS configuration resources. The implementation of the API layer is highly extensible and can be used as a foundation for building custom data models. The libray is freely provided to the open source community for building robust applications using Arista EOS eAPI. Support is provided as best effort through Github iusses. -Prerequisites -------------- +Requirements +------------ * Arista EOS 4.12 or later * Arista eAPI enabled for at least one transport (see official EOS Config Guide at arista.com for details) diff --git a/guide/quickstart.rst b/guide/quickstart.rst deleted file mode 100644 index 41feb59..0000000 --- a/guide/quickstart.rst +++ /dev/null @@ -1,4 +0,0 @@ -Quick Start -=========== - -.. contents:: :local: \ No newline at end of file diff --git a/guide/testing.rst b/guide/testing.rst index 79ab0db..d28b5c4 100644 --- a/guide/testing.rst +++ b/guide/testing.rst @@ -1,4 +1,8 @@ Testing Modules =============== -.. contents:: :local: \ No newline at end of file +.. contents:: :local: + +The rbeapi library provides spec tests. To run the spec tests, you will need to update the dut.conf file found in spec/fixtures. The switch used for testing should have at least interfaces Ethernet1-7. + + To run the spec tests, run bundle exec rspec spec from the root of the rbeapi source folder. diff --git a/guide/troubleshooting.rst b/guide/troubleshooting.rst deleted file mode 100644 index 3fa493d..0000000 --- a/guide/troubleshooting.rst +++ /dev/null @@ -1 +0,0 @@ -.. _troubleshooting: \ No newline at end of file diff --git a/guide/upgrading.rst b/guide/upgrading.rst new file mode 100644 index 0000000..1467255 --- /dev/null +++ b/guide/upgrading.rst @@ -0,0 +1,10 @@ +Upgrading +========= + +.. contents:: :local: + +On EOS: + + Arista# no extension pe-rbeapi-0.3.0-1.swix + Arista# extension rbeapi-puppet3-0.4.0-1.swix + Arista# copy installed-extensions boot-extensions diff --git a/lib/rbeapi/api/aaa.rb b/lib/rbeapi/api/aaa.rb index 956d325..aa5dfb4 100644 --- a/lib/rbeapi/api/aaa.rb +++ b/lib/rbeapi/api/aaa.rb @@ -263,7 +263,7 @@ def find_type(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # aaa group server # # @param name [String] The name of the aaa group server to create in the @@ -286,7 +286,7 @@ def create(name, type) # # @since eos_version 4.13.7M # - # commands + # ===Commands # no aaa group server [radius | tacacs+] # # @param name [String] The name of the aaa group server to create in the @@ -420,7 +420,7 @@ def add_tacacs_server(name, server, opts = {}) # # eos_version 4.13.7M # - # commands + # ===Commands # aaa group server [radius | tacacs+] # no server # diff --git a/lib/rbeapi/api/acl.rb b/lib/rbeapi/api/acl.rb index 6124523..6735e69 100644 --- a/lib/rbeapi/api/acl.rb +++ b/lib/rbeapi/api/acl.rb @@ -194,7 +194,7 @@ def parse_entries(config) # # @since eos_version 4.13.7M # - # commands + # ===Commands # ip access-list standard # # @param name [String] The ACL name to create on the node. Must @@ -213,7 +213,7 @@ def create(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # no ip access-list standard # # @param name [String] The ACL name to delete on the node. @@ -230,7 +230,7 @@ def delete(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # default no ip access-list standard # # @param name [String] The ACL name to set to the default value diff --git a/lib/rbeapi/api/bgp.rb b/lib/rbeapi/api/bgp.rb index 25d11b9..efdba9d 100644 --- a/lib/rbeapi/api/bgp.rb +++ b/lib/rbeapi/api/bgp.rb @@ -195,7 +195,7 @@ def parse_networks(config) # Optional parameters can be passed in to initialize BGP specific # settings. # - # commands + # ===Commands # router bgp # # @param bgp_as [String] The BGP autonomous system number to be @@ -247,7 +247,7 @@ def create(bgp_as, opts = {}) ## # delete will delete the BGP routing instance from the node. # - # commands + # ===Commands # no router bgp # # @return [Boolean] Returns true if the command completed successfully. @@ -262,7 +262,7 @@ def delete # keyword. This command has the same effect as deleting the BGP # routine instance from the nodes running configuration. # - # commands + # ===Commands # default router bgp # # @return [Boolean] returns true if the command complete successfully @@ -294,7 +294,7 @@ def configure_bgp(cmd) ## # set_router_id sets the router_id for the BGP routing instance. # - # commands + # ===Commands # router bgp # {no | default} router-id # @@ -325,7 +325,7 @@ def set_router_id(opts = {}) # set_shutdown configures the administrative state for the global # BGP routing process. The value option is not used by this method. # - # commands + # ===Commands # router bgp # {no | default} shutdown # @@ -352,7 +352,7 @@ def set_shutdown(opts = {}) # set_maximum_paths sets the maximum number of equal cost paths and # the maximum number of installed ECMP routes. # - # commands + # ===Commands # router bgp # {no | default} # maximum-paths [ecmp ] @@ -391,7 +391,7 @@ def set_maximum_paths(maximum_paths, maximum_ecmp_paths, opts = {}) ## # add_network creates a new instance of a BGP network on the node. # - # commands + # ===Commands # router bgp # network / # route-map @@ -415,7 +415,7 @@ def add_network(prefix, masklen, route_map = nil) ## # remove_network removes the instance of a BGP network on the node. # - # commands + # ===Commands # router bgp # {no} shutdown # @@ -720,7 +720,7 @@ def create(name) ## # delete will delete the BGP neighbor from the node. # - # commands + # ===Commands # no neighbor # or # no neighbor peer-group @@ -765,7 +765,7 @@ def neigh_command_builder(name, cmd, opts) ## # set_peer_group creates a BGP static peer group name. # - # commands + # ===Commands # router bgp # {no | default} neighbor peer-group # @@ -790,7 +790,7 @@ def set_peer_group(name, opts = {}) # set_remote_as configures the expected AS number for a neighbor # (peer). # - # commands + # ===Commands # router bgp # {no | default} neighbor remote-as # @@ -815,7 +815,7 @@ def set_remote_as(name, opts = {}) # set_shutdown disables the specified neighbor. The value option is # not used by this method. # - # commands + # ===Commands # router bgp # {no | default} neighbor shutdown # @@ -843,7 +843,7 @@ def set_shutdown(name, opts = {}) # attributes to the specified BGP neighbor. The value option is # not used by this method. # - # commands + # ===Commands # router bgp # {no | default} neighbor send-community # @@ -869,7 +869,7 @@ def set_send_community(name, opts = {}) # BGP-speaking neighbor or neighbors in the specified peer group. # The value option is not used by this method. # - # commands + # ===Commands # router bgp # {no | default} neighbor next-hop-self # @@ -893,7 +893,7 @@ def set_next_hop_self(name, opts = {}) # set_route_map_in command applies a route map to inbound BGP # routes. # - # commands + # ===Commands # router bgp # {no | default} neighbor route-map in # @@ -919,7 +919,7 @@ def set_route_map_in(name, opts = {}) # set_route_map_out command applies a route map to outbound BGP # routes. # - # commands + # ===Commands # router bgp # {no | default} neighbor route-map out # @@ -945,7 +945,7 @@ def set_route_map_out(name, opts = {}) # set_description associates descriptive text with the specified # peer or peer group. # - # commands + # ===Commands # router bgp # {no | default} neighbor description # diff --git a/lib/rbeapi/api/dns.rb b/lib/rbeapi/api/dns.rb index 2072ccf..f2046d0 100644 --- a/lib/rbeapi/api/dns.rb +++ b/lib/rbeapi/api/dns.rb @@ -126,7 +126,7 @@ def set_domain_name(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # ip name-server # no ip name-server # default ip name-server @@ -193,7 +193,7 @@ def remove_name_server(server) # # @since eos_version 4.13.7M # - # commands + # ===Commands # ip domain-list # no ip domain-list # default ip domain-list diff --git a/lib/rbeapi/api/ipinterfaces.rb b/lib/rbeapi/api/ipinterfaces.rb index 7b270a4..c3a47e2 100644 --- a/lib/rbeapi/api/ipinterfaces.rb +++ b/lib/rbeapi/api/ipinterfaces.rb @@ -170,7 +170,7 @@ def parse_helper_addresses(config) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # no switchport # @@ -191,7 +191,7 @@ def create(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # no ip address # switchport @@ -215,7 +215,7 @@ def delete(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # ip address # no ip address @@ -252,7 +252,7 @@ def set_address(name, opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # mtu # no mtu @@ -289,7 +289,7 @@ def set_mtu(name, opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # ip helper-address # no ip helper-address diff --git a/lib/rbeapi/api/logging.rb b/lib/rbeapi/api/logging.rb index 1c09a9a..ee5da73 100644 --- a/lib/rbeapi/api/logging.rb +++ b/lib/rbeapi/api/logging.rb @@ -100,7 +100,7 @@ def parse_hosts # # @since eos_version 4.13.7M # - # commands + # ===Commands # logging on # no logging on # default logging on @@ -126,7 +126,7 @@ def set_enable(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # logging host # # @param name [String] The host name or ip address of the destination @@ -144,7 +144,7 @@ def add_host(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # no logging host # # @param name [String] The host name or ip address of the destination diff --git a/lib/rbeapi/api/mlag.rb b/lib/rbeapi/api/mlag.rb index b57ccd0..eb5d57b 100644 --- a/lib/rbeapi/api/mlag.rb +++ b/lib/rbeapi/api/mlag.rb @@ -211,7 +211,7 @@ def parse_interfaces # # @since eos_version 4.13.7M # - # commands + # ===Commands # mlag configuration # domain-id # no domain-id @@ -245,7 +245,7 @@ def set_domain_id(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # mlag configuration # local-interface # no local-interface @@ -280,7 +280,7 @@ def set_local_interface(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # mlag configuration # peer-link # no peer-link @@ -315,7 +315,7 @@ def set_peer_link(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # mlag configuration # peer-address # no peer-address @@ -350,7 +350,7 @@ def set_peer_address(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # mlag configuration # shutdown # no shutdown @@ -386,7 +386,7 @@ def set_shutdown(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # mlag # no mlag diff --git a/lib/rbeapi/api/ntp.rb b/lib/rbeapi/api/ntp.rb index 4ae0058..27f91de 100644 --- a/lib/rbeapi/api/ntp.rb +++ b/lib/rbeapi/api/ntp.rb @@ -107,7 +107,7 @@ def parse_servers # # @since eos_version 4.13.7M # - # commands + # ===Commands # ntp source # no ntp source # default ntp source @@ -168,7 +168,7 @@ def remove_server(server) # # @since eos_version 4.13.7M # - # commands + # ===Commands # ntp server prefer # no ntp server prefer # diff --git a/lib/rbeapi/api/radius.rb b/lib/rbeapi/api/radius.rb index c2e73f7..e918658 100644 --- a/lib/rbeapi/api/radius.rb +++ b/lib/rbeapi/api/radius.rb @@ -172,7 +172,7 @@ def parse_servers # # @since eos_version 4.13.7M # - # commands + # ===Commands # radius-server key # no radius-server key # default radius-server key @@ -219,7 +219,7 @@ def set_global_key(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # radius-server timeout # no radius-server timeout # default radius-server timeout @@ -250,7 +250,7 @@ def set_global_timeout(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # radius-server retransmit # no radius-server retransmit # default radius-server retransmit diff --git a/lib/rbeapi/api/routemaps.rb b/lib/rbeapi/api/routemaps.rb index 9f75b43..a05cfe4 100644 --- a/lib/rbeapi/api/routemaps.rb +++ b/lib/rbeapi/api/routemaps.rb @@ -271,7 +271,7 @@ def name_commands(name, action, seqno, opts = {}) # # rubocop:disable Metrics/MethodLength # - # commands + # ===Commands # route-map action seqno description # match set continue # @@ -386,7 +386,7 @@ def remove_set_statements(name, action, seqno, cmds) # running configuration. If the delete method is called and the # routemap name does not exist, this method will succeed. # - # commands + # ===Commands # no route-map # # @param name [String] The routemap name to delete from the node. @@ -408,7 +408,7 @@ def delete(name, action, seqno) # exist then this method will not perform any changes but still # return True. # - # commands + # ===Commands # no route-map # # @param name [String] The routemap name to set to default. @@ -426,7 +426,7 @@ def default(name, action, seqno) # set_match_statements will set the match values for a specified routemap. # If the specified routemap does not exist, it will be created. # - # commands + # ===Commands # route-map action seqno match # # @param name [String] The name of the routemap to create. @@ -451,7 +451,7 @@ def set_match_statements(name, action, seqno, value) # set_set_statements will set the set values for a specified routemap. # If the specified routemap does not exist, it will be created. # - # commands + # ===Commands # route-map action seqno set # # @param name [String] The name of the routemap to create. @@ -476,7 +476,7 @@ def set_set_statements(name, action, seqno, value) # set_continue will set the continue value for a specified routemap. # If the specified routemap does not exist, it will be created. # - # commands + # ===Commands # route-map action seqno continue # # @param name [String] The name of the routemap to create. @@ -499,7 +499,7 @@ def set_continue(name, action, seqno, value) # set_description will set the description for a specified routemap. # If the specified routemap does not exist, it will be created. # - # commands + # ===Commands # route-map action seqno description # # @param name [String] The name of the routemap to create. diff --git a/lib/rbeapi/api/snmp.rb b/lib/rbeapi/api/snmp.rb index f4d38fe..db1bc56 100644 --- a/lib/rbeapi/api/snmp.rb +++ b/lib/rbeapi/api/snmp.rb @@ -187,7 +187,7 @@ def parse_notifications # # @since eos_version 4.13.7M # - # commands + # ===Commands # snmp-server enable traps # no snmp-server enable traps # default snmp-server enable traps @@ -217,7 +217,7 @@ def set_notification(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # snmp-server location # no snmp-server location # default snmp-server location @@ -248,7 +248,7 @@ def set_location(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # snmp-server contact # no snmp-server contact # default snmp-server contact @@ -279,7 +279,7 @@ def set_contact(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # snmp-server chassis-id # no snmp-server chassis-id # default snmp-server chassis-id @@ -310,7 +310,7 @@ def set_chassis_id(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # snmp-server source-interface # no snmp-server source-interface # default snmp-server source-interface @@ -356,7 +356,7 @@ def add_community(name, access = 'ro') # # @since eos_version 4.13.7M # - # commands + # ===Commands # no snmp-server community # # @param name [String] The name of the snmp community to add to the @@ -374,7 +374,7 @@ def remove_community(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # no snmp-server [ro|rw] # snmp-server [ro|rw] # diff --git a/lib/rbeapi/api/staticroutes.rb b/lib/rbeapi/api/staticroutes.rb index 313b0a7..8d74967 100644 --- a/lib/rbeapi/api/staticroutes.rb +++ b/lib/rbeapi/api/staticroutes.rb @@ -88,7 +88,7 @@ def getall ## # Creates a static route in EOS. May add or overwrite an existing route. # - # commands + # ===Commands # ip route [router_ip] [distance] [tag ] # [name ] # @@ -123,7 +123,7 @@ def create(destination, nexthop, opts = {}) # Removes a given route from EOS. May remove multiple routes if nexthop # is not specified. # - # commands + # ===Commands # no ip route [nexthop] # # @param destination [String] The destination and prefix matching the diff --git a/lib/rbeapi/api/stp.rb b/lib/rbeapi/api/stp.rb index 20e5b9c..34bfef3 100644 --- a/lib/rbeapi/api/stp.rb +++ b/lib/rbeapi/api/stp.rb @@ -117,7 +117,7 @@ def interfaces # # @since eos_version 4.13.7M # - # commands + # ===Commands # spanning-tree mode # no spanning-tree mode # default spanning-tree mode diff --git a/lib/rbeapi/api/switchports.rb b/lib/rbeapi/api/switchports.rb index 45c9b15..16a3e62 100644 --- a/lib/rbeapi/api/switchports.rb +++ b/lib/rbeapi/api/switchports.rb @@ -255,7 +255,7 @@ def set_mode(name, opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # switchport trunk allowed vlan add # no switchport trunk allowed vlan # default switchport trunk allowed vlan diff --git a/lib/rbeapi/api/users.rb b/lib/rbeapi/api/users.rb index ca0f8d1..73c5ebd 100644 --- a/lib/rbeapi/api/users.rb +++ b/lib/rbeapi/api/users.rb @@ -180,7 +180,7 @@ def parse_user_entry(user) # # @since eos_version 4.13.7M # - # commands + # ===Commands # username nopassword privilege role # username secret [0,5,sha512] ... # @@ -239,7 +239,7 @@ def create(name, opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # no username # # @param name [String] The user name to delete from the node. @@ -256,7 +256,7 @@ def delete(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # default username # # @param name [String] The user name to default in the nodes @@ -277,7 +277,7 @@ def default(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # username privilege # no username privilege # default username privilege @@ -310,7 +310,7 @@ def set_privilege(name, opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # username role # no username role # default username role @@ -343,7 +343,7 @@ def set_role(name, opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # username sshkey # no username sshkey # default username sshkey diff --git a/lib/rbeapi/api/vlans.rb b/lib/rbeapi/api/vlans.rb index ef02a23..e173403 100644 --- a/lib/rbeapi/api/vlans.rb +++ b/lib/rbeapi/api/vlans.rb @@ -159,7 +159,7 @@ def parse_trunk_groups(config) # # @since eos_version 4.13.7M # - # commands + # ===Commands # vlan # # @param id [String, Integer] The vlan id to create on the node. The @@ -177,7 +177,7 @@ def create(id) # # @since eos_version 4.13.7M # - # commands + # ===Commands # no vlan # # @param id [String, Integer] The vlan id to delete from the node. The @@ -195,7 +195,7 @@ def delete(id) # # @since eos_version 4.13.7M # - # commands + # ===Commands # default vlan # # @param id [String, Integer] The vlan id to default in the nodes @@ -217,7 +217,7 @@ def default(id) # # @since eos_version 4.13.7M # - # commands + # ===Commands # vlan # name # no name @@ -255,7 +255,7 @@ def set_name(id, opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # vlan # state [active, suspend] # no state @@ -298,7 +298,7 @@ def set_state(id, opts = {}) # # @since version 4.13.7M # - # commands + # ===Commands # vlan # trunk group # @@ -320,7 +320,7 @@ def add_trunk_group(id, value) # # @since eos_version 4.13.7M # - # commands + # ===Commands # vlan # no trunk group # diff --git a/lib/rbeapi/api/vrrp.rb b/lib/rbeapi/api/vrrp.rb index 90d3fa0..2a42ea7 100644 --- a/lib/rbeapi/api/vrrp.rb +++ b/lib/rbeapi/api/vrrp.rb @@ -454,7 +454,7 @@ def parse_delay_reload(config, vrid) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # vrrp ... # @@ -570,7 +570,7 @@ def create(name, vrid, opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # no vrrp # @@ -593,7 +593,7 @@ def delete(name, vrid) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # default vrrp # @@ -609,7 +609,7 @@ def default(name, vrid) ## # set_shutdown enables and disables the virtual router. # - # commands + # ===Commands # interface # {no | default} vrrp shutdown # @@ -640,7 +640,7 @@ def set_shutdown(name, vrid, opts = {}) ## # set_primary_ip sets the primary IP address for the virtual router. # - # commands + # ===Commands # interface # {no | default} vrrp ip # @@ -667,7 +667,7 @@ def set_primary_ip(name, vrid, opts = {}) ## # set_priority sets the priority for a virtual router. # - # commands + # ===Commands # interface # {no | default} vrrp priority # @@ -694,7 +694,7 @@ def set_priority(name, vrid, opts = {}) ## # set_description sets the description for a virtual router. # - # commands + # ===Commands # interface # {no | default} vrrp description # @@ -775,7 +775,7 @@ def build_secondary_ip_cmd(name, vrid, ip_addrs) # currently set for the virtual router but are included in the # ip_addrs array value passed in. # - # commands + # ===Commands # interface # {no} vrrp ip secondary # @@ -797,7 +797,7 @@ def set_secondary_ip(name, vrid, ip_addrs) ## # set_ip_version sets the VRRP version for a virtual router. # - # commands + # ===Commands # interface # {no | default} vrrp ip version # @@ -826,7 +826,7 @@ def set_ip_version(name, vrid, opts = {}) # advertisement messages that the switch sends to routers in the # specified virtual router ID. # - # commands + # ===Commands # interface # {no | default} vrrp timers advertise # @@ -855,7 +855,7 @@ def set_timers_advertise(name, vrid, opts = {}) # advertisement packets sent to VRRP group members for the # specified virtual router ID. # - # commands + # ===Commands # interface # {no | default} vrrp mac-address advertisement-interval # @@ -888,7 +888,7 @@ def set_mac_addr_adv_interval(name, vrid, opts = {}) # when a master virtual router is not present on the subnet, # regardless of priority settings. # - # commands + # ===Commands # interface # {no | default} vrrp preempt # @@ -917,7 +917,7 @@ def set_preempt(name, vrid, opts = {}) # set_preempt_delay_min sets the minimum time in seconds for the # virtual router to wait before taking over the active role. # - # commands + # ===Commands # interface # {no | default} vrrp preempt delay minimum # @@ -946,7 +946,7 @@ def set_preempt_delay_min(name, vrid, opts = {}) # only. This delay period applies only to the first interface-up # event after the virtual router has reloaded. # - # commands + # ===Commands # interface # {no | default} vrrp preempt delay reload # @@ -974,7 +974,7 @@ def set_preempt_delay_reload(name, vrid, opts = {}) # set_delay_reload sets the delay between system reboot and VRRP # initialization for the virtual router. # - # commands + # ===Commands # interface # {no | default} vrrp delay reload # @@ -1085,7 +1085,7 @@ def build_tracks_cmd(name, vrid, tracks) # tracks that are not currently set for the virtual router but are # included in the tracks array value passed in. # - # commands + # ===Commands # interface # {no} vrrp track [] # From 2737b5671ef99d2a41980e080e5edf0f137484a4 Mon Sep 17 00:00:00 2001 From: John Corbin Date: Mon, 25 Jan 2016 17:31:48 -0800 Subject: [PATCH 050/110] Add support for DEFAULT section to eapi config file. Fixes issue #71 --- lib/rbeapi/client.rb | 11 +++++++---- spec/fixtures/test.conf | 6 +++--- spec/unit/rbeapi/client_spec.rb | 1 + 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/rbeapi/client.rb b/lib/rbeapi/client.rb index fe5ebb8..e5d04d8 100644 --- a/lib/rbeapi/client.rb +++ b/lib/rbeapi/client.rb @@ -226,11 +226,14 @@ def read(filename) # For each section, if the host parameter is omitted then the # connection name is used. + has_default = self.has_section?('DEFAULT') sections.each do |name| - if name.start_with?('connection:') - conn = self["#{name}"] - conn['host'] = name.split(':')[1] unless conn['host'] - end + next unless name.start_with?('connection:') + conn = self["#{name}"] + conn['host'] = name.split(':')[1] unless conn['host'] + + # Merge in the default values into the connections + conn.merge!(self['DEFAULT']) { |_key, v1, _v2| v1 } if has_default end return if get_connection 'localhost' diff --git a/spec/fixtures/test.conf b/spec/fixtures/test.conf index 595eda7..555c767 100644 --- a/spec/fixtures/test.conf +++ b/spec/fixtures/test.conf @@ -1,6 +1,8 @@ -[connection:veos01] +[DEFAULT] username: eapi password: password + +[connection:veos01] transport: http host: veos01 @@ -14,8 +16,6 @@ host: veos03 [connection:veos04] host: 172.16.10.1 -username: eapi -password: password enablepwd: itsasecret port: 1234 transport: https diff --git a/spec/unit/rbeapi/client_spec.rb b/spec/unit/rbeapi/client_spec.rb index 4af7038..7e4fbd9 100644 --- a/spec/unit/rbeapi/client_spec.rb +++ b/spec/unit/rbeapi/client_spec.rb @@ -121,6 +121,7 @@ def wildcard_conf it 'returns the configuration options for the connection' do expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('veos01')).to eq(veos01) + expect(subject.config_for('veos05')).to eq(veos05) end end From 5584f1071592fcaa385a9a86a4cb39b295debb84 Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Mon, 8 Feb 2016 13:28:25 -0500 Subject: [PATCH 051/110] Update CHANGELOG for v0.5.1 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24b152b..b4ea109 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ Ruby Client for eAPI ==================== +## v0.5.1, February, 2016 + +- Fix issue where vlans API was not returning all configured vlan trunk_groups. + ## v0.5.0, January, 2016 - Add optional ‘mode’ parameter to set_members() method in port-channel From 2e919e7d50bad13065029418f00c42fdff9bca06 Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Mon, 8 Feb 2016 13:30:55 -0500 Subject: [PATCH 052/110] Update version string --- Gemfile | 2 +- README.md | 22 +++++++++++----------- lib/rbeapi/version.rb | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Gemfile b/Gemfile index 548e7a7..db3a9d1 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,7 @@ group :development, :test do gem 'pry', require: false gem 'pry-doc', require: false gem 'pry-stack_explorer', require: false - gem 'rbeapi', '0.5.0', path: '.' + gem 'rbeapi', '0.5.1', path: '.' gem 'ci_reporter_rspec', require: false gem 'simplecov-json', require: false gem 'simplecov-rcov', require: false diff --git a/README.md b/README.md index 390903b..3173708 100644 --- a/README.md +++ b/README.md @@ -235,21 +235,21 @@ Copy the RPMs to an EOS device then run the 'swix create' command. Examples: Puppet Open Source: cd /mnt/flash; \ - swix create rbeapi-0.5.0-1.swix \ - rubygem-rbeapi-0.5.0-1.eos4.noarch.rpm \ + swix create rbeapi-0.5.1-1.swix \ + rubygem-rbeapi-0.5.1-1.eos4.noarch.rpm \ rubygem-inifile-3.0.0-3.eos4.noarch.rpm \ rubygem-netaddr-1.5.0-2.eos4.noarch.rpm \ rubygem-net_http_unix-0.2.1-3.eos4.noarch.rpm Puppet-enterprise agent (3.x): cd/mnt/flash; \ - swix create rbeapi-puppet3-0.5.0-1.swix \ - rubygem-rbeapi-puppet3-0.5.0-1.eos4.noarch.rpm \ + swix create rbeapi-puppet3-0.5.1-1.swix \ + rubygem-rbeapi-puppet3-0.5.1-1.eos4.noarch.rpm \ rubygem-inifile-puppet3-3.0.0-3.eos4.noarch.rpm \ rubygem-netaddr-puppet3-1.5.0-2.eos4.noarch.rpm Puppet-All-in-one agent (2015.x/4.x): cd/mnt/flash; \ - swix create rbeapi-puppet-aio-0.5.0-1.swix \ - rubygem-rbeapi-puppet-aio-0.5.0-1.eos4.noarch.rpm \ + swix create rbeapi-puppet-aio-0.5.1-1.swix \ + rubygem-rbeapi-puppet-aio-0.5.1-1.eos4.noarch.rpm \ rubygem-inifile-puppet-aio-3.0.0-3.eos4.noarch.rpm \ rubygem-netaddr-puppet-aio-1.5.0-2.eos4.noarch.rpm \ rubygem-net_http_unix-puppet-aio-0.2.1-3.eos4.noarch.rpm @@ -260,13 +260,13 @@ Copy the RPMs to an EOS device then run the 'swix create' command. Arista# copy flash: Arista# bash -bash-4.1# cd /mnt/flash/ - -bash-4.1# swix create rbeapi-puppet3-0.5.0-1.swix \ - rubygem-rbeapi-puppet3-0.5.0-1.eos4.noarch.rpm \ + -bash-4.1# swix create rbeapi-puppet3-0.5.1-1.swix \ + rubygem-rbeapi-puppet3-0.5.1-1.eos4.noarch.rpm \ rubygem-inifile-puppet3-3.0.0-1.eos4.noarch.rpm \ rubygem-netaddr-puppet3-1.5.0-1.eos4.noarch.rpm -bash-4.1# exit - Arista# copy flash:rbeapi-puppet3-0.5.0-1.swix extension: - Arista# extension rbeapi-puppet3-0.5.0-1.swix + Arista# copy flash:rbeapi-puppet3-0.5.1-1.swix extension: + Arista# extension rbeapi-puppet3-0.5.1-1.swix Arista# copy installed-extensions boot-extensions ``` @@ -275,7 +275,7 @@ Copy the RPMs to an EOS device then run the 'swix create' command. On EOS: ``` Arista# no extension pe-rbeapi-0.3.0-1.swix - Arista# extension rbeapi-puppet3-0.5.0-1.swix + Arista# extension rbeapi-puppet3-0.5.1-1.swix Arista# copy installed-extensions boot-extensions ``` diff --git a/lib/rbeapi/version.rb b/lib/rbeapi/version.rb index 9c4cb0b..da3475c 100644 --- a/lib/rbeapi/version.rb +++ b/lib/rbeapi/version.rb @@ -33,5 +33,5 @@ # # # Rbeapi toplevel namespace. module Rbeapi - VERSION = '0.5.0' + VERSION = '0.5.1' end From 42dd8daa9146814c9e3d876280650f04472ad473 Mon Sep 17 00:00:00 2001 From: John Corbin Date: Sun, 31 Jan 2016 06:48:08 -0800 Subject: [PATCH 053/110] Only first trunk group was being returned. Fixes issue #113 --- lib/rbeapi/api/vlans.rb | 2 +- spec/system/rbeapi/api/vlans_spec.rb | 7 +++++-- spec/unit/rbeapi/api/vlans/default_spec.rb | 2 +- spec/unit/rbeapi/api/vlans/fixture_vlans.text | 2 ++ 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/rbeapi/api/vlans.rb b/lib/rbeapi/api/vlans.rb index e173403..561bcea 100644 --- a/lib/rbeapi/api/vlans.rb +++ b/lib/rbeapi/api/vlans.rb @@ -145,7 +145,7 @@ def parse_state(config) # # @return [Hash] Returns the resource hash attribute. def parse_trunk_groups(config) - values = config.scan(/trunk group (.+)$/).first + values = config.scan(/trunk group (.+)$/).flatten values = [] unless values { trunk_groups: values } end diff --git a/spec/system/rbeapi/api/vlans_spec.rb b/spec/system/rbeapi/api/vlans_spec.rb index 546873e..fe0692f 100644 --- a/spec/system/rbeapi/api/vlans_spec.rb +++ b/spec/system/rbeapi/api/vlans_spec.rb @@ -14,10 +14,13 @@ context '#get' do describe 'with defaults' do let(:entity) do - { name: 'default', state: 'active', trunk_groups: [] } + { name: 'default', state: 'active', trunk_groups: %w(mlag test) } end - before { node.config(['no vlan 1-4094', 'vlan 1']) } + before do + node.config(['no vlan 1-4094', 'vlan 1', 'trunk group mlag', + 'trunk group test']) + end it 'returns the vlan resource' do expect(subject.get('1')).to eq(entity) diff --git a/spec/unit/rbeapi/api/vlans/default_spec.rb b/spec/unit/rbeapi/api/vlans/default_spec.rb index 6c5c0f2..09f48c5 100644 --- a/spec/unit/rbeapi/api/vlans/default_spec.rb +++ b/spec/unit/rbeapi/api/vlans/default_spec.rb @@ -21,7 +21,7 @@ def vlans describe '#get' do let(:entity) do - { name: 'default', state: 'active', trunk_groups: [] } + { name: 'default', state: 'active', trunk_groups: %w(mlag_ctl test) } end it 'returns the vlan resource' do diff --git a/spec/unit/rbeapi/api/vlans/fixture_vlans.text b/spec/unit/rbeapi/api/vlans/fixture_vlans.text index 3f1489f..8330a80 100644 --- a/spec/unit/rbeapi/api/vlans/fixture_vlans.text +++ b/spec/unit/rbeapi/api/vlans/fixture_vlans.text @@ -2,4 +2,6 @@ vlan 1 name default state active no private-vlan + trunk group mlag_ctl + trunk group test ! From d8e6029cdd1f626ee4e98f4dae60e8b90cb71070 Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Tue, 12 Jan 2016 06:19:14 -0500 Subject: [PATCH 054/110] Bump version strings --- Gemfile | 4 ++++ README.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index db3a9d1..611e5f7 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,11 @@ group :development, :test do gem 'pry', require: false gem 'pry-doc', require: false gem 'pry-stack_explorer', require: false +<<<<<<< HEAD gem 'rbeapi', '0.5.1', path: '.' +======= + gem 'rbeapi', '0.5.0', path: '.' +>>>>>>> Bump version strings gem 'ci_reporter_rspec', require: false gem 'simplecov-json', require: false gem 'simplecov-rcov', require: false diff --git a/README.md b/README.md index 3173708..be522c3 100644 --- a/README.md +++ b/README.md @@ -296,7 +296,7 @@ corresponding test cases otherwise the pull request will be rejected. # License -Copyright (c) 2015, Arista Networks, Inc. All rights reserved. +Copyright (c) 2016, Arista Networks, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: From 0d57782bb2dee0fd0cf57a9392c40c974c8e45d9 Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Mon, 8 Feb 2016 14:28:15 -0500 Subject: [PATCH 055/110] Fixup version --- Gemfile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Gemfile b/Gemfile index 611e5f7..db3a9d1 100644 --- a/Gemfile +++ b/Gemfile @@ -24,11 +24,7 @@ group :development, :test do gem 'pry', require: false gem 'pry-doc', require: false gem 'pry-stack_explorer', require: false -<<<<<<< HEAD gem 'rbeapi', '0.5.1', path: '.' -======= - gem 'rbeapi', '0.5.0', path: '.' ->>>>>>> Bump version strings gem 'ci_reporter_rspec', require: false gem 'simplecov-json', require: false gem 'simplecov-rcov', require: false From 882a570ca559b3ec5e781aaa40625a544d07f751 Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Fri, 30 Oct 2015 14:35:53 -0400 Subject: [PATCH 056/110] Add build badge for Jenkins --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e0790cb..f0ab5a5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Arista eAPI Ruby Library +Jenkins [![Build Status](https://revproxy.arista.com/eosplus/ci/buildStatus/icon?job=rbeapi_start)](https://revproxy.arista.com/eosplus/ci/job/rbeapi_start/) + #### Table of Contents 1. [Overview] (#overview) From 88ddd21de557d3586fd7690e3fc801e7e780c20a Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 30 Nov 2015 12:34:28 -0700 Subject: [PATCH 057/110] Working on filling code coverage gaps. --- .../api/acl_spec.rb} | 0 spec/system/rbeapi/api/bgp_neighbors_spec.rb | 354 +++++++++++++++++ spec/system/rbeapi/api/bgp_spec.rb | 375 ++++++++++++++++++ .../api/ospf_interfaces_spec.rb} | 0 .../api/ospf_spec.rb} | 0 spec/system/rbeapi/api/staticroutes_spec.rb | 177 +++++++++ 6 files changed, 906 insertions(+) rename spec/system/{api_acl_spec.rb => rbeapi/api/acl_spec.rb} (100%) create mode 100644 spec/system/rbeapi/api/bgp_neighbors_spec.rb create mode 100644 spec/system/rbeapi/api/bgp_spec.rb rename spec/system/{api_ospf_interfaces_spec.rb => rbeapi/api/ospf_interfaces_spec.rb} (100%) rename spec/system/{api_ospf_spec.rb => rbeapi/api/ospf_spec.rb} (100%) create mode 100644 spec/system/rbeapi/api/staticroutes_spec.rb diff --git a/spec/system/api_acl_spec.rb b/spec/system/rbeapi/api/acl_spec.rb similarity index 100% rename from spec/system/api_acl_spec.rb rename to spec/system/rbeapi/api/acl_spec.rb diff --git a/spec/system/rbeapi/api/bgp_neighbors_spec.rb b/spec/system/rbeapi/api/bgp_neighbors_spec.rb new file mode 100644 index 0000000..9a54027 --- /dev/null +++ b/spec/system/rbeapi/api/bgp_neighbors_spec.rb @@ -0,0 +1,354 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' +require 'rbeapi/api/bgp' + +describe Rbeapi::Api::BgpNeighbors do + subject { described_class.new(node) } + + let(:node) do + Rbeapi::Client.config.read(fixture_file('dut.conf')) + Rbeapi::Client.connect_to('dut') + end + + describe '#get' do + let(:entity) do + { peer_group: nil, + remote_as: nil, + send_community: false, + shutdown: false, + description: nil, + next_hop_self: false, + route_map_in: nil, + route_map_out: nil } + end + + before do + node.config(['no router bgp 64600', 'router bgp 64600', + 'neighbor eBGP_GROUP peer-group']) + end + + it 'returns the BGP neighbor resource' do + expect(subject.get('eBGP_GROUP')).to eq(entity) + end + end + + describe '#getall' do + let(:entity) do + { + 'eBGP_GROUP' => { + peer_group: nil, remote_as: nil, send_community: false, + shutdown: false, description: nil, next_hop_self: false, + route_map_in: nil, route_map_out: nil + }, + '192.168.255.1' => { + peer_group: 'eBGP_GROUP', remote_as: '65000', send_community: true, + shutdown: true, description: nil, next_hop_self: true, + route_map_in: nil, route_map_out: nil + }, + '192.168.255.3' => { + peer_group: 'eBGP_GROUP', remote_as: '65001', send_community: true, + shutdown: true, description: nil, next_hop_self: true, + route_map_in: nil, route_map_out: nil + } + } + end + + before do + node.config(['no router bgp 64600', 'router bgp 64600', + 'neighbor 192.168.255.1 peer-group eBGP_GROUP', + 'neighbor 192.168.255.1 remote-as 65000', + 'neighbor 192.168.255.3 peer-group eBGP_GROUP', + 'neighbor 192.168.255.3 remote-as 65001']) + end + + it 'returns all the neighbors' do + expect(subject.getall).to eq(entity) + end + + it 'returns a hash collection' do + expect(subject.getall).to be_a_kind_of(Hash) + end + + it 'has three entries' do + expect(subject.getall.size).to eq(3) + end + end + + describe '#create' do + let(:before) do + { peer_group: nil, + remote_as: nil, + send_community: true, + shutdown: true, + description: nil, + next_hop_self: true, + route_map_in: nil, + route_map_out: nil } + end + + let(:after) do + { peer_group: nil, + remote_as: nil, + send_community: false, + shutdown: true, + description: nil, + next_hop_self: false, + route_map_in: nil, + route_map_out: nil } + end + + before { node.config(['no router bgp 64600', 'router bgp 64600']) } + + it 'create a new BGP neighbor' do + expect(subject.get('edge')).to eq(before) + expect(subject.create('edge')).to be_truthy + + expect(subject.get('edge')).to eq(after) + end + end + + describe '#delete' do + let(:before) do + { peer_group: nil, + remote_as: nil, + send_community: false, + shutdown: true, + description: nil, + next_hop_self: false, + route_map_in: nil, + route_map_out: nil } + end + + let(:after) do + { peer_group: nil, + remote_as: nil, + send_community: true, + shutdown: true, + description: nil, + next_hop_self: true, + route_map_in: nil, + route_map_out: nil } + end + + it 'delete a BGP resource' do + expect(subject.get('edge')).to eq(before) + expect(subject.delete('edge')).to be_truthy + + expect(subject.get('edge')).to eq(after) + end + end + + describe '#set_peer_group' do + before do + node.config(['no router bgp 64600', 'router bgp 64600', + 'neighbor eBGP_GROUP peer-group']) + end + + it 'set the peer group' do + expect(subject.get('192.168.255.1')[:peer_group]).to eq(nil) + expect(subject.set_peer_group('192.168.255.1', value: 'eBGP_GROUP')) + .to be_truthy + expect(subject.get('192.168.255.1')[:peer_group]).to eq('eBGP_GROUP') + end + + it 'remove the peer group value' do + expect(subject.set_peer_group('192.168.255.1', value: 'eBGP_GROUP')) + .to be_truthy + expect(subject.get('192.168.255.1')[:peer_group]).to eq('eBGP_GROUP') + expect(subject.set_peer_group('192.168.255.1', enable: false)) + .to be_truthy + expect(subject.get('192.168.255.1')[:peer_group]).to eq(nil) + end + + it 'defaults the peer group value' do + expect(subject.set_peer_group('192.168.255.1', value: 'eBGP_GROUP')) + .to be_truthy + expect(subject.set_peer_group('192.168.255.1', default: true)) + .to be_truthy + expect(subject.get('192.168.255.1')[:peer_group]).to eq(nil) + end + end + + describe '#set_remote_as' do + it 'set the remote AS value' do + expect(subject.get('eng')[:remote_as]).to eq(nil) + expect(subject.set_remote_as('eng', value: '10')).to be_truthy + expect(subject.get('eng')[:remote_as]).to eq('10') + end + + it 'remove the remote AS value' do + expect(subject.get('eng')[:remote_as]).to eq('10') + expect(subject.set_remote_as('eng', enable: false)) + .to be_truthy + expect(subject.get('eng')[:remote_as]).to eq(nil) + end + + it 'defaults the remote AS value' do + expect(subject.set_remote_as('eng', value: '10')).to be_truthy + expect(subject.set_remote_as('eng', default: true)) + .to be_truthy + expect(subject.get('eng')[:remote_as]).to eq(nil) + end + end + + describe '#set_shutdown' do + it 'shutdown neighbor' do + expect(subject.get('eng')[:shutdown]).to eq(false) + expect(subject.set_shutdown('eng')).to be_truthy + expect(subject.get('eng')[:shutdown]).to eq(true) + end + + it 'negate shutdown neighbor' do + expect(subject.get('eng')[:shutdown]).to eq(true) + expect(subject.set_shutdown('eng', enable: false)).to be_truthy + expect(subject.get('eng')[:shutdown]).to eq(true) + end + + it 'default shutdown neighbor' do + expect(subject.get('eng')[:shutdown]).to eq(true) + expect(subject.set_shutdown('eng', default: true)).to be_truthy + expect(subject.get('eng')[:shutdown]).to eq(false) + end + end + + describe '#set_send_community' do + it 'enable neighbor send community' do + expect(subject.get('eng')[:send_community]).to eq(false) + expect(subject.set_send_community('eng')).to be_truthy + expect(subject.get('eng')[:send_community]).to eq(true) + end + + it 'negate neighbor send community' do + expect(subject.get('eng')[:send_community]).to eq(true) + expect(subject.set_send_community('eng', enable: false)).to be_truthy + expect(subject.get('eng')[:send_community]).to eq(false) + end + + it 'default neighbor send community' do + expect(subject.set_send_community('eng')).to be_truthy + expect(subject.get('eng')[:send_community]).to eq(true) + expect(subject.set_send_community('eng', default: true)).to be_truthy + expect(subject.get('eng')[:send_community]).to eq(false) + end + end + + describe '#set_next_hop_self' do + it 'enable neighbor next hop self' do + expect(subject.get('eng')[:next_hop_self]).to eq(false) + expect(subject.set_next_hop_self('eng')).to be_truthy + expect(subject.get('eng')[:next_hop_self]).to eq(true) + end + + it 'negate neighbor next hop self' do + expect(subject.get('eng')[:next_hop_self]).to eq(true) + expect(subject.set_next_hop_self('eng', enable: false)).to be_truthy + expect(subject.get('eng')[:next_hop_self]).to eq(false) + end + + it 'default neighbor next hop self' do + expect(subject.set_next_hop_self('eng')).to be_truthy + expect(subject.get('eng')[:next_hop_self]).to eq(true) + expect(subject.set_next_hop_self('eng', default: true)).to be_truthy + expect(subject.get('eng')[:next_hop_self]).to eq(false) + end + end + + describe '#set_route_map_in' do + it 'set route map in value' do + expect(subject.get('eng')[:route_map_in]).to eq(nil) + expect(subject.set_route_map_in('eng', value: 'edge')).to be_truthy + expect(subject.get('eng')[:route_map_in]).to eq('edge') + end + + it 'negate route map in value' do + expect(subject.get('eng')[:route_map_in]).to eq('edge') + expect(subject.set_route_map_in('eng', value: 'edge', enable: false)) + .to be_truthy + expect(subject.get('eng')[:route_map_in]).to eq(nil) + end + + it 'default route map in value' do + expect(subject.set_route_map_in('eng', value: 'edge')).to be_truthy + expect(subject.get('eng')[:route_map_in]).to eq('edge') + expect(subject.set_route_map_in('eng', value: 'edge', default: true)) + .to be_truthy + expect(subject.get('eng')[:route_map_in]).to eq(nil) + end + end + + describe '#set_route_map_out' do + it 'set route map out value' do + expect(subject.get('eng')[:route_map_out]).to eq(nil) + expect(subject.set_route_map_out('eng', value: 'edge')).to be_truthy + expect(subject.get('eng')[:route_map_out]).to eq('edge') + end + + it 'negate route map out value' do + expect(subject.get('eng')[:route_map_out]).to eq('edge') + expect(subject.set_route_map_out('eng', value: 'edge', enable: false)) + .to be_truthy + expect(subject.get('eng')[:route_map_out]).to eq(nil) + end + + it 'default route map out value' do + expect(subject.set_route_map_out('eng', value: 'edge')).to be_truthy + expect(subject.get('eng')[:route_map_out]).to eq('edge') + expect(subject.set_route_map_out('eng', value: 'edge', default: true)) + .to be_truthy + expect(subject.get('eng')[:route_map_out]).to eq(nil) + end + end + + describe '#set_description' do + it 'set the description value' do + expect(subject.get('eng')[:description]).to eq(nil) + expect(subject.set_description('eng', value: 'text')).to be_truthy + expect(subject.get('eng')[:description]).to eq('text') + end + + it 'negate the description value' do + expect(subject.get('eng')[:description]).to eq('text') + expect(subject.set_description('eng', enable: false)).to be_truthy + expect(subject.get('eng')[:description]).to eq(nil) + end + + it 'defaults the description value' do + expect(subject.set_description('eng', value: 'text')).to be_truthy + expect(subject.get('eng')[:description]).to eq('text') + expect(subject.set_description('eng', default: true)).to be_truthy + expect(subject.get('eng')[:description]).to eq(nil) + end + end +end diff --git a/spec/system/rbeapi/api/bgp_spec.rb b/spec/system/rbeapi/api/bgp_spec.rb new file mode 100644 index 0000000..063c11c --- /dev/null +++ b/spec/system/rbeapi/api/bgp_spec.rb @@ -0,0 +1,375 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' +require 'rbeapi/api/bgp' + +describe Rbeapi::Api::Bgp do + subject { described_class.new(node) } + + let(:node) do + Rbeapi::Client.config.read(fixture_file('dut.conf')) + Rbeapi::Client.connect_to('dut') + end + + let(:test) do + { bgp_as: '64600', + router_id: '192.168.254.1', + shutdown: false, + maximum_paths: 32, + maximum_ecmp_paths: 32, + networks: [ + { prefix: '192.168.254.1', masklen: 32, route_map: nil }, + { prefix: '192.168.254.2', masklen: 32, route_map: 'rmap' } + ], + neighbors: { + 'eBGP_GROUP' => { + peer_group: nil, remote_as: nil, send_community: false, + shutdown: false, description: nil, next_hop_self: false, + route_map_in: nil, route_map_out: nil + }, + '192.168.255.1' => { + peer_group: 'eBGP_GROUP', remote_as: '65000', send_community: true, + shutdown: true, description: nil, next_hop_self: true, + route_map_in: nil, route_map_out: nil + }, + '192.168.255.3' => { + peer_group: 'eBGP_GROUP', remote_as: '65001', send_community: true, + shutdown: true, description: nil, next_hop_self: true, + route_map_in: nil, route_map_out: nil + } + } + } + end + + describe '#get' do + before do + node.config(['no router bgp 64600', 'router bgp 64600', + 'no shutdown', + 'router-id 192.168.254.1', + 'bgp convergence time 300', + 'bgp convergence slow-peer time 90', + 'no bgp confederation identifier', + 'no update wait-for-convergence', + 'no update wait-install', + 'bgp log-neighbor-changes', + 'bgp default ipv4-unicast', + 'no bgp default ipv6-unicast', + 'timers bgp 60 180', + 'distance bgp 20 200 200', + 'graceful-restart stalepath-time 300', + 'no bgp cluster-id', + 'bgp client-to-client reflection', + 'graceful-restart-helper', + 'bgp peer-mac-resolution-timeout 0', + 'bgp enforce-first-as', + 'no default-metric', + 'no bgp always-compare-med', + 'no bgp bestpath med missing-as-worst', + 'no bgp bestpath med confed', + 'no bgp host-routes fib direct-install', + 'maximum-paths 32 ecmp 32', + 'bgp listen limit 1000', + 'no bgp aspath-cmp-include-nexthop', + 'no bgp tie-break-on-age', + 'no bgp tie-break-on-router-id', + 'no bgp tie-break-on-originator-id', + 'no bgp tie-break-on-cluster-list-length', + 'neighbor eBGP_GROUP peer-group', + 'no neighbor eBGP_GROUP remote-as', + 'no neighbor eBGP_GROUP import-localpref', + 'no neighbor eBGP_GROUP export-localpref', + 'no neighbor eBGP_GROUP description', + 'no neighbor eBGP_GROUP next-hop-self', + 'no neighbor eBGP_GROUP next-hop-peer', + 'no neighbor eBGP_GROUP allowas-in', + 'no neighbor eBGP_GROUP send-community', + 'no neighbor eBGP_GROUP shutdown', + 'no neighbor eBGP_GROUP remove-private-as', + 'no neighbor eBGP_GROUP out-delay', + 'no neighbor eBGP_GROUP local-as', + 'no neighbor eBGP_GROUP weight', + 'no neighbor eBGP_GROUP transport connection-mode passive', + 'no neighbor eBGP_GROUP update-source', + 'no neighbor eBGP_GROUP dont-capability-negotiate', + 'neighbor eBGP_GROUP fall-over bfd', + 'no neighbor eBGP_GROUP local-v6-addr', + 'neighbor eBGP_GROUP soft-reconfiguration inbound', + 'no neighbor eBGP_GROUP ebgp-multihop', + 'no neighbor eBGP_GROUP route-reflector-client', + 'no neighbor eBGP_GROUP timers', + 'no neighbor eBGP_GROUP route-map in', + 'neighbor eBGP_GROUP graceful-restart-helper', + 'no neighbor eBGP_GROUP route-map out', + 'no neighbor eBGP_GROUP prefix-list in', + 'no neighbor eBGP_GROUP prefix-list out', + 'neighbor eBGP_GROUP password 7 6C/HkrwJ53+dsHumQf49Wg==', + 'no neighbor eBGP_GROUP default-originate', + 'neighbor eBGP_GROUP enforce-first-as', + 'no neighbor eBGP_GROUP metric-out', + 'neighbor eBGP_GROUP maximum-routes 12000', + 'neighbor 192.168.255.1 peer-group eBGP_GROUP', + 'neighbor 192.168.255.1 remote-as 65000', + 'neighbor 192.168.255.3 peer-group eBGP_GROUP', + 'neighbor 192.168.255.3 remote-as 65001', + 'network 192.168.254.1/32', + 'network 192.168.254.2/32 route-map rmap', + 'bgp redistribute-internal', + 'aggregate-address 192.168.255.0/28 summary-only', + 'no redistribute connected', + 'no redistribute ospf match internal', + 'no redistribute ospf match external', + 'no redistribute ospf match nssa-external', + 'no redistribute ospf3 match internal', + 'no redistribute ospf3 match external', + 'no redistribute static', + 'no redistribute rip', + 'no redistribute aggregate', + 'address-family ipv4', + 'default neighbor eBGP_GROUP activate', + 'no neighbor eBGP_GROUP route-map in', + 'no neighbor eBGP_GROUP route-map out', + 'no neighbor eBGP_GROUP default-originate', + 'default neighbor 192.168.255.1 activate', + 'default neighbor 192.168.255.3 activate', + 'address-family ipv6', + 'default neighbor eBGP_GROUP activate', + 'no neighbor eBGP_GROUP route-map in', + 'no neighbor eBGP_GROUP route-map out', + 'no neighbor eBGP_GROUP prefix-list in', + 'no neighbor eBGP_GROUP prefix-list out', + 'no neighbor eBGP_GROUP default-originate', + 'default neighbor 192.168.255.1 activate', + 'default neighbor 192.168.255.3 activate']) + end + + it 'returns the BGP resource' do + expect(subject.get).to eq(test) + end + end + + describe '#create' do + let(:response) do + { + bgp_as: '1000', + router_id: nil, + shutdown: false, + maximum_paths: 1, + maximum_ecmp_paths: 128, + networks: [], + neighbors: {} + } + end + + before do + node.config(['no router bgp 64600']) + end + + it 'create a new BGP resource' do + expect(subject.get).to eq(nil) + expect(subject.create('1000')).to be_truthy + expect(subject.get).to eq(response) + end + + it 'create with enable' do + expect(subject.get).to eq(nil) + expect(subject.create('1000', enable: true)).to be_truthy + expect(subject.get).to eq(response) + end + + it 'create with router_id' do + expect(subject.get).to eq(nil) + expect(subject.create('1000', router_id: '1.2.3.4')).to be_truthy + expect(subject.get[:router_id]).to eq('1.2.3.4') + end + + it 'create with maximum paths' do + expect(subject.get).to eq(nil) + expect(subject.create('1000', maximum_paths: 3)).to be_truthy + expect(subject.get[:maximum_paths]).to eq(3) + end + + it 'create with maximum paths and ecmp paths' do + expect(subject.get).to eq(nil) + expect(subject.create('1000', maximum_paths: 13, + maximum_ecmp_paths: 13)).to be_truthy + expect(subject.get[:maximum_paths]).to eq(13) + expect(subject.get[:maximum_ecmp_paths]).to eq(13) + end + + it 'raises ArgumentError for create with ecmp paths only' do + expect { subject.create('1000', maximum_ecmp_paths: 13) }.to \ + raise_error ArgumentError + end + + it 'create with all options set' do + expect(subject.create('1000', enable: true, router_id: '1.2.3.4', + maximum_paths: 13, + maximum_ecmp_paths: 13)).to be_truthy + expect(subject.get[:router_id]).to eq('1.2.3.4') + expect(subject.get[:maximum_paths]).to eq(13) + expect(subject.get[:maximum_ecmp_paths]).to eq(13) + end + end + + describe '#delete' do + before do + node.config(['no router bgp 1000', 'router bgp 1000']) + end + + let(:response) do + { + bgp_as: '1000', + router_id: nil, + shutdown: false, + maximum_paths: 1, + maximum_ecmp_paths: 128, + networks: [], + neighbors: {} + } + end + + it 'delete a BGP resource' do + expect(subject.get).to eq(response) + expect(subject.delete).to be_truthy + expect(subject.get).to eq(nil) + end + end + + describe '#default' do + before do + node.config(['no router bgp 1000', 'router bgp 1000', + 'maximum-paths 13 ecmp 15']) + end + + let(:before) do + { + bgp_as: '1000', + router_id: nil, + shutdown: false, + maximum_paths: 13, + maximum_ecmp_paths: 15, + networks: [], + neighbors: {} + } + end + + it 'sets router to default value' do + expect(subject.get).to eq(before) + expect(subject.default).to be_truthy + expect(subject.get).to eq(nil) + end + end + + describe '#set_router_id' do + before do + node.config(['no router bgp 1000', 'router bgp 1000']) + end + + it 'set the router id' do + expect(subject.set_router_id(value: '1.2.3.4')).to be_truthy + expect(subject.get[:router_id]).to eq('1.2.3.4') + end + + it 'remove the router-id without a value' do + expect(subject.set_router_id(enable: false)).to be_truthy + expect(subject.get[:router_id]).to eq(nil) + end + + it 'remove the router-id with a value' do + expect(subject.set_router_id(value: '1.2.3.4', enable: false)) + .to be_truthy + expect(subject.get[:router_id]).to eq(nil) + end + + it 'defaults the router-id without a value' do + expect(subject.set_router_id(value: '1.2.3.4')).to be_truthy + expect(subject.set_router_id(default: true)).to be_truthy + expect(subject.get[:router_id]).to eq(nil) + end + + it 'defaults the router-id with a value' do + expect(subject.set_router_id(value: '1.2.3.4', default: true)) + .to be_truthy + expect(subject.get[:router_id]).to eq(nil) + end + end + + describe '#set_shutdown' do + it 'enable BGP routing process' do + expect(subject.set_shutdown(enable: true)).to be_truthy + end + + it 'disable BGP routing process' do + expect(subject.set_shutdown(enable: false)).to be_truthy + end + + it 'default BGP routing process state' do + expect(subject.set_shutdown(default: true)).to be_truthy + end + end + + describe '#set_maximum_paths' do + it 'set the maximum paths and ecmp paths' do + expect(subject.set_maximum_paths(13, 16)).to be_truthy + end + + it 'remove the maximum paths' do + expect(subject.set_maximum_paths(0, 0, enable: false)).to be_truthy + end + + it 'defaults the maximum paths' do + expect(subject.set_maximum_paths(0, 0, default: true)).to be_truthy + end + end + + describe '#add_network' do + it 'add a BGP network with a route map' do + expect(subject.add_network('1.2.3.0', 24, 'eng')).to be_truthy + end + + it 'add a BGP network without a route map' do + expect(subject.add_network('1.2.3.0', 24)).to be_truthy + end + end + + describe '#remove_network' do + it 'remove a BGP network with a route map' do + expect(subject.remove_network('1.2.3.0', 24, 'eng')).to be_truthy + end + + it 'remove a BGP network without a route map' do + expect(subject.remove_network('1.2.3.0', 24)).to be_truthy + end + end +end diff --git a/spec/system/api_ospf_interfaces_spec.rb b/spec/system/rbeapi/api/ospf_interfaces_spec.rb similarity index 100% rename from spec/system/api_ospf_interfaces_spec.rb rename to spec/system/rbeapi/api/ospf_interfaces_spec.rb diff --git a/spec/system/api_ospf_spec.rb b/spec/system/rbeapi/api/ospf_spec.rb similarity index 100% rename from spec/system/api_ospf_spec.rb rename to spec/system/rbeapi/api/ospf_spec.rb diff --git a/spec/system/rbeapi/api/staticroutes_spec.rb b/spec/system/rbeapi/api/staticroutes_spec.rb new file mode 100644 index 0000000..a4980e2 --- /dev/null +++ b/spec/system/rbeapi/api/staticroutes_spec.rb @@ -0,0 +1,177 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' +require 'rbeapi/api/staticroutes' + +describe Rbeapi::Api::Staticroutes do + subject { described_class.new(node) } + + let(:node) do + Rbeapi::Client.config.read(fixture_file('dut.conf')) + Rbeapi::Client.connect_to('dut') + end + + describe '#getall' do + let(:resource) { subject.getall } + + before do + node.config(['no ip route 1.2.3.4/32', + 'no ip route 192.0.2.0/24', + 'no ip route 192.0.3.0/24', + 'ip route 1.2.3.4/32 Ethernet7 4 tag 3 name frank', + 'ip route 1.2.3.4/32 Null0 32 tag 3 name fred', + 'ip route 192.0.2.0/24 Ethernet7 3 tag 0 name dummy1', + 'ip route 192.0.3.0/24 192.0.3.1 1 tag 0 name dummy2']) + end + + it 'returns the staticroute collection' do + expect(subject.getall).to include(destination: '1.2.3.4/32', + nexthop: 'Ethernet7', + distance: '4', + tag: '3', + name: 'frank') + expect(subject.getall).to include(destination: '1.2.3.4/32', + nexthop: 'Null0', + distance: '32', + tag: '3', + name: 'fred') + expect(subject.getall).to include(destination: '192.0.2.0/24', + nexthop: 'Ethernet7', + distance: '3', + tag: '0', + name: 'dummy1') + expect(subject.getall).to include(destination: '192.0.3.0/24', + nexthop: '192.0.3.1', + distance: '1', + tag: '0', + name: 'dummy2') + end + + it 'returns a hash collection' do + expect(subject.getall).to be_a_kind_of(Array) + end + + it 'has four entries' do + expect(subject.getall.size).to eq(4) + end + end + + describe '#create' do + let(:resource) { subject.getall } + + before(:each) do + node.config(['no ip route 1.2.3.4/32', + 'no ip route 192.0.2.0/24', + 'no ip route 192.0.3.0/24']) + end + + context 'creates a new staticroute resoure' do + it 'with minimum input' do + expect(subject.getall).to eq([]) + expect(subject.create('192.0.2.0/24', 'Ethernet1')).to be_truthy + expect(subject.getall).to eq(resource) + end + + it 'with a router_ip' do + node.config(['ip route 192.0.2.0/24 Ethernet1']) + expect(subject.getall).to eq(resource) + + expect(subject.create('192.0.2.0/24', 'Ethernet1', + router_ip: '192.168.1.1')).to be_truthy + expect(subject.getall).to eq(resource) + end + + it 'with distance (metric)' do + node.config(['ip route 192.0.2.0/24 Ethernet1']) + expect(subject.getall).to eq(resource) + + expect(subject.create('192.0.2.0/24', 'Ethernet1', distance: 254)) + .to be_truthy + expect(subject.getall).to include(destination: '192.0.2.0/24', + nexthop: 'Ethernet1', + distance: '254', + tag: '0', + name: nil) + end + + it 'with a tag' do + node.config(['ip route 192.0.2.0/24 Ethernet1']) + expect(subject.getall).to eq(resource) + + expect(subject.create('192.0.2.0/24', 'Ethernet1', tag: 3)) + .to be_truthy + expect(subject.getall).to include(destination: '192.0.2.0/24', + nexthop: 'Ethernet1', + distance: '1', + tag: '3', + name: nil) + end + + it 'with a name' do + node.config(['ip route 192.0.2.0/24 Ethernet1']) + expect(subject.getall).to eq(resource) + + expect(subject.create('192.0.2.0/24', 'Ethernet1', name: 'my_route')) + .to be_truthy + expect(subject.getall).to include(destination: '192.0.2.0/24', + nexthop: 'Ethernet1', + distance: '1', + tag: '0', + name: 'my_route') + end + end + end + + describe '#delete' do + let(:resource) { subject.getall } + + before do + node.config(['ip route 192.0.2.0/24 Ethernet1']) + end + + context 'deletes a staticroute resource' do + it 'given only a destination network' do + expect(subject.getall).to eq(resource) + expect(subject.delete('192.0.2.0/24')).to be_truthy + expect(subject.getall).to eq([]) + end + + it 'given a destination and nexthop' do + expect(subject.getall).to eq(resource) + expect(subject.delete('192.0.2.0/24', 'Ethernet1')).to be_truthy + expect(subject.getall).to eq([]) + end + end + end +end From 4ba8adde8c3c8bb3835f10b21130632ea769475c Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 30 Nov 2015 16:26:37 -0700 Subject: [PATCH 058/110] Ensure that nil is returned when you try to get nonexistent username. --- lib/rbeapi/api/users.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rbeapi/api/users.rb b/lib/rbeapi/api/users.rb index c546f9a..6d5cde9 100644 --- a/lib/rbeapi/api/users.rb +++ b/lib/rbeapi/api/users.rb @@ -94,7 +94,7 @@ def get(name) (username\s+#{name}\s+ sshkey\s+(?.*)$)?/x) user = config.scan(user_re) - return nil unless user + return nil unless user && user[0] parse_user_entry(user[0]) end From d16ed209f0b63fcb172b403dac5165936096fcdd Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Tue, 1 Dec 2015 14:03:16 -0700 Subject: [PATCH 059/110] Adding users system test. Currently having an issue with sha512 encryption. --- spec/system/rbeapi/api/users_spec.rb | 322 +++++++++++++++++++++++++++ 1 file changed, 322 insertions(+) create mode 100644 spec/system/rbeapi/api/users_spec.rb diff --git a/spec/system/rbeapi/api/users_spec.rb b/spec/system/rbeapi/api/users_spec.rb new file mode 100644 index 0000000..d6d8a1a --- /dev/null +++ b/spec/system/rbeapi/api/users_spec.rb @@ -0,0 +1,322 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' +require 'rbeapi/api/users' + +describe Rbeapi::Api::Users do + subject { described_class.new(node) } + + let(:node) do + Rbeapi::Client.config.read(fixture_file('dut.conf')) + Rbeapi::Client.connect_to('dut') + end + + let(:sshkey) do + 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKL1UtBALa4CvFUsHUipN' \ + 'ymA04qCXuAtTwNcMj84bTUzUI+q7mdzRCTLkllXeVxKuBnaTm2PW7W67K5C' \ + 'Vpl0EVCm6IY7FS7kc4nlnD/tFvTvShy/fzYQRAdM7ZfVtegW8sMSFJzBR/T' \ + '/Y/sxI16Y/dQb8fC3la9T25XOrzsFrQiKRZmJGwg8d+0RLxpfMg0s/9ATwQ' \ + 'Kp6tPoLE4f3dKlAgSk5eENyVLA3RsypWADHpenHPcB7sa8D38e1TS+n+EUy' \ + 'Adb3Yov+5ESAbgLIJLd52Xv+FyYi0c2L49ByBjcRrupp4zfXn4DNRnEG4K6' \ + 'GcmswHuMEGZv5vjJ9OYaaaaaaa' + end + + let(:secret) do + '$1$Ehb5lL0D$N3MgrkfMFxmeh0FSZ5sEZ1' + end + + let(:test) do + { name: 'rbeapi', + privilege: 1, + role: nil, + nopassword: false, + encryption: 'md5', + secret: secret, + sshkey: sshkey + } + end + + describe '#getall' do + let(:resource) { subject.getall } + + let(:test1_entries) do + { 'admin' => { name: 'admin', privilege: 1, + role: 'network-admin', nopassword: true, + encryption: nil, secret: nil, sshkey: nil }, + 'rbeapi' => { name: 'rbeapi', privilege: 1, role: nil, + nopassword: false, encryption: 'md5', + secret: secret, + sshkey: sshkey } + } + end + + before do + node.config(['no username rbeapi', + 'no username user1', + 'username admin privilege 1 role network-admin nopassword', + "username rbeapi privilege 1 secret 5 #{secret}", + "username rbeapi sshkey #{sshkey}"]) + end + + it 'returns the username collection' do + expect(subject.getall).to include(test1_entries) + end + + it 'returns a hash collection' do + expect(subject.getall).to be_a_kind_of(Hash) + end + + it 'has two entries' do + expect(subject.getall.size).to eq(2) + end + end + + describe '#get' do + it 'returns the user resource for given name' do + expect(subject.get('rbeapi')).to eq(test) + end + + it 'returns a hash' do + expect(subject.get('rbeapi')).to be_a_kind_of(Hash) + end + + it 'has two entries' do + expect(subject.get('rbeapi').size).to eq(7) + end + end + + describe '#create' do + before do + node.config(['no username rbeapi']) + end + + it 'create a new user name with no password' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', nopassword: :true)).to be_truthy + expect(subject.get('rbeapi')[:nopassword]).to eq(true) + end + + it 'create a new user name with no password and privilege' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', + privilege: 4, + nopassword: :true)).to be_truthy + expect(subject.get('rbeapi')[:privilege]).to eq(4) + end + + it 'create a new user name with no password, privilege, and role' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', + privilege: 4, + role: 'net-minion', + nopassword: :true)).to be_truthy + expect(subject.get('rbeapi')[:privilege]).to eq(4) + expect(subject.get('rbeapi')[:role]).to eq('net-minion') + expect(subject.get('rbeapi')[:nopassword]).to eq(true) + end + + it 'create a new user name with a password' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', secret: 'icanttellyou')).to be_truthy + expect(subject.get('rbeapi')[:encryption]).to eq('md5') + end + + it 'create a new user name with a password and privilege' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', + secret: 'icanttellyou', + privilege: 5)).to be_truthy + expect(subject.get('rbeapi')[:encryption]).to eq('md5') + expect(subject.get('rbeapi')[:privilege]).to eq(5) + end + + it 'create a new user name with a password, privilege, and role' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', + secret: 'icanttellyou', + privilege: 5, role: 'net')).to be_truthy + expect(subject.get('rbeapi')[:encryption]).to eq('md5') + expect(subject.get('rbeapi')[:privilege]).to eq(5) + expect(subject.get('rbeapi')[:role]).to eq('net') + end + + it 'create a new user name with a password and md5 encryption' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', + secret: '$1$Wb4zN5EH$ILNgYb3Ehzs85S9KpoFW4.', + encryption: 'md5')).to be_truthy + expect(subject.get('rbeapi')[:encryption]).to eq('md5') + expect(subject.get('rbeapi')[:secret]) + .to eq('$1$Wb4zN5EH$ILNgYb3Ehzs85S9KpoFW4.') + end + + it 'create a new user name with a password and sha512 encryption' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', + secret: '$6$somesalt$rkDq7Az4Efjo', + encryption: 'sha512')).to be_truthy + expect(subject.get('rbeapi')).to eq(nil) + end + + it 'create a new user name with a password, sha512 encryption, and key' do + expect(subject.get('rbeapi')).to eq(nil) + expect(subject.create('rbeapi', + secret: '$6$somesalt$rkDq7Az4Efjo', + encryption: 'sha512', + sshkey: sshkey)).to be_truthy + end + + it 'raises ArgumentError for create without required args ' do + expect { subject.create('rbeapi') }.to \ + raise_error ArgumentError + end + + it 'raises ArgumentError for invalid encryption value' do + expect { subject.create('name', encryption: 'bogus') }.to \ + raise_error ArgumentError + end + end + + describe '#delete' do + before do + node.config(['username user1 privilege 1 role network-admin nopassword']) + end + + it 'delete a username resource' do + expect(subject.get('user1')[:name]).to eq('user1') + expect(subject.delete('user1')).to be_truthy + expect(subject.get('user1')).to eq(nil) + end + end + + describe '#default' do + before do + node.config(['username user1 privilege 1 role network-admin nopassword']) + end + + it 'sets username resource to default value' do + expect(subject.get('user1')[:name]).to eq('user1') + expect(subject.default('user1')).to be_truthy + expect(subject.get('user1')).to eq(nil) + end + end + + describe '#set_privilege' do + before do + node.config(['no username rbeapi', + 'username rbeapi role network-admin nopassword']) + end + + it 'set the privilege' do + expect(subject.set_privilege('rbeapi', value: '13')).to be_truthy + expect(subject.get('rbeapi')[:privilege]).to eq(13) + end + + it 'remove the privilege without a value' do + expect(subject.set_privilege('rbeapi', enable: false)).to be_truthy + expect(subject.get('rbeapi')).to eq(nil) + end + + it 'remove the privilege with a value' do + expect(subject.set_privilege('rbeapi', value: '13', enable: false)) + .to be_truthy + expect(subject.get('rbeapi')).to eq(nil) + end + + it 'defaults the privilege without a value' do + expect(subject.set_privilege('rbeapi', default: true)).to be_truthy + expect(subject.get('rbeapi')).to eq(nil) + end + + it 'defaults the privilege with a value' do + expect(subject.set_privilege('rbeapi', value: '3', default: true)) + .to be_truthy + expect(subject.get('rbeapi')).to eq(nil) + end + end + + describe '#set_role' do + before do + node.config(['no username rbeapi', 'username rbeapi nopassword']) + end + + it 'set the role' do + expect(subject.set_role('rbeapi', value: 'net-minion')).to be_truthy + expect(subject.get('rbeapi')[:role]).to eq('net-minion') + end + + it 'remove the role without a value' do + expect(subject.set_role('rbeapi', enable: false)).to be_truthy + expect(subject.get('rbeapi')[:role]).to eq(nil) + end + + it 'remove the role with a value' do + expect(subject.set_role('rbeapi', value: 'net', enable: false)) + .to be_truthy + expect(subject.get('rbeapi')[:role]).to eq(nil) + end + + it 'defaults the role without a value' do + expect(subject.set_role('rbeapi', default: true)).to be_truthy + expect(subject.get('rbeapi')[:role]).to eq(nil) + end + + it 'defaults the role with a value' do + expect(subject.set_role('rbeapi', value: 'net', default: true)) + .to be_truthy + expect(subject.get('rbeapi')[:role]).to eq(nil) + end + end + + describe '#set_sshkey' do + before do + node.config(['no username rbeapi', 'username rbeapi nopassword']) + end + + it 'set the sshkey' do + expect(subject.set_sshkey('rbeapi', value: sshkey)).to be_truthy + end + + it 'remove the sshkey with a value' do + expect(subject.set_sshkey('rbeapi', value: sshkey, enable: false)) + .to be_truthy + expect(subject.get('rbeapi')[:sshkey]).to eq(nil) + end + + it 'defaults the sshkey without a value' do + expect(subject.set_sshkey('rbeapi', default: true)).to be_truthy + expect(subject.get('rbeapi')[:sshkey]).to eq(nil) + end + end +end From 22660aaedf3cd8670567e7121ae0e5d0bf7073ef Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Wed, 2 Dec 2015 19:33:48 -0700 Subject: [PATCH 060/110] Add vrrp system test --- spec/system/rbeapi/api/vrrp_spec.rb | 703 ++++++++++++++++++++++++++++ 1 file changed, 703 insertions(+) create mode 100644 spec/system/rbeapi/api/vrrp_spec.rb diff --git a/spec/system/rbeapi/api/vrrp_spec.rb b/spec/system/rbeapi/api/vrrp_spec.rb new file mode 100644 index 0000000..55f2ddc --- /dev/null +++ b/spec/system/rbeapi/api/vrrp_spec.rb @@ -0,0 +1,703 @@ +require 'spec_helper' + +require 'rbeapi/client' +require 'rbeapi/api/vrrp' + +describe Rbeapi::Api::Vrrp do + subject { described_class.new(node) } + + let(:node) do + Rbeapi::Client.config.read(fixture_file('dut.conf')) + Rbeapi::Client.connect_to('dut') + end + + before :all do + @sec_ips = ['1.2.3.1', '1.2.3.2', '1.2.3.3', '1.2.3.4'] + @tracks = [{ name: 'Ethernet3', action: 'decrement', amount: 33 }, + { name: 'Ethernet2', action: 'decrement', amount: 22 }, + { name: 'Ethernet2', action: 'shutdown' }] + end + + describe '#get' do + before do + node.config(['no interface Vlan150', 'no interface Vlan100', + 'interface Vlan100', 'interface Vlan150', + 'ip address 40.10.5.8/24', 'vrrp 30 priority 100', + 'vrrp 30 timers advertise 1', + 'vrrp 30 mac-address advertisement-interval 30', + 'no vrrp 30 preempt', 'vrrp 30 preempt delay minimum 0', + 'vrrp 30 preempt delay reload 0', 'vrrp 30 delay reload 0', + 'no vrrp 30 authentication', 'vrrp 30 ip 40.10.5.31', + 'vrrp 30 ipv6 ::', 'vrrp 30 description The description', + 'vrrp 30 shutdown', 'vrrp 30 track Ethernet1 decrement 5', + 'no vrrp 30 bfd ip', 'no vrrp 30 bfd ipv6', + 'vrrp 30 ip version 2', 'vrrp 40 priority 200', + 'vrrp 40 timers advertise 1', + 'vrrp 40 mac-address advertisement-interval 30', + 'vrrp 40 preempt', 'vrrp 40 preempt delay minimum 0', + 'vrrp 40 preempt delay reload 0', 'vrrp 40 delay reload 0', + 'no vrrp 40 authentication', 'vrrp 40 ip 40.10.5.32', + 'vrrp 40 ipv6 ::', 'no vrrp 40 description', + 'no vrrp 40 shutdown', + 'vrrp 40 track Ethernet3 decrement 33', + 'vrrp 40 track Ethernet2 decrement 22', + 'vrrp 40 track Ethernet2 shutdown', 'no vrrp 40 bfd ip', + 'no vrrp 40 bfd ipv6', 'vrrp 40 ip version 2']) + end + + let(:entity) do + { 30 => { primary_ip: '40.10.5.31', delay_reload: 0, + description: 'The description', enable: false, ip_version: 2, + mac_addr_adv_interval: 30, preempt: false, preempt_delay_min: 0, + preempt_delay_reload: 0, priority: 100, secondary_ip: [], + timers_advertise: 1, + track: [ + { name: 'Ethernet1', action: 'decrement', amount: 5 } + ] + }, + 40 => { primary_ip: '40.10.5.32', delay_reload: 0, description: nil, + enable: true, ip_version: 2, mac_addr_adv_interval: 30, + preempt: true, preempt_delay_min: 0, preempt_delay_reload: 0, + priority: 200, secondary_ip: [], timers_advertise: 1, + track: @tracks + } + } + end + + it 'returns the virtual router resource' do + expect(subject.get('Vlan150')).to eq(entity) + end + end + + describe '#getall' do + it 'returns a hash collection' do + expect(subject.getall).to be_a_kind_of(Hash) + end + + it 'returns the virtual router collection' do + expect(subject.getall).to include('Vlan100') + expect(subject.getall).to include('Vlan150') + end + end + + describe '#create' do + before do + node.config(['no interface Vlan100']) + end + + it 'creates a new virtual router with enable true' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, enable: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'creates a new virtual router with enable false' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, enable: false)).to be_truthy + expect(subject.get('Vlan100')).to include(9) + end + + it 'creates a new virtual router with primary ip' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, primary_ip: '1.2.3.4')).to be_truthy + expect(subject.get('Vlan100')[9][:primary_ip]).to eq('1.2.3.4') + end + + it 'creates a new virtual router with priority' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, primary_ip: '1.2.3.4', + priority: 100)).to be_truthy + expect(subject.get('Vlan100')[9][:priority]).to eq(100) + end + + it 'creates a new virtual router with description' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, description: 'Desc')).to be_truthy + expect(subject.get('Vlan100')[9][:description]).to eq('Desc') + end + + it 'creates a new virtual router with secondary ips' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, primary_ip: '100.99.98.100')) + .to be_truthy + expect(subject.create('Vlan100', 9, + secondary_ip: ['100.99.98.71', + '100.99.98.70'])).to be_truthy + expect(subject.get('Vlan100')[9][:secondary_ip]).to eq(['100.99.98.70', + '100.99.98.71']) + end + + it 'creates a new virtual router with ip version 2' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', + 9, + primary_ip: '100.99.98.100', + ip_version: 2)).to be_truthy + expect(subject.get('Vlan100')[9][:ip_version]).to eq(2) + end + + it 'creates a new virtual router with timers advertise' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, timers_advertise: 77)).to be_truthy + expect(subject.get('Vlan100')[9][:timers_advertise]).to eq(77) + end + + it 'creates a new virtual router with mac addr adv interval' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, mac_addr_adv_interval: 77)) + .to be_truthy + expect(subject.get('Vlan100')[9][:mac_addr_adv_interval]).to eq(77) + end + + it 'creates a new virtual router with preemt true' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, primary_ip: '100.99.98.100')) + .to be_truthy + expect(subject.create('Vlan100', 9, preempt: true)).to be_truthy + expect(subject.get('Vlan100')[9][:preempt]).to eq(true) + end + + it 'creates a new virtual router with preemt false' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, preempt: false)).to be_truthy + expect(subject.get('Vlan100')[9][:preempt]).to eq(false) + end + + it 'creates a new virtual router with preempt delay min' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, preempt_delay_min: 100)) + .to be_truthy + expect(subject.get('Vlan100')[9][:preempt_delay_min]).to eq(100) + end + + it 'creates a new virtual router with preempt delay reload' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, preempt_delay_reload: 100)) + .to be_truthy + expect(subject.get('Vlan100')[9][:preempt_delay_reload]).to eq(100) + end + + it 'creates a new virtual router with preempt delay reload' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, delay_reload: 100)).to be_truthy + expect(subject.get('Vlan100')[9][:delay_reload]).to eq(100) + end + + it 'creates a new virtual router with track values' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, primary_ip: '100.99.98.100')) + .to be_truthy + expect(subject.create('Vlan100', + 9, + track: [{ name: 'Ethernet3', + action: 'decrement', + amount: 33 }, + { name: 'Ethernet2', + action: 'decrement', + amount: 22 }, + { name: 'Ethernet2', + action: 'shutdown' }])).to be_truthy + expect(subject.get('Vlan100')[9][:track]).to eq(@tracks) + end + + it 'creates a new virtual router resource with enable and primary ip' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, enable: true, primary_ip: '1.2.3.4')) + .to be_truthy + expect(subject.get('Vlan100')[9][:primary_ip]).to eq('1.2.3.4') + end + + it 'creates a new virtual router resource with enable and priority' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, primary_ip: '100.99.98.100')) + .to be_truthy + expect(subject.create('Vlan100', 9, enable: true, priority: 100)) + .to be_truthy + expect(subject.get('Vlan100')[9][:priority]).to eq(100) + end + + it 'creates a new virtual router resource with enable and description' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, enable: true, description: 'Desc')) + .to be_truthy + expect(subject.get('Vlan100')[9][:description]).to eq('Desc') + end + + it 'creates a new virtual router resource with enable and secondary_ip' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, primary_ip: '100.99.98.100')) + .to be_truthy + expect(subject.create('Vlan100', + 9, + enable: true, + secondary_ip: ['1.2.3.1', + '1.2.3.2', + '1.2.3.3', '1.2.3.4'])).to be_truthy + expect(subject.get('Vlan100')[9][:secondary_ip]).to eq(@sec_ips) + end + + it 'creates a new virtual router resource with all options set' do + expect(subject.get('Vlan100')).to eq(nil) + expect(subject.create('Vlan100', 9, primary_ip: '100.99.98.100')) + .to be_truthy + expect(subject.create('Vlan100', + 9, + enable: true, + priority: 100, + description: 'Desc', + secondary_ip: ['100.99.98.71', + '100.99.98.70'], + ip_version: 2, + timers_advertise: 77, + mac_addr_adv_interval: 77, + preempt: true, + preempt_delay_min: 100, + preempt_delay_reload: 100, + delay_reload: 100, + track: [{ name: 'Ethernet3', + action: 'decrement', + amount: 33 }, + { name: 'Ethernet2', + action: 'decrement', + amount: 22 }, + { name: 'Ethernet2', + action: 'shutdown' }])).to be_truthy + end + + it 'raises ArgumentError for create without options' do + expect { subject.create('Vlan100', 9) }.to \ + raise_error ArgumentError + end + end + + describe '#delete' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'deletes a virtual router resource' do + expect(subject.delete('Vlan100', 9)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#default' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'sets virtual router resource to default' do + expect(subject.default('Vlan100', 9)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_shutdown' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'enable Vlan100 vrid 9' do + expect(subject.set_shutdown('Vlan100', 9)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'disable Vlan100 vrid 9' do + expect(subject.create('Vlan100', 9, primary_ip: '100.99.98.100')) + .to be_truthy + expect(subject.set_shutdown('Vlan100', 9, enable: false)).to be_truthy + expect(subject.get('Vlan100')[9][:enable]).to eq(false) + end + + it 'defaults Vlan100 vrid 9' do + expect(subject.set_shutdown('Vlan100', 9, default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_shutdown('Vlan100', 9, enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_primary_ip' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'set primary IP address' do + expect(subject.set_primary_ip('Vlan100', 9, + value: '1.2.3.4')).to be_truthy + expect(subject.get('Vlan100')[9][:primary_ip]).to eq('1.2.3.4') + end + + it 'disable primary IP address' do + expect(subject.set_primary_ip('Vlan100', 9, value: '1.2.3.4', + enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults primary IP address' do + expect(subject.set_primary_ip('Vlan100', 9, value: '1.2.3.4', + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_primary_ip('Vlan100', 9, enable: false, + value: '1.2.3.4', + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_priority' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'set priority' do + expect(subject.set_priority('Vlan100', 9, value: 13)).to be_truthy + expect(subject.get('Vlan100')[9][:priority]).to eq(13) + end + + it 'disable priority' do + expect(subject.set_priority('Vlan100', 9, enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults priority' do + expect(subject.set_priority('Vlan100', 9, default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_priority('Vlan100', 9, enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_description' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'set description' do + expect(subject.set_description('Vlan100', 9, + value: 'Howdy')).to be_truthy + expect(subject.get('Vlan100')[9][:description]).to eq('Howdy') + end + + it 'disable description' do + expect(subject.set_description('Vlan100', 9, enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults description' do + expect(subject.set_description('Vlan100', 9, default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_description('Vlan100', 9, enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_secondary_ip' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'set secondary IP addresses' do + # Set current IP addresses + expect(subject.set_secondary_ip('Vlan100', 9, @sec_ips)).to be_truthy + expect(subject.get('Vlan100')[9][:secondary_ip]).to eq(@sec_ips) + end + + it 'remove all secondary IP addresses' do + # Set current IP addresses + expect(subject.set_secondary_ip('Vlan100', 9, @sec_ips)).to be_truthy + # Delete all IP addresses + expect(subject.set_secondary_ip('Vlan100', 9, [])).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_ip_version' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'set VRRP version' do + expect(subject.set_ip_version('Vlan100', 9, value: 3)).to be_truthy + expect(subject.get('Vlan100')[9][:ip_version]).to eq(3) + end + + it 'disable VRRP version' do + expect(subject.set_ip_version('Vlan100', 9, enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults VRRP version' do + expect(subject.set_ip_version('Vlan100', 9, default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_ip_version('Vlan100', 9, enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_timers_advertise' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'set advertise timer' do + expect(subject.set_timers_advertise('Vlan100', 9, value: 7)).to be_truthy + expect(subject.get('Vlan100')[9][:timers_advertise]).to eq(7) + end + + it 'disable advertise timer' do + expect(subject.set_timers_advertise('Vlan100', 9, + enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults advertise timer' do + expect(subject.set_timers_advertise('Vlan100', 9, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_timers_advertise('Vlan100', 9, + enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_mac_addr_adv_interval' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'set mac address advertisement interval' do + expect(subject.set_mac_addr_adv_interval('Vlan100', 9, + value: 12)).to be_truthy + expect(subject.get('Vlan100')[9][:mac_addr_adv_interval]).to eq(12) + end + + it 'disable mac address advertisement interval' do + expect(subject.set_mac_addr_adv_interval('Vlan100', 9, + enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults mac address advertisement interval' do + expect(subject.set_mac_addr_adv_interval('Vlan100', 9, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_mac_addr_adv_interval('Vlan100', 9, + enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_preempt' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'enable preempt mode' do + expect(subject.create('Vlan100', 9, primary_ip: '100.99.98.100')) + .to be_truthy + expect(subject.set_preempt('Vlan100', 9)).to be_truthy + expect(subject.get('Vlan100')[9][:preempt]).to eq(true) + end + + it 'disable preempt mode' do + expect(subject.set_preempt('Vlan100', 9, enable: false)).to be_truthy + expect(subject.get('Vlan100')[9][:preempt]).to eq(false) + end + + it 'defaults preempt mode' do + expect(subject.set_preempt('Vlan100', 9, default: true)).to be_truthy + expect(subject.get('Vlan100')[9][:preempt]).to eq(false) + end + + it 'default option takes precedence' do + expect(subject.set_preempt('Vlan100', 9, enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')[9][:preempt]).to eq(false) + end + end + + describe '#set_preempt_delay_min' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'enable preempt mode' do + expect(subject.set_preempt_delay_min('Vlan100', 9, value: 8)).to be_truthy + expect(subject.get('Vlan100')[9][:preempt_delay_min]).to eq(8) + end + + it 'disable preempt mode' do + expect(subject.set_preempt_delay_min('Vlan100', 9, + enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults preempt mode' do + expect(subject.set_preempt_delay_min('Vlan100', 9, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_preempt_delay_min('Vlan100', 9, + enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_preempt_delay_reload' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'enable preempt delay reload' do + expect(subject.set_preempt_delay_reload('Vlan100', 9, + value: 8)).to be_truthy + expect(subject.get('Vlan100')[9][:preempt_delay_reload]).to eq(8) + end + + it 'disable preempt delay reload' do + expect(subject.set_preempt_delay_reload('Vlan100', 9, + enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults preempt delay reload' do + expect(subject.set_preempt_delay_reload('Vlan100', 9, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_preempt_delay_reload('Vlan100', 9, + enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_delay_reload' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + it 'enable delay reload' do + expect(subject.set_delay_reload('Vlan100', 9, value: 8)).to be_truthy + expect(subject.get('Vlan100')[9][:delay_reload]).to eq(8) + end + + it 'disable delay reload' do + expect(subject.set_delay_reload('Vlan100', 9, enable: false)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'defaults delay reload' do + expect(subject.set_delay_reload('Vlan100', 9, default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'default option takes precedence' do + expect(subject.set_delay_reload('Vlan100', 9, + enable: false, + default: true)).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + end + + describe '#set_tracks' do + before do + node.config(['no interface Vlan100', 'interface Vlan100', + 'vrrp 9 priority 100']) + end + + before :all do + @bad_key = [{ nombre: 'Ethernet3', action: 'decrement', amount: 33 }] + @miss_key = [{ action: 'decrement', amount: 33 }] + @bad_action = [{ name: 'Ethernet3', action: 'dec', amount: 33 }] + @sem_key = [{ name: 'Ethernet3', action: 'shutdown', amount: 33 }] + @bad_amount = [{ name: 'Ethernet3', action: 'decrement', amount: -1 }] + end + + it 'set tracks' do + # Set current IP addresses + expect(subject.set_tracks('Vlan100', 9, @tracks)).to be_truthy + expect(subject.get('Vlan100')[9][:track]).to eq(@tracks) + end + + it 'remove all tracks' do + # Set current IP addresses + expect(subject.set_tracks('Vlan100', 9, @tracks)).to be_truthy + # Delete all IP addresses + expect(subject.set_tracks('Vlan100', 9, [])).to be_truthy + expect(subject.get('Vlan100')).to eq({}) + end + + it 'raises ArgumentError for track hash with a bad key' do + expect { subject.set_tracks('Vlan100', 9, @bad_key) }.to \ + raise_error ArgumentError + end + + it 'raises ArgumentError for track hash with missing required key' do + expect { subject.set_tracks('Vlan100', 9, @miss_key) }.to \ + raise_error ArgumentError + end + + it 'raises ArgumentError for track hash with invalid action' do + expect { subject.set_tracks('Vlan100', 9, @bad_action) }.to \ + raise_error ArgumentError + end + + it 'raises ArgumentError for track hash with shutdown and amount' do + expect { subject.set_tracks('Vlan100', 9, @sem_key) }.to \ + raise_error ArgumentError + end + + it 'raises ArgumentError for track hash with negative amount' do + expect { subject.set_tracks('Vlan100', 9, @bad_amount) }.to \ + raise_error ArgumentError + end + end +end From 19e9e759f732cf7ac99cab3598562fc30869aae9 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Wed, 2 Dec 2015 20:16:44 -0700 Subject: [PATCH 061/110] Add valid sha512 password to user system test --- spec/system/rbeapi/api/users_spec.rb | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/spec/system/rbeapi/api/users_spec.rb b/spec/system/rbeapi/api/users_spec.rb index d6d8a1a..57925ca 100644 --- a/spec/system/rbeapi/api/users_spec.rb +++ b/spec/system/rbeapi/api/users_spec.rb @@ -53,6 +53,11 @@ end let(:secret) do + '$6$RMxgK5ALGIf.nWEC$tHuKCyfNtJMCY561P52dTzHUmYMmLxb/M' \ + 'xik.j3vMUs8lMCPocM00/NAS.SN6GCWx7d/vQIgxnClyQLAb7n3x0' + end + + let(:md5_secret) do '$1$Ehb5lL0D$N3MgrkfMFxmeh0FSZ5sEZ1' end @@ -62,7 +67,7 @@ role: nil, nopassword: false, encryption: 'md5', - secret: secret, + secret: md5_secret, sshkey: sshkey } end @@ -76,7 +81,7 @@ encryption: nil, secret: nil, sshkey: nil }, 'rbeapi' => { name: 'rbeapi', privilege: 1, role: nil, nopassword: false, encryption: 'md5', - secret: secret, + secret: md5_secret, sshkey: sshkey } } end @@ -85,7 +90,7 @@ node.config(['no username rbeapi', 'no username user1', 'username admin privilege 1 role network-admin nopassword', - "username rbeapi privilege 1 secret 5 #{secret}", + "username rbeapi privilege 1 secret 5 #{md5_secret}", "username rbeapi sshkey #{sshkey}"]) end @@ -184,17 +189,18 @@ it 'create a new user name with a password and sha512 encryption' do expect(subject.get('rbeapi')).to eq(nil) expect(subject.create('rbeapi', - secret: '$6$somesalt$rkDq7Az4Efjo', + secret: secret, encryption: 'sha512')).to be_truthy - expect(subject.get('rbeapi')).to eq(nil) + expect(subject.get('rbeapi')[:encryption]).to eq('sha512') end it 'create a new user name with a password, sha512 encryption, and key' do expect(subject.get('rbeapi')).to eq(nil) expect(subject.create('rbeapi', - secret: '$6$somesalt$rkDq7Az4Efjo', + secret: secret, encryption: 'sha512', sshkey: sshkey)).to be_truthy + expect(subject.get('rbeapi')[:encryption]).to eq('sha512') end it 'raises ArgumentError for create without required args ' do From 203ff4bf7e9182af0963fe20dc357637193c0146 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Tue, 8 Dec 2015 07:49:15 -0700 Subject: [PATCH 062/110] Working on code coverage. --- spec/system/rbeapi/api/dns_spec.rb | 18 +++++++++++++++++- .../system/rbeapi/api/interfaces_vxlan_spec.rb | 1 - spec/system/rbeapi/api/ospf_interfaces_spec.rb | 5 +++-- spec/system/rbeapi/api/ospf_spec.rb | 12 ++++++++++-- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/spec/system/rbeapi/api/dns_spec.rb b/spec/system/rbeapi/api/dns_spec.rb index eb683cb..9a2201a 100644 --- a/spec/system/rbeapi/api/dns_spec.rb +++ b/spec/system/rbeapi/api/dns_spec.rb @@ -114,11 +114,27 @@ expect(subject.get[:domain_list]).to be_empty end - it 'default the name servers list' do + it 'default true the name servers list' do expect(subject.get[:domain_list]).to be_empty + expect(subject.set_domain_list(value: servers)).to be_truthy expect(subject.set_domain_list(default: true)).to be_truthy expect(subject.get[:domain_list]).to be_empty end + + it 'default false the name servers list' do + expect(subject.get[:domain_list]).to be_empty + expect(subject.set_domain_list(default: false, + value: servers)).to be_truthy + expect(subject.get[:domain_list]).to eq(servers) + end + + it 'default the name servers list with previous values' do + expect(subject.get[:domain_list]).to be_empty + expect(subject.set_domain_list(value: %w(foob bat))).to be_truthy + expect(subject.set_domain_list(default: false, + value: servers)).to be_truthy + expect(subject.get[:domain_list]).to eq(servers) + end end describe '#add_domain_list' do diff --git a/spec/system/rbeapi/api/interfaces_vxlan_spec.rb b/spec/system/rbeapi/api/interfaces_vxlan_spec.rb index e40ea6c..89f91e0 100644 --- a/spec/system/rbeapi/api/interfaces_vxlan_spec.rb +++ b/spec/system/rbeapi/api/interfaces_vxlan_spec.rb @@ -41,7 +41,6 @@ before { node.config('no interface Vxlan1') } it 'creates a new interface resource' do - expect(subject.get('Vxlan1')).to be_nil expect(subject.create('Vxlan1')).to be_truthy expect(subject.get('Vxlan1')).not_to be_nil end diff --git a/spec/system/rbeapi/api/ospf_interfaces_spec.rb b/spec/system/rbeapi/api/ospf_interfaces_spec.rb index 3b1b22a..66f479a 100644 --- a/spec/system/rbeapi/api/ospf_interfaces_spec.rb +++ b/spec/system/rbeapi/api/ospf_interfaces_spec.rb @@ -12,8 +12,9 @@ describe '#get' do before do node.config(['default interface Ethernet1', 'interface Ethernet1', - 'no switchport', 'ip address 88.99.99.99/24', 'exit', - 'default interface Ethernet2']) + 'no switchport', 'ip address 88.99.99.99/24', + 'ip ospf network point-to-point', + 'exit', 'default interface Ethernet2']) end it 'returns an ospf interface resource instance' do diff --git a/spec/system/rbeapi/api/ospf_spec.rb b/spec/system/rbeapi/api/ospf_spec.rb index ff66d2c..9464c25 100644 --- a/spec/system/rbeapi/api/ospf_spec.rb +++ b/spec/system/rbeapi/api/ospf_spec.rb @@ -10,10 +10,18 @@ let(:node) { Rbeapi::Client.connect_to('dut') } describe '#get' do - before { node.config(['no router ospf 1', 'router ospf 1']) } + before do + node.config(['no router ospf 1', + 'router ospf 1', + 'router-id 1.1.1.1', + 'redistribute static route-map word', + 'network 192.168.10.10/24 area 0.0.0.0']) + end let(:entity) do - { 'router_id' => '', 'areas' => {}, 'redistribute' => {} } + { 'router_id' => '1.1.1.1', + 'areas' => { '0.0.0.0' => ['192.168.10.0/24'] }, + 'redistribute' => { 'static' => { 'route_map' => 'word' } } } end it 'returns an ospf resource instance' do From e8e6cddf534901a9ba1e68ff1fd099472bbdb00c Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Wed, 9 Dec 2015 20:40:50 -0700 Subject: [PATCH 063/110] Expanding test coverage. --- .../system/rbeapi/api/interfaces_base_spec.rb | 51 +++++++++++++-- .../rbeapi/api/interfaces_ethernet_spec.rb | 14 ++++ spec/system/rbeapi/api/ospf_spec.rb | 5 +- spec/system/rbeapi/api/snmp_spec.rb | 65 +++++++++++++++++++ spec/system/rbeapi/api/stp_instances_spec.rb | 20 ++++++ spec/system/rbeapi/api/stp_interfaces_spec.rb | 7 ++ spec/system/rbeapi/api/switchports_spec.rb | 54 +++++++++------ .../system/rbeapi/api/varp_interfaces_spec.rb | 34 ++++++++++ 8 files changed, 223 insertions(+), 27 deletions(-) diff --git a/spec/system/rbeapi/api/interfaces_base_spec.rb b/spec/system/rbeapi/api/interfaces_base_spec.rb index e81b94f..ae27da1 100644 --- a/spec/system/rbeapi/api/interfaces_base_spec.rb +++ b/spec/system/rbeapi/api/interfaces_base_spec.rb @@ -11,15 +11,56 @@ Rbeapi::Client.connect_to('dut') end + describe '#respond_to?' do + it 'test to validate endpoint' do + expect(subject.respond_to?('get', 'Ethernet1')).to be_truthy + end + end + describe '#get' do - let(:entity) do - { name: 'Loopback0', type: 'generic', description: '', shutdown: false } + context 'with interface Loopback' do + let(:entity) do + { name: 'Loopback0', type: 'generic', description: '', shutdown: false } + end + + before { node.config(['no interface Loopback0', 'interface Loopback0']) } + + it 'returns the interface resource' do + expect(subject.get('Loopback0')).to eq(entity) + end end - before { node.config(['no interface Loopback0', 'interface Loopback0']) } + context 'with interface Port-Channel' do + let(:entity) do + { name: 'Port-Channel1', type: 'portchannel', description: '', + shutdown: false, members: [], lacp_mode: 'on', minimum_links: '0', + lacp_fallback: 'disabled', lacp_timeout: '90' } + end + + before do + node.config(['no interface Loopback0', 'no interface Port-Channel1', + 'interface Port-Channel1']) + end + + it 'returns the interface resource' do + expect(subject.get('Port-Channel1')).to eq(entity) + end + end + + context 'with interface Vxlan' do + let(:entity) do + { name: 'Vxlan1', type: 'vxlan', description: '', + shutdown: false, source_interface: '', multicast_group: '', + udp_port: 4789, flood_list: [], vlans: {} } + end + + before do + node.config(['no interface Vxlan1', 'interface Vxlan1']) + end - it 'returns the interface resource' do - expect(subject.get('Loopback0')).to eq(entity) + it 'returns the interface resource' do + expect(subject.get('Vxlan1')).to eq(entity) + end end end diff --git a/spec/system/rbeapi/api/interfaces_ethernet_spec.rb b/spec/system/rbeapi/api/interfaces_ethernet_spec.rb index d8b5c5a..1940ef4 100644 --- a/spec/system/rbeapi/api/interfaces_ethernet_spec.rb +++ b/spec/system/rbeapi/api/interfaces_ethernet_spec.rb @@ -1,3 +1,4 @@ + require 'spec_helper' require 'rbeapi/client' @@ -85,6 +86,19 @@ end end + describe '#set_speed' do + before { node.config(['default interface Ethernet1']) } + + it 'sets default true' do + expect(subject.set_speed('Ethernet1', default: true)).to be_truthy + end + + it 'sets enable true' do + expect(subject.set_speed('Ethernet1', default: false, + enable: true)).to be_falsy + end + end + describe '#set_sflow' do it 'sets the sflow value to true' do node.config(['interface Ethernet1', 'no sflow enable']) diff --git a/spec/system/rbeapi/api/ospf_spec.rb b/spec/system/rbeapi/api/ospf_spec.rb index 9464c25..22c95d1 100644 --- a/spec/system/rbeapi/api/ospf_spec.rb +++ b/spec/system/rbeapi/api/ospf_spec.rb @@ -15,12 +15,13 @@ 'router ospf 1', 'router-id 1.1.1.1', 'redistribute static route-map word', - 'network 192.168.10.10/24 area 0.0.0.0']) + 'network 192.168.10.10/24 area 0.0.0.0', + 'network 192.168.11.10/24 area 0.0.0.0']) end let(:entity) do { 'router_id' => '1.1.1.1', - 'areas' => { '0.0.0.0' => ['192.168.10.0/24'] }, + 'areas' => { '0.0.0.0' => ['192.168.10.0/24', '192.168.11.0/24'] }, 'redistribute' => { 'static' => { 'route_map' => 'word' } } } end diff --git a/spec/system/rbeapi/api/snmp_spec.rb b/spec/system/rbeapi/api/snmp_spec.rb index 43763a3..7184db6 100644 --- a/spec/system/rbeapi/api/snmp_spec.rb +++ b/spec/system/rbeapi/api/snmp_spec.rb @@ -23,6 +23,30 @@ end end + describe '#set_notification' do + before { node.config(['default snmp-server']) } + + it 'configures the snmp notification value to on' do + expect(subject.set_notification(state: 'on', + name: 'bgp')).to be_truthy + expect(subject.get[:notifications][0]).to eq(name: 'bgp', + state: 'on') + end + + it 'configures the snmp notification value to off' do + expect(subject.set_notification(state: 'off', + name: 'bgp')).to be_truthy + expect(subject.get[:notifications][0]).to eq(name: 'bgp', + state: 'off') + end + + it 'configures the snmp notification value to default' do + expect(subject.set_notification(state: 'default', + name: 'all')).to be_truthy + expect(subject.get).to include(:notifications) + end + end + describe '#set_location' do before { node.config(['no snmp-server location']) } @@ -119,6 +143,47 @@ end end + describe '#add_community' do + before { node.config('no snmp-server community foo') } + + it 'adds the specified community' do + expect(subject.add_community('foo')).to be_truthy + expect(subject.get[:communities]['foo'][:access]).to eq('ro') + end + + it 'adds the specified community ro' do + expect(subject.add_community('foo', 'ro')).to be_truthy + expect(subject.get[:communities]['foo'][:access]).to eq('ro') + end + + it 'adds the specified community rw' do + expect(subject.add_community('foo', 'rw')).to be_truthy + expect(subject.get[:communities]['foo'][:access]).to eq('rw') + end + end + + describe '#remove_community' do + before { node.config('default snmp-server community foo') } + + it 'removes the specified community foo' do + expect(subject.remove_community('foo')).to be_truthy + end + end + + describe '#set_community_access' do + before { node.config('default snmp-server community foo') } + + it 'sets the community access to ro' do + expect(subject.set_community_access('foo', 'ro')).to be_truthy + expect(subject.get[:communities]['foo'][:access]).to eq('ro') + end + + it 'sets the community access to rw' do + expect(subject.set_community_access('foo', 'rw')).to be_truthy + expect(subject.get[:communities]['foo'][:access]).to eq('rw') + end + end + describe '#set_community_acl' do before do node.config(['no snmp-server community foo', diff --git a/spec/system/rbeapi/api/stp_instances_spec.rb b/spec/system/rbeapi/api/stp_instances_spec.rb index 80b47bf..3170751 100644 --- a/spec/system/rbeapi/api/stp_instances_spec.rb +++ b/spec/system/rbeapi/api/stp_instances_spec.rb @@ -65,5 +65,25 @@ expect(subject.set_priority('1', value: '4096')).to be_truthy expect(subject.get('1')[:priority]).to eq('4096') end + + it 'set the instance priority to default' do + expect(subject.set_priority('1', value: '4096', + default: true)).to be_truthy + expect(subject.get('1')[:priority]).to eq('32768') + end + + it 'set the instance priority to enable false' do + expect(subject.set_priority('1', value: '4096', + default: false, + enable: false)).to be_truthy + expect(subject.get('1')[:priority]).to eq('32768') + end + + it 'set the instance priority to enable true' do + expect(subject.set_priority('1', value: '4096', + default: false, + enable: true)).to be_truthy + expect(subject.get('1')[:priority]).to eq('4096') + end end end diff --git a/spec/system/rbeapi/api/stp_interfaces_spec.rb b/spec/system/rbeapi/api/stp_interfaces_spec.rb index 471c268..ac770ac 100644 --- a/spec/system/rbeapi/api/stp_interfaces_spec.rb +++ b/spec/system/rbeapi/api/stp_interfaces_spec.rb @@ -89,6 +89,13 @@ end describe '#set_bpduguard' do + it 'sets the bpduguard value to default true' do + node.config(['interface Ethernet1', 'no spanning-tree bpduguard']) + expect(subject.get('Ethernet1')[:bpduguard]).to be_falsy + expect(subject.set_bpduguard('Ethernet1', default: true)).to be_truthy + expect(subject.get('Ethernet1')[:bpduguard]).to be_falsey + end + it 'sets the bpduguard value to true' do node.config(['interface Ethernet1', 'no spanning-tree bpduguard']) expect(subject.get('Ethernet1')[:bpduguard]).to be_falsy diff --git a/spec/system/rbeapi/api/switchports_spec.rb b/spec/system/rbeapi/api/switchports_spec.rb index dff9316..9b209f7 100644 --- a/spec/system/rbeapi/api/switchports_spec.rb +++ b/spec/system/rbeapi/api/switchports_spec.rb @@ -16,26 +16,40 @@ [:mode, :access_vlan, :trunk_native_vlan, :trunk_allowed_vlans] end - before do - node.config(['default interface Ethernet1', 'interface Ethernet2', - 'no switchport']) - end - - it 'returns the switchport resource' do - expect(subject.get('Ethernet1')).not_to be_nil - end - - it 'does not return a nonswitchport resource' do - expect(subject.get('Ethernet2')).to be_nil - end - - it 'has all required keys' do - expect(subject.get('Ethernet1').keys).to eq(keys) - end - - it 'returns allowed_vlans as an array' do - expect(subject.get('Ethernet1')[:trunk_allowed_vlans]) - .to be_a_kind_of(Array) + context 'vlan as an integer range' do + before do + node.config(['default interface Ethernet1', 'interface Ethernet2', + 'no switchport']) + end + + it 'returns the switchport resource' do + expect(subject.get('Ethernet1')).not_to be_nil + end + + it 'does not return a nonswitchport resource' do + expect(subject.get('Ethernet2')).to be_nil + end + + it 'has all required keys' do + expect(subject.get('Ethernet1').keys).to eq(keys) + end + + it 'returns allowed_vlans as an array' do + expect(subject.get('Ethernet1')[:trunk_allowed_vlans]) + .to be_a_kind_of(Array) + end + end + + context 'vlan as an integer' do + before do + node.config(['default interface Ethernet1', + 'interface Ethernet1', + 'switchport trunk allowed vlan 1']) + end + + it 'returns the switchport resource' do + expect(subject.get('Ethernet1')).not_to be_nil + end end end diff --git a/spec/system/rbeapi/api/varp_interfaces_spec.rb b/spec/system/rbeapi/api/varp_interfaces_spec.rb index 276dae9..c161543 100644 --- a/spec/system/rbeapi/api/varp_interfaces_spec.rb +++ b/spec/system/rbeapi/api/varp_interfaces_spec.rb @@ -91,4 +91,38 @@ expect { subject.set_addresses('Vlan100') }.to raise_error ArgumentError end end + + describe '#add_address' do + before do + node.config(['ip virtual-router mac-address aabb.ccdd.eeff', + 'no interface Vlan99', 'no interface Vlan100', + 'default interface Vlan100', 'interface Vlan100', + 'ip address 99.99.99.99/24', 'exit']) + end + + it 'adds a new address to the list of addresses' do + expect(subject.get('Vlan100')[:addresses]).not_to include('99.99.99.98') + expect(subject.add_address('Vlan100', '99.99.99.98')) + .to be_truthy + expect(subject.get('Vlan100')[:addresses]).to include('99.99.99.98') + end + end + + describe '#remove_address' do + before do + node.config(['ip virtual-router mac-address aabb.ccdd.eeff', + 'no interface Vlan99', 'no interface Vlan100', + 'default interface Vlan100', 'interface Vlan100', + 'ip address 99.99.99.99/24', 'exit']) + end + + it 'removes the address from the list of addresses' do + expect(subject.add_address('Vlan100', '99.99.99.98')) + .to be_truthy + expect(subject.get('Vlan100')[:addresses]).to include('99.99.99.98') + expect(subject.remove_address('Vlan100', '99.99.99.98')) + .to be_truthy + expect(subject.get('Vlan100')[:addresses]).to eq([]) + end + end end From ebb13c33543e1f7b4619394078ff3e63a4c1e31f Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Sun, 13 Dec 2015 19:55:01 -0700 Subject: [PATCH 064/110] Working on tests for framework. --- spec/system/rbeapi/client_spec.rb | 153 ++++++++++++++++ spec/unit/rbeapi/client/default_spec.rb | 229 ++++++++++++++++++++++++ 2 files changed, 382 insertions(+) create mode 100644 spec/system/rbeapi/client_spec.rb create mode 100644 spec/unit/rbeapi/client/default_spec.rb diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb new file mode 100644 index 0000000..b4150d9 --- /dev/null +++ b/spec/system/rbeapi/client_spec.rb @@ -0,0 +1,153 @@ +require 'spec_helper' + +require 'rbeapi/client' + +describe Rbeapi::Client do + subject { described_class } + + def dut_conf + fixture_file('dut.conf') + end + + def test_conf + fixture_file('test.conf') + end + + let(:node) do + subject.config.read(fixture_file('dut.conf')) + subject.connect_to('dut') + end + + # Client class methods + describe '#connect_to' do + it 'retrieves the node config' do + expect(node).not_to be_nil + end + end + + describe '#config' do + it 'returns the currently loaded config object' do + expect(subject.config.read(dut_conf)) + .not_to be_nil + expect(subject.connect_to('dut')).not_to be_nil + end + end + + describe '#config_for' do + it 'returns the configuration options for the connection' do + expect(subject.config_for('dut')).not_to be_nil + end + end + + describe '#load_config' do + it 'overrides the default conf file loaded in the config' do + expect(subject.load_config(test_conf)) + .to eq(nil) + expect(subject.config_for('dut')).to eq(nil) + expect(subject.config_for('veos01')) + .to eq('username' => 'eapi', + 'password' => 'password', + 'transport' => 'http', + 'host' => 'veos01') + end + end + + # Config class methods + describe 'config' do + it 'gets the loaded configuration file data' do + expect(subject.config).not_to be_nil + end + end + + describe '#read' do + it 'read the specified filename and load it' do + expect(subject.config.read(dut_conf)) + .to eq(transport: 'socket') + end + end + + describe '#get_connection' do + it 'get connection dut' do + expect(subject.config.get_connection('dut')).not_to be_nil + end + end + + describe '#reload' do + it 'reloads the configuration file' do + expect(subject.config.reload(filename: [dut_conf])) + .to eq(transport: 'socket') + end + end + + describe '#add_connection' do + it 'adds a new connection section' do + expect(subject.config.add_connection('test2', + username: 'test2', + password: 'test', + transport: 'http', + host: 'test2' + )).to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') + end + end + + # Node Class Methods + describe '#running_config' do + it 'gets the nodes running config' do + expect(node.running_config).not_to be_nil + end + end + + describe '#startup_config' do + it 'gets the nodes startup-configuration' do + expect(node.startup_config).not_to be_nil + end + end + + describe '#enable_authentication' do + it 'gets the nodes startup-configuration' do + expect(node.enable_authentication('password')).to eq('password') + end + end + + describe '#config' do + it 'puts switch into config mode' do + expect(node.config(['no ip virtual-router mac-address'])).to be_truthy + end + + it 'puts switch into config mode with options' do + expect(node.config(['no ip virtual-router mac-address'], + encoding: 'json', + open_timeout: 27.00, + read_timeout: 27.00)).to be_truthy + end + end + + describe '#enable' do + it 'puts the switch into privilege mode' do + expect(node.enable('show hostname', encoding: 'text')[0]) + .to include(:command, :result, :encoding) + end + end + + describe '#run_commands' do + it 'send commands to node' do + expect(node.run_commands('show hostname', encoding: 'text')[0]) + .to include('output') + end + end + + describe '#api' do + it 'returns api module' do + expect(node.api('vlans')).not_to be_nil + end + end + + describe '#refresh' do + it 'refreshes configs for next call' do + expect(node.refresh).to eq(nil) + end + end +end diff --git a/spec/unit/rbeapi/client/default_spec.rb b/spec/unit/rbeapi/client/default_spec.rb new file mode 100644 index 0000000..817bf56 --- /dev/null +++ b/spec/unit/rbeapi/client/default_spec.rb @@ -0,0 +1,229 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' + +include FixtureHelpers + +describe Rbeapi::Client do + subject { described_class } + + let(:node) { double('node') } + + def dut_conf + fixture_file('dut.conf') + end + + def test_conf + fixture_file('test.conf') + end + + let(:dut) do + File.read(dut_conf) + end + + let(:test) do + File.read(test_conf) + end + + let(:veos01) do + { + 'username' => 'eapi', + 'password' => 'password', + 'transport' => 'http', + 'host' => 'veos01' + } + end + + # Client class methods + describe '#config_for' do + it 'returns the configuration options for the connection' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) + end + end + + describe '#connect_to' do + it 'retrieves the node config' do + expect(subject.connect_to('veos01')).to be_truthy + end + end + + describe '#load_config' do + it 'overrides the default conf file loaded in the config' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config_for('dut')).to eq(nil) + expect(subject.config_for('veos01')) + .to eq(veos01) + end + end + + # Config class methods + describe 'config' do + it 'gets the loaded configuration file data' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config.to_s).to eq(test) + end + end + + describe '#read' do + it 'read the specified filename and load it' do + expect(subject.config.read(test_conf)).to eq(nil) + end + end + + describe '#get_connection' do + it 'get connection dut' do + expect(subject.config.get_connection('veos01')).to eq(veos01) + end + end + + describe '#reload' do + it 'reloads the configuration file' do + expect(subject.config.get_connection('veos01')).to eq(veos01) + expect(subject.config.reload(filename: [dut_conf])) + .to eq(transport: 'socket') + expect(subject.config.get_connection('veos01')).to eq(nil) + end + end + + describe '#add_connection' do + it 'adds a new connection section' do + expect(subject.config.add_connection('test2', + username: 'test2', + password: 'test', + transport: 'http', + host: 'test2' + )).to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') + expect(subject.config.get_connection('test2')) + .to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') + end + end + + # Node Class Methods + describe '#running_config' do + it 'gets the nodes running config' do + allow(node).to receive(:running_config).and_return(test) + expect(node).to receive(:running_config) + expect(node.running_config.to_s).to eq(test) + end + end + + describe '#startup_config' do + it 'gets the nodes startup-configuration' do + allow(node).to receive(:startup_config).and_return(test) + expect(node).to receive(:startup_config) + expect(node.startup_config).to eq(test) + end + end + + describe '#enable_authentication' do + it 'gets the nodes startup-configuration' do + expect(node).to receive(:enable_authentication).with('newpassword') + expect(node.enable_authentication('newpassword')).to eq(nil) + end + end + + describe '#config' do + it 'puts switch into config mode' do + expect(node).to receive(:config) + .with(['no ip virtual-router mac-address']) + expect(node.config(['no ip virtual-router mac-address'])).to eq(nil) + end + + it 'puts switch into config mode with options' do + expect(node).to receive(:config) + .with(['no ip virtual-router mac-address'], + encoding: 'json', + open_timeout: 27.00, + read_timeout: 27.00) + expect(node.config(['no ip virtual-router mac-address'], + encoding: 'json', + open_timeout: 27.00, + read_timeout: 27.00)).to eq(nil) + end + end + + describe '#enable' do + it 'puts the switch into privilege mode' do + expect(node).to receive(:enable).with('show hostname', encoding: 'text') + expect(node.enable('show hostname', encoding: 'text')) + .to eq(nil) + end + end + + describe '#run_commands' do + it 'send commands to node' do + expect(node).to receive(:run_commands) + .with('show hostname', encoding: 'text') + expect(node.run_commands('show hostname', encoding: 'text')) + .to eq(nil) + end + end + + describe '#get_config' do + it 'will retrieve the specified configuration' do + expect(node).to receive(:get_config) + .with(config: 'running-config') + expect(node.get_config(config: 'running-config')) + .to eq(nil) + end + + it 'will retrieve the specified configuration with param' do + expect(node).to receive(:get_config) + .with(config: 'running-config', param: 'all') + expect(node.get_config(config: 'running-config', param: 'all')) + .to eq(nil) + end + end + + describe '#api' do + it 'returns api module' do + expect(node).to receive(:api).with('vlans') + expect(node.api('vlans')).to eq(nil) + end + end + + describe '#refresh' do + it 'refreshes configs for next call' do + expect(node).to receive(:refresh) + expect(node.refresh).to eq(nil) + end + end +end From d9ca8153768debc63dec2d1c279c4540d9285c6b Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Sun, 13 Dec 2015 20:08:20 -0700 Subject: [PATCH 065/110] Get tests passing --- spec/system/rbeapi/api/users_spec.rb | 4 ---- spec/unit/rbeapi/api/users/default_spec.rb | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/spec/system/rbeapi/api/users_spec.rb b/spec/system/rbeapi/api/users_spec.rb index 57925ca..2623cce 100644 --- a/spec/system/rbeapi/api/users_spec.rb +++ b/spec/system/rbeapi/api/users_spec.rb @@ -101,10 +101,6 @@ it 'returns a hash collection' do expect(subject.getall).to be_a_kind_of(Hash) end - - it 'has two entries' do - expect(subject.getall.size).to eq(2) - end end describe '#get' do diff --git a/spec/unit/rbeapi/api/users/default_spec.rb b/spec/unit/rbeapi/api/users/default_spec.rb index c395f67..af04395 100644 --- a/spec/unit/rbeapi/api/users/default_spec.rb +++ b/spec/unit/rbeapi/api/users/default_spec.rb @@ -96,7 +96,7 @@ def users expect(subject.getall).to be_a_kind_of(Hash) end - it 'has two entries' do + it 'has three entries' do expect(subject.getall.size).to eq(3) end end From d5e4a9bfa83b422c22a69cda6305f99cac366b72 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Sun, 13 Dec 2015 20:30:08 -0700 Subject: [PATCH 066/110] Fixture file. --- spec/fixtures/test.conf | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 spec/fixtures/test.conf diff --git a/spec/fixtures/test.conf b/spec/fixtures/test.conf new file mode 100644 index 0000000..e955d73 --- /dev/null +++ b/spec/fixtures/test.conf @@ -0,0 +1,29 @@ +[connection:veos01] +username : eapi +password : password +transport : http +host : veos01 + +[connection:veos02] +transport : http +host : veos02 + +[connection:veos03] +transport : socket +host : veos03 + +[connection:veos04] +host : 172.16.10.1 +username : eapi +password : password +enablepwd : itsasecret +port : 1234 +transport : https + +[connection: localhost] +transport : http_local +host : localhost + +[connection:localhost] +transport : socket +host : localhost From 8ae6dc9c670a22f5e656825ea196363804001a95 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 14 Dec 2015 12:06:57 -0700 Subject: [PATCH 067/110] Working on tests. --- spec/system/rbeapi/client_spec.rb | 54 ++++++++++++++++--------- spec/unit/rbeapi/client/default_spec.rb | 6 ++- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb index b4150d9..078d919 100644 --- a/spec/system/rbeapi/client_spec.rb +++ b/spec/system/rbeapi/client_spec.rb @@ -18,64 +18,80 @@ def test_conf subject.connect_to('dut') end + let(:dut) do + File.read(dut_conf) + end + + let(:test) do + File.read(test_conf) + end + + let(:veos01) do + { + 'username' => 'eapi', + 'password' => 'password', + 'transport' => 'http', + 'host' => 'veos01' + } + end + # Client class methods describe '#connect_to' do it 'retrieves the node config' do - expect(node).not_to be_nil + expect(node).to be_kind_of(Rbeapi::Client::Node) end end describe '#config' do it 'returns the currently loaded config object' do - expect(subject.config.read(dut_conf)) - .not_to be_nil - expect(subject.connect_to('dut')).not_to be_nil + expect(subject.config.read(dut_conf)).to eq(transport: 'socket') + expect(subject.connect_to('dut')).to be_kind_of(Rbeapi::Client::Node) end end describe '#config_for' do it 'returns the configuration options for the connection' do - expect(subject.config_for('dut')).not_to be_nil + expect(subject.config.read(test_conf)).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) end end describe '#load_config' do it 'overrides the default conf file loaded in the config' do - expect(subject.load_config(test_conf)) - .to eq(nil) + expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('dut')).to eq(nil) - expect(subject.config_for('veos01')) - .to eq('username' => 'eapi', - 'password' => 'password', - 'transport' => 'http', - 'host' => 'veos01') + expect(subject.config_for('veos01')).to eq(veos01) end end # Config class methods describe 'config' do it 'gets the loaded configuration file data' do - expect(subject.config).not_to be_nil + expect(subject.config.to_s).to eq(test) end end describe '#read' do it 'read the specified filename and load it' do - expect(subject.config.read(dut_conf)) - .to eq(transport: 'socket') + expect(subject.load_config(dut_conf)).to eq(transport: 'socket') + expect(subject.config.read(test_conf)).to eq(nil) + expect(subject.config.to_s).to eq(test) end end describe '#get_connection' do it 'get connection dut' do - expect(subject.config.get_connection('dut')).not_to be_nil + expect(subject.config.get_connection('veos01')).to eq(veos01) end end describe '#reload' do it 'reloads the configuration file' do - expect(subject.config.reload(filename: [dut_conf])) + expect(subject.load_config(dut_conf)) .to eq(transport: 'socket') + expect(subject.config.reload(filename: [test_conf])) + .to eq(nil) + expect(subject.config.to_s).to eq(test) end end @@ -108,7 +124,7 @@ def test_conf describe '#enable_authentication' do it 'gets the nodes startup-configuration' do - expect(node.enable_authentication('password')).to eq('password') + expect(node.enable_authentication('newpassword')).to eq('newpassword') end end @@ -141,7 +157,7 @@ def test_conf describe '#api' do it 'returns api module' do - expect(node.api('vlans')).not_to be_nil + expect(node.api('vlans')).to be_kind_of(Rbeapi::Api::Vlans) end end diff --git a/spec/unit/rbeapi/client/default_spec.rb b/spec/unit/rbeapi/client/default_spec.rb index 817bf56..03aaeda 100644 --- a/spec/unit/rbeapi/client/default_spec.rb +++ b/spec/unit/rbeapi/client/default_spec.rb @@ -83,8 +83,7 @@ def test_conf it 'overrides the default conf file loaded in the config' do expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('dut')).to eq(nil) - expect(subject.config_for('veos01')) - .to eq(veos01) + expect(subject.config_for('veos01')).to eq(veos01) end end @@ -98,7 +97,9 @@ def test_conf describe '#read' do it 'read the specified filename and load it' do + expect(subject.load_config(dut_conf)).to eq(transport: 'socket') expect(subject.config.read(test_conf)).to eq(nil) + expect(subject.config.to_s).to eq(test) end end @@ -114,6 +115,7 @@ def test_conf expect(subject.config.reload(filename: [dut_conf])) .to eq(transport: 'socket') expect(subject.config.get_connection('veos01')).to eq(nil) + expect(subject.config.get_connection('dut')).not_to be_nil end end From a79306bb881e0f44212430fee2e0cc970faa259c Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 14 Dec 2015 13:20:56 -0700 Subject: [PATCH 068/110] remove framework tests --- spec/system/rbeapi/client_spec.rb | 169 ----------------- spec/unit/rbeapi/client/default_spec.rb | 231 ------------------------ 2 files changed, 400 deletions(-) delete mode 100644 spec/system/rbeapi/client_spec.rb delete mode 100644 spec/unit/rbeapi/client/default_spec.rb diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb deleted file mode 100644 index 078d919..0000000 --- a/spec/system/rbeapi/client_spec.rb +++ /dev/null @@ -1,169 +0,0 @@ -require 'spec_helper' - -require 'rbeapi/client' - -describe Rbeapi::Client do - subject { described_class } - - def dut_conf - fixture_file('dut.conf') - end - - def test_conf - fixture_file('test.conf') - end - - let(:node) do - subject.config.read(fixture_file('dut.conf')) - subject.connect_to('dut') - end - - let(:dut) do - File.read(dut_conf) - end - - let(:test) do - File.read(test_conf) - end - - let(:veos01) do - { - 'username' => 'eapi', - 'password' => 'password', - 'transport' => 'http', - 'host' => 'veos01' - } - end - - # Client class methods - describe '#connect_to' do - it 'retrieves the node config' do - expect(node).to be_kind_of(Rbeapi::Client::Node) - end - end - - describe '#config' do - it 'returns the currently loaded config object' do - expect(subject.config.read(dut_conf)).to eq(transport: 'socket') - expect(subject.connect_to('dut')).to be_kind_of(Rbeapi::Client::Node) - end - end - - describe '#config_for' do - it 'returns the configuration options for the connection' do - expect(subject.config.read(test_conf)).to eq(nil) - expect(subject.config_for('veos01')).to eq(veos01) - end - end - - describe '#load_config' do - it 'overrides the default conf file loaded in the config' do - expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config_for('dut')).to eq(nil) - expect(subject.config_for('veos01')).to eq(veos01) - end - end - - # Config class methods - describe 'config' do - it 'gets the loaded configuration file data' do - expect(subject.config.to_s).to eq(test) - end - end - - describe '#read' do - it 'read the specified filename and load it' do - expect(subject.load_config(dut_conf)).to eq(transport: 'socket') - expect(subject.config.read(test_conf)).to eq(nil) - expect(subject.config.to_s).to eq(test) - end - end - - describe '#get_connection' do - it 'get connection dut' do - expect(subject.config.get_connection('veos01')).to eq(veos01) - end - end - - describe '#reload' do - it 'reloads the configuration file' do - expect(subject.load_config(dut_conf)) - .to eq(transport: 'socket') - expect(subject.config.reload(filename: [test_conf])) - .to eq(nil) - expect(subject.config.to_s).to eq(test) - end - end - - describe '#add_connection' do - it 'adds a new connection section' do - expect(subject.config.add_connection('test2', - username: 'test2', - password: 'test', - transport: 'http', - host: 'test2' - )).to eq(username: 'test2', - password: 'test', - transport: 'http', - host: 'test2') - end - end - - # Node Class Methods - describe '#running_config' do - it 'gets the nodes running config' do - expect(node.running_config).not_to be_nil - end - end - - describe '#startup_config' do - it 'gets the nodes startup-configuration' do - expect(node.startup_config).not_to be_nil - end - end - - describe '#enable_authentication' do - it 'gets the nodes startup-configuration' do - expect(node.enable_authentication('newpassword')).to eq('newpassword') - end - end - - describe '#config' do - it 'puts switch into config mode' do - expect(node.config(['no ip virtual-router mac-address'])).to be_truthy - end - - it 'puts switch into config mode with options' do - expect(node.config(['no ip virtual-router mac-address'], - encoding: 'json', - open_timeout: 27.00, - read_timeout: 27.00)).to be_truthy - end - end - - describe '#enable' do - it 'puts the switch into privilege mode' do - expect(node.enable('show hostname', encoding: 'text')[0]) - .to include(:command, :result, :encoding) - end - end - - describe '#run_commands' do - it 'send commands to node' do - expect(node.run_commands('show hostname', encoding: 'text')[0]) - .to include('output') - end - end - - describe '#api' do - it 'returns api module' do - expect(node.api('vlans')).to be_kind_of(Rbeapi::Api::Vlans) - end - end - - describe '#refresh' do - it 'refreshes configs for next call' do - expect(node.refresh).to eq(nil) - end - end -end diff --git a/spec/unit/rbeapi/client/default_spec.rb b/spec/unit/rbeapi/client/default_spec.rb deleted file mode 100644 index 03aaeda..0000000 --- a/spec/unit/rbeapi/client/default_spec.rb +++ /dev/null @@ -1,231 +0,0 @@ -# -# Copyright (c) 2015, Arista Networks, Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# Neither the name of Arista Networks nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -require 'spec_helper' - -require 'rbeapi/client' - -include FixtureHelpers - -describe Rbeapi::Client do - subject { described_class } - - let(:node) { double('node') } - - def dut_conf - fixture_file('dut.conf') - end - - def test_conf - fixture_file('test.conf') - end - - let(:dut) do - File.read(dut_conf) - end - - let(:test) do - File.read(test_conf) - end - - let(:veos01) do - { - 'username' => 'eapi', - 'password' => 'password', - 'transport' => 'http', - 'host' => 'veos01' - } - end - - # Client class methods - describe '#config_for' do - it 'returns the configuration options for the connection' do - expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config_for('veos01')).to eq(veos01) - end - end - - describe '#connect_to' do - it 'retrieves the node config' do - expect(subject.connect_to('veos01')).to be_truthy - end - end - - describe '#load_config' do - it 'overrides the default conf file loaded in the config' do - expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config_for('dut')).to eq(nil) - expect(subject.config_for('veos01')).to eq(veos01) - end - end - - # Config class methods - describe 'config' do - it 'gets the loaded configuration file data' do - expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config.to_s).to eq(test) - end - end - - describe '#read' do - it 'read the specified filename and load it' do - expect(subject.load_config(dut_conf)).to eq(transport: 'socket') - expect(subject.config.read(test_conf)).to eq(nil) - expect(subject.config.to_s).to eq(test) - end - end - - describe '#get_connection' do - it 'get connection dut' do - expect(subject.config.get_connection('veos01')).to eq(veos01) - end - end - - describe '#reload' do - it 'reloads the configuration file' do - expect(subject.config.get_connection('veos01')).to eq(veos01) - expect(subject.config.reload(filename: [dut_conf])) - .to eq(transport: 'socket') - expect(subject.config.get_connection('veos01')).to eq(nil) - expect(subject.config.get_connection('dut')).not_to be_nil - end - end - - describe '#add_connection' do - it 'adds a new connection section' do - expect(subject.config.add_connection('test2', - username: 'test2', - password: 'test', - transport: 'http', - host: 'test2' - )).to eq(username: 'test2', - password: 'test', - transport: 'http', - host: 'test2') - expect(subject.config.get_connection('test2')) - .to eq(username: 'test2', - password: 'test', - transport: 'http', - host: 'test2') - end - end - - # Node Class Methods - describe '#running_config' do - it 'gets the nodes running config' do - allow(node).to receive(:running_config).and_return(test) - expect(node).to receive(:running_config) - expect(node.running_config.to_s).to eq(test) - end - end - - describe '#startup_config' do - it 'gets the nodes startup-configuration' do - allow(node).to receive(:startup_config).and_return(test) - expect(node).to receive(:startup_config) - expect(node.startup_config).to eq(test) - end - end - - describe '#enable_authentication' do - it 'gets the nodes startup-configuration' do - expect(node).to receive(:enable_authentication).with('newpassword') - expect(node.enable_authentication('newpassword')).to eq(nil) - end - end - - describe '#config' do - it 'puts switch into config mode' do - expect(node).to receive(:config) - .with(['no ip virtual-router mac-address']) - expect(node.config(['no ip virtual-router mac-address'])).to eq(nil) - end - - it 'puts switch into config mode with options' do - expect(node).to receive(:config) - .with(['no ip virtual-router mac-address'], - encoding: 'json', - open_timeout: 27.00, - read_timeout: 27.00) - expect(node.config(['no ip virtual-router mac-address'], - encoding: 'json', - open_timeout: 27.00, - read_timeout: 27.00)).to eq(nil) - end - end - - describe '#enable' do - it 'puts the switch into privilege mode' do - expect(node).to receive(:enable).with('show hostname', encoding: 'text') - expect(node.enable('show hostname', encoding: 'text')) - .to eq(nil) - end - end - - describe '#run_commands' do - it 'send commands to node' do - expect(node).to receive(:run_commands) - .with('show hostname', encoding: 'text') - expect(node.run_commands('show hostname', encoding: 'text')) - .to eq(nil) - end - end - - describe '#get_config' do - it 'will retrieve the specified configuration' do - expect(node).to receive(:get_config) - .with(config: 'running-config') - expect(node.get_config(config: 'running-config')) - .to eq(nil) - end - - it 'will retrieve the specified configuration with param' do - expect(node).to receive(:get_config) - .with(config: 'running-config', param: 'all') - expect(node.get_config(config: 'running-config', param: 'all')) - .to eq(nil) - end - end - - describe '#api' do - it 'returns api module' do - expect(node).to receive(:api).with('vlans') - expect(node.api('vlans')).to eq(nil) - end - end - - describe '#refresh' do - it 'refreshes configs for next call' do - expect(node).to receive(:refresh) - expect(node.refresh).to eq(nil) - end - end -end From 073ad05d346c9d1ee82b136ee998cef700048e30 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 14 Dec 2015 13:30:46 -0700 Subject: [PATCH 069/110] update git ignore and remove fixture file. --- .gitignore | 3 +++ spec/fixtures/test.conf | 29 ----------------------------- 2 files changed, 3 insertions(+), 29 deletions(-) delete mode 100644 spec/fixtures/test.conf diff --git a/.gitignore b/.gitignore index 0a1085b..c9d4a6e 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,6 @@ Gemfile.lock rpmbuild rpms *.spec + +# Other +/spec/fixtures/dut.conf diff --git a/spec/fixtures/test.conf b/spec/fixtures/test.conf deleted file mode 100644 index e955d73..0000000 --- a/spec/fixtures/test.conf +++ /dev/null @@ -1,29 +0,0 @@ -[connection:veos01] -username : eapi -password : password -transport : http -host : veos01 - -[connection:veos02] -transport : http -host : veos02 - -[connection:veos03] -transport : socket -host : veos03 - -[connection:veos04] -host : 172.16.10.1 -username : eapi -password : password -enablepwd : itsasecret -port : 1234 -transport : https - -[connection: localhost] -transport : http_local -host : localhost - -[connection:localhost] -transport : socket -host : localhost From f8d9516b40d1ade3ceed6347177bd137d0667bdb Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 14 Dec 2015 13:45:11 -0700 Subject: [PATCH 070/110] Add basic framework tests. --- spec/fixtures/test.conf | 29 +++ spec/system/rbeapi/client_spec.rb | 169 +++++++++++++++++ spec/unit/rbeapi/client/default_spec.rb | 231 ++++++++++++++++++++++++ 3 files changed, 429 insertions(+) create mode 100644 spec/fixtures/test.conf create mode 100644 spec/system/rbeapi/client_spec.rb create mode 100644 spec/unit/rbeapi/client/default_spec.rb diff --git a/spec/fixtures/test.conf b/spec/fixtures/test.conf new file mode 100644 index 0000000..e955d73 --- /dev/null +++ b/spec/fixtures/test.conf @@ -0,0 +1,29 @@ +[connection:veos01] +username : eapi +password : password +transport : http +host : veos01 + +[connection:veos02] +transport : http +host : veos02 + +[connection:veos03] +transport : socket +host : veos03 + +[connection:veos04] +host : 172.16.10.1 +username : eapi +password : password +enablepwd : itsasecret +port : 1234 +transport : https + +[connection: localhost] +transport : http_local +host : localhost + +[connection:localhost] +transport : socket +host : localhost diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb new file mode 100644 index 0000000..078d919 --- /dev/null +++ b/spec/system/rbeapi/client_spec.rb @@ -0,0 +1,169 @@ +require 'spec_helper' + +require 'rbeapi/client' + +describe Rbeapi::Client do + subject { described_class } + + def dut_conf + fixture_file('dut.conf') + end + + def test_conf + fixture_file('test.conf') + end + + let(:node) do + subject.config.read(fixture_file('dut.conf')) + subject.connect_to('dut') + end + + let(:dut) do + File.read(dut_conf) + end + + let(:test) do + File.read(test_conf) + end + + let(:veos01) do + { + 'username' => 'eapi', + 'password' => 'password', + 'transport' => 'http', + 'host' => 'veos01' + } + end + + # Client class methods + describe '#connect_to' do + it 'retrieves the node config' do + expect(node).to be_kind_of(Rbeapi::Client::Node) + end + end + + describe '#config' do + it 'returns the currently loaded config object' do + expect(subject.config.read(dut_conf)).to eq(transport: 'socket') + expect(subject.connect_to('dut')).to be_kind_of(Rbeapi::Client::Node) + end + end + + describe '#config_for' do + it 'returns the configuration options for the connection' do + expect(subject.config.read(test_conf)).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) + end + end + + describe '#load_config' do + it 'overrides the default conf file loaded in the config' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config_for('dut')).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) + end + end + + # Config class methods + describe 'config' do + it 'gets the loaded configuration file data' do + expect(subject.config.to_s).to eq(test) + end + end + + describe '#read' do + it 'read the specified filename and load it' do + expect(subject.load_config(dut_conf)).to eq(transport: 'socket') + expect(subject.config.read(test_conf)).to eq(nil) + expect(subject.config.to_s).to eq(test) + end + end + + describe '#get_connection' do + it 'get connection dut' do + expect(subject.config.get_connection('veos01')).to eq(veos01) + end + end + + describe '#reload' do + it 'reloads the configuration file' do + expect(subject.load_config(dut_conf)) + .to eq(transport: 'socket') + expect(subject.config.reload(filename: [test_conf])) + .to eq(nil) + expect(subject.config.to_s).to eq(test) + end + end + + describe '#add_connection' do + it 'adds a new connection section' do + expect(subject.config.add_connection('test2', + username: 'test2', + password: 'test', + transport: 'http', + host: 'test2' + )).to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') + end + end + + # Node Class Methods + describe '#running_config' do + it 'gets the nodes running config' do + expect(node.running_config).not_to be_nil + end + end + + describe '#startup_config' do + it 'gets the nodes startup-configuration' do + expect(node.startup_config).not_to be_nil + end + end + + describe '#enable_authentication' do + it 'gets the nodes startup-configuration' do + expect(node.enable_authentication('newpassword')).to eq('newpassword') + end + end + + describe '#config' do + it 'puts switch into config mode' do + expect(node.config(['no ip virtual-router mac-address'])).to be_truthy + end + + it 'puts switch into config mode with options' do + expect(node.config(['no ip virtual-router mac-address'], + encoding: 'json', + open_timeout: 27.00, + read_timeout: 27.00)).to be_truthy + end + end + + describe '#enable' do + it 'puts the switch into privilege mode' do + expect(node.enable('show hostname', encoding: 'text')[0]) + .to include(:command, :result, :encoding) + end + end + + describe '#run_commands' do + it 'send commands to node' do + expect(node.run_commands('show hostname', encoding: 'text')[0]) + .to include('output') + end + end + + describe '#api' do + it 'returns api module' do + expect(node.api('vlans')).to be_kind_of(Rbeapi::Api::Vlans) + end + end + + describe '#refresh' do + it 'refreshes configs for next call' do + expect(node.refresh).to eq(nil) + end + end +end diff --git a/spec/unit/rbeapi/client/default_spec.rb b/spec/unit/rbeapi/client/default_spec.rb new file mode 100644 index 0000000..03aaeda --- /dev/null +++ b/spec/unit/rbeapi/client/default_spec.rb @@ -0,0 +1,231 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' + +include FixtureHelpers + +describe Rbeapi::Client do + subject { described_class } + + let(:node) { double('node') } + + def dut_conf + fixture_file('dut.conf') + end + + def test_conf + fixture_file('test.conf') + end + + let(:dut) do + File.read(dut_conf) + end + + let(:test) do + File.read(test_conf) + end + + let(:veos01) do + { + 'username' => 'eapi', + 'password' => 'password', + 'transport' => 'http', + 'host' => 'veos01' + } + end + + # Client class methods + describe '#config_for' do + it 'returns the configuration options for the connection' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) + end + end + + describe '#connect_to' do + it 'retrieves the node config' do + expect(subject.connect_to('veos01')).to be_truthy + end + end + + describe '#load_config' do + it 'overrides the default conf file loaded in the config' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config_for('dut')).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) + end + end + + # Config class methods + describe 'config' do + it 'gets the loaded configuration file data' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config.to_s).to eq(test) + end + end + + describe '#read' do + it 'read the specified filename and load it' do + expect(subject.load_config(dut_conf)).to eq(transport: 'socket') + expect(subject.config.read(test_conf)).to eq(nil) + expect(subject.config.to_s).to eq(test) + end + end + + describe '#get_connection' do + it 'get connection dut' do + expect(subject.config.get_connection('veos01')).to eq(veos01) + end + end + + describe '#reload' do + it 'reloads the configuration file' do + expect(subject.config.get_connection('veos01')).to eq(veos01) + expect(subject.config.reload(filename: [dut_conf])) + .to eq(transport: 'socket') + expect(subject.config.get_connection('veos01')).to eq(nil) + expect(subject.config.get_connection('dut')).not_to be_nil + end + end + + describe '#add_connection' do + it 'adds a new connection section' do + expect(subject.config.add_connection('test2', + username: 'test2', + password: 'test', + transport: 'http', + host: 'test2' + )).to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') + expect(subject.config.get_connection('test2')) + .to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') + end + end + + # Node Class Methods + describe '#running_config' do + it 'gets the nodes running config' do + allow(node).to receive(:running_config).and_return(test) + expect(node).to receive(:running_config) + expect(node.running_config.to_s).to eq(test) + end + end + + describe '#startup_config' do + it 'gets the nodes startup-configuration' do + allow(node).to receive(:startup_config).and_return(test) + expect(node).to receive(:startup_config) + expect(node.startup_config).to eq(test) + end + end + + describe '#enable_authentication' do + it 'gets the nodes startup-configuration' do + expect(node).to receive(:enable_authentication).with('newpassword') + expect(node.enable_authentication('newpassword')).to eq(nil) + end + end + + describe '#config' do + it 'puts switch into config mode' do + expect(node).to receive(:config) + .with(['no ip virtual-router mac-address']) + expect(node.config(['no ip virtual-router mac-address'])).to eq(nil) + end + + it 'puts switch into config mode with options' do + expect(node).to receive(:config) + .with(['no ip virtual-router mac-address'], + encoding: 'json', + open_timeout: 27.00, + read_timeout: 27.00) + expect(node.config(['no ip virtual-router mac-address'], + encoding: 'json', + open_timeout: 27.00, + read_timeout: 27.00)).to eq(nil) + end + end + + describe '#enable' do + it 'puts the switch into privilege mode' do + expect(node).to receive(:enable).with('show hostname', encoding: 'text') + expect(node.enable('show hostname', encoding: 'text')) + .to eq(nil) + end + end + + describe '#run_commands' do + it 'send commands to node' do + expect(node).to receive(:run_commands) + .with('show hostname', encoding: 'text') + expect(node.run_commands('show hostname', encoding: 'text')) + .to eq(nil) + end + end + + describe '#get_config' do + it 'will retrieve the specified configuration' do + expect(node).to receive(:get_config) + .with(config: 'running-config') + expect(node.get_config(config: 'running-config')) + .to eq(nil) + end + + it 'will retrieve the specified configuration with param' do + expect(node).to receive(:get_config) + .with(config: 'running-config', param: 'all') + expect(node.get_config(config: 'running-config', param: 'all')) + .to eq(nil) + end + end + + describe '#api' do + it 'returns api module' do + expect(node).to receive(:api).with('vlans') + expect(node.api('vlans')).to eq(nil) + end + end + + describe '#refresh' do + it 'refreshes configs for next call' do + expect(node).to receive(:refresh) + expect(node.refresh).to eq(nil) + end + end +end From ece07010b021a62eb6adee8e3659c761937e3591 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Sat, 19 Dec 2015 13:43:50 -0700 Subject: [PATCH 071/110] Add Aaa tests --- spec/system/rbeapi/api/aaa_groups_spec.rb | 122 ++++++++++++++++++++ spec/system/rbeapi/api/aaa_spec.rb | 90 +++++++++++++++ spec/unit/rbeapi/api/aaa/aaa_groups_spec.rb | 111 ++++++++++++++++++ spec/unit/rbeapi/api/aaa/aaa_spec.rb | 77 ++++++++++++ spec/unit/rbeapi/api/aaa/fixture_aaa.text | 3 + 5 files changed, 403 insertions(+) create mode 100644 spec/system/rbeapi/api/aaa_groups_spec.rb create mode 100644 spec/system/rbeapi/api/aaa_spec.rb create mode 100644 spec/unit/rbeapi/api/aaa/aaa_groups_spec.rb create mode 100644 spec/unit/rbeapi/api/aaa/aaa_spec.rb create mode 100644 spec/unit/rbeapi/api/aaa/fixture_aaa.text diff --git a/spec/system/rbeapi/api/aaa_groups_spec.rb b/spec/system/rbeapi/api/aaa_groups_spec.rb new file mode 100644 index 0000000..0eb9a61 --- /dev/null +++ b/spec/system/rbeapi/api/aaa_groups_spec.rb @@ -0,0 +1,122 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' +require 'rbeapi/api/aaa' + +describe Rbeapi::Api::AaaGroups do + subject { described_class.new(node) } + + let(:node) do + Rbeapi::Client.config.read(fixture_file('dut.conf')) + Rbeapi::Client.connect_to('dut') + end + + let(:all) do + { + 'blah' => { + type: 'radius', + servers: [] + }, + 'blahtwo' => { + type: 'radius', + servers: [] + } + } + end + + let(:blah) do + { + type: 'radius', + servers: [] + } + end + + let(:blahthree) do + { + type: 'tacacs+', + servers: [] + } + end + + let(:servers) do + [{ + name: 'localhost', + auth_port: '1812', + acct_port: '1813' + }] + end + + describe '#get' do + before do + node.config(['no aaa group server radius blah', + 'no aaa group server radius blahtwo', + 'no aaa group server tacacs+ blahthree', + 'aaa group server radius blah', 'exit', + 'aaa group server radius blahtwo', 'exit']) + end + + it 'returns the resource for given name' do + expect(subject.get('blah')).to eq(blah) + end + end + + describe '#getall' do + it 'returns all of the aaa group resources' do + expect(subject.getall).to eq(all) + end + end + + describe '#create' do + it 'adds a new aaa group' do + expect(subject.create('blahthree', 'tacacs+')).to eq(true) + expect(subject.get('blahthree')).to eq(blahthree) + end + end + + describe '#delete' do + it 'removes specified aaa group' do + expect(subject.get('blahthree')).to eq(blahthree) + expect(subject.delete('blahthree')).to eq(true) + expect(subject.get('blahthree')).to eq(nil) + end + end + + describe '#set_servers' do + it 'removes all servers and then adds one' do + expect(subject.set_servers('blahtwo', [{ name: 'localhost' }])) + .to eq(true) + expect(subject.get('blahtwo')[:servers]).to eq(servers) + end + end +end diff --git a/spec/system/rbeapi/api/aaa_spec.rb b/spec/system/rbeapi/api/aaa_spec.rb new file mode 100644 index 0000000..3b37571 --- /dev/null +++ b/spec/system/rbeapi/api/aaa_spec.rb @@ -0,0 +1,90 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' +require 'rbeapi/api/aaa' + +describe Rbeapi::Api::Aaa do + subject { described_class.new(node) } + + let(:node) do + Rbeapi::Client.config.read(fixture_file('dut.conf')) + Rbeapi::Client.connect_to('dut') + end + + let(:test) do + { + groups: { + 'blah' => { + type: 'radius', + servers: [] + }, + 'blahtwo' => { + type: 'radius', + servers: [] + } + } + } + end + + describe '#get' do + before do + node.config(['no aaa group server radius blah', + 'no aaa group server radius blahtwo', + 'aaa group server radius blah', 'exit', + 'aaa group server radius blahtwo', 'exit']) + end + + it 'returns the resource for given name' do + expect(subject.get).to eq(test) + end + + it 'returns a hash' do + expect(subject.get).to be_a_kind_of(Hash) + end + + it 'has two entries' do + expect(subject.get[:groups].size).to eq(2) + end + end + + describe '#groups' do + it 'returns new node instance' do + expect(subject.groups).to be_a_kind_of(Rbeapi::Api::AaaGroups) + end + + it 'returns a hash' do + expect(subject.groups).to be_a_kind_of(Object) + end + end +end diff --git a/spec/unit/rbeapi/api/aaa/aaa_groups_spec.rb b/spec/unit/rbeapi/api/aaa/aaa_groups_spec.rb new file mode 100644 index 0000000..ba41189 --- /dev/null +++ b/spec/unit/rbeapi/api/aaa/aaa_groups_spec.rb @@ -0,0 +1,111 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/api/aaa' + +include FixtureHelpers + +describe Rbeapi::Api::AaaGroups do + subject { described_class.new(node) } + + let(:node) { double('node') } + + let(:all) do + { + 'blah' => { + type: 'radius', + servers: [] + } + } + end + + let(:blah) do + { + type: 'radius', + servers: [] + } + end + + let(:blahthree) do + { + type: 'tacacs+', + servers: [] + } + end + + def aaa + aaa = Fixtures[:aaa] + return aaa if aaa + fixture('aaa', format: :text, dir: File.dirname(__FILE__)) + end + + before :each do + allow(subject.node).to receive(:running_config).and_return(aaa) + end + + describe '#get' do + it 'returns the resource for given name' do + expect(subject.get('blah')).to eq(blah) + end + end + + describe '#getall' do + it 'returns all of the aaa group resources' do + expect(subject.getall).to eq(all) + end + end + + describe '#create' do + it 'adds a new aaa group' do + expect(node).to receive(:config) + .with(['aaa group server tacacs+ blahthree', 'exit']) + expect(subject.create('blahthree', 'tacacs+')).to eq(true) + end + end + + describe '#delete' do + it 'removes specified aaa group' do + expect(subject.delete('blahthree')).to eq(true) + expect(subject.get('blahthree')).to eq(nil) + end + end + + describe '#set_servers' do + it 'removes all servers and then adds one' do + expect(node).to receive(:config) + .with(['aaa group server radius blah', 'server localhost ', 'exit']) + expect(subject.set_servers('blah', [{ name: 'localhost' }])) + .to eq(true) + end + end +end diff --git a/spec/unit/rbeapi/api/aaa/aaa_spec.rb b/spec/unit/rbeapi/api/aaa/aaa_spec.rb new file mode 100644 index 0000000..090bc71 --- /dev/null +++ b/spec/unit/rbeapi/api/aaa/aaa_spec.rb @@ -0,0 +1,77 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/api/aaa' + +include FixtureHelpers + +describe Rbeapi::Api::Aaa do + subject { described_class.new(node) } + + let(:node) { double('node') } + + let(:test) do + { + groups: { + 'blah' => { + type: 'radius', + servers: [] + } + } + } + end + + def aaa + aaa = Fixtures[:aaa] + return aaa if aaa + fixture('aaa', format: :text, dir: File.dirname(__FILE__)) + end + + before :each do + allow(subject.node).to receive(:running_config).and_return(aaa) + end + + describe '#get' do + it 'returns the resource for given name' do + expect(subject.get).to eq(test) + end + + it 'returns a hash' do + expect(subject.get).to be_a_kind_of(Hash) + end + + it 'has two entries' do + expect(subject.get.size).to eq(1) + end + end +end diff --git a/spec/unit/rbeapi/api/aaa/fixture_aaa.text b/spec/unit/rbeapi/api/aaa/fixture_aaa.text new file mode 100644 index 0000000..78b8bd2 --- /dev/null +++ b/spec/unit/rbeapi/api/aaa/fixture_aaa.text @@ -0,0 +1,3 @@ +aaa group server radius blah +no aaa root +aaa authentication policy local allow-nopassword-remote-login \ No newline at end of file From 27689d09a0aa162d63fbd29018afbbc3f17b2cfc Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Tue, 22 Dec 2015 09:22:20 -0700 Subject: [PATCH 072/110] Shorten config block in bgp test. --- spec/system/rbeapi/api/bgp_spec.rb | 128 ++++------------------------- 1 file changed, 14 insertions(+), 114 deletions(-) diff --git a/spec/system/rbeapi/api/bgp_spec.rb b/spec/system/rbeapi/api/bgp_spec.rb index 063c11c..d04078a 100644 --- a/spec/system/rbeapi/api/bgp_spec.rb +++ b/spec/system/rbeapi/api/bgp_spec.rb @@ -72,105 +72,29 @@ } end + let(:response) do + { + bgp_as: '1000', + router_id: nil, + shutdown: false, + maximum_paths: 1, + maximum_ecmp_paths: 128, + networks: [], + neighbors: {} + } + end + describe '#get' do before do node.config(['no router bgp 64600', 'router bgp 64600', - 'no shutdown', - 'router-id 192.168.254.1', - 'bgp convergence time 300', - 'bgp convergence slow-peer time 90', - 'no bgp confederation identifier', - 'no update wait-for-convergence', - 'no update wait-install', - 'bgp log-neighbor-changes', - 'bgp default ipv4-unicast', - 'no bgp default ipv6-unicast', - 'timers bgp 60 180', - 'distance bgp 20 200 200', - 'graceful-restart stalepath-time 300', - 'no bgp cluster-id', - 'bgp client-to-client reflection', - 'graceful-restart-helper', - 'bgp peer-mac-resolution-timeout 0', - 'bgp enforce-first-as', - 'no default-metric', - 'no bgp always-compare-med', - 'no bgp bestpath med missing-as-worst', - 'no bgp bestpath med confed', - 'no bgp host-routes fib direct-install', - 'maximum-paths 32 ecmp 32', - 'bgp listen limit 1000', - 'no bgp aspath-cmp-include-nexthop', - 'no bgp tie-break-on-age', - 'no bgp tie-break-on-router-id', - 'no bgp tie-break-on-originator-id', - 'no bgp tie-break-on-cluster-list-length', - 'neighbor eBGP_GROUP peer-group', - 'no neighbor eBGP_GROUP remote-as', - 'no neighbor eBGP_GROUP import-localpref', - 'no neighbor eBGP_GROUP export-localpref', - 'no neighbor eBGP_GROUP description', - 'no neighbor eBGP_GROUP next-hop-self', - 'no neighbor eBGP_GROUP next-hop-peer', - 'no neighbor eBGP_GROUP allowas-in', - 'no neighbor eBGP_GROUP send-community', - 'no neighbor eBGP_GROUP shutdown', - 'no neighbor eBGP_GROUP remove-private-as', - 'no neighbor eBGP_GROUP out-delay', - 'no neighbor eBGP_GROUP local-as', - 'no neighbor eBGP_GROUP weight', - 'no neighbor eBGP_GROUP transport connection-mode passive', - 'no neighbor eBGP_GROUP update-source', - 'no neighbor eBGP_GROUP dont-capability-negotiate', - 'neighbor eBGP_GROUP fall-over bfd', - 'no neighbor eBGP_GROUP local-v6-addr', - 'neighbor eBGP_GROUP soft-reconfiguration inbound', - 'no neighbor eBGP_GROUP ebgp-multihop', - 'no neighbor eBGP_GROUP route-reflector-client', - 'no neighbor eBGP_GROUP timers', - 'no neighbor eBGP_GROUP route-map in', - 'neighbor eBGP_GROUP graceful-restart-helper', - 'no neighbor eBGP_GROUP route-map out', - 'no neighbor eBGP_GROUP prefix-list in', - 'no neighbor eBGP_GROUP prefix-list out', - 'neighbor eBGP_GROUP password 7 6C/HkrwJ53+dsHumQf49Wg==', - 'no neighbor eBGP_GROUP default-originate', - 'neighbor eBGP_GROUP enforce-first-as', - 'no neighbor eBGP_GROUP metric-out', - 'neighbor eBGP_GROUP maximum-routes 12000', + 'router-id 192.168.254.1', 'maximum-paths 32 ecmp 32', 'neighbor 192.168.255.1 peer-group eBGP_GROUP', 'neighbor 192.168.255.1 remote-as 65000', 'neighbor 192.168.255.3 peer-group eBGP_GROUP', 'neighbor 192.168.255.3 remote-as 65001', 'network 192.168.254.1/32', 'network 192.168.254.2/32 route-map rmap', - 'bgp redistribute-internal', - 'aggregate-address 192.168.255.0/28 summary-only', - 'no redistribute connected', - 'no redistribute ospf match internal', - 'no redistribute ospf match external', - 'no redistribute ospf match nssa-external', - 'no redistribute ospf3 match internal', - 'no redistribute ospf3 match external', - 'no redistribute static', - 'no redistribute rip', - 'no redistribute aggregate', - 'address-family ipv4', - 'default neighbor eBGP_GROUP activate', - 'no neighbor eBGP_GROUP route-map in', - 'no neighbor eBGP_GROUP route-map out', - 'no neighbor eBGP_GROUP default-originate', - 'default neighbor 192.168.255.1 activate', - 'default neighbor 192.168.255.3 activate', - 'address-family ipv6', - 'default neighbor eBGP_GROUP activate', - 'no neighbor eBGP_GROUP route-map in', - 'no neighbor eBGP_GROUP route-map out', - 'no neighbor eBGP_GROUP prefix-list in', - 'no neighbor eBGP_GROUP prefix-list out', - 'no neighbor eBGP_GROUP default-originate', - 'default neighbor 192.168.255.1 activate', - 'default neighbor 192.168.255.3 activate']) + 'aggregate-address 192.168.255.0/28 summary-only']) end it 'returns the BGP resource' do @@ -179,18 +103,6 @@ end describe '#create' do - let(:response) do - { - bgp_as: '1000', - router_id: nil, - shutdown: false, - maximum_paths: 1, - maximum_ecmp_paths: 128, - networks: [], - neighbors: {} - } - end - before do node.config(['no router bgp 64600']) end @@ -247,18 +159,6 @@ node.config(['no router bgp 1000', 'router bgp 1000']) end - let(:response) do - { - bgp_as: '1000', - router_id: nil, - shutdown: false, - maximum_paths: 1, - maximum_ecmp_paths: 128, - networks: [], - neighbors: {} - } - end - it 'delete a BGP resource' do expect(subject.get).to eq(response) expect(subject.delete).to be_truthy From c7a07f9f05f68067265e7657a8b1bc1c95b8fa5d Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Tue, 22 Dec 2015 16:28:55 -0700 Subject: [PATCH 073/110] Checking in. --- lib/rbeapi/api/aaa.rb | 42 ++++++++++++++++++++++------------ lib/rbeapi/api/acl.rb | 2 +- lib/rbeapi/api/dns.rb | 2 +- lib/rbeapi/api/interfaces.rb | 2 +- lib/rbeapi/api/ipinterfaces.rb | 2 +- lib/rbeapi/api/logging.rb | 2 +- lib/rbeapi/api/mlag.rb | 2 +- lib/rbeapi/api/ntp.rb | 4 ++-- lib/rbeapi/api/ospf.rb | 2 +- lib/rbeapi/api/prefixlists.rb | 2 +- lib/rbeapi/api/radius.rb | 2 +- lib/rbeapi/api/routemaps.rb | 2 +- lib/rbeapi/api/snmp.rb | 2 +- lib/rbeapi/api/staticroutes.rb | 2 +- lib/rbeapi/api/stp.rb | 2 +- lib/rbeapi/api/switchports.rb | 2 +- lib/rbeapi/api/system.rb | 2 +- lib/rbeapi/api/tacacs.rb | 2 +- lib/rbeapi/api/users.rb | 2 +- lib/rbeapi/api/varp.rb | 2 +- lib/rbeapi/api/vlans.rb | 2 +- lib/rbeapi/api/vrrp.rb | 2 +- 22 files changed, 50 insertions(+), 36 deletions(-) diff --git a/lib/rbeapi/api/aaa.rb b/lib/rbeapi/api/aaa.rb index f6289c7..5392136 100644 --- a/lib/rbeapi/api/aaa.rb +++ b/lib/rbeapi/api/aaa.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Aaa class manages Authorization, Authentication and Accounting (AAA) @@ -47,6 +47,8 @@ def get response end + ## + # Returns an object node for working with AaaGroups class. def groups return @groups if @groups @groups = AaaGroups.new node @@ -55,20 +57,20 @@ def groups end ## - # The AaaGroups class manages the server groups on a EOS node. + # The AaaGroups class manages the server groups on an EOS node. class AaaGroups < Entity DEFAULT_RADIUS_AUTH_PORT = 1812 DEFAULT_RADIUS_ACCT_PORT = 1813 - # Regular express that parses the radius servers from the aaa group - # server radius configuration block + # Regular expression that parses the radius servers from the aaa group + # server radius configuration block. RADIUS_GROUP_SERVER = /\s{3}server [ ]([^\s]+) [ ]auth-port[ ](\d+) [ ]acct-port[ ](\d+)/x - # Regular expression that parse the tacacs servers from the aaa group - # server tacacs+ configuration block + # Regular expression that parses the tacacs servers from the aaa group + # server tacacs+ configuration block. TACACS_GROUP_SERVER = /\s{3}server [ ]([^\s]+) (?:[ ]vrf[ ](\w+))? @@ -76,20 +78,20 @@ class AaaGroups < Entity ## # get returns the aaa server group resource hash that describes the - # current configuration for the specified server group name + # current configuration for the specified server group name. # # The resource hash returned contains the following: # * type: (String) The server group type. Valid values are either - # 'tacacs' or 'radius' + # 'tacacs' or 'radius'. # * servers: (Array) The set of servers associated with the group. - # Servers are returned as either IP address or host name + # Servers are returned as either IP address or host name. # - # @param [String] :name The server group name to return f:rom the nodes + # @param [String] :name The server group name to return from the nodes # current running configuration. If the name is not configured a nil # object is returned. # # @return [nil, Hash] returns the resource hash for the - # specified name. If the name does not exist, a nil object is returned + # specified name. If the name does not exist, a nil object is returned. def get(name) block = get_block("aaa group server ([^\s]+) #{name}") return nil unless block @@ -99,6 +101,18 @@ def get(name) response end + ## + # getall returns a aaa server groups hash + # + # The resource hash returned contains the following: + # * name: (String) The server group name. + # * type: (String) The server group type. Valid values are either + # 'tacacs' or 'radius' + # * servers: (Array) The set of servers associated with the group. + # Servers are returned as either IP address or host name + # + # @return [Hash] returns the resource hashes for + # configured aaa groups. If none exist, a nil object is returned def getall cfg = config.scan(/aaa group server (?:radius|tacacs\+) (.+)$/) cfg.each_with_object({}) do |name, hsh| @@ -109,7 +123,7 @@ def getall ## # parse_type scans the specified configuration block and returns the - # server group type as either 'tacacs' or 'radius' The type value is + # server group type as either 'tacacs' or 'radius'. The type value is # expected to always be present in the config. # # @api private @@ -175,8 +189,8 @@ def parse_radius_server(config) private :parse_radius_server ## - # parse_tacacs_server scans the provide configuration block and returns - # the list of servers configured. The configuration block is expected to + # parse_tacacs_server scans the provided configuration block and returns + # the list of configured servers. The configuration block is expected to # be a tacacs configuration block. If there are no servers configured # for the group the servers value will return an empty array. # diff --git a/lib/rbeapi/api/acl.rb b/lib/rbeapi/api/acl.rb index f4a591b..8503cd3 100644 --- a/lib/rbeapi/api/acl.rb +++ b/lib/rbeapi/api/acl.rb @@ -33,7 +33,7 @@ require 'rbeapi/api' ## -# Eos is the toplevel namespace for working with Arista EOS nodes +# Rbeapi toplevel namespace module Rbeapi ## # Api is module namespace for working with the EOS command API diff --git a/lib/rbeapi/api/dns.rb b/lib/rbeapi/api/dns.rb index 787443d..9263020 100644 --- a/lib/rbeapi/api/dns.rb +++ b/lib/rbeapi/api/dns.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Dns class manages DNS settings on an EOS node. diff --git a/lib/rbeapi/api/interfaces.rb b/lib/rbeapi/api/interfaces.rb index d154219..dee136b 100644 --- a/lib/rbeapi/api/interfaces.rb +++ b/lib/rbeapi/api/interfaces.rb @@ -36,7 +36,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Api module namespace + # Api is module namespace for working with the EOS command API module Api ## # The Interfaces class manages all physical and logical interfaces on an diff --git a/lib/rbeapi/api/ipinterfaces.rb b/lib/rbeapi/api/ipinterfaces.rb index 568f3ac..873c482 100644 --- a/lib/rbeapi/api/ipinterfaces.rb +++ b/lib/rbeapi/api/ipinterfaces.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api # # The Ipinterface class provides an instance for managing logical diff --git a/lib/rbeapi/api/logging.rb b/lib/rbeapi/api/logging.rb index 05e1f99..dc9816e 100644 --- a/lib/rbeapi/api/logging.rb +++ b/lib/rbeapi/api/logging.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Logging class manages logging settings on an EOS node. diff --git a/lib/rbeapi/api/mlag.rb b/lib/rbeapi/api/mlag.rb index 99779b7..a397c97 100644 --- a/lib/rbeapi/api/mlag.rb +++ b/lib/rbeapi/api/mlag.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Mlag class provides a configuration instance for working with diff --git a/lib/rbeapi/api/ntp.rb b/lib/rbeapi/api/ntp.rb index e1d756d..337a794 100644 --- a/lib/rbeapi/api/ntp.rb +++ b/lib/rbeapi/api/ntp.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Eos is the toplevel namespace for working with Arista EOS nodes +# Rbeapi toplevel namespace module Rbeapi ## - # Api is module namesapce for working with the EOS command API + # Api is module namespace for working with the EOS command API module Api ## # The Ntp class provides an instance for working with the nodes diff --git a/lib/rbeapi/api/ospf.rb b/lib/rbeapi/api/ospf.rb index 46486af..eb4c120 100644 --- a/lib/rbeapi/api/ospf.rb +++ b/lib/rbeapi/api/ospf.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Ospf class is a global class that provides an instance for working diff --git a/lib/rbeapi/api/prefixlists.rb b/lib/rbeapi/api/prefixlists.rb index 379819c..6bef554 100644 --- a/lib/rbeapi/api/prefixlists.rb +++ b/lib/rbeapi/api/prefixlists.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Prefixlists class provides a configuration instance for working diff --git a/lib/rbeapi/api/radius.rb b/lib/rbeapi/api/radius.rb index 86c1481..399ca86 100644 --- a/lib/rbeapi/api/radius.rb +++ b/lib/rbeapi/api/radius.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # Radius provides instance methods to retrieve and set radius configuration diff --git a/lib/rbeapi/api/routemaps.rb b/lib/rbeapi/api/routemaps.rb index ca6494c..fca8556 100644 --- a/lib/rbeapi/api/routemaps.rb +++ b/lib/rbeapi/api/routemaps.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Routemaps class manages routemaps. A route map is a list of rules diff --git a/lib/rbeapi/api/snmp.rb b/lib/rbeapi/api/snmp.rb index fd2ea60..309a814 100644 --- a/lib/rbeapi/api/snmp.rb +++ b/lib/rbeapi/api/snmp.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Api is module namespace for working with eAPI abstractions + # Api is module namespace for working with the EOS command API module Api ## # The Snmp class provides a class implementation for working with the diff --git a/lib/rbeapi/api/staticroutes.rb b/lib/rbeapi/api/staticroutes.rb index 739aa64..1efe459 100644 --- a/lib/rbeapi/api/staticroutes.rb +++ b/lib/rbeapi/api/staticroutes.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Staticroutes class provides a configuration instance for working diff --git a/lib/rbeapi/api/stp.rb b/lib/rbeapi/api/stp.rb index 79def53..caf9926 100644 --- a/lib/rbeapi/api/stp.rb +++ b/lib/rbeapi/api/stp.rb @@ -34,7 +34,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Stp class provides a base class instance for working with diff --git a/lib/rbeapi/api/switchports.rb b/lib/rbeapi/api/switchports.rb index 373b7d5..eb92d0b 100644 --- a/lib/rbeapi/api/switchports.rb +++ b/lib/rbeapi/api/switchports.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Api is module namesapce for working with the EOS command API + # Api is module namespace for working with the EOS command API module Api ## # The Switchport class provides a base class instance for working with diff --git a/lib/rbeapi/api/system.rb b/lib/rbeapi/api/system.rb index 34b0e06..45fceaa 100644 --- a/lib/rbeapi/api/system.rb +++ b/lib/rbeapi/api/system.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The System class configures the node system services such as diff --git a/lib/rbeapi/api/tacacs.rb b/lib/rbeapi/api/tacacs.rb index a955349..b3e9cf9 100644 --- a/lib/rbeapi/api/tacacs.rb +++ b/lib/rbeapi/api/tacacs.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Api is module namesapce for working with the EOS command API + # Api is module namespace for working with the EOS command API module Api ## # Tacacs provides instance methods to retrieve and set tacacs configuration diff --git a/lib/rbeapi/api/users.rb b/lib/rbeapi/api/users.rb index 6d5cde9..d4cadd4 100644 --- a/lib/rbeapi/api/users.rb +++ b/lib/rbeapi/api/users.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Api is module namesapce for working with the EOS command API + # Api is module namespace for working with the EOS command API module Api ## # The Users class provides configuration of local user resources for diff --git a/lib/rbeapi/api/varp.rb b/lib/rbeapi/api/varp.rb index 47d6d53..09f9ec6 100644 --- a/lib/rbeapi/api/varp.rb +++ b/lib/rbeapi/api/varp.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Rbeapi::Api + # Api is module namespace for working with the EOS command API module Api ## # The Varp class provides an instance for working with the global diff --git a/lib/rbeapi/api/vlans.rb b/lib/rbeapi/api/vlans.rb index 5ce3ad2..4934c05 100644 --- a/lib/rbeapi/api/vlans.rb +++ b/lib/rbeapi/api/vlans.rb @@ -35,7 +35,7 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Api is module namesapce for working with the EOS command API + # Api is module namespace for working with the EOS command API module Api ## # The Vlan class provides a class implementation for working with the diff --git a/lib/rbeapi/api/vrrp.rb b/lib/rbeapi/api/vrrp.rb index 69cf370..a8b1b1d 100644 --- a/lib/rbeapi/api/vrrp.rb +++ b/lib/rbeapi/api/vrrp.rb @@ -32,7 +32,7 @@ require 'rbeapi/api' ## -# Eos is the toplevel namespace for working with Arista EOS nodes +# Rbeapi toplevel namespace module Rbeapi ## # Api is module namespace for working with the EOS command API From efbdc9a78ab996379233ebb96b765ae5ae28717f Mon Sep 17 00:00:00 2001 From: John Corbin Date: Wed, 23 Dec 2015 07:25:14 -0800 Subject: [PATCH 074/110] Added support for trunk groups. Fixes #38 --- lib/rbeapi/api/switchports.rb | 56 +++++++++++++++++++++ spec/system/rbeapi/api/switchports_spec.rb | 58 +++++++++++++++++++++- 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/lib/rbeapi/api/switchports.rb b/lib/rbeapi/api/switchports.rb index eb92d0b..16c89af 100644 --- a/lib/rbeapi/api/switchports.rb +++ b/lib/rbeapi/api/switchports.rb @@ -69,6 +69,7 @@ def get(name) response.merge!(parse_access_vlan(config)) response.merge!(parse_trunk_native_vlan(config)) response.merge!(parse_trunk_allowed_vlans(config)) + response.merge!(parse_trunk_groups(config)) response end @@ -76,16 +77,19 @@ def parse_mode(config) mdata = /(?<=\s{3}switchport\smode\s)(.+)$/.match(config) { mode: mdata[1] } end + private :parse_mode def parse_access_vlan(config) mdata = /(?<=access\svlan\s)(.+)$/.match(config) { access_vlan: mdata[1] } end + private :parse_access_vlan def parse_trunk_native_vlan(config) mdata = /(?<=trunk\snative\svlan\s)(.+)$/.match(config) { trunk_native_vlan: mdata[1] } end + private :parse_trunk_native_vlan def parse_trunk_allowed_vlans(config) mdata = /(?<=trunk\sallowed\svlan\s)(.+)$/.match(config) @@ -101,6 +105,14 @@ def parse_trunk_allowed_vlans(config) end { trunk_allowed_vlans: values } end + private :parse_trunk_allowed_vlans + + def parse_trunk_groups(config) + mdata = config.scan(/(?<=trunk\sgroup\s)(.+)$/) + mdata = mdata.flatten if mdata.length > 0 + { trunk_groups: mdata } + end + private :parse_trunk_groups ## # Retrieves all switchport interfaces from the running-config @@ -248,6 +260,50 @@ def set_access_vlan(name, opts = {}) cmd = command_builder('switchport access vlan', opts) configure_interface(name, cmd) end + + ## + # Configures the trunk group vlans for the specified interface. + # Trunk groups not currently set are added and trunk groups + # currently configured but not in the passed in value array are removed. + # + # @param [String] name The name of the interface to configure + # @param [Hash] opts The configuration parameters for the interface + # @option opts [string] :value Set of values to configure the trunk group + # @option opts [Boolean] :enable If false then the command is + # negated. Default is true. + # @option opts [Boolean] :default The value should be set to default + # Default takes precedence over enable. + # + # @return [Boolean] True if the commands succeed otherwise False + def set_trunk_groups(name, opts = {}) + default = opts.fetch(:default, false) + if default + return configure_interface(name, 'default switchport trunk group') + end + + enable = opts.fetch(:enable, true) + unless enable + return configure_interface(name, 'no switchport trunk group') + end + + value = opts.fetch(:value, []) + fail ArgumentError, 'value must be an Array' unless value.is_a?(Array) + + value = Set.new value + current_value = Set.new get(name)[:trunk_groups] + + cmds = [] + # Add trunk groups that are not currently in the list + value.difference(current_value).each do |group| + cmds << "switchport trunk group #{group}" + end + + # Remove trunk groups that are not in the new list + current_value.difference(value).each do |group| + cmds << "no switchport trunk group #{group}" + end + configure_interface(name, cmds) if cmds.length > 0 + end end end end diff --git a/spec/system/rbeapi/api/switchports_spec.rb b/spec/system/rbeapi/api/switchports_spec.rb index 9b209f7..65740d0 100644 --- a/spec/system/rbeapi/api/switchports_spec.rb +++ b/spec/system/rbeapi/api/switchports_spec.rb @@ -13,7 +13,8 @@ describe '#get' do let(:keys) do - [:mode, :access_vlan, :trunk_native_vlan, :trunk_allowed_vlans] + [:mode, :access_vlan, :trunk_native_vlan, :trunk_allowed_vlans, + :trunk_groups] end context 'vlan as an integer range' do @@ -220,4 +221,59 @@ expect(subject.get('Ethernet1')[:trunk_allowed_vlans].length).to eq(4094) end end + + describe '#set_trunk_groups' do + before do + node.config(['interface Ethernet1', 'default switchport trunk group']) + end + + it 'raises an ArgumentError if value is not an array' do + expect { subject.set_trunk_groups('Ethernet1', value: 'foo') } + .to raise_error(ArgumentError) + end + + it 'sets trunk group to foo bar bang' do + node.config(['interface Ethernet1', 'switchport trunk group bang', + 'switchport trunk group baz']) + expect(subject.get('Ethernet1')[:trunk_groups]).to eq(%w(bang baz)) + expect(subject.set_trunk_groups('Ethernet1', value: %w(foo bar bang))) + .to be_truthy + expect(subject.get('Ethernet1')[:trunk_groups].sort) + .to eq(%w(bang bar foo)) + end + + it 'clears trunk group if no value specified' do + node.config(['interface Ethernet1', 'switchport trunk group bang', + 'switchport trunk group baz']) + expect(subject.get('Ethernet1')[:trunk_groups]).to eq(%w(bang baz)) + expect(subject.set_trunk_groups('Ethernet1')).to be_truthy + expect(subject.get('Ethernet1')[:trunk_groups]).to be_empty + end + + it 'negate switchport trunk group' do + node.config(['interface Ethernet1', 'switchport trunk group bang', + 'switchport trunk group baz']) + expect(subject.get('Ethernet1')[:trunk_groups]).to eq(%w(bang baz)) + expect(subject.set_trunk_groups('Ethernet1', value: %w(foo bar bang))) + .to be_truthy + expect(subject.get('Ethernet1')[:trunk_groups].sort) + .to eq(%w(bang bar foo)) + expect(subject.set_trunk_groups('Ethernet1', enable: false)) + .to be_truthy + expect(subject.get('Ethernet1')[:trunk_groups]).to be_empty + end + + it 'default switchport trunk group' do + node.config(['interface Ethernet1', 'switchport trunk group bang', + 'switchport trunk group baz']) + expect(subject.get('Ethernet1')[:trunk_groups]).to eq(%w(bang baz)) + expect(subject.set_trunk_groups('Ethernet1', value: %w(foo bar bang))) + .to be_truthy + expect(subject.get('Ethernet1')[:trunk_groups].sort) + .to eq(%w(bang bar foo)) + expect(subject.set_trunk_groups('Ethernet1', default: true)) + .to be_truthy + expect(subject.get('Ethernet1')[:trunk_groups]).to be_empty + end + end end From 6fa2fd36c7c5ecb3c3b9e9648a596ba3d76cdb14 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Wed, 23 Dec 2015 09:10:44 -0700 Subject: [PATCH 075/110] Shorten config block. --- spec/system/rbeapi/api/vrrp_spec.rb | 38 ++++++++++++++++------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/spec/system/rbeapi/api/vrrp_spec.rb b/spec/system/rbeapi/api/vrrp_spec.rb index 55f2ddc..486982e 100644 --- a/spec/system/rbeapi/api/vrrp_spec.rb +++ b/spec/system/rbeapi/api/vrrp_spec.rb @@ -20,29 +20,33 @@ describe '#get' do before do - node.config(['no interface Vlan150', 'no interface Vlan100', - 'interface Vlan100', 'interface Vlan150', - 'ip address 40.10.5.8/24', 'vrrp 30 priority 100', + node.config(['no interface Vlan150', + 'no interface Vlan100', + 'interface Vlan100', + 'interface Vlan150', + 'ip address 40.10.5.8/24', + 'vrrp 30 priority 100', 'vrrp 30 timers advertise 1', 'vrrp 30 mac-address advertisement-interval 30', - 'no vrrp 30 preempt', 'vrrp 30 preempt delay minimum 0', - 'vrrp 30 preempt delay reload 0', 'vrrp 30 delay reload 0', - 'no vrrp 30 authentication', 'vrrp 30 ip 40.10.5.31', - 'vrrp 30 ipv6 ::', 'vrrp 30 description The description', - 'vrrp 30 shutdown', 'vrrp 30 track Ethernet1 decrement 5', - 'no vrrp 30 bfd ip', 'no vrrp 30 bfd ipv6', - 'vrrp 30 ip version 2', 'vrrp 40 priority 200', + 'no vrrp 30 preempt', + 'vrrp 30 preempt delay reload 0', + 'vrrp 30 delay reload 0', + 'vrrp 30 ip 40.10.5.31', + 'vrrp 30 description The description', + 'vrrp 30 shutdown', + 'vrrp 30 track Ethernet1 decrement 5', + 'vrrp 30 ip version 2', + 'vrrp 40 priority 200', 'vrrp 40 timers advertise 1', 'vrrp 40 mac-address advertisement-interval 30', - 'vrrp 40 preempt', 'vrrp 40 preempt delay minimum 0', - 'vrrp 40 preempt delay reload 0', 'vrrp 40 delay reload 0', - 'no vrrp 40 authentication', 'vrrp 40 ip 40.10.5.32', - 'vrrp 40 ipv6 ::', 'no vrrp 40 description', - 'no vrrp 40 shutdown', + 'vrrp 40 preempt', + 'vrrp 40 preempt delay reload 0', + 'vrrp 40 delay reload 0', + 'vrrp 40 ip 40.10.5.32', 'vrrp 40 track Ethernet3 decrement 33', 'vrrp 40 track Ethernet2 decrement 22', - 'vrrp 40 track Ethernet2 shutdown', 'no vrrp 40 bfd ip', - 'no vrrp 40 bfd ipv6', 'vrrp 40 ip version 2']) + 'vrrp 40 track Ethernet2 shutdown', + 'vrrp 40 ip version 2']) end let(:entity) do From c429936f0b4a4f9e69356970121bd750901674bf Mon Sep 17 00:00:00 2001 From: John Corbin Date: Fri, 1 Jan 2016 15:31:54 -0800 Subject: [PATCH 076/110] Add lacp_mode option when setting port-channel members. Fixes #58 --- lib/rbeapi/api/interfaces.rb | 29 ++++++-- .../rbeapi/api/interfaces_portchannel_spec.rb | 68 +++++++++++++++++++ 2 files changed, 91 insertions(+), 6 deletions(-) diff --git a/lib/rbeapi/api/interfaces.rb b/lib/rbeapi/api/interfaces.rb index dee136b..a4617bc 100644 --- a/lib/rbeapi/api/interfaces.rb +++ b/lib/rbeapi/api/interfaces.rb @@ -773,24 +773,41 @@ def set_minimum_links(name, opts = {}) # @param [Array] :members The array of physical interface members to add # to the port-channel logical interface. # + # @param [str] :mode The LACP mode to configure the member interfaces to. + # Valid values are 'on, 'passive', 'active'. When there are + # existing channel-group members and their lacp mode differs + # from this attribute, all of those members will be removed and + # then re-added using the specified lacp mode. If this attribute + # is omitted, the existing lacp mode will be used for new + # member additions. + # # @return [Boolean] returns true if the command completed successfully - def set_members(name, members) + def set_members(name, members, mode = nil) current_members = Set.new parse_members(name)[:members] members = Set.new members + lacp_mode = parse_lacp_mode(name)[:lacp_mode] + if mode && mode != lacp_mode + lacp_mode = mode + set_lacp_mode(name, lacp_mode) + end + + cmds = [] + grpid = /(\d+)/.match(name)[0] + # remove members from the current port-channel interface current_members.difference(members).each do |intf| - result = remove_member(name, intf) - return false unless result + cmds << "interface #{intf}" + cmds << "no channel-group #{grpid}" end # add new member interfaces to the port-channel members.difference(current_members).each do |intf| - result = add_member(name, intf) - return false unless result + cmds << "interface #{intf}" + cmds << "channel-group #{grpid} mode #{lacp_mode}" end - true + configure(cmds) end ## diff --git a/spec/system/rbeapi/api/interfaces_portchannel_spec.rb b/spec/system/rbeapi/api/interfaces_portchannel_spec.rb index 8afd324..6814e98 100644 --- a/spec/system/rbeapi/api/interfaces_portchannel_spec.rb +++ b/spec/system/rbeapi/api/interfaces_portchannel_spec.rb @@ -134,6 +134,74 @@ expect(subject.get('Port-Channel1')[:members]).to eq(%w(Ethernet1 Ethernet3)) end + + it 'updates the member interfaces and mode on existing interface' do + node.config(['no interface Port-Channel1', 'interface Ethernet1-2', + 'channel-group 1 mode on']) + expect(subject.get('Port-Channel1')[:members]).to eq(%w(Ethernet1 + Ethernet2)) + expect(subject.get('Port-Channel1')[:lacp_mode]).to eq('on') + expect(subject.set_members('Port-Channel1', + %w(Ethernet1 Ethernet3), + 'active')).to be_truthy + expect(subject.get('Port-Channel1')[:members]).to eq(%w(Ethernet1 + Ethernet3)) + expect(subject.get('Port-Channel1')[:lacp_mode]).to eq('active') + end + end + + describe '#add_member' do + before do + node.config(['no interface Port-Channel1', + 'interface Port-Channel1']) + end + + it 'adds new members to the port-channel interface' do + node.config(['no interface Port-Channel1', 'interface Port-Channel1']) + expect(subject.get('Port-Channel1')[:members]).not_to include('Ethernet1') + expect(subject.add_member('Port-Channel1', 'Ethernet1')).to be_truthy + expect(subject.get('Port-Channel1')[:members]).to eq(['Ethernet1']) + end + + it 'updates the member interfaces on existing interface' do + node.config(['no interface Port-Channel1', 'interface Ethernet1-2', + 'channel-group 1 mode on']) + expect(subject.get('Port-Channel1')[:members]).to eq(%w(Ethernet1 + Ethernet2)) + expect(subject.add_member('Port-Channel1', 'Ethernet3')).to be_truthy + expect(subject.get('Port-Channel1')[:members]).to eq(%w(Ethernet1 + Ethernet2 + Ethernet3)) + expect(subject.get('Port-Channel1')[:lacp_mode]).to eq('on') + end + + it 'no update to the member interfaces on existing interface' do + node.config(['no interface Port-Channel1', 'interface Ethernet1-2', + 'channel-group 1 mode active']) + expect(subject.get('Port-Channel1')[:members]).to eq(%w(Ethernet1 + Ethernet2)) + expect(subject.add_member('Port-Channel1', 'Ethernet2')).to be_truthy + expect(subject.get('Port-Channel1')[:members]).to eq(%w(Ethernet1 + Ethernet2)) + expect(subject.get('Port-Channel1')[:lacp_mode]).to eq('active') + end + end + + describe '#remove_member' do + before do + node.config(['no interface Port-Channel1', + 'interface Port-Channel1']) + end + + it 'removes the member interface on existing interface' do + node.config(['no interface Port-Channel1', 'interface Ethernet1-2', + 'channel-group 1 mode on']) + expect(subject.get('Port-Channel1')[:members]).to eq(%w(Ethernet1 + Ethernet2)) + expect(subject.remove_member('Port-Channel1', 'Ethernet1')).to be_truthy + expect(subject.get('Port-Channel1')[:members]).to eq(['Ethernet2']) + expect(subject.get('Port-Channel1')[:lacp_mode]).to eq('on') + end end describe '#set_lacp_mode' do From 6e09287021df3bad8ff7904d13101cce3ffd3d18 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Sat, 2 Jan 2016 14:35:53 -0700 Subject: [PATCH 077/110] Working on beefing up framework tests. --- spec/fixtures/test.conf | 46 +++--- spec/system/rbeapi/client_spec.rb | 78 ++++++++-- spec/unit/rbeapi/client/default_spec.rb | 180 ++++++++++++++++++------ 3 files changed, 236 insertions(+), 68 deletions(-) diff --git a/spec/fixtures/test.conf b/spec/fixtures/test.conf index e955d73..595eda7 100644 --- a/spec/fixtures/test.conf +++ b/spec/fixtures/test.conf @@ -1,29 +1,39 @@ [connection:veos01] -username : eapi -password : password -transport : http -host : veos01 +username: eapi +password: password +transport: http +host: veos01 [connection:veos02] -transport : http -host : veos02 +transport: http +host: veos02 [connection:veos03] -transport : socket -host : veos03 +transport: socket +host: veos03 [connection:veos04] -host : 172.16.10.1 -username : eapi -password : password -enablepwd : itsasecret -port : 1234 -transport : https +host: 172.16.10.1 +username: eapi +password: password +enablepwd: itsasecret +port: 1234 +transport: https + +[connection:veos05] +host: 172.16.131.40 +username: admin +password: admin +enablepwd: password +transport: https +port: 1234 +open_timeout: 12 +read_timeout: 12 [connection: localhost] -transport : http_local -host : localhost +transport: http_local +host: localhost [connection:localhost] -transport : socket -host : localhost +transport: socket +host: localhost diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb index 078d919..83867dd 100644 --- a/spec/system/rbeapi/client_spec.rb +++ b/spec/system/rbeapi/client_spec.rb @@ -35,6 +35,34 @@ def test_conf } end + let(:veos05) do + { + 'host' => '172.16.131.40', + 'username' => 'admin', + 'password' => 'admin', + 'enablepwd' => 'password', + 'transport' => 'https', + 'port' => 1234, + 'open_timeout' => 12, + 'read_timeout' => 12 + } + end + + let(:test_data) do + [ + '[connection:veos01]', + '[connection:veos02]', + '[connection:veos03', + '[connection:veos04]', + '[connection:veos05]', + '[connection: localhost]', + 'username', + 'password', + 'transport', + 'host' + ] + end + # Client class methods describe '#connect_to' do it 'retrieves the node config' do @@ -50,10 +78,15 @@ def test_conf end describe '#config_for' do - it 'returns the configuration options for the connection' do + it 'returns the configuration options for veos01' do expect(subject.config.read(test_conf)).to eq(nil) expect(subject.config_for('veos01')).to eq(veos01) end + + it 'returns the configuration options for veos05' do + expect(subject.config.read(test_conf)).to eq(nil) + expect(subject.config_for('veos05')).to eq(veos05) + end end describe '#load_config' do @@ -67,7 +100,7 @@ def test_conf # Config class methods describe 'config' do it 'gets the loaded configuration file data' do - expect(subject.config.to_s).to eq(test) + expect(subject.config.to_s).to include(test_data[0]) end end @@ -75,14 +108,18 @@ def test_conf it 'read the specified filename and load it' do expect(subject.load_config(dut_conf)).to eq(transport: 'socket') expect(subject.config.read(test_conf)).to eq(nil) - expect(subject.config.to_s).to eq(test) + expect(subject.config.to_s).to include(test_data[0]) end end describe '#get_connection' do - it 'get connection dut' do + it 'get connection veos01' do expect(subject.config.get_connection('veos01')).to eq(veos01) end + + it 'get connection veos05' do + expect(subject.config.get_connection('veos05')).to eq(veos05) + end end describe '#reload' do @@ -91,7 +128,7 @@ def test_conf .to eq(transport: 'socket') expect(subject.config.reload(filename: [test_conf])) .to eq(nil) - expect(subject.config.to_s).to eq(test) + expect(subject.config.to_s).to include(test_data[0]) end end @@ -143,15 +180,40 @@ def test_conf describe '#enable' do it 'puts the switch into privilege mode' do + expect(node.enable('show hostname')[0]) + .to include(:command, :result, :encoding) + end + + it 'puts the switch into privilege mode with encoding' do expect(node.enable('show hostname', encoding: 'text')[0]) .to include(:command, :result, :encoding) end + + it 'puts the switch into privilege mode with open and read timeout' do + expect(node.enable('show hostname', + open_timeout: 29, + read_timeout: 29)[0]).to include(:command, + :result, + :encoding) + end end describe '#run_commands' do - it 'send commands to node' do - expect(node.run_commands('show hostname', encoding: 'text')[0]) - .to include('output') + it 'sends commands to node' do + expect(node.run_commands(['show hostname'])[0]) + .to include('fqdn', 'hostname') + end + + it 'sends commands to node with encoding' do + expect(node.run_commands('show hostname', encoding: 'text')[0]['output']) + .to include('FQDN', 'Hostname') + end + + it 'sends commands with open and read timeout' do + expect(node.run_commands('show hostname', + open_timeout: 26, + read_timeout: 26)[0]).to include('fqdn', + 'hostname') end end diff --git a/spec/unit/rbeapi/client/default_spec.rb b/spec/unit/rbeapi/client/default_spec.rb index 03aaeda..bdbd874 100644 --- a/spec/unit/rbeapi/client/default_spec.rb +++ b/spec/unit/rbeapi/client/default_spec.rb @@ -38,7 +38,10 @@ describe Rbeapi::Client do subject { described_class } - let(:node) { double('node') } + let(:node) do + subject.config.read(fixture_file('dut.conf')) + subject.connect_to('dut') + end def dut_conf fixture_file('dut.conf') @@ -65,24 +68,68 @@ def test_conf } end + let(:veos05) do + { + 'host' => '172.16.131.40', + 'username' => 'admin', + 'password' => 'admin', + 'enablepwd' => 'password', + 'transport' => 'https', + 'port' => 1234, + 'open_timeout' => 12, + 'read_timeout' => 12 + } + end + + let(:test_data) do + [ + '[connection:veos01]', + '[connection:veos02]', + '[connection:veos03', + '[connection:veos04]', + '[connection:veos05]', + '[connection: localhost]', + 'username', + 'password', + 'transport', + 'host' + ] + end + # Client class methods describe '#config_for' do it 'returns the configuration options for the connection' do expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('veos01')).to eq(veos01) end + + it 'returns nil if connection does not exist' do + expect(subject.config_for('veos22')).to eq(nil) + end end describe '#connect_to' do it 'retrieves the node config' do expect(subject.connect_to('veos01')).to be_truthy end + + it 'returns nil if connection does not exist' do + expect(subject.connect_to('veos22')).to eq(nil) + end end describe '#load_config' do it 'overrides the default conf file loaded in the config' do expect(subject.load_config(test_conf)).to eq(nil) + end + + it 'returns nil if connection does not exit' do + expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('dut')).to eq(nil) + end + + it 'returns conf settings if connection exists' do + expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('veos01')).to eq(veos01) end end @@ -91,22 +138,31 @@ def test_conf describe 'config' do it 'gets the loaded configuration file data' do expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config.to_s).to eq(test) + expect(subject.config.to_s).to include(test_data[0]) end end describe '#read' do - it 'read the specified filename and load it' do - expect(subject.load_config(dut_conf)).to eq(transport: 'socket') + it 'read the specified filename and load dut' do + expect(subject.config.read(dut_conf)).to eq(transport: 'socket') + expect(subject.config.to_s) + .to include('host', 'username', 'password', '[connection:dut]') + end + + it 'read the specified filename and load test' do expect(subject.config.read(test_conf)).to eq(nil) - expect(subject.config.to_s).to eq(test) + expect(subject.config.to_s).to include(test_data[0]) end end describe '#get_connection' do - it 'get connection dut' do + it 'get connection veos01' do expect(subject.config.get_connection('veos01')).to eq(veos01) end + + it 'get connection veos05' do + expect(subject.config.get_connection('veos05')).to eq(veos05) + end end describe '#reload' do @@ -141,90 +197,130 @@ def test_conf # Node Class Methods describe '#running_config' do it 'gets the nodes running config' do - allow(node).to receive(:running_config).and_return(test) - expect(node).to receive(:running_config) - expect(node.running_config.to_s).to eq(test) + expect(node.running_config).to be_truthy + end + + it 'expects running config to return a string' do + expect(node.running_config).to be_kind_of(String) end end describe '#startup_config' do it 'gets the nodes startup-configuration' do - allow(node).to receive(:startup_config).and_return(test) - expect(node).to receive(:startup_config) - expect(node.startup_config).to eq(test) + expect(node.startup_config).to be_truthy + end + + it 'expects startup-configuration to be a string' do + expect(node.startup_config).to be_kind_of(String) end end describe '#enable_authentication' do it 'gets the nodes startup-configuration' do - expect(node).to receive(:enable_authentication).with('newpassword') - expect(node.enable_authentication('newpassword')).to eq(nil) + expect(node.enable_authentication('newpassword')).to eq('newpassword') end end describe '#config' do it 'puts switch into config mode' do - expect(node).to receive(:config) - .with(['no ip virtual-router mac-address']) - expect(node.config(['no ip virtual-router mac-address'])).to eq(nil) + expect(node.config(['no ip virtual-router mac-address'])) + .to be_truthy + end + + it 'expects config to return array' do + expect(node.config(['no ip virtual-router mac-address'])) + .to be_kind_of(Array) end - it 'puts switch into config mode with options' do - expect(node).to receive(:config) - .with(['no ip virtual-router mac-address'], - encoding: 'json', - open_timeout: 27.00, - read_timeout: 27.00) + it 'puts switch into config mode with options and returns array' do expect(node.config(['no ip virtual-router mac-address'], encoding: 'json', open_timeout: 27.00, - read_timeout: 27.00)).to eq(nil) + read_timeout: 27.00)) + .to be_kind_of(Array) + end + + it 'returns error if invalid command' do + expect { node.config(['no ip virtual-router mac-addresses']) } + .to raise_error Rbeapi::Eapilib::CommandError end end describe '#enable' do it 'puts the switch into privilege mode' do - expect(node).to receive(:enable).with('show hostname', encoding: 'text') - expect(node.enable('show hostname', encoding: 'text')) - .to eq(nil) + expect(node.enable('show hostname')[0][:result]) + .to include('fqdn', 'hostname') + end + + it 'puts the switch into privilege mode with encoding' do + expect(node.enable('show hostname', encoding: 'text')[0][:encoding]) + .to eq('text') + end + + it 'puts the switch into privilege mode with strict option' do + expect(node.enable('show hostname', strict: true)[0]) + .to include(:command, :result, :encoding) + end + + it 'puts the switch into privilege mode with read and open timeout' do + expect(node.enable('show hostname', + read_timeout: 29, + open_timeout: 29)[0]) + .to include(:command, :result, :encoding) + end + + it 'raises invalid command error' do + expect { node.enable(['show hostname', 'do this thing']) } + .to raise_error Rbeapi::Eapilib::CommandError end end describe '#run_commands' do + it 'expects run_commands to be a string' do + expect(node.run_commands('show hostname', encoding: 'text')[0]['output']) + .to be_kind_of String + end + it 'send commands to node' do - expect(node).to receive(:run_commands) - .with('show hostname', encoding: 'text') - expect(node.run_commands('show hostname', encoding: 'text')) - .to eq(nil) + expect(node.run_commands('show hostname', encoding: 'text')[0]['output']) + .to include('Hostname:', 'FQDN:') + end + + it 'expects run_commands to raise a command error' do + expect { node.run_commands('do this thing') } + .to raise_error Rbeapi::Eapilib::CommandError end end describe '#get_config' do - it 'will retrieve the specified configuration' do - expect(node).to receive(:get_config) - .with(config: 'running-config') + it 'will retrieve the specified configuration and return array' do expect(node.get_config(config: 'running-config')) - .to eq(nil) + .to be_kind_of(Array) end - it 'will retrieve the specified configuration with param' do - expect(node).to receive(:get_config) - .with(config: 'running-config', param: 'all') + it 'will retrieve with param and return array' do expect(node.get_config(config: 'running-config', param: 'all')) - .to eq(nil) + .to be_kind_of(Array) + end + + it 'raises invalid command error' do + expect { node.get_config(config: 'running-configurations') } + .to raise_error Rbeapi::Eapilib::CommandError end end describe '#api' do it 'returns api module' do - expect(node).to receive(:api).with('vlans') - expect(node.api('vlans')).to eq(nil) + expect(node.api('vlans')).to be_kind_of(Rbeapi::Api::Vlans) + end + + it 'returns error if invalid name' do + expect { node.api('vlanss') }.to raise_error end end describe '#refresh' do it 'refreshes configs for next call' do - expect(node).to receive(:refresh) expect(node.refresh).to eq(nil) end end From 562918c5ae265a5a43d2800a1e31c4a391276f87 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Sun, 3 Jan 2016 23:01:25 -0700 Subject: [PATCH 078/110] Expanding test coverage. --- spec/unit/rbeapi/client/default_spec.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/spec/unit/rbeapi/client/default_spec.rb b/spec/unit/rbeapi/client/default_spec.rb index bdbd874..57f142d 100644 --- a/spec/unit/rbeapi/client/default_spec.rb +++ b/spec/unit/rbeapi/client/default_spec.rb @@ -240,6 +240,19 @@ def test_conf .to be_kind_of(Array) end + describe 'set dry run' do + before do + # Prevents puts from writing to console + allow($stdout).to receive(:puts) + node.dry_run = true + end + + it 'expects config to do dry run' do + expect(node.config(['no ip virtual-router mac-address'])) + .to eq(nil) + end + end + it 'returns error if invalid command' do expect { node.config(['no ip virtual-router mac-addresses']) } .to raise_error Rbeapi::Eapilib::CommandError @@ -286,6 +299,11 @@ def test_conf .to include('Hostname:', 'FQDN:') end + it 'sends commands with enablepwd set' do + expect(node.enable_authentication('icanttellyou')).to eq('icanttellyou') + expect(node.run_commands('show hostname')).to be_truthy + end + it 'expects run_commands to raise a command error' do expect { node.run_commands('do this thing') } .to raise_error Rbeapi::Eapilib::CommandError From 7303df512b36f7c5c81067a976eb7025e317ee0c Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 4 Jan 2016 10:47:18 -0700 Subject: [PATCH 079/110] Remove unit tests because node cannot be mocked for these tests. --- spec/system/rbeapi/client_spec.rb | 194 ++++++++++--- spec/unit/rbeapi/client/default_spec.rb | 345 ------------------------ 2 files changed, 160 insertions(+), 379 deletions(-) delete mode 100644 spec/unit/rbeapi/client/default_spec.rb diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb index 83867dd..df3269d 100644 --- a/spec/system/rbeapi/client_spec.rb +++ b/spec/system/rbeapi/client_spec.rb @@ -1,3 +1,34 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# require 'spec_helper' require 'rbeapi/client' @@ -64,35 +95,39 @@ def test_conf end # Client class methods - describe '#connect_to' do - it 'retrieves the node config' do - expect(node).to be_kind_of(Rbeapi::Client::Node) + describe '#config_for' do + it 'returns the configuration options for the connection' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) end - end - describe '#config' do - it 'returns the currently loaded config object' do - expect(subject.config.read(dut_conf)).to eq(transport: 'socket') - expect(subject.connect_to('dut')).to be_kind_of(Rbeapi::Client::Node) + it 'returns nil if connection does not exist' do + expect(subject.config_for('veos22')).to eq(nil) end end - describe '#config_for' do - it 'returns the configuration options for veos01' do - expect(subject.config.read(test_conf)).to eq(nil) - expect(subject.config_for('veos01')).to eq(veos01) + describe '#connect_to' do + it 'retrieves the node config' do + expect(subject.connect_to('veos01')).to be_truthy end - it 'returns the configuration options for veos05' do - expect(subject.config.read(test_conf)).to eq(nil) - expect(subject.config_for('veos05')).to eq(veos05) + it 'returns nil if connection does not exist' do + expect(subject.connect_to('veos22')).to eq(nil) end end describe '#load_config' do it 'overrides the default conf file loaded in the config' do expect(subject.load_config(test_conf)).to eq(nil) + end + + it 'returns nil if connection does not exit' do + expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('dut')).to eq(nil) + end + + it 'returns conf settings if connection exists' do + expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('veos01')).to eq(veos01) end end @@ -100,13 +135,19 @@ def test_conf # Config class methods describe 'config' do it 'gets the loaded configuration file data' do + expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config.to_s).to include(test_data[0]) end end describe '#read' do - it 'read the specified filename and load it' do - expect(subject.load_config(dut_conf)).to eq(transport: 'socket') + it 'read the specified filename and load dut' do + expect(subject.config.read(dut_conf)).to eq(transport: 'socket') + expect(subject.config.to_s) + .to include('host', 'username', 'password', '[connection:dut]') + end + + it 'read the specified filename and load test' do expect(subject.config.read(test_conf)).to eq(nil) expect(subject.config.to_s).to include(test_data[0]) end @@ -124,11 +165,11 @@ def test_conf describe '#reload' do it 'reloads the configuration file' do - expect(subject.load_config(dut_conf)) + expect(subject.config.get_connection('veos01')).to eq(veos01) + expect(subject.config.reload(filename: [dut_conf])) .to eq(transport: 'socket') - expect(subject.config.reload(filename: [test_conf])) - .to eq(nil) - expect(subject.config.to_s).to include(test_data[0]) + expect(subject.config.get_connection('veos01')).to eq(nil) + expect(subject.config.get_connection('dut')).not_to be_nil end end @@ -143,19 +184,38 @@ def test_conf password: 'test', transport: 'http', host: 'test2') + expect(subject.config.get_connection('test2')) + .to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') end end # Node Class Methods + describe 'node' do + it 'retrieves the node' do + expect(node).to be_kind_of(Rbeapi::Client::Node) + end + end + describe '#running_config' do it 'gets the nodes running config' do - expect(node.running_config).not_to be_nil + expect(node.running_config).to be_truthy + end + + it 'expects running config to return a string' do + expect(node.running_config).to be_kind_of(String) end end describe '#startup_config' do it 'gets the nodes startup-configuration' do - expect(node.startup_config).not_to be_nil + expect(node.startup_config).to be_truthy + end + + it 'expects startup-configuration to be a string' do + expect(node.startup_config).to be_kind_of(String) end end @@ -167,46 +227,81 @@ def test_conf describe '#config' do it 'puts switch into config mode' do - expect(node.config(['no ip virtual-router mac-address'])).to be_truthy + expect(node.config(['no ip virtual-router mac-address'])) + .to be_truthy end - it 'puts switch into config mode with options' do + it 'expects config to return array' do + expect(node.config(['no ip virtual-router mac-address'])) + .to be_kind_of(Array) + end + + it 'puts switch into config mode with options and returns array' do expect(node.config(['no ip virtual-router mac-address'], encoding: 'json', open_timeout: 27.00, - read_timeout: 27.00)).to be_truthy + read_timeout: 27.00)) + .to be_kind_of(Array) + end + + describe 'set dry run' do + before do + # Prevents puts from writing to console + allow($stdout).to receive(:puts) + node.dry_run = true + end + + it 'expects config to do dry run' do + expect(node.config(['no ip virtual-router mac-address'])) + .to eq(nil) + end + end + + it 'returns error if invalid command' do + expect { node.config(['no ip virtual-router mac-addresses']) } + .to raise_error Rbeapi::Eapilib::CommandError end end describe '#enable' do it 'puts the switch into privilege mode' do - expect(node.enable('show hostname')[0]) - .to include(:command, :result, :encoding) + expect(node.enable('show hostname')[0][:result]) + .to include('fqdn', 'hostname') end it 'puts the switch into privilege mode with encoding' do - expect(node.enable('show hostname', encoding: 'text')[0]) + expect(node.enable('show hostname', encoding: 'text')[0][:encoding]) + .to eq('text') + end + + it 'puts the switch into privilege mode with strict option' do + expect(node.enable('show hostname', strict: true)[0]) .to include(:command, :result, :encoding) end - it 'puts the switch into privilege mode with open and read timeout' do + it 'puts the switch into privilege mode with read and open timeout' do expect(node.enable('show hostname', open_timeout: 29, read_timeout: 29)[0]).to include(:command, :result, :encoding) end + + it 'raises invalid command error' do + expect { node.enable(['show hostname', 'do this thing']) } + .to raise_error Rbeapi::Eapilib::CommandError + end end describe '#run_commands' do - it 'sends commands to node' do - expect(node.run_commands(['show hostname'])[0]) - .to include('fqdn', 'hostname') + it 'expects run_commands to be a string' do + expect(node.run_commands('show hostname', encoding: 'text')[0]['output']) + .to be_kind_of String end it 'sends commands to node with encoding' do expect(node.run_commands('show hostname', encoding: 'text')[0]['output']) - .to include('FQDN', 'Hostname') + .to include('FQDN:', 'Hostname:') end it 'sends commands with open and read timeout' do @@ -215,12 +310,43 @@ def test_conf read_timeout: 26)[0]).to include('fqdn', 'hostname') end + + it 'sends commands with enablepwd set' do + expect(node.enable_authentication('icanttellyou')).to eq('icanttellyou') + expect(node.run_commands('show hostname')).to be_truthy + end + + it 'expects run_commands to raise a command error' do + expect { node.run_commands('do this thing') } + .to raise_error Rbeapi::Eapilib::CommandError + end + end + + describe '#get_config' do + it 'will retrieve the specified configuration and return array' do + expect(node.get_config(config: 'running-config')) + .to be_kind_of(Array) + end + + it 'will retrieve with param and return array' do + expect(node.get_config(config: 'running-config', param: 'all')) + .to be_kind_of(Array) + end + + it 'raises invalid command error' do + expect { node.get_config(config: 'running-configurations') } + .to raise_error Rbeapi::Eapilib::CommandError + end end describe '#api' do it 'returns api module' do expect(node.api('vlans')).to be_kind_of(Rbeapi::Api::Vlans) end + + it 'returns error if invalid name' do + expect { node.api('vlanss') }.to raise_error + end end describe '#refresh' do diff --git a/spec/unit/rbeapi/client/default_spec.rb b/spec/unit/rbeapi/client/default_spec.rb deleted file mode 100644 index 57f142d..0000000 --- a/spec/unit/rbeapi/client/default_spec.rb +++ /dev/null @@ -1,345 +0,0 @@ -# -# Copyright (c) 2015, Arista Networks, Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# Neither the name of Arista Networks nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -require 'spec_helper' - -require 'rbeapi/client' - -include FixtureHelpers - -describe Rbeapi::Client do - subject { described_class } - - let(:node) do - subject.config.read(fixture_file('dut.conf')) - subject.connect_to('dut') - end - - def dut_conf - fixture_file('dut.conf') - end - - def test_conf - fixture_file('test.conf') - end - - let(:dut) do - File.read(dut_conf) - end - - let(:test) do - File.read(test_conf) - end - - let(:veos01) do - { - 'username' => 'eapi', - 'password' => 'password', - 'transport' => 'http', - 'host' => 'veos01' - } - end - - let(:veos05) do - { - 'host' => '172.16.131.40', - 'username' => 'admin', - 'password' => 'admin', - 'enablepwd' => 'password', - 'transport' => 'https', - 'port' => 1234, - 'open_timeout' => 12, - 'read_timeout' => 12 - } - end - - let(:test_data) do - [ - '[connection:veos01]', - '[connection:veos02]', - '[connection:veos03', - '[connection:veos04]', - '[connection:veos05]', - '[connection: localhost]', - 'username', - 'password', - 'transport', - 'host' - ] - end - - # Client class methods - describe '#config_for' do - it 'returns the configuration options for the connection' do - expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config_for('veos01')).to eq(veos01) - end - - it 'returns nil if connection does not exist' do - expect(subject.config_for('veos22')).to eq(nil) - end - end - - describe '#connect_to' do - it 'retrieves the node config' do - expect(subject.connect_to('veos01')).to be_truthy - end - - it 'returns nil if connection does not exist' do - expect(subject.connect_to('veos22')).to eq(nil) - end - end - - describe '#load_config' do - it 'overrides the default conf file loaded in the config' do - expect(subject.load_config(test_conf)).to eq(nil) - end - - it 'returns nil if connection does not exit' do - expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config_for('dut')).to eq(nil) - end - - it 'returns conf settings if connection exists' do - expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config_for('veos01')).to eq(veos01) - end - end - - # Config class methods - describe 'config' do - it 'gets the loaded configuration file data' do - expect(subject.load_config(test_conf)).to eq(nil) - expect(subject.config.to_s).to include(test_data[0]) - end - end - - describe '#read' do - it 'read the specified filename and load dut' do - expect(subject.config.read(dut_conf)).to eq(transport: 'socket') - expect(subject.config.to_s) - .to include('host', 'username', 'password', '[connection:dut]') - end - - it 'read the specified filename and load test' do - expect(subject.config.read(test_conf)).to eq(nil) - expect(subject.config.to_s).to include(test_data[0]) - end - end - - describe '#get_connection' do - it 'get connection veos01' do - expect(subject.config.get_connection('veos01')).to eq(veos01) - end - - it 'get connection veos05' do - expect(subject.config.get_connection('veos05')).to eq(veos05) - end - end - - describe '#reload' do - it 'reloads the configuration file' do - expect(subject.config.get_connection('veos01')).to eq(veos01) - expect(subject.config.reload(filename: [dut_conf])) - .to eq(transport: 'socket') - expect(subject.config.get_connection('veos01')).to eq(nil) - expect(subject.config.get_connection('dut')).not_to be_nil - end - end - - describe '#add_connection' do - it 'adds a new connection section' do - expect(subject.config.add_connection('test2', - username: 'test2', - password: 'test', - transport: 'http', - host: 'test2' - )).to eq(username: 'test2', - password: 'test', - transport: 'http', - host: 'test2') - expect(subject.config.get_connection('test2')) - .to eq(username: 'test2', - password: 'test', - transport: 'http', - host: 'test2') - end - end - - # Node Class Methods - describe '#running_config' do - it 'gets the nodes running config' do - expect(node.running_config).to be_truthy - end - - it 'expects running config to return a string' do - expect(node.running_config).to be_kind_of(String) - end - end - - describe '#startup_config' do - it 'gets the nodes startup-configuration' do - expect(node.startup_config).to be_truthy - end - - it 'expects startup-configuration to be a string' do - expect(node.startup_config).to be_kind_of(String) - end - end - - describe '#enable_authentication' do - it 'gets the nodes startup-configuration' do - expect(node.enable_authentication('newpassword')).to eq('newpassword') - end - end - - describe '#config' do - it 'puts switch into config mode' do - expect(node.config(['no ip virtual-router mac-address'])) - .to be_truthy - end - - it 'expects config to return array' do - expect(node.config(['no ip virtual-router mac-address'])) - .to be_kind_of(Array) - end - - it 'puts switch into config mode with options and returns array' do - expect(node.config(['no ip virtual-router mac-address'], - encoding: 'json', - open_timeout: 27.00, - read_timeout: 27.00)) - .to be_kind_of(Array) - end - - describe 'set dry run' do - before do - # Prevents puts from writing to console - allow($stdout).to receive(:puts) - node.dry_run = true - end - - it 'expects config to do dry run' do - expect(node.config(['no ip virtual-router mac-address'])) - .to eq(nil) - end - end - - it 'returns error if invalid command' do - expect { node.config(['no ip virtual-router mac-addresses']) } - .to raise_error Rbeapi::Eapilib::CommandError - end - end - - describe '#enable' do - it 'puts the switch into privilege mode' do - expect(node.enable('show hostname')[0][:result]) - .to include('fqdn', 'hostname') - end - - it 'puts the switch into privilege mode with encoding' do - expect(node.enable('show hostname', encoding: 'text')[0][:encoding]) - .to eq('text') - end - - it 'puts the switch into privilege mode with strict option' do - expect(node.enable('show hostname', strict: true)[0]) - .to include(:command, :result, :encoding) - end - - it 'puts the switch into privilege mode with read and open timeout' do - expect(node.enable('show hostname', - read_timeout: 29, - open_timeout: 29)[0]) - .to include(:command, :result, :encoding) - end - - it 'raises invalid command error' do - expect { node.enable(['show hostname', 'do this thing']) } - .to raise_error Rbeapi::Eapilib::CommandError - end - end - - describe '#run_commands' do - it 'expects run_commands to be a string' do - expect(node.run_commands('show hostname', encoding: 'text')[0]['output']) - .to be_kind_of String - end - - it 'send commands to node' do - expect(node.run_commands('show hostname', encoding: 'text')[0]['output']) - .to include('Hostname:', 'FQDN:') - end - - it 'sends commands with enablepwd set' do - expect(node.enable_authentication('icanttellyou')).to eq('icanttellyou') - expect(node.run_commands('show hostname')).to be_truthy - end - - it 'expects run_commands to raise a command error' do - expect { node.run_commands('do this thing') } - .to raise_error Rbeapi::Eapilib::CommandError - end - end - - describe '#get_config' do - it 'will retrieve the specified configuration and return array' do - expect(node.get_config(config: 'running-config')) - .to be_kind_of(Array) - end - - it 'will retrieve with param and return array' do - expect(node.get_config(config: 'running-config', param: 'all')) - .to be_kind_of(Array) - end - - it 'raises invalid command error' do - expect { node.get_config(config: 'running-configurations') } - .to raise_error Rbeapi::Eapilib::CommandError - end - end - - describe '#api' do - it 'returns api module' do - expect(node.api('vlans')).to be_kind_of(Rbeapi::Api::Vlans) - end - - it 'returns error if invalid name' do - expect { node.api('vlanss') }.to raise_error - end - end - - describe '#refresh' do - it 'refreshes configs for next call' do - expect(node.refresh).to eq(nil) - end - end -end From ca2db980cb0b58eb952ee6a48f66e9c32fb84f00 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 4 Jan 2016 12:55:26 -0700 Subject: [PATCH 080/110] Add unit tests back. --- spec/unit/rbeapi/client_spec.rb | 168 ++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 spec/unit/rbeapi/client_spec.rb diff --git a/spec/unit/rbeapi/client_spec.rb b/spec/unit/rbeapi/client_spec.rb new file mode 100644 index 0000000..57af804 --- /dev/null +++ b/spec/unit/rbeapi/client_spec.rb @@ -0,0 +1,168 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/client' + +include FixtureHelpers + +describe Rbeapi::Client do + subject { described_class } + + let(:node) { double('node') } + + def dut_conf + fixture_file('dut.conf') + end + + def test_conf + fixture_file('test.conf') + end + + let(:dut) do + File.read(dut_conf) + end + + let(:test) do + File.read(test_conf) + end + + let(:veos01) do + { + 'username' => 'eapi', + 'password' => 'password', + 'transport' => 'http', + 'host' => 'veos01' + } + end + + let(:veos05) do + { + 'host' => '172.16.131.40', + 'username' => 'admin', + 'password' => 'admin', + 'enablepwd' => 'password', + 'transport' => 'https', + 'port' => 1234, + 'open_timeout' => 12, + 'read_timeout' => 12 + } + end + + let(:test_data) do + [ + '[connection:veos01]', + '[connection:veos02]', + '[connection:veos03', + '[connection:veos04]', + '[connection:veos05]', + '[connection: localhost]', + 'username', + 'password', + 'transport', + 'host' + ] + end + + # Client class methods + describe '#config_for' do + it 'returns the configuration options for the connection' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) + end + end + + describe '#connect_to' do + it 'retrieves the node config' do + expect(subject.connect_to('veos01')).to be_truthy + end + end + + describe '#load_config' do + it 'overrides the default conf file loaded in the config' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config_for('dut')).to eq(nil) + expect(subject.config_for('veos01')).to eq(veos01) + end + end + + # Config class methods + describe 'config' do + it 'gets the loaded configuration file data' do + expect(subject.load_config(test_conf)).to eq(nil) + expect(subject.config.to_s).to include(test_data[0]) + end + end + + describe '#read' do + it 'read the specified filename and load it' do + expect(subject.load_config(dut_conf)).to eq(transport: 'socket') + expect(subject.config.read(test_conf)).to eq(nil) + expect(subject.config.to_s).to include(test_data[0]) + end + end + + describe '#get_connection' do + it 'get connection dut' do + expect(subject.config.get_connection('veos01')).to eq(veos01) + end + end + + describe '#reload' do + it 'reloads the configuration file' do + expect(subject.config.get_connection('veos01')).to eq(veos01) + expect(subject.config.reload(filename: [dut_conf])) + .to eq(transport: 'socket') + expect(subject.config.get_connection('veos01')).to eq(nil) + expect(subject.config.get_connection('dut')).not_to be_nil + end + end + + describe '#add_connection' do + it 'adds a new connection section' do + expect(subject.config.add_connection('test2', + username: 'test2', + password: 'test', + transport: 'http', + host: 'test2' + )).to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') + expect(subject.config.get_connection('test2')) + .to eq(username: 'test2', + password: 'test', + transport: 'http', + host: 'test2') + end + end +end From a935980552d5046c49051a20c683d37b4cc9831e Mon Sep 17 00:00:00 2001 From: John Corbin Date: Tue, 5 Jan 2016 06:27:26 -0800 Subject: [PATCH 081/110] Relax check on getall entries Routemaps that exist on the switch before test was run will be returned by getall. There is no easy way to clear out all the routemaps and didn't want to loop on the entries not created by test and delete them. --- spec/system/rbeapi/api/routemaps_spec.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/spec/system/rbeapi/api/routemaps_spec.rb b/spec/system/rbeapi/api/routemaps_spec.rb index 4b6edca..a40b456 100644 --- a/spec/system/rbeapi/api/routemaps_spec.rb +++ b/spec/system/rbeapi/api/routemaps_spec.rb @@ -15,8 +15,7 @@ let(:resource) { subject.get } before do - node.config(['no route-map test', 'no route-map test1', - 'no route-map test2', 'no route-map test3', + node.config(['no route-map test', 'route-map test permit 10', 'route-map test permit 20', 'description descript', 'match ip address prefix-list MYLOOPBACK', @@ -90,8 +89,8 @@ expect(subject.getall).to be_a_kind_of(Hash) end - it 'has a key for description' do - expect(subject.getall.count).to eq(2) + it 'has at least two entries' do + expect(subject.getall.count).to be > 2 end it 'returns the routemap collection' do From 570c95c08fa20eb507abde223241f127a1262d03 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Wed, 6 Jan 2016 21:02:25 -0700 Subject: [PATCH 082/110] test timeout values --- lib/rbeapi/eapilib.rb | 8 ++++++++ spec/system/rbeapi/client_spec.rb | 19 +++++++++++++++++++ spec/unit/rbeapi/client_spec.rb | 2 -- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/rbeapi/eapilib.rb b/lib/rbeapi/eapilib.rb index c16bce2..9472e67 100644 --- a/lib/rbeapi/eapilib.rb +++ b/lib/rbeapi/eapilib.rb @@ -162,6 +162,14 @@ def timeouts(opts = {}) @read_timeout = opts.fetch(:read_timeout, DEFAULT_HTTP_READ_TIMEOUT) end + ## + # Gets values for open_timeout and read_timeout + # + # @return [Hash] open_timeout and read_timeout + def get_timeouts + { open_timeout: @open_timeout, read_timeout: @read_timeout } + end + ## # Generates the eAPI JSON request message. # diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb index df3269d..b422caf 100644 --- a/spec/system/rbeapi/client_spec.rb +++ b/spec/system/rbeapi/client_spec.rb @@ -354,4 +354,23 @@ def test_conf expect(node.refresh).to eq(nil) end end + + describe 'test timeouts' do + it 'loads default timeout values' do + expect(node.connection.get_timeouts).to eq(open_timeout: 10, + read_timeout: 10) + end + + describe 'loads veos05' do + let(:node) do + subject.config.read(fixture_file('test.conf')) + subject.connect_to('veos05') + end + + it 'loads timeout values from conf file' do + expect(node.connection.get_timeouts).to eq(open_timeout: 12, + read_timeout: 12) + end + end + end end diff --git a/spec/unit/rbeapi/client_spec.rb b/spec/unit/rbeapi/client_spec.rb index 57af804..2e52615 100644 --- a/spec/unit/rbeapi/client_spec.rb +++ b/spec/unit/rbeapi/client_spec.rb @@ -38,8 +38,6 @@ describe Rbeapi::Client do subject { described_class } - let(:node) { double('node') } - def dut_conf fixture_file('dut.conf') end From 7ea4e7092aab711645ceb49276ff87cd13dbb03c Mon Sep 17 00:00:00 2001 From: John Corbin Date: Wed, 6 Jan 2016 20:29:47 -0800 Subject: [PATCH 083/110] Test check should be at least 2, not more than 2. --- spec/system/rbeapi/api/routemaps_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/rbeapi/api/routemaps_spec.rb b/spec/system/rbeapi/api/routemaps_spec.rb index a40b456..ee3cff4 100644 --- a/spec/system/rbeapi/api/routemaps_spec.rb +++ b/spec/system/rbeapi/api/routemaps_spec.rb @@ -90,7 +90,7 @@ end it 'has at least two entries' do - expect(subject.getall.count).to be > 2 + expect(subject.getall.count).to be >= 2 end it 'returns the routemap collection' do From addc94ff50c80507677264a4c8b94fd8f1073450 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Thu, 7 Jan 2016 11:19:45 -0700 Subject: [PATCH 084/110] Get initial unit tests running. --- .../rbeapi/api/switchports/default_spec.rb | 245 +++++++++++++++ .../api/switchports/fixture_switchports.text | 284 ++++++++++++++++++ 2 files changed, 529 insertions(+) create mode 100644 spec/unit/rbeapi/api/switchports/default_spec.rb create mode 100644 spec/unit/rbeapi/api/switchports/fixture_switchports.text diff --git a/spec/unit/rbeapi/api/switchports/default_spec.rb b/spec/unit/rbeapi/api/switchports/default_spec.rb new file mode 100644 index 0000000..d34dccf --- /dev/null +++ b/spec/unit/rbeapi/api/switchports/default_spec.rb @@ -0,0 +1,245 @@ +# +# Copyright (c) 2015, Arista Networks, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Arista Networks nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +require 'spec_helper' + +require 'rbeapi/api/switchports' + +include FixtureHelpers + +describe Rbeapi::Api::Switchports do + subject { described_class.new(node) } + + let(:node) { double('node') } + + def switchports + switchports = Fixtures[:switchports] + return switchports if switchports + fixture('switchports', format: :text, dir: File.dirname(__FILE__)) + end + + before :each do + allow(subject.node).to receive(:running_config).and_return(switchports) + end + + describe '#get' do + let(:keys) do + [:mode, :access_vlan, :trunk_native_vlan, :trunk_allowed_vlans, + :trunk_groups] + end + + context 'vlan as an integer range' do + it 'returns the switchport resource' do + expect(subject.get('Ethernet1')).not_to be_nil + end + + it 'does not return a nonswitchport resource' do + expect(subject.get('Ethernet2')).to be_nil + end + + it 'has all required keys' do + expect(subject.get('Ethernet1').keys).to eq(keys) + end + + it 'returns allowed_vlans as an array' do + expect(subject.get('Ethernet1')[:trunk_allowed_vlans]) + .to be_a_kind_of(Array) + end + end + + context 'vlan as an integer' do + it 'returns the switchport resource' do + expect(subject.get('Ethernet1')).not_to be_nil + end + end + end + + describe '#getall' do + it 'returns the switchport collection' do + expect(subject.getall).to include('Ethernet1') + end + + it 'returns a hash collection' do + expect(subject.getall).to be_a_kind_of(Hash) + end + end + + describe '#create' do + it 'creates a new switchport resource' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'no ip address', 'switchport']) + expect(subject.create('Ethernet1')).to be_truthy + end + end + + describe '#delete' do + it 'deletes a switchport resource' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'no switchport']) + expect(subject.delete('Ethernet1')).to be_truthy + end + end + + describe '#default' do + it 'sets Ethernet1 to default' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'default switchport']) + expect(subject.default('Ethernet1')).to be_truthy + end + end + + describe '#set_mode' do + it 'sets mode value to access' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'switchport mode access']) + expect(subject.set_mode('Ethernet1', value: 'access')).to be_truthy + end + + it 'sets the mode value to trunk' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'switchport mode trunk']) + expect(subject.set_mode('Ethernet1', value: 'trunk')).to be_truthy + end + + it 'negate the mode value' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'no switchport mode']) + expect(subject.set_mode('Ethernet1', enable: false)).to be_truthy + end + + it 'default the mode value' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'default switchport mode']) + expect(subject.set_mode('Ethernet1', default: true)).to be_truthy + end + end + + describe '#set_access_vlan' do + it 'sets the access vlan value to 100' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'switchport access vlan 100']) + expect(subject.set_access_vlan('Ethernet1', value: '100')).to be_truthy + end + + it 'negates the access vlan value' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'no switchport access vlan']) + expect(subject.set_access_vlan('Ethernet1', enable: false)).to be_truthy + end + + it 'defaults the access vlan value' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'default switchport access vlan']) + expect(subject.set_access_vlan('Ethernet1', default: true)).to be_truthy + end + end + + describe '#set_trunk_native_vlan' do + it 'sets the trunk native vlan to 100' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'switchport trunk native vlan 100']) + expect(subject.set_trunk_native_vlan('Ethernet1', value: '100')) + .to be_truthy + end + + it 'negates the trunk native vlan' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'no switchport trunk native vlan']) + expect(subject.set_trunk_native_vlan('Ethernet1', enable: false)) + .to be_truthy + end + + it 'defaults the trunk native vlan' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'default switchport trunk native vlan']) + expect(subject.set_trunk_native_vlan('Ethernet1', default: true)) + .to be_truthy + end + end + + describe '#set_trunk_allowed_vlans' do + it 'raises an ArgumentError if value is not an array' do + expect { subject.set_trunk_allowed_vlans('Ethernet1', value: '1-100') } + .to raise_error(ArgumentError) + end + + it 'sets vlan 8 and 9 to the trunk allowed vlans' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'switchport trunk allowed vlan none', + 'switchport trunk allowed vlan 8,9']) + expect(subject.set_trunk_allowed_vlans('Ethernet1', value: [8, 9])) + .to be_truthy + end + + it 'negate switchport trunk allowed vlan' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'no switchport trunk allowed vlan']) + expect(subject.set_trunk_allowed_vlans('Ethernet1', enable: false)) + .to be_truthy + end + + it 'default switchport trunk allowed vlan' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'default switchport trunk allowed vlan']) + expect(subject.set_trunk_allowed_vlans('Ethernet1', default: true)) + .to be_truthy + end + end + + describe '#set_trunk_groups' do + it 'raises an ArgumentError if value is not an array' do + expect { subject.set_trunk_groups('Ethernet1', value: 'foo') } + .to raise_error(ArgumentError) + end + + it 'sets trunk group to foo bar bang' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'switchport trunk group foo', + 'switchport trunk group bar', 'switchport trunk group bang']) + expect(subject.set_trunk_groups('Ethernet1', value: %w(foo bar bang))) + .to be_truthy + end + + it 'negate switchport trunk group' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'no switchport trunk group']) + expect(subject.set_trunk_groups('Ethernet1', enable: false)) + .to be_truthy + end + + it 'default switchport trunk group' do + expect(node).to receive(:config) + .with(['interface Ethernet1', 'default switchport trunk group']) + expect(subject.set_trunk_groups('Ethernet1', default: true)) + .to be_truthy + end + end +end diff --git a/spec/unit/rbeapi/api/switchports/fixture_switchports.text b/spec/unit/rbeapi/api/switchports/fixture_switchports.text new file mode 100644 index 0000000..060b80c --- /dev/null +++ b/spec/unit/rbeapi/api/switchports/fixture_switchports.text @@ -0,0 +1,284 @@ +interface Ethernet1 + no description + no shutdown + default load-interval + logging event link-status use-global + no dcbx mode + no mac-address + no link-debounce + no flowcontrol send + no flowcontrol receive + no mac timestamp + no speed + no l2 mtu + default logging event congestion-drops + default unidirectional + switchport access vlan 1 + switchport trunk native vlan 1 + switchport trunk allowed vlan 1-4094 + switchport mode access + switchport mac address learning + no switchport private-vlan mapping + switchport + default encapsulation dot1q vlan + no l2-protocol encapsulation dot1q vlan 0 + snmp trap link-status + no channel-group + lacp rate normal + lacp port-priority 32768 + lldp transmit + lldp receive + no msrp + no mvrp + no switchport port-security + switchport port-security maximum 1 + default qos trust + qos cos 5 + qos dscp 2 + no shape rate + mc-tx-queue 0 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + mc-tx-queue 1 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + mc-tx-queue 2 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + mc-tx-queue 3 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 0 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 1 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 2 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 3 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 4 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 5 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 6 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 7 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + sflow enable + no spanning-tree portfast + spanning-tree portfast auto + no spanning-tree link-type + no spanning-tree bpduguard + no spanning-tree bpdufilter + no spanning-tree cost + spanning-tree port-priority 128 + no spanning-tree guard + no spanning-tree bpduguard rate-limit + logging event spanning-tree use-global + switchport tap native vlan 1 + no switchport tap identity + switchport tap allowed vlan 1-4094 + switchport tool allowed vlan 1-4094 + no switchport tool identity + no switchport tap truncation + no switchport tool truncation + no switchport tap default group + no switchport tool group + no switchport tool dot1q remove outer +! +interface Ethernet2 + no description + no shutdown + default load-interval + mtu 1500 + logging event link-status use-global + no dcbx mode + no mac-address + no link-debounce + no flowcontrol send + no flowcontrol receive + no mac timestamp + no speed + no l2 mtu + default logging event congestion-drops + default unidirectional + no switchport + default encapsulation dot1q vlan + no l2-protocol encapsulation dot1q vlan 0 + snmp trap link-status + no ip proxy-arp + no ip local-proxy-arp + no ip address + no ip verify unicast + default arp timeout 14400 + default ipv6 nd cache expire 14400 + bfd interval 300 min_rx 300 multiplier 3 + no bfd echo + default ip dhcp smart-relay + no ip helper-address + no ipv6 dhcp relay destination + ip dhcp relay information option circuit-id Ethernet2 + no ip igmp + ip igmp version 3 + ip igmp last-member-query-count 2 + ip igmp last-member-query-interval 10 + ip igmp query-max-response-time 100 + ip igmp query-interval 125 + ip igmp startup-query-count 2 + ip igmp startup-query-interval 310 + ip igmp router-alert optional connected + ip igmp host-proxy + no ip igmp host-proxy report-interval + ip igmp host-proxy version 3 + no ip igmp host-proxy + no ipv6 enable + no ipv6 address + no ipv6 verify unicast + no ipv6 nd ra suppress + ipv6 nd ra interval msec 200000 + ipv6 nd ra lifetime 1800 + no ipv6 nd ra mtu suppress + no ipv6 nd managed-config-flag + no ipv6 nd other-config-flag + ipv6 nd reachable-time 0 + ipv6 nd router-preference medium + ipv6 nd ra dns-servers lifetime 300 + ipv6 nd ra dns-suffixes lifetime 300 + ipv6 nd ra hop-limit 64 + no channel-group + lacp rate normal + lacp port-priority 32768 + lldp transmit + lldp receive + ip mfib fastdrop + no msrp + no mvrp + default ntp serve + no ip pim sparse-mode + no ip pim border-router + ip pim query-interval 30 + ip pim join-prune-interval 60 + ip pim dr-priority 1 + no ip pim neighbor-filter + default ip pim bfd-instance + no ip pim bsr-border + default qos trust + qos cos 5 + qos dscp 2 + no shape rate + mc-tx-queue 0 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + mc-tx-queue 1 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + mc-tx-queue 2 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + mc-tx-queue 3 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 0 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 1 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 2 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 3 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 4 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 5 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 6 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + ! + uc-tx-queue 7 + priority strict + no bandwidth percent + no shape rate + no bandwidth guaranteed + sflow enable +! From b96089d6f88778d6e2b8c0d06f7fc6c4f1fa00b9 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Thu, 7 Jan 2016 17:01:47 -0700 Subject: [PATCH 085/110] Ensure all parse methods are private. --- lib/rbeapi/api/dns.rb | 3 +++ lib/rbeapi/api/logging.rb | 1 + lib/rbeapi/api/ntp.rb | 1 + lib/rbeapi/api/system.rb | 2 ++ 4 files changed, 7 insertions(+) diff --git a/lib/rbeapi/api/dns.rb b/lib/rbeapi/api/dns.rb index 9263020..30f2b1e 100644 --- a/lib/rbeapi/api/dns.rb +++ b/lib/rbeapi/api/dns.rb @@ -64,17 +64,20 @@ def parse_domain_name mdata = /ip domain-name ([\w.]+)/.match(config) { domain_name: mdata.nil? ? '' : mdata[1] } end + private :parse_domain_name def parse_name_servers servers = config.scan(/(?:ip name-server vrf )(?:\w+)\s(.+)/) values = servers.each_with_object([]) { |srv, arry| arry << srv.first } { name_servers: values } end + private :parse_name_servers def parse_domain_list search = config.scan(/(?<=^ip\sdomain-list\s).+$/) { domain_list: search } end + private :parse_domain_list ## # Configure the domain-name value in the running-config diff --git a/lib/rbeapi/api/logging.rb b/lib/rbeapi/api/logging.rb index dc9816e..d21a00a 100644 --- a/lib/rbeapi/api/logging.rb +++ b/lib/rbeapi/api/logging.rb @@ -80,6 +80,7 @@ def parse_hosts hosts = config.scan(/(?<=^logging\shost\s)[^\s]+/) { hosts: hosts } end + private :parse_hosts ## # set_enable configures the global logging instance on the node as either diff --git a/lib/rbeapi/api/ntp.rb b/lib/rbeapi/api/ntp.rb index 337a794..9b6403e 100644 --- a/lib/rbeapi/api/ntp.rb +++ b/lib/rbeapi/api/ntp.rb @@ -95,6 +95,7 @@ def parse_servers end { servers: values } end + private :parse_servers ## # set_source_interface configures the ntp source value in the nodes diff --git a/lib/rbeapi/api/system.rb b/lib/rbeapi/api/system.rb index 45fceaa..bcabbfc 100644 --- a/lib/rbeapi/api/system.rb +++ b/lib/rbeapi/api/system.rb @@ -62,11 +62,13 @@ def parse_hostname(config) mdata = /(?<=^hostname\s)(.+)$/.match(config) { hostname: mdata.nil? ? '' : mdata[1] } end + private :parse_hostname def parse_iprouting(config) mdata = /no\sip\srouting/.match(config) { iprouting: mdata.nil? ? true : false } end + private :parse_iprouting ## # Configures the system hostname value in the running-config From f865ffbfd2d2f15dbdcdc4ace059cc9153dbad3d Mon Sep 17 00:00:00 2001 From: John Corbin Date: Fri, 8 Jan 2016 10:06:54 -0800 Subject: [PATCH 086/110] Catch errors and syslog them when parsing eapi conf file. Created utils method to syslog warning messages. Updated add_connection to return nil instead of returning connection values. Updated tests to deal with add_connection return value change. Added test case for bad conf file and empty conf file. Added test case to verify EAPI_CONF path is used. Fixes issue #82 --- lib/rbeapi/client.rb | 17 ++++++---- lib/rbeapi/utils.rb | 10 ++++++ spec/fixtures/eapi.conf.yaml | 6 ++++ spec/fixtures/empty.conf | 0 spec/fixtures/env_path.conf | 5 +++ spec/system/rbeapi/client_spec.rb | 32 +++---------------- spec/unit/rbeapi/client_spec.rb | 53 +++++++++++++++++++++---------- 7 files changed, 71 insertions(+), 52 deletions(-) create mode 100644 spec/fixtures/eapi.conf.yaml create mode 100644 spec/fixtures/empty.conf create mode 100644 spec/fixtures/env_path.conf diff --git a/lib/rbeapi/client.rb b/lib/rbeapi/client.rb index 640c0dd..4395a87 100644 --- a/lib/rbeapi/client.rb +++ b/lib/rbeapi/client.rb @@ -90,7 +90,7 @@ def config_for(name) end ## - # Retrieves the node config form the loaded configuration file and + # Retrieves the node config from the loaded configuration file and # returns a Rbeapi::Node instance for working with the remote node. # # @param [String] :name The named configuration to use for creating the @@ -110,10 +110,7 @@ def connect_to(name) ## # Builds a connection object to a remote node using the specified # options and return an instance of Rbeapi::Connection. All - # configuration options can be passed via the :opts param or can be - # overridden using environment variables. Environment variables are - # specified by prepending EAPI to the option name. For instance to - # override the host param use EAPI_HOST. + # configuration options can be passed via the :opts param. # # @param [Hash] :opts the options to create a message with # @option :opts [String] :host The IP address or hostname of the remote @@ -205,7 +202,12 @@ def autoload(opts = {}) # # @param [String] :filename The full path to the filename to load def read(filename) - super(filename: filename) + begin + super(filename: filename) + rescue IniFile::Error => exc + Rbeapi::Utils.syslog_warning("#{exc}: in eapi conf file: #{filename}") + return + end # For each section, if the host parameter is omitted then the # connection name is used @@ -252,13 +254,14 @@ def get_connection(name) end ## - # Adds a new connection section to the current configuration + # Adds a new connection section to the current configuration # # @param [String] :name The name of the connection to add to the # configuration. # @param [Hash] :values The properties for the connection def add_connection(name, values) self["connection:#{name}"] = values + nil end end diff --git a/lib/rbeapi/utils.rb b/lib/rbeapi/utils.rb index 348e05b..d5337ab 100644 --- a/lib/rbeapi/utils.rb +++ b/lib/rbeapi/utils.rb @@ -30,6 +30,8 @@ # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # +require 'syslog' + ## # Rbeapi toplevel namespace module Rbeapi @@ -64,5 +66,13 @@ def self.class_from_string(name) mod.const_get(cls) end end + + ## + # Syslogs a warning message. + # + # @param [String] :message The message to log. + def self.syslog_warning(message) + Syslog.open('rbeapi', Syslog::LOG_PID) { |s| s.warning message } + end end end diff --git a/spec/fixtures/eapi.conf.yaml b/spec/fixtures/eapi.conf.yaml new file mode 100644 index 0000000..9102805 --- /dev/null +++ b/spec/fixtures/eapi.conf.yaml @@ -0,0 +1,6 @@ +--- +:username: admin +:password: admin +:use_ssl: true +:port: 199 +:hostname: bogus diff --git a/spec/fixtures/empty.conf b/spec/fixtures/empty.conf new file mode 100644 index 0000000..e69de29 diff --git a/spec/fixtures/env_path.conf b/spec/fixtures/env_path.conf new file mode 100644 index 0000000..d5a5d12 --- /dev/null +++ b/spec/fixtures/env_path.conf @@ -0,0 +1,5 @@ +[connection:env_path] +host: 172.16.131.40 +username: admin +password: admin +transport: https diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb index b422caf..0e653a1 100644 --- a/spec/system/rbeapi/client_spec.rb +++ b/spec/system/rbeapi/client_spec.rb @@ -81,16 +81,7 @@ def test_conf let(:test_data) do [ - '[connection:veos01]', - '[connection:veos02]', - '[connection:veos03', - '[connection:veos04]', - '[connection:veos05]', - '[connection: localhost]', - 'username', - 'password', - 'transport', - 'host' + '[connection:veos01]' ] end @@ -142,7 +133,7 @@ def test_conf describe '#read' do it 'read the specified filename and load dut' do - expect(subject.config.read(dut_conf)).to eq(transport: 'socket') + expect(subject.config.read(dut_conf)).to eq(nil) expect(subject.config.to_s) .to include('host', 'username', 'password', '[connection:dut]') end @@ -166,8 +157,7 @@ def test_conf describe '#reload' do it 'reloads the configuration file' do expect(subject.config.get_connection('veos01')).to eq(veos01) - expect(subject.config.reload(filename: [dut_conf])) - .to eq(transport: 'socket') + expect(subject.config.reload(filename: [dut_conf])).to eq(nil) expect(subject.config.get_connection('veos01')).to eq(nil) expect(subject.config.get_connection('dut')).not_to be_nil end @@ -180,10 +170,7 @@ def test_conf password: 'test', transport: 'http', host: 'test2' - )).to eq(username: 'test2', - password: 'test', - transport: 'http', - host: 'test2') + )).to eq(nil) expect(subject.config.get_connection('test2')) .to eq(username: 'test2', password: 'test', @@ -219,12 +206,6 @@ def test_conf end end - describe '#enable_authentication' do - it 'gets the nodes startup-configuration' do - expect(node.enable_authentication('newpassword')).to eq('newpassword') - end - end - describe '#config' do it 'puts switch into config mode' do expect(node.config(['no ip virtual-router mac-address'])) @@ -311,11 +292,6 @@ def test_conf 'hostname') end - it 'sends commands with enablepwd set' do - expect(node.enable_authentication('icanttellyou')).to eq('icanttellyou') - expect(node.run_commands('show hostname')).to be_truthy - end - it 'expects run_commands to raise a command error' do expect { node.run_commands('do this thing') } .to raise_error Rbeapi::Eapilib::CommandError diff --git a/spec/unit/rbeapi/client_spec.rb b/spec/unit/rbeapi/client_spec.rb index 2e52615..51de6a6 100644 --- a/spec/unit/rbeapi/client_spec.rb +++ b/spec/unit/rbeapi/client_spec.rb @@ -46,6 +46,14 @@ def test_conf fixture_file('test.conf') end + def empty_conf + fixture_file('empty.conf') + end + + def yaml_conf + fixture_file('eapi.conf.yaml') + end + let(:dut) do File.read(dut_conf) end @@ -78,21 +86,26 @@ def test_conf let(:test_data) do [ - '[connection:veos01]', - '[connection:veos02]', - '[connection:veos03', - '[connection:veos04]', - '[connection:veos05]', - '[connection: localhost]', - 'username', - 'password', - 'transport', - 'host' + '[connection:veos01]' ] end + let(:default_entry) { "[connection:localhost]\ntransport : socket\n" } + # Client class methods describe '#config_for' do + # Verify that the EAPI_CONF env variable path is used by default + # when the Config class is instantiated/reload-ed. + it 'env path to config file' do + # Store env path for the eapi conf file and reload the class + conf = fixture_dir + '/env_path.conf' + ENV.store('EAPI_CONF', conf) + subject.config.reload + + # Verify env_path.conf file was loaded + expect(subject.config.to_s).to include('[connection:env_path]') + end + it 'returns the configuration options for the connection' do expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('veos01')).to eq(veos01) @@ -119,11 +132,21 @@ def test_conf expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config.to_s).to include(test_data[0]) end + + it 'loading empty config file does not fail' do + expect(subject.load_config(empty_conf)).to eq(nil) + expect(subject.config.to_s).to eq(default_entry) + end + + it 'does not load bad config file data' do + expect(subject.load_config(yaml_conf)).to eq(nil) + expect(subject.config.to_s).to eq('') + end end describe '#read' do it 'read the specified filename and load it' do - expect(subject.load_config(dut_conf)).to eq(transport: 'socket') + expect(subject.load_config(dut_conf)).to eq(nil) expect(subject.config.read(test_conf)).to eq(nil) expect(subject.config.to_s).to include(test_data[0]) end @@ -138,8 +161,7 @@ def test_conf describe '#reload' do it 'reloads the configuration file' do expect(subject.config.get_connection('veos01')).to eq(veos01) - expect(subject.config.reload(filename: [dut_conf])) - .to eq(transport: 'socket') + expect(subject.config.reload(filename: [dut_conf])).to eq(nil) expect(subject.config.get_connection('veos01')).to eq(nil) expect(subject.config.get_connection('dut')).not_to be_nil end @@ -152,10 +174,7 @@ def test_conf password: 'test', transport: 'http', host: 'test2' - )).to eq(username: 'test2', - password: 'test', - transport: 'http', - host: 'test2') + )).to eq(nil) expect(subject.config.get_connection('test2')) .to eq(username: 'test2', password: 'test', From 0e4857131e3786c30ab8f8515239775818843b67 Mon Sep 17 00:00:00 2001 From: John Corbin Date: Fri, 8 Jan 2016 10:19:25 -0800 Subject: [PATCH 087/110] Set enable password for a connection. Fixes issue #72 --- lib/rbeapi/client.rb | 6 +++++- spec/system/rbeapi/client_spec.rb | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/rbeapi/client.rb b/lib/rbeapi/client.rb index 4395a87..b4db988 100644 --- a/lib/rbeapi/client.rb +++ b/lib/rbeapi/client.rb @@ -105,6 +105,10 @@ def connect_to(name) config = Rbeapi::Utils.transform_keys_to_symbols(config) connection = connect config Node.new(connection) + node = Node.new(connection) + enablepwd = config.fetch(:enablepwd, nil) + node.enable_authentication(enablepwd) if enablepwd + node end ## @@ -119,7 +123,7 @@ def connect_to(name) # the eAPI connection with # @option :opts [String] :password The password to use to authenticate # the eAPI connection with - # @option :opts [String] :enable_pwd The enable password (if defined) to + # @option :opts [String] :enablepwd The enable password (if defined) to # pass to the remote node to enter privilege mode # @option :opts [String] :use_ssl Specifies whether or not to use the # HTTP or HTTPS protocol diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb index 0e653a1..a05dd99 100644 --- a/spec/system/rbeapi/client_spec.rb +++ b/spec/system/rbeapi/client_spec.rb @@ -57,6 +57,8 @@ def test_conf File.read(test_conf) end + let(:enablepwd) { 'enable_admin' } + let(:veos01) do { 'username' => 'eapi', @@ -298,6 +300,19 @@ def test_conf end end + describe '#run_commands with enable password' do + # Before the tests Set the enable password on the dut + before(:each) { node.config(["enable secret 0 #{enablepwd}"]) } + + # After the tests clear the enable password on the dut + after(:each) { node.config(['no enable secret']) } + + it 'sends commands with enablepwd set' do + expect(node.enable_authentication(enablepwd)).to eq(enablepwd) + expect(node.run_commands('show hostname')).to be_truthy + end + end + describe '#get_config' do it 'will retrieve the specified configuration and return array' do expect(node.get_config(config: 'running-config')) From 266ee60177c1c1c92608a2c88dd744ea3c17ca9d Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Sat, 9 Jan 2016 11:45:07 -0700 Subject: [PATCH 088/110] Update get and getall documentation. --- lib/rbeapi/api/aaa.rb | 50 ++++++++++++----- lib/rbeapi/api/acl.rb | 60 ++++++++++++++++++++- lib/rbeapi/api/bgp.rb | 81 ++++++++++++++++++++++++++++ lib/rbeapi/api/dns.rb | 19 +++++++ lib/rbeapi/api/interfaces.rb | 98 +++++++++++++++++++++++++--------- lib/rbeapi/api/ipinterfaces.rb | 13 ++++- lib/rbeapi/api/logging.rb | 10 +++- lib/rbeapi/api/mlag.rb | 28 ++++++---- lib/rbeapi/api/ntp.rb | 2 +- lib/rbeapi/api/ospf.rb | 31 +++++++---- lib/rbeapi/api/prefixlists.rb | 22 ++++++-- lib/rbeapi/api/radius.rb | 16 +++--- lib/rbeapi/api/routemaps.rb | 10 ++-- lib/rbeapi/api/snmp.rb | 6 +-- lib/rbeapi/api/stp.rb | 51 +++++++++++++----- lib/rbeapi/api/switchports.rb | 70 +++++++++++++++++++++++- lib/rbeapi/api/system.rb | 23 +++++++- lib/rbeapi/api/tacacs.rb | 17 +++--- lib/rbeapi/api/users.rb | 11 +++- lib/rbeapi/api/varp.rb | 46 +++++++++++++--- lib/rbeapi/api/vlans.rb | 18 +++++-- 21 files changed, 566 insertions(+), 116 deletions(-) diff --git a/lib/rbeapi/api/aaa.rb b/lib/rbeapi/api/aaa.rb index 5392136..16dd75b 100644 --- a/lib/rbeapi/api/aaa.rb +++ b/lib/rbeapi/api/aaa.rb @@ -41,6 +41,25 @@ module Api # The Aaa class manages Authorization, Authentication and Accounting (AAA) # on an EOS node. class Aaa < Entity + ## + # get returns a hash of all Aaa resources + # + # @example + # { + # : { + # : { + # type: , + # servers: + # }, + # : { + # type: , + # servers: + # } + # } + # } + # + # @return [Hash] Returns the Aaa resources as a + # Hash. If no Aaa resources are found, an empty hash is returned. def get response = {} response[:groups] = groups.getall @@ -80,18 +99,18 @@ class AaaGroups < Entity # get returns the aaa server group resource hash that describes the # current configuration for the specified server group name. # - # The resource hash returned contains the following: - # * type: (String) The server group type. Valid values are either - # 'tacacs' or 'radius'. - # * servers: (Array) The set of servers associated with the group. - # Servers are returned as either IP address or host name. + # @example + # { + # type: , + # servers: + # } # # @param [String] :name The server group name to return from the nodes # current running configuration. If the name is not configured a nil # object is returned. # # @return [nil, Hash] returns the resource hash for the - # specified name. If the name does not exist, a nil object is returned. + # specified name. If the name does not exist, a nil object is returned def get(name) block = get_block("aaa group server ([^\s]+) #{name}") return nil unless block @@ -104,12 +123,17 @@ def get(name) ## # getall returns a aaa server groups hash # - # The resource hash returned contains the following: - # * name: (String) The server group name. - # * type: (String) The server group type. Valid values are either - # 'tacacs' or 'radius' - # * servers: (Array) The set of servers associated with the group. - # Servers are returned as either IP address or host name + # @example + # { + # : { + # type: , + # servers: + # }, + # : { + # type: , + # servers: + # } + # } # # @return [Hash] returns the resource hashes for # configured aaa groups. If none exist, a nil object is returned @@ -174,7 +198,6 @@ def parse_servers(config, type) # @param [String] :config The aaa server group block configuration for the # group name to parse # - # # @return [Hash] resource hash attribute def parse_radius_server(config) values = config.scan(RADIUS_GROUP_SERVER).map do |(name, auth, acct)| @@ -199,7 +222,6 @@ def parse_radius_server(config) # @param [String] :config The aaa server group block configuration for the # group name to parse # - # # @return [Hash] resource hash attribute def parse_tacacs_server(config) values = config.scan(TACACS_GROUP_SERVER).map do |(name, vrf, port)| diff --git a/lib/rbeapi/api/acl.rb b/lib/rbeapi/api/acl.rb index 8503cd3..dafd5f7 100644 --- a/lib/rbeapi/api/acl.rb +++ b/lib/rbeapi/api/acl.rb @@ -56,10 +56,29 @@ def initialize(node) ## # get returns the specified ACL from the nodes current configuration. # + # @example + # { + # : { + # seqno: , + # action: , + # srcaddr: , + # srcprefixle: , + # log: + # }, + # : { + # seqno: , + # action: , + # srcaddr: , + # srcprefixle: , + # log: + # }, + # ... + # } + # # @param [String] :name The ACL name. # # @return [nil, Hash] Returns the ACL resource as a - # Hash. + # Hash. Returns nil if name does not exist. def get(name) config = get_block("ip access-list standard #{name}") return nil unless config @@ -72,6 +91,45 @@ def get(name) # configuration as a hash. The ACL resource collection hash is # keyed by the ACL name. # + # @example + # { + # : { + # : { + # seqno: , + # action: , + # srcaddr: , + # srcprefixle: , + # log: + # }, + # : { + # seqno: , + # action: , + # srcaddr: , + # srcprefixle: , + # log: + # }, + # ... + # }, + # : { + # : { + # seqno: , + # action: , + # srcaddr: , + # srcprefixle: , + # log: + # }, + # : { + # seqno: , + # action: , + # srcaddr: , + # srcprefixle: , + # log: + # }, + # ... + # }, + # ... + # } + # # @return [nil, Hash] Returns a hash that represents # the entire ACL collection from the nodes running configuration. # If there are no ACLs configured, this method will return an diff --git a/lib/rbeapi/api/bgp.rb b/lib/rbeapi/api/bgp.rb index 079e897..67d3a63 100644 --- a/lib/rbeapi/api/bgp.rb +++ b/lib/rbeapi/api/bgp.rb @@ -51,6 +51,50 @@ def initialize(node) # get returns the BGP routing configuration from the nodes current # configuration. # + # @example + # { + # bgp_as: , + # router_id: , + # shutdown: , + # maximum_paths: , + # maximum_ecmp_paths: + # networks: [ + # { + # prefix: , + # masklen: , + # route_map: + # }, + # { + # prefix: , + # masklen: , + # route_map: + # } + # ], + # neighbors: { + # name: { + # peer_group: , + # remote_as: , + # send_community: , + # shutdown: , + # description: , + # next_hop_selp: , + # route_map_in: , + # route_map_out: + # }, + # name: { + # peer_group: , + # remote_as: , + # send_community: , + # shutdown: , + # description: , + # next_hop_selp: , + # route_map_in: , + # route_map_out: + # }, + # ... + # } + # } + # # @return [nil, Hash] Returns the BGP resource as a # Hash. def get @@ -397,6 +441,18 @@ class BgpNeighbors < Entity # get returns a single BGP neighbor entry from the nodes current # configuration. # + # @example + # { + # peer_group: , + # remote_as: , + # send_community: , + # shutdown: , + # description: + # next_hop_self: + # route_map_in: + # route_map_out: + # } + # # @param [String] :name The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). @@ -422,6 +478,31 @@ def get(name) # getall returns the collection of all neighbor entries for the # BGP router instance. # + # @example + # { + # : { + # peer_group: , + # remote_as: , + # send_community: , + # shutdown: , + # description: + # next_hop_self: + # route_map_in: + # route_map_out: + # }, + # : { + # peer_group: , + # remote_as: , + # send_community: , + # shutdown: , + # description: + # next_hop_self: + # route_map_in: + # route_map_out: + # }, + # ... + # } + # # @return [nil, Hash] Returns a hash that # represents the entire BGP neighbor collection from the nodes # running configuration. If there a BGP router is not configured diff --git a/lib/rbeapi/api/dns.rb b/lib/rbeapi/api/dns.rb index 30f2b1e..03e9ef1 100644 --- a/lib/rbeapi/api/dns.rb +++ b/lib/rbeapi/api/dns.rb @@ -60,12 +60,25 @@ def get response end + ## + # parse_domain_name parses the domain-name from config + # + # @api private + # + # @return [Hash] resource hash attribute def parse_domain_name mdata = /ip domain-name ([\w.]+)/.match(config) { domain_name: mdata.nil? ? '' : mdata[1] } end private :parse_domain_name + ## + # parse_name_servers parses the name-server values from + # config + # + # @api private + # + # @return [Hash] resource hash attribute def parse_name_servers servers = config.scan(/(?:ip name-server vrf )(?:\w+)\s(.+)/) values = servers.each_with_object([]) { |srv, arry| arry << srv.first } @@ -73,6 +86,12 @@ def parse_name_servers end private :parse_name_servers + ## + # parse_domain_list parses the domain-list from config + # + # @api private + # + # @return [Hash] resource hash attribute def parse_domain_list search = config.scan(/(?<=^ip\sdomain-list\s).+$/) { domain_list: search } diff --git a/lib/rbeapi/api/interfaces.rb b/lib/rbeapi/api/interfaces.rb index a4617bc..f2e2de3 100644 --- a/lib/rbeapi/api/interfaces.rb +++ b/lib/rbeapi/api/interfaces.rb @@ -47,10 +47,52 @@ def initialize(node) @instances = {} end + ## + # get returns a hash of interface configurations for the given name + # + # @example + # { + # name: , + # type: , + # description: , + # shutdown: + # } + # + # @param [String] :name The interface name to return a resource for from + # the nodes configuration + # + # @return [nil, Hash] Returns the interface resource as a + # Hash. If the specified name is not found in the nodes current + # configuration a nil object is returned def get(name) get_instance(name).get(name) end + ## + # getall returns a hash of interface configurations + # + # @example + # { + # : { + # name: , + # type: , + # description: , + # shutdown: , + # ... + # }, + # : { + # name: , + # type: , + # description: , + # shutdown: , + # ... + # }, + # ... + # } + # + # @return [Hash] Returns the interface resources as a + # Hash. If none exist in the nodes current + # configuration an empty hash is returned def getall interfaces = config.scan(/(?<=^interface\s).+$/) @@ -60,6 +102,13 @@ def getall end end + ## + # get_instance returns an interface instance for the given name + # + # @param [String] :name The interface name to return an instance for + # + # @return [Object] Returns the interface instance as an + # Object. def get_instance(name) name = name[0, 2].upcase case name @@ -287,20 +336,18 @@ class EthernetInterface < BaseInterface # get returns the specified Ethernet interface resource hash that # represents the interface's current configuration in the node. # - # The resource hash returned contains the following information: - # - # * name (string): the interface name (eg Ethernet1) - # * type (string): will always be 'ethernet' - # * description (string): the interface description value - # * speed (string): the current speed setting for the interface speed - # * forced (boolean): true if auto negotiation is disabled otherwise - # false - # * sflow (boolean): true if sflow is enabled on the interface - # otherwise false - # * flowcontrol_send (string): the interface flowcontrol send value. - # Valid values are 'on' or 'off' - # * flowconrol_receive (string): the interface flowcontrol receive - # value. Valid values are 'on' or 'off' + # @example + # { + # name: , + # type: , + # description: , + # shutdown: , + # speed: , + # forced: , + # sflow: , + # flowcontrol_send: , + # flowcontrol_receive: + # } # # @param [String] :name The interface name to return a resource hash # for from the node's running configuration @@ -319,7 +366,6 @@ def get(name) response.merge!(parse_sflow(config)) response.merge!(parse_flowcontrol_send(config)) response.merge!(parse_flowcontrol_receive(config)) - response end @@ -955,16 +1001,18 @@ class VxlanInterface < BaseInterface # BaseInterface get method and adds the Vxlan specific attributes to # the hash # - # The returned resource hash contains the following - # - # * name: (String) The full interface name identifier - # * type: (String) 'vxlan' - # * description: (String) The configured interface description - # * shutdown: (Boolean) The admin state of the interface - # * source_interface: (String) The vxlan source-interface value - # * multicast_group: (String) The vxlan multicast-group value - # * udp_port: (Fixnum) The vxlan udp-port value - # * flood_list: (Array) The list of VTEPs to flood traffic towards + # @example + # { + # name: , + # type: , + # description: , + # shutdown: , + # source_interface: , + # multicast_group: , + # udp_port: , + # flood_list: , + # vlans: + # } # # @param [String] :name The interface name to return from the nodes # configuration. This optional parameter defaults to Vxlan1 diff --git a/lib/rbeapi/api/ipinterfaces.rb b/lib/rbeapi/api/ipinterfaces.rb index 873c482..ddeb80c 100644 --- a/lib/rbeapi/api/ipinterfaces.rb +++ b/lib/rbeapi/api/ipinterfaces.rb @@ -79,7 +79,17 @@ def get(name) # # @example # { - # : {...} + # : { + # address: + # mtu: + # helper_addresses: array + # }, + # : { + # address: + # mtu: + # helper_addresses: array + # }, + # ... # } # # @see get Ipaddress resource example @@ -103,6 +113,7 @@ def getall # ipaddress resource hash. # # @api private + # # @param [String] :config The IP interface configuration block returned # from the node's running configuration # diff --git a/lib/rbeapi/api/logging.rb b/lib/rbeapi/api/logging.rb index d21a00a..f5b18c1 100644 --- a/lib/rbeapi/api/logging.rb +++ b/lib/rbeapi/api/logging.rb @@ -46,7 +46,7 @@ class Logging < Entity # # @example # { - # enable: [true, false] + # enable: [true, false], # hosts: array # } # @@ -65,6 +65,10 @@ def get # command is expected to always be in the node's configuration. This # methods return value is intended to be merged into the logging resource # hash. + # + # @api private + # + # @return [Hash] resource hash attribute def parse_enable value = /no logging on/ !~ config { enable: value } @@ -76,6 +80,10 @@ def parse_enable # logging hosts are configured, then the value for hosts will be an empty # array. The return value is intended to be merged into the logging # resource hash + # + # @api private + # + # @return [Hash] resource hash attribute def parse_hosts hosts = config.scan(/(?<=^logging\shost\s)[^\s]+/) { hosts: hosts } diff --git a/lib/rbeapi/api/mlag.rb b/lib/rbeapi/api/mlag.rb index a397c97..e88a67f 100644 --- a/lib/rbeapi/api/mlag.rb +++ b/lib/rbeapi/api/mlag.rb @@ -50,15 +50,25 @@ class Mlag < Entity # get scans the current nodes configuration and returns the values as # a Hash describing the current state. # - # The resource hash returned contains the following: - # * domain_id: (String) The MLAG domain-id value - # * local_interface: (String) The MLAG local-interface value - # * peer_address: (String) The IP address of the MLAG peer - # * peer_link: (String) The MLAG transit peer-link value - # * shutdown: (Boolean) The administrative staet of the mlag - # configuration - # * interfaces: (Hash) The list of configured MLAG interfaces. (See - # parse_interfaces for the Hash details) + # @example + # { + # global: { + # domain_id: , + # local_interface: , + # peer_address: , + # peer_link: , + # shutdown: + # }, + # interfaces: { + # : { + # mlag_id: + # }, + # : { + # mlag_id: + # }, + # ... + # } + # } # # @see parse_interfaces # diff --git a/lib/rbeapi/api/ntp.rb b/lib/rbeapi/api/ntp.rb index 9b6403e..2b1e78d 100644 --- a/lib/rbeapi/api/ntp.rb +++ b/lib/rbeapi/api/ntp.rb @@ -48,7 +48,7 @@ class Ntp < Entity # # @example # { - # source_interface: + # source_interface: , # servers: { # prefer: [true, false] # } diff --git a/lib/rbeapi/api/ospf.rb b/lib/rbeapi/api/ospf.rb index eb4c120..8772825 100644 --- a/lib/rbeapi/api/ospf.rb +++ b/lib/rbeapi/api/ospf.rb @@ -48,13 +48,15 @@ class Ospf < Entity # # @example # { - # "router_id": - # "areas": { + # router_id: + # areas: { # : array # }, - # "redistribute" + # redistribute: {} # } # + # @param [String] :inst The ospf instance name + # # @return [Hash] A Ruby hash object that provides the OSPF settings as # key / value pairs. def get(inst) @@ -90,9 +92,16 @@ def get(inst) # # @example # { - # : {...} - # "interfaces": {...} + # : { + # router_id: , + # areas: {}, + # redistribute: {} + # }, + # interfaces: {} # } + # + # @return [Hash] A Ruby hash object that provides the OSPF settings as + # key / value pairs. def getall instances = config.scan(/(?<=^router\sospf\s)\d+$/) response = instances.each_with_object({}) do |inst, hsh| @@ -147,8 +156,7 @@ class OspfInterfaces < Entity # # Example # { - # "name": , - # "network_type": + # network_type: # } # # @param [String] :name The interface name to return the configuration @@ -174,8 +182,13 @@ def get(name) # # Example # { - # : {...}, - # : {...} + # : { + # network_type: + # }, + # : { + # network_type: + # }, + # ... # } # # @return [nil, Hash] A Ruby hash that represents the diff --git a/lib/rbeapi/api/prefixlists.rb b/lib/rbeapi/api/prefixlists.rb index 6bef554..1c42c31 100644 --- a/lib/rbeapi/api/prefixlists.rb +++ b/lib/rbeapi/api/prefixlists.rb @@ -48,16 +48,17 @@ class Prefixlists < Entity # @example # { # : { - # "next_hop": , - # "name": + # next_hop: , + # name: # } # } # + # @param [String] :name The name of the prefix-list to return + # # @returns [Hash The method will return all of the # configured static routes on the node as a Ruby hash object. If # there are no static routes configured, this method will return # an empty hash - def get(name) config = get_block("ip prefix-list #{name}") return nil unless config @@ -69,6 +70,21 @@ def get(name) end end + ## + # Returns the static routes configured on the node + # + # @example + # { + # : { + # next_hop: , + # name: + # } + # } + # + # @returns [Hash The method will return all of the + # configured static routes on the node as a Ruby hash object. If + # there are no static routes configured, this method will return + # an empty hash def getall lists = config.scan(/(?<=^ip\sprefix-list\s).+/) lists.each_with_object({}) do |name, hsh| diff --git a/lib/rbeapi/api/radius.rb b/lib/rbeapi/api/radius.rb index 399ca86..33b449a 100644 --- a/lib/rbeapi/api/radius.rb +++ b/lib/rbeapi/api/radius.rb @@ -61,14 +61,14 @@ class Radius < Entity # This method is intended to be used by a provider's instances class # method. # - # The resource hash returned contains the following information: - # * key: (String) the key either in plain text or hashed format - # * key_format: (Fixnum) e.g. 0 or 7 - # * timeout: (Fixnum) seconds before the timeout period ends - # * retransmit: (Fixnum), e.g. 3, attempts after first timeout expiry. - # * servers: (Array), - # - # @api public + # @example + # { + # key: , + # key_format: , + # timeout: , + # retransmit: , + # servers: + # } # # @return [Array] Single element Array of resource hashes def get diff --git a/lib/rbeapi/api/routemaps.rb b/lib/rbeapi/api/routemaps.rb index fca8556..7be95b3 100644 --- a/lib/rbeapi/api/routemaps.rb +++ b/lib/rbeapi/api/routemaps.rb @@ -81,8 +81,8 @@ class Routemaps < Entity # } # } # - # @param [String] name The routemap name to return a resource for from the - # nodes configuration + # @param [String] :name The routemap name to return a resource for from + # the nodes configuration # # @return [nil, Hash] Returns the routemap resource as a # Hash. If the specified name is not found in the nodes current @@ -174,10 +174,11 @@ def getall ## # parse entries is a private method to get the routemap rules. # + # @api private + # # @return [nil, Hash] returns a hash that represents the # rules for routemaps from the nodes running configuration. If # there are no routemaps configured, this method will return nil. - # def parse_entries(name) entries = config.scan(/^route-map\s#{name}\s.+$/) return nil if entries.empty? @@ -196,11 +197,12 @@ def parse_entries(name) ## # parse rule is a private method to parse a rule. # + # @api private + # # @return [Hash] returns a hash that represents the # rules for routemaps from the nodes running configuration. If # there are no routemaps configured, this method will return an empty # hash. - # def parse_rules(rules) rules.split("\n").each_with_object({}) do |rule, rule_hsh| mdata = /\s{3}(\w+)\s/.match(rule) diff --git a/lib/rbeapi/api/snmp.rb b/lib/rbeapi/api/snmp.rb index 309a814..6f24e44 100644 --- a/lib/rbeapi/api/snmp.rb +++ b/lib/rbeapi/api/snmp.rb @@ -57,9 +57,9 @@ class Snmp < Entity # # @example # { - # location: - # contact: - # chassis_id: + # location: , + # contact: , + # chassis_id: , # source_interface: # } # diff --git a/lib/rbeapi/api/stp.rb b/lib/rbeapi/api/stp.rb index caf9926..bd2a25f 100644 --- a/lib/rbeapi/api/stp.rb +++ b/lib/rbeapi/api/stp.rb @@ -48,13 +48,20 @@ class Stp < Entity # @example # { # mode: - # instances: {...} - # interfaces: {...} + # instances: { + # : { + # priority: + # } + # } + # interfaces: { + # : { + # portfast: , + # portfast_type: , + # bpduguard: + # } + # } # } # - # @see StpInstances instances get example - # @eee StpInterfaces interfaces get example - # # @return [Hash] returns a Hash of attributes derived from eAPI def get response = {} @@ -150,6 +157,8 @@ class StpInstances < Entity # priority: # } # + # @param [String] :inst The named stp instance to return + # # @return [nil, Hash: {...} + # : { + # priority: + # }, + # : { + # priority: + # }, + # ... # } # - # @see get Instance get example - # # @return [Hash] returns all configured stp instances # found in the nodes running configuration def getall @@ -265,10 +278,14 @@ class StpInterfaces < Entity # # @example # { - # portfast: [true, false] - # bpduguard: [true, false] + # portfast: , + # portfast_type: , + # bpduguard: # } # + # @param [String] :name The interface name to return a resource for from + # the nodes configuration + # # @return [nil, Hash] returns the stp interface as a # resource hash def get(name) @@ -289,11 +306,19 @@ def get(name) # # @example # { - # : {...} + # : { + # portfast: , + # portfast_type: , + # bpduguard: + # }, + # : { + # portfast: , + # portfast_type: , + # bpduguard: + # }, + # ... # } # - # @see get Interface example - # # @return [Hash] returns the stp interfaces config as a # resource hash from the nodes running configuration def getall diff --git a/lib/rbeapi/api/switchports.rb b/lib/rbeapi/api/switchports.rb index 16c89af..b10ed7b 100644 --- a/lib/rbeapi/api/switchports.rb +++ b/lib/rbeapi/api/switchports.rb @@ -55,7 +55,7 @@ class Switchports < Entity # "access_vlan": # } # - # @param [String] name The full name of the interface to get. The + # @param [String] :name The full name of the interface to get. The # interface name must be the full interface (ie Ethernet, not Et) # # @return [Hash] a hash that includes the switchport properties @@ -73,24 +73,63 @@ def get(name) response end + ## + # parse_mode parses switchport mode from the provided config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_mode(config) mdata = /(?<=\s{3}switchport\smode\s)(.+)$/.match(config) { mode: mdata[1] } end private :parse_mode + ## + # parse_access_vlan parses access vlan from the provided + # config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_access_vlan(config) mdata = /(?<=access\svlan\s)(.+)$/.match(config) { access_vlan: mdata[1] } end private :parse_access_vlan + ## + # parse_trunk_native_vlan parses trunk native vlan from + # the provided config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_trunk_native_vlan(config) mdata = /(?<=trunk\snative\svlan\s)(.+)$/.match(config) { trunk_native_vlan: mdata[1] } end private :parse_trunk_native_vlan + ## + # parse_trunk_allowed_vlans parses trunk allowed vlan from + # the provided config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_trunk_allowed_vlans(config) mdata = /(?<=trunk\sallowed\svlan\s)(.+)$/.match(config) return { trunk_allowed_vlans: [] } unless mdata[1] != 'none' @@ -107,6 +146,16 @@ def parse_trunk_allowed_vlans(config) end private :parse_trunk_allowed_vlans + ## + # parse_trunk_groups parses trunk group values from the + # provided config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_trunk_groups(config) mdata = config.scan(/(?<=trunk\sgroup\s)(.+)$/) mdata = mdata.flatten if mdata.length > 0 @@ -117,6 +166,25 @@ def parse_trunk_groups(config) ## # Retrieves all switchport interfaces from the running-config # + # @example + # { + # : { + # mode: , + # access_vlan: , + # trunk_native_vlan: , + # trunk_allowed_vlans: , + # trunk_groups: + # }, + # : { + # mode: , + # access_vlan: , + # trunk_native_vlan: , + # trunk_allowed_vlans: , + # trunk_groups: + # }, + # ... + # } + # # @return [Array] an array of switchport hashes def getall interfaces = config.scan(/(?<=^interface\s)([Et|Po].+)$/) diff --git a/lib/rbeapi/api/system.rb b/lib/rbeapi/api/system.rb index bcabbfc..063529a 100644 --- a/lib/rbeapi/api/system.rb +++ b/lib/rbeapi/api/system.rb @@ -42,11 +42,12 @@ module Api # hostname and domain name class System < Entity ## - # Returns the system settings + # Returns the system settings for hostname and iprouting # # @example # { - # hostname: + # hostname: , + # iprouting: # } # # @return [Hash] A Ruby hash object that provides the system settings as @@ -58,12 +59,30 @@ def get response end + ## + # parse_hostname parses hostname values from the provided config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_hostname(config) mdata = /(?<=^hostname\s)(.+)$/.match(config) { hostname: mdata.nil? ? '' : mdata[1] } end private :parse_hostname + ## + # parse_iprouting parses ip routing from the provided config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_iprouting(config) mdata = /no\sip\srouting/.match(config) { iprouting: mdata.nil? ? true : false } diff --git a/lib/rbeapi/api/tacacs.rb b/lib/rbeapi/api/tacacs.rb index b3e9cf9..4b34ae5 100644 --- a/lib/rbeapi/api/tacacs.rb +++ b/lib/rbeapi/api/tacacs.rb @@ -63,15 +63,14 @@ class Tacacs < Entity # This method is intended to be used by a provider's instances class # method. # - # The resource hash returned contains the following information: - # * name: ('settings') - # * enable: (true | false) if tacacs functionality is enabled. This is - # always true for EOS. - # * key: (String) the key either in plain text or hashed format - # * key_format: (Integer) e.g. 0 or 7 - # * timeout: (Integer) seconds before the timeout period ends - # - # @api public + # @example + # { + # name: , + # enable: , + # key: , + # key_format: , + # timeout: + # } # # @return [Array] Single element Array of resource hashes def get diff --git a/lib/rbeapi/api/users.rb b/lib/rbeapi/api/users.rb index d4cadd4..593157e 100644 --- a/lib/rbeapi/api/users.rb +++ b/lib/rbeapi/api/users.rb @@ -76,7 +76,7 @@ def initialize(node) # sshkey: # } # - # @param [String] name The user name to return a resource for from the + # @param [String] :name The user name to return a resource for from the # nodes configuration # # @return [nil, Hash] Returns the user resource as a @@ -114,6 +114,15 @@ def get(name) # secret: , # sshkey: # }, + # : { + # name: , + # privilege: , + # role: , + # nopassword: , + # encryption: <'cleartext', 'md5', 'sha512'> + # secret: , + # sshkey: + # }, # ... # ] # diff --git a/lib/rbeapi/api/varp.rb b/lib/rbeapi/api/varp.rb index 09f9ec6..45a4dcd 100644 --- a/lib/rbeapi/api/varp.rb +++ b/lib/rbeapi/api/varp.rb @@ -44,10 +44,18 @@ class Varp < Entity ## # Returns the global VARP configuration from the node # - # Example + # @example # { - # "mac_address": , - # "interfaces": {...} + # mac_address: , + # interfaces: { + # : { + # addresses: + # }, + # : { + # addresses: + # }, + # ... + # } # } # # @return [Hash] A Ruby hash object that provides the Varp settings as @@ -59,6 +67,15 @@ def get response end + ## + # parse_mac_address parses mac-address values from the provided config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_mac_address(config) # ip virtual-router mac-address value will always # be stored in aa:bb:cc:dd:ee:ff format @@ -97,7 +114,7 @@ class VarpInterfaces < Entity ## # Returns a single VARP interface configuration # - # Example + # @example # { # "addresses": array # } @@ -119,10 +136,15 @@ def get(name) # Returns the collection of MLAG interfaces as a hash index by the # interface name # - # Example + # @example # { - # "name": {...}, - # "name": {...} + # : { + # addresses: + # }, + # : { + # addresses: + # }, + # ... # } # # @return [nil, Hash] A Ruby hash that represents the @@ -138,6 +160,16 @@ def getall end end + ## + # parse_addresses parses ip virtual-router address from the provided + # config + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute def parse_addresses(config) addrs = config.scan(/(?<=\s{3}ip\svirtual-router\saddress\s).+$/) { addresses: addrs } diff --git a/lib/rbeapi/api/vlans.rb b/lib/rbeapi/api/vlans.rb index 4934c05..5567030 100644 --- a/lib/rbeapi/api/vlans.rb +++ b/lib/rbeapi/api/vlans.rb @@ -50,12 +50,12 @@ class Vlans < Entity # # @example # { - # name: - # state: + # name: , + # state: , # trunk_groups: array[] Returns the vlan resource as a @@ -78,7 +78,17 @@ def get(id) # # @example # { - # : {...} + # : { + # name: , + # state: , + # trunk_groups: array[: { + # name: , + # state: , + # trunk_groups: array[ Date: Sat, 9 Jan 2016 11:46:07 -0700 Subject: [PATCH 089/110] Making changes for auto doc generation. --- Rakefile | 19 ++ guide/Makefile | 177 ++++++++++++++ guide/_static/arista_logo_11-trans-w.png | Bin 0 -> 26494 bytes guide/_static/arista_logo_jpg-11.jpg | Bin 0 -> 45261 bytes guide/_static/favicon.ico | Bin 0 -> 4286 bytes guide/conf.py | 279 +++++++++++++++++++++++ guide/cookbook.rst | 4 + guide/developing.rst | 4 + guide/faq.rst | 4 + guide/index.rst | 23 ++ guide/installation.rst | 4 + guide/license.rst | 5 + guide/overview.rst | 20 ++ guide/quickstart.rst | 4 + guide/release-notes.rst | 6 + guide/testing.rst | 4 + guide/troubleshooting.rst | 1 + 17 files changed, 554 insertions(+) create mode 100644 guide/Makefile create mode 100644 guide/_static/arista_logo_11-trans-w.png create mode 100644 guide/_static/arista_logo_jpg-11.jpg create mode 100644 guide/_static/favicon.ico create mode 100644 guide/conf.py create mode 100644 guide/cookbook.rst create mode 100644 guide/developing.rst create mode 100644 guide/faq.rst create mode 100644 guide/index.rst create mode 100644 guide/installation.rst create mode 100644 guide/license.rst create mode 100644 guide/overview.rst create mode 100644 guide/quickstart.rst create mode 100644 guide/release-notes.rst create mode 100644 guide/testing.rst create mode 100644 guide/troubleshooting.rst diff --git a/Rakefile b/Rakefile index 27626c2..f41752a 100644 --- a/Rakefile +++ b/Rakefile @@ -155,3 +155,22 @@ task ci_spec: [:ci_prep, 'ci:setup:rspec', :spec] require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) + +desc 'Generate typedoc.rst for the guide' +task :typedoc do + system 'rbeapi doc -r type \ + | awk \'/This page/{flag=1}/augeas/{flag=0}/eos_/{flag=1}/ exec/\ + {flag=0}/\*This page/{flag=1}flag\' \ + | pandoc --from=markdown --to=rst --output=- \ + > guide/typedoc.rst' +end + +desc 'Generate Getting Started Guide HTML' +task guide: [:typedoc] do + system 'make -C guide html' +end + +desc 'Clean Getting Started docs' +task :guide_clean do + system 'make -C guide clean' +end diff --git a/guide/Makefile b/guide/Makefile new file mode 100644 index 0000000..1985178 --- /dev/null +++ b/guide/Makefile @@ -0,0 +1,177 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Rbeapi.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Rbeapi.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Rbeapi" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Rbeapi" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/guide/_static/arista_logo_11-trans-w.png b/guide/_static/arista_logo_11-trans-w.png new file mode 100644 index 0000000000000000000000000000000000000000..dec3830240e8774e8036da4e39f15fc024d348f3 GIT binary patch literal 26494 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 literal 0 HcmV?d00001 diff --git a/guide/_static/favicon.ico b/guide/_static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..cf55b0c85d981ebce5ef33b723be1ede8f26cbc1 GIT binary patch literal 4286 zcmeH|yK7WI6o+SnCWS<;)Fi^D5FfQ7iHK{FbShZ*2Z&K(VX64Q-8NtmA7CTcCLqKn zWe~L4LJ=QmXOYCxM?#2RaNY4c!GXhJW*>J$s=eXM+;ir4e&^oFor!Y=eujsg{C2au zo!jG_I}D`UX^?#P>aIX+1tyQVIryP?&3#`?+er@3e)z2VNYAHm2!4ZClsoAatHt}i z@|RveVMw%$cg$QyEL&((F1(II&GeWI=Hz?fgPDIx+!Hi;M?AK}JLCPzdJ~VrU!%L6 zw{NJ!@0RgQt}VJpMl0XQK=5jJr1l{EGM;x+KInGBlF`o-UueRZ^+aEQ7oflEkHo!J zt7GQRnHpW6x|hG(3FC9g_{jG+sx`5DG_oI_nc7reotN)-!SB!`Be*)JUFu~keu+MrX)hCt5qX*;+&|Ytdw>7Ad zGgjVJ*US*-x~Mw>vR}2|^^_U92S)picyCJIN}l?%@mwc9U~9>ZfIVX`T3x#_o_+8M z^cu*%E(9;`<@|ncGz(f2w0TB+PJ%s~CxRDqw?RK&bd7>O&xrqH(?j;>AjlbO|9{`e z)1y%hJ$AuY(C_)2*q*U($tCwlqaMxX@I7z(>t~VsKX9~}Pu_XFaywe}=|o4LtEPXQc)SzOc53M*XY&-SfviRHOl-%utL?79R v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +html_logo = '_static/arista_logo_11-trans-w.png' + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +html_favicon = '_static/favicon.ico' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'rbeapidoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ('index', 'rbeapi.tex', u'Rbeapi Documentation', + u'Arista Networks - EOS+ Consulting Services', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +latex_logo = '_static/arista_logo_jpg-11.jpg' + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'rbeapi', u'Rbeapi Documentation', + [u'Arista Networks - EOS+ Consulting Services'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'Rbeapi', u'Rbeapi Documentation', + u'Arista Networks - EOS+ Consulting Services', 'Rbeapi', 'Ruby API for EOS.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/guide/cookbook.rst b/guide/cookbook.rst new file mode 100644 index 0000000..c5535bd --- /dev/null +++ b/guide/cookbook.rst @@ -0,0 +1,4 @@ +Cookbook +============ + +.. contents:: :local: \ No newline at end of file diff --git a/guide/developing.rst b/guide/developing.rst new file mode 100644 index 0000000..5e7e5e4 --- /dev/null +++ b/guide/developing.rst @@ -0,0 +1,4 @@ +Developing +========== + +.. contents:: :local: \ No newline at end of file diff --git a/guide/faq.rst b/guide/faq.rst new file mode 100644 index 0000000..eb5392d --- /dev/null +++ b/guide/faq.rst @@ -0,0 +1,4 @@ +FAQ +=== + +.. contents:: :local: \ No newline at end of file diff --git a/guide/index.rst b/guide/index.rst new file mode 100644 index 0000000..fb21811 --- /dev/null +++ b/guide/index.rst @@ -0,0 +1,23 @@ +.. Rbeapi documentation master file, created by + sphinx-quickstart on Fri Jan 8 11:04:02 2016. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to Rbeapi's documentation! +================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + overview + quickstart + installation + cookbook + troubleshooting + developing + testing + faq + release-notes + license \ No newline at end of file diff --git a/guide/installation.rst b/guide/installation.rst new file mode 100644 index 0000000..3c4aa04 --- /dev/null +++ b/guide/installation.rst @@ -0,0 +1,4 @@ +Installation +============ + +.. contents:: :local: \ No newline at end of file diff --git a/guide/license.rst b/guide/license.rst new file mode 100644 index 0000000..df32f7b --- /dev/null +++ b/guide/license.rst @@ -0,0 +1,5 @@ +License +======= + +.. include:: ../LICENSE + :literal: \ No newline at end of file diff --git a/guide/overview.rst b/guide/overview.rst new file mode 100644 index 0000000..d97ec29 --- /dev/null +++ b/guide/overview.rst @@ -0,0 +1,20 @@ +Overview +======== + +.. contents:: :local: + +Introduction +------------ + +The Ruby Client for eAPI provides a native Ruby implementation for programming Arista EOS network devices using Ruby. The Ruby client provides the ability to build native applications in Ruby that can communicate with EOS either locally via Unix domain sockets (on-box) or remotely over a HTTP/S transport (off-box). It uses a standard INI-style configuration file to specifiy one or more connection profiles. + +The rbeapi implemenation also provides an API layer for building native Ruby objects that allow for configuration and state extraction of EOS nodes. The API layer provides a consistent implementation for working with EOS configuration resources. The implementation of the API layer is highly extensible and can be used as a foundation for building custom data models. + +The libray is freely provided to the open source community for building robust applications using Arista EOS eAPI. Support is provided as best effort through Github iusses. + +Prerequisites +------------- + +* Arista EOS 4.12 or later +* Arista eAPI enabled for at least one transport (see official EOS Config Guide at arista.com for details) +* Ruby 1.9.3 or later \ No newline at end of file diff --git a/guide/quickstart.rst b/guide/quickstart.rst new file mode 100644 index 0000000..41feb59 --- /dev/null +++ b/guide/quickstart.rst @@ -0,0 +1,4 @@ +Quick Start +=========== + +.. contents:: :local: \ No newline at end of file diff --git a/guide/release-notes.rst b/guide/release-notes.rst new file mode 100644 index 0000000..31b3783 --- /dev/null +++ b/guide/release-notes.rst @@ -0,0 +1,6 @@ +Release Notes +============= + +.. toctree:: + :maxdepth: 2 + :titlesonly: \ No newline at end of file diff --git a/guide/testing.rst b/guide/testing.rst new file mode 100644 index 0000000..79ab0db --- /dev/null +++ b/guide/testing.rst @@ -0,0 +1,4 @@ +Testing Modules +=============== + +.. contents:: :local: \ No newline at end of file diff --git a/guide/troubleshooting.rst b/guide/troubleshooting.rst new file mode 100644 index 0000000..3fa493d --- /dev/null +++ b/guide/troubleshooting.rst @@ -0,0 +1 @@ +.. _troubleshooting: \ No newline at end of file From c019a893c0dcc80c2c5b66ff1c877c5f7425d89e Mon Sep 17 00:00:00 2001 From: John Corbin Date: Mon, 11 Jan 2016 07:37:10 -0800 Subject: [PATCH 090/110] Add terminal to configure command to work around AAA issue found in pyeapi. --- lib/rbeapi/client.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rbeapi/client.rb b/lib/rbeapi/client.rb index b4db988..dac0e44 100644 --- a/lib/rbeapi/client.rb +++ b/lib/rbeapi/client.rb @@ -339,7 +339,7 @@ def enable_authentication(password) def config(commands, opts = {}) commands = [*commands] unless commands.respond_to?('each') - commands.insert(0, 'configure') + commands.insert(0, 'configure terminal') if @dry_run puts '[rbeapi dry-run commands]' From bba9d373bd08a6636039330c1ffae6e1351b4188 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 11 Jan 2016 11:33:46 -0700 Subject: [PATCH 091/110] Adding missing documentation. --- lib/rbeapi/api/dns.rb | 26 +++++++++++- lib/rbeapi/api/ospf.rb | 79 +++++++++++++++++++++++++++++++++++ lib/rbeapi/api/prefixlists.rb | 27 ++++++++++++ lib/rbeapi/api/snmp.rb | 9 ++++ 4 files changed, 140 insertions(+), 1 deletion(-) diff --git a/lib/rbeapi/api/dns.rb b/lib/rbeapi/api/dns.rb index 03e9ef1..f3777cb 100644 --- a/lib/rbeapi/api/dns.rb +++ b/lib/rbeapi/api/dns.rb @@ -41,7 +41,7 @@ module Api # The Dns class manages DNS settings on an EOS node. class Dns < Entity ## - # Returns the DNS resource + # get returns the DNS resource # # @example # { @@ -157,10 +157,22 @@ def set_name_servers(opts = {}) configure cmds end + ## + # add_name_server adds an ip name-server. + # + # @param [String] :server The name of the ip name-server to create + # + # @return [Boolean] returns true if the command completed successfully def add_name_server(server) configure "ip name-server #{server}" end + ## + # remove_name_server removes the specified ip name-server. + # + # @param [String] :server The name of the ip name-server to remove + # + # @return [Boolean] returns true if the command completed successfully def remove_name_server(server) configure "no ip name-server #{server}" end @@ -212,10 +224,22 @@ def set_domain_list(opts = {}) configure cmds end + ## + # add_domain_list adds an ip domain-list. + # + # @param [String] :name The name of the ip domain-list to add + # + # @return [Boolean] returns true if the command completed successfully def add_domain_list(name) configure "ip domain-list #{name}" end + ## + # remove_domain_list removes a specified ip domain-list. + # + # @param [String] :name The name of the ip domain-list to remove + # + # @return [Boolean] returns true if the command completed successfully def remove_domain_list(name) configure "no ip domain-list #{name}" end diff --git a/lib/rbeapi/api/ospf.rb b/lib/rbeapi/api/ospf.rb index 8772825..8f4fea4 100644 --- a/lib/rbeapi/api/ospf.rb +++ b/lib/rbeapi/api/ospf.rb @@ -117,28 +117,91 @@ def interfaces @interfaces end + ## + # create will create a router ospf with the specified pid + # + # @param [String] :pid The router ospf to create + # + # @return [Boolean] returns true if the command completed successfully def create(pid) configure "router ospf #{pid}" end + ## + # delete will remove the specified router ospf + # + # @param [String] :pid The router ospf to remove + # + # @return [Boolean] returns true if the command completed successfully def delete(pid) configure "no router ospf #{pid}" end + ## + # set_router_id sets router ospf router-id with pid and options + # + # @param [String] :pid The router ospf name + # + # @param [hash] :opts Optional keyword arguments + # + # @option :opts [Boolean] :enable If false then the command is + # negated. Default is true. + # + # @option :opts [Boolean] :default Configure the router-id to default. + # + # @return [Boolean] returns true if the command completed successfully def set_router_id(pid, opts = {}) cmd = command_builder('router-id', opts) cmds = ["router ospf #{pid}", cmd] configure cmds end + ## + # add_network adds network settings for router ospf and network area. + # + # @param [String] :pid The pid for router ospf + # + # @param [String] :net The network name + # + # @param [String] :area The network area name + # + # @return [Boolean] returns true if the command completed successfully def add_network(pid, net, area) configure ["router ospf #{pid}", "network #{net} area #{area}"] end + ## + # remove_network removes network settings for router ospf and network + # area. + # + # @param [String] :pid The pid for router ospf + # + # @param [String] :net The network name + # + # @param [String] :area The network area name + # + # @return [Boolean] returns true if the command completed successfully def remove_network(pid, net, area) configure ["router ospf #{pid}", "no network #{net} area #{area}"] end + ## + # set_redistribute sets router ospf router-id with pid and options + # + # @param [String] :pid The router ospf name + # + # @param [String] :proto The redistribute value + # + # @param [hash] :opts Optional keyword arguments + # + # @option :opts [String] :routemap The route-map value + # + # @option :opts [Boolean] :enable If false then the command is + # negated. Default is true. + # + # @option :opts [Boolean] :default Configure the router-id to default. + # + # @return [Boolean] returns true if the command completed successfully def set_redistribute(pid, proto, opts = {}) routemap = opts[:routemap] cmds = ["router ospf #{pid}", "redistribute #{proto}"] @@ -202,6 +265,22 @@ def getall end end + ## + # set_network_type sets network type with options + # + # @param [String] :name The name of the interface + # + # @param [hash] :opts Optional keyword arguments + # + # @option :opts [String] :value The point-to-point value + # + # @option :opts [Boolean] :enable If false then the command is + # negated. Default is true. + # + # @option :opts [Boolean] :default Configure the ip ospf network + # to default. + # + # @return [Boolean] returns true if the command completed successfully def set_network_type(name, opts = {}) value = opts[:value] return false unless [nil, 'point-to-point'].include?(value) diff --git a/lib/rbeapi/api/prefixlists.rb b/lib/rbeapi/api/prefixlists.rb index 1c42c31..9e076fa 100644 --- a/lib/rbeapi/api/prefixlists.rb +++ b/lib/rbeapi/api/prefixlists.rb @@ -93,10 +93,29 @@ def getall end end + ## + # create will create a new ip prefix-list with designated name. + # + # @param [String] :name The name of the ip prefix-list + # + # @return [Boolean] returns true if the command completed successfully def create(name) configure "ip prefix-list #{name}" end + ## + # add_rule will create an ip prefix-list with the designated name, + # seqno, action and prefix. + # + # @param [String] :name The name of the ip prefix-list + # + # @param [String] :seq The seq value + # + # @param [String] :action The action value + # + # @param [String] :prefix The prefix value + # + # @return [Boolean] returns true if the command completed successfully def add_rule(name, action, prefix, seq = nil) cmd = "ip prefix-list #{name}" cmd << " seq #{seq}" if seq @@ -104,6 +123,14 @@ def add_rule(name, action, prefix, seq = nil) configure cmd end + ## + # delete will remove the designated prefix-list + # + # @param [String] :name The name of the ip prefix-list + # + # @param [String] :seq The seq value + # + # @return [Boolean] returns true if the command completed successfully def delete(name, seq = nil) cmd = "no ip prefix-list #{name}" cmd << " seq #{seq}" if seq diff --git a/lib/rbeapi/api/snmp.rb b/lib/rbeapi/api/snmp.rb index 6f24e44..3006260 100644 --- a/lib/rbeapi/api/snmp.rb +++ b/lib/rbeapi/api/snmp.rb @@ -403,6 +403,15 @@ def set_community_acl(name, opts = {}) configure cmds end + ## + # set_community_access configures snmp-server community with designated + # name and access values. + # + # @param [String] :name The snmp-server community name value + # + # @param [String] :access The snmp-server community access value + # + # @return [Boolean] returns true if the command completed successfully def set_community_access(name, access) configure "snmp-server community #{name} #{access}" end From 9e191901f2482fcb268d1edae3bc3cc971c6e10d Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 11 Jan 2016 11:41:17 -0700 Subject: [PATCH 092/110] rubocop issues. --- lib/rbeapi/api/prefixlists.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rbeapi/api/prefixlists.rb b/lib/rbeapi/api/prefixlists.rb index 9e076fa..0a2435d 100644 --- a/lib/rbeapi/api/prefixlists.rb +++ b/lib/rbeapi/api/prefixlists.rb @@ -97,7 +97,7 @@ def getall # create will create a new ip prefix-list with designated name. # # @param [String] :name The name of the ip prefix-list - # + # # @return [Boolean] returns true if the command completed successfully def create(name) configure "ip prefix-list #{name}" @@ -114,7 +114,7 @@ def create(name) # @param [String] :action The action value # # @param [String] :prefix The prefix value - # + # # @return [Boolean] returns true if the command completed successfully def add_rule(name, action, prefix, seq = nil) cmd = "ip prefix-list #{name}" From 28172e88fba45e9c9449ab1b70414c5215a8f09c Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 11 Jan 2016 11:44:55 -0700 Subject: [PATCH 093/110] Change this back. --- lib/rbeapi/api/vrrp.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rbeapi/api/vrrp.rb b/lib/rbeapi/api/vrrp.rb index a8b1b1d..69cf370 100644 --- a/lib/rbeapi/api/vrrp.rb +++ b/lib/rbeapi/api/vrrp.rb @@ -32,7 +32,7 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Eos is the toplevel namespace for working with Arista EOS nodes module Rbeapi ## # Api is module namespace for working with the EOS command API From 472e40ddbe72fc1553c071c023597be22b9b9b79 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Mon, 11 Jan 2016 13:40:09 -0700 Subject: [PATCH 094/110] Update copyright year and getall count to spec. --- spec/unit/rbeapi/api/switchports/default_spec.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/spec/unit/rbeapi/api/switchports/default_spec.rb b/spec/unit/rbeapi/api/switchports/default_spec.rb index d34dccf..6217276 100644 --- a/spec/unit/rbeapi/api/switchports/default_spec.rb +++ b/spec/unit/rbeapi/api/switchports/default_spec.rb @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, Arista Networks, Inc. +# Copyright (c) 2016, Arista Networks, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -90,6 +90,10 @@ def switchports it 'returns a hash collection' do expect(subject.getall).to be_a_kind_of(Hash) end + + it 'returns a hash collection' do + expect(subject.getall.count).to eq(1) + end end describe '#create' do From b123f2f884e63e596575b2919d20633c10a9e205 Mon Sep 17 00:00:00 2001 From: John Corbin Date: Mon, 11 Jan 2016 13:15:26 -0800 Subject: [PATCH 095/110] Copy configuration entry before modifying with connection specific info. Fixes issue #86 --- lib/rbeapi/client.rb | 5 ++-- spec/fixtures/wildcard.conf | 43 +++++++++++++++++++++++++++++++++ spec/unit/rbeapi/client_spec.rb | 26 ++++++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 spec/fixtures/wildcard.conf diff --git a/lib/rbeapi/client.rb b/lib/rbeapi/client.rb index dac0e44..ed2bd16 100644 --- a/lib/rbeapi/client.rb +++ b/lib/rbeapi/client.rb @@ -99,8 +99,9 @@ def config_for(name) # @return [Rbeapi::Node, nil] Returns an instance of Rbeapi::Node. If # the named configuration is not found then nil is returned def connect_to(name) - config = config_for(name) - return nil unless config + config_entry = config_for(name) + return nil unless config_entry + config = config_entry.dup config['host'] = name if config['host'] == '*' config = Rbeapi::Utils.transform_keys_to_symbols(config) connection = connect config diff --git a/spec/fixtures/wildcard.conf b/spec/fixtures/wildcard.conf new file mode 100644 index 0000000..69a3e65 --- /dev/null +++ b/spec/fixtures/wildcard.conf @@ -0,0 +1,43 @@ +[connection:veos01] +username: eapi +password: password +transport: http +host: veos01 + +[connection:veos02] +transport: http +host: veos02 + +[connection:veos03] +transport: socket +host: veos03 + +[connection:veos04] +host: 172.16.10.1 +username: eapi +password: password +enablepwd: itsasecret +port: 1234 +transport: https + +[connection:veos05] +host: 172.16.131.40 +username: admin +password: admin +enablepwd: password +transport: https +port: 1234 +open_timeout: 12 +read_timeout: 12 + +[connection: localhost] +transport: http_local +host: localhost + +[connection:localhost] +transport: socket +host: localhost + +[connection:*] +username: foo +password: bar diff --git a/spec/unit/rbeapi/client_spec.rb b/spec/unit/rbeapi/client_spec.rb index 51de6a6..4af7038 100644 --- a/spec/unit/rbeapi/client_spec.rb +++ b/spec/unit/rbeapi/client_spec.rb @@ -54,6 +54,10 @@ def yaml_conf fixture_file('eapi.conf.yaml') end + def wildcard_conf + fixture_file('wildcard.conf') + end + let(:dut) do File.read(dut_conf) end @@ -84,6 +88,14 @@ def yaml_conf } end + let(:wildcard) do + { + 'username' => 'foo', + 'password' => 'bar', + 'host' => '*' + } + end + let(:test_data) do [ '[connection:veos01]' @@ -116,6 +128,14 @@ def yaml_conf it 'retrieves the node config' do expect(subject.connect_to('veos01')).to be_truthy end + + it 'check connection wildcard host name' do + expect(subject.load_config(wildcard_conf)).to eq(nil) + expect(subject.connect_to('host1')).to be_truthy + expect(subject.config.get_connection('host1')) .to eq(wildcard) + expect(subject.connect_to('host2')).to be_truthy + expect(subject.config.get_connection('host2')) .to eq(wildcard) + end end describe '#load_config' do @@ -156,6 +176,12 @@ def yaml_conf it 'get connection dut' do expect(subject.config.get_connection('veos01')).to eq(veos01) end + + it 'connection wildcard works' do + expect(subject.load_config(wildcard_conf)).to eq(nil) + expect(subject.config.get_connection('host1')) .to eq(wildcard) + expect(subject.config.get_connection('host2')) .to eq(wildcard) + end end describe '#reload' do From c3bba664a4341b0dc9f941558c2375aec041a593 Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Tue, 12 Jan 2016 06:19:14 -0500 Subject: [PATCH 096/110] Bump version strings --- Gemfile | 2 +- README.md | 22 +++++++++++----------- lib/rbeapi/version.rb | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Gemfile b/Gemfile index 4d206b8..548e7a7 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,7 @@ group :development, :test do gem 'pry', require: false gem 'pry-doc', require: false gem 'pry-stack_explorer', require: false - gem 'rbeapi', '0.4.0', path: '.' + gem 'rbeapi', '0.5.0', path: '.' gem 'ci_reporter_rspec', require: false gem 'simplecov-json', require: false gem 'simplecov-rcov', require: false diff --git a/README.md b/README.md index f0ab5a5..2c9a7a4 100644 --- a/README.md +++ b/README.md @@ -232,21 +232,21 @@ Copy the RPMs to an EOS device then run the 'swix create' command. Examples: Puppet Open Source: cd /mnt/flash; \ - swix create rbeapi-0.4.0-1.swix \ - rubygem-rbeapi-0.4.0-1.eos4.noarch.rpm \ + swix create rbeapi-0.5.0-1.swix \ + rubygem-rbeapi-0.5.0-1.eos4.noarch.rpm \ rubygem-inifile-3.0.0-3.eos4.noarch.rpm \ rubygem-netaddr-1.5.0-2.eos4.noarch.rpm \ rubygem-net_http_unix-0.2.1-3.eos4.noarch.rpm Puppet-enterprise agent (3.x): cd/mnt/flash; \ - swix create rbeapi-puppet3-0.4.0-1.swix \ - rubygem-rbeapi-puppet3-0.4.0-1.eos4.noarch.rpm \ + swix create rbeapi-puppet3-0.5.0-1.swix \ + rubygem-rbeapi-puppet3-0.5.0-1.eos4.noarch.rpm \ rubygem-inifile-puppet3-3.0.0-3.eos4.noarch.rpm \ rubygem-netaddr-puppet3-1.5.0-2.eos4.noarch.rpm Puppet-All-in-one agent (2015.x/4.x): cd/mnt/flash; \ - swix create rbeapi-puppet-aio-0.4.0-1.swix \ - rubygem-rbeapi-puppet-aio-0.4.0-1.eos4.noarch.rpm \ + swix create rbeapi-puppet-aio-0.5.0-1.swix \ + rubygem-rbeapi-puppet-aio-0.5.0-1.eos4.noarch.rpm \ rubygem-inifile-puppet-aio-3.0.0-3.eos4.noarch.rpm \ rubygem-netaddr-puppet-aio-1.5.0-2.eos4.noarch.rpm \ rubygem-net_http_unix-puppet-aio-0.2.1-3.eos4.noarch.rpm @@ -257,13 +257,13 @@ Copy the RPMs to an EOS device then run the 'swix create' command. Arista# copy flash: Arista# bash -bash-4.1# cd /mnt/flash/ - -bash-4.1# swix create rbeapi-puppet3-0.4.0-1.swix \ - rubygem-rbeapi-puppet3-0.4.0-1.eos4.noarch.rpm \ + -bash-4.1# swix create rbeapi-puppet3-0.5.0-1.swix \ + rubygem-rbeapi-puppet3-0.5.0-1.eos4.noarch.rpm \ rubygem-inifile-puppet3-3.0.0-1.eos4.noarch.rpm \ rubygem-netaddr-puppet3-1.5.0-1.eos4.noarch.rpm -bash-4.1# exit - Arista# copy flash:rbeapi-puppet3-0.4.0-1.swix extension: - Arista# extension rbeapi-puppet3-0.4.0-1.swix + Arista# copy flash:rbeapi-puppet3-0.5.0-1.swix extension: + Arista# extension rbeapi-puppet3-0.5.0-1.swix Arista# copy installed-extensions boot-extensions ``` @@ -272,7 +272,7 @@ Copy the RPMs to an EOS device then run the 'swix create' command. On EOS: ``` Arista# no extension pe-rbeapi-0.3.0-1.swix - Arista# extension rbeapi-puppet3-0.4.0-1.swix + Arista# extension rbeapi-puppet3-0.5.0-1.swix Arista# copy installed-extensions boot-extensions ``` diff --git a/lib/rbeapi/version.rb b/lib/rbeapi/version.rb index d179c37..53c83dc 100644 --- a/lib/rbeapi/version.rb +++ b/lib/rbeapi/version.rb @@ -33,5 +33,5 @@ # # # Rbeapi toplevel namespace module Rbeapi - VERSION = '0.4.0' + VERSION = '0.5.0' end From 74d8eea3089aceef46ed68cb599844314923fdd2 Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Tue, 12 Jan 2016 11:23:09 -0500 Subject: [PATCH 097/110] Update CHANGELOG / release notes --- CHANGELOG.md | 20 ++++++++++++ guide/release-notes-0.5.0.rst | 60 +++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 guide/release-notes-0.5.0.rst diff --git a/CHANGELOG.md b/CHANGELOG.md index c88f90c..24b152b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,26 @@ Ruby Client for eAPI ==================== +## v0.5.0, January, 2016 + +- Add optional ‘mode’ parameter to set_members() method in port-channel + interfaces API +- Add support for trunk groups +- Ensure multiple connections based on the wildcard settings do not clobber + each other. +- Add ‘terminal’ to the ‘configure’ command to workaround AAA issue +- Fix issue where ‘enablepw’ in the eapi.conf was not properly used +- Catch errors and syslog them when parsing eapi conf file. + In the event of an unparsable eapi.conf, a syslog warning will be generated + but the app will continue to attempt to utilize the default localhost conn. +- Ensure that nil is returned when getting nonexistent username +- Ensure all parse methods are private +- Add tests for timeout values +- Update framework tests +- Add unit tests for switchports +- Address code coverage gaps + + ## v0.4.0, November, 2015 - New users API diff --git a/guide/release-notes-0.5.0.rst b/guide/release-notes-0.5.0.rst new file mode 100644 index 0000000..13c3b4e --- /dev/null +++ b/guide/release-notes-0.5.0.rst @@ -0,0 +1,60 @@ +Release 0.5.0 - January 2016 +---------------------------- + +.. contents:: :local: + +Enhancements +^^^^^^^^^^^^ + +* Add lacp_mode option when setting port-channel members. (`89 `_) [`devrobo `_] + .. comment +* Add support for trunk groups. (`88 `_) [`devrobo `_] + .. comment +* Unit tests for switchports (`94 `_) [`websitescenes `_] + .. comment +* Ensure all parse methods are private. (`93 `_) [`websitescenes `_] + .. comment +* Add tests for timeout values (`92 `_) [`websitescenes `_] + .. comment +* Relax check on getall entries (`91 `_) [`devrobo `_] + .. comment +* Update framework tests (`90 `_) [`websitescenes `_] + .. comment +* Add basic framework tests. (`85 `_) [`websitescenes `_] + .. comment +* Address code coverage gaps (`84 `_) [`websitescenes `_] + .. comment + +Fixed +^^^^^ + +* Copy configuration entry before modifying with connection specific info. (`101 `_) + .. comment +* Add 'terminal' to configure command to work around AAA issue. (`99 `_) + .. comment +* Set enable password for a connection. (`96 `_) + .. comment +* Catch errors and syslog them when parsing eapi conf file. (`95 `_) + In the event of an unparsable ``eapi.conf`` file, which could occur due to other tools which used a YAML syntax instead of INI, rbeapi will log a warning via syslog, but continue to attempt a default connection to localhost. + .. comment +* Ensure that nil is returned when getting nonexistent username. (`83 `_) + .. comment +* Failure when eapi.conf is not formatted correctly (`82 `_) + In the event of an unparsable ``eapi.conf`` file, which could occur due to other tools which used a YAML syntax instead of INI, rbeapi will log a warning via syslog, but continue to attempt a default connection to localhost. +* Enable password setting in the .eapi.conf file not honored (`72 `_) + ``enablepwd`` is now properly used, if defined, in the ``eapi.conf`` +* API interfaces should accept an lacp_mode to configure for port-channel members (`58 `_) + ``set_members()`` now configures LACP mode when adding members to a port-channel + +Known Caveats +^^^^^^^^^^^^^ + +* Add support for commands with input (`100 `_) + .. comment +* Wildcard connection config gets clobbered (`86 `_) + .. comment +* Need to validate value keyword in set methods when array (`40 `_) + .. comment +* get_connect should raise an error instead of returning nil if no connection is found (`31 `_) + .. comment + From 61a7424289f3717ab0b5de9149a8c66966070030 Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Thu, 14 Jan 2016 10:13:01 -0500 Subject: [PATCH 098/110] testing build status icons --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2c9a7a4..390903b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # Arista eAPI Ruby Library -Jenkins [![Build Status](https://revproxy.arista.com/eosplus/ci/buildStatus/icon?job=rbeapi_start)](https://revproxy.arista.com/eosplus/ci/job/rbeapi_start/) - #### Table of Contents 1. [Overview] (#overview) @@ -15,6 +13,11 @@ Jenkins [![Build Status](https://revproxy.arista.com/eosplus/ci/buildStatus/icon 6. [Testing] (#testing) 7. [License] (#license) +## Build status + +Style/package build: [![Start Build Status](https://revproxy.arista.com/eosplus/ci/buildStatus/icon?job=rbeapi_start&style=plastic)](https://revproxy.arista.com/eosplus/ci/job/rbeapi_start) + +Unit/System spec/coverage: [![Spec Build Status](https://revproxy.arista.com/eosplus/ci/buildStatus/icon?job=rbeapi_spec&style=plastic)](https://revproxy.arista.com/eosplus/ci/job/rbeapi_spec) # Overview From 4f0ee5a18448e69c563d579356fe1b6406e4a359 Mon Sep 17 00:00:00 2001 From: John Corbin Date: Thu, 14 Jan 2016 11:51:05 -0800 Subject: [PATCH 099/110] Added support for setting system banners. Fixes #100 --- lib/rbeapi/api/system.rb | 69 +++++++++++++++++-- lib/rbeapi/client.rb | 10 ++- spec/system/rbeapi/api/system_spec.rb | 48 ++++++++++++- spec/unit/rbeapi/api/system/default_spec.rb | 44 ++++++++++-- .../rbeapi/api/system/fixture_system.text | 14 ++++ 5 files changed, 172 insertions(+), 13 deletions(-) diff --git a/lib/rbeapi/api/system.rb b/lib/rbeapi/api/system.rb index 063529a..1d9abfd 100644 --- a/lib/rbeapi/api/system.rb +++ b/lib/rbeapi/api/system.rb @@ -41,13 +41,20 @@ module Api # The System class configures the node system services such as # hostname and domain name class System < Entity + def initialize(node) + super(node) + @banners_re = Regexp.new(/^banner\s+(login|motd)\s?$\n(.*?)$\nEOF$\n/m) + end + ## - # Returns the system settings for hostname and iprouting + # Returns the system settings for hostname, iprouting, and banners # # @example # { # hostname: , - # iprouting: + # iprouting: , + # banner_motd: , + # banner_login: # } # # @return [Hash] A Ruby hash object that provides the system settings as @@ -56,6 +63,7 @@ def get response = {} response.merge!(parse_hostname(config)) response.merge!(parse_iprouting(config)) + response.merge!(parse_banners(config)) response end @@ -89,6 +97,31 @@ def parse_iprouting(config) end private :parse_iprouting + ## + # Parses the global config and returns the value for both motd + # and login banners. + # + # @api private + # + # @param [String] :config The configuration block returned + # from the node's running configuration + # + # @return [Hash] resource hash attribute. If the + # banner is not set it will return a value of None for that key. + def parse_banners(config) + motd_value = login_value = '' + entries = config.scan(@banners_re) + entries.each do |type, value| + if type == 'motd' + motd_value = value + elsif type == 'login' + login_value = value + end + end + { banner_motd: motd_value, banner_login: login_value } + end + private :parse_banners + ## # Configures the system hostname value in the running-config # @@ -96,7 +129,8 @@ def parse_iprouting(config) # @option opts [string] :value The value to set the hostname to # @option :opts [Boolean] :enable If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default + # @option :opts [Boolean] :default If true configure the command using + # the default keyword. Default is false. # # @return [Boolean] returns true if the command completed successfully def set_hostname(opts = {}) @@ -110,14 +144,39 @@ def set_hostname(opts = {}) # @param [Hash] opts The configuration parameters # @option :opts [Boolean] :enable True if ip routing should be enabled # or False if ip routing should be disabled. Default is true. - # @option opts [Boolean] :default Controls the use of the default - # keyword. Default is false. + # @option :opts [Boolean] :default If true configure the command using + # the default keyword. Default is false. # # @return [Boolean] returns true if the command completed successfully def set_iprouting(opts = {}) cmd = command_builder('ip routing', opts) configure(cmd) end + + ## + # Configures system banners + # + # @param [String] :banner_type banner to be changed (likely either + # login or motd) + # @param [Hash] opts The configuration parameters + # @option opts [string] :value The value to set for the banner. + # @option :opts [Boolean] :enable If false then the command is + # negated. Default is true. + # @option :opts [Boolean] :default If true configure the command using + # the default keyword. Default is false. + # + # @return [Boolean] returns true if the command completed successfully + def set_banner(banner_type, opts = {}) + value = opts[:value] + cmd_string = "banner #{banner_type}" + if value + value += "\n" if value[-1, 1] != "\n" + cmd = [{ cmd: cmd_string, input: value }] + else + cmd = command_builder(cmd_string, opts) + end + configure(cmd) + end end end end diff --git a/lib/rbeapi/client.rb b/lib/rbeapi/client.rb index ed2bd16..e11c53a 100644 --- a/lib/rbeapi/client.rb +++ b/lib/rbeapi/client.rb @@ -327,7 +327,10 @@ def enable_authentication(password) # the empty hash from the response output before return the array # to the caller # - # @param [Array] commands An ordered list of commands to execute + # @param [Array] :commands An ordered list of commands to + # execute. A string in the list is an eapi command. A Hash entry in the + # array consists of the following key value pairs: + # { cmd: 'eapi command', input: 'text passed into stdin for command' } # @option :opts [String] :encoding The encoding scheme to use for sending # and receive eAPI messages. Valid values are json and text. The # default value is json @@ -361,7 +364,10 @@ def config(commands, opts = {}) # # rubocop:disable Metrics/MethodLength # - # @param [Array] commands An ordered list of commands to execute + # @param [Array] :commands An ordered list of commands to + # execute. A string in the list is an eapi command. A Hash entry in the + # array consists of the following key value pairs: + # { cmd: 'eapi command', input: 'text passed into stdin for command' } # @option :opts [String] :encoding The encoding scheme to use for sending # and receive eAPI messages. Valid values are json and text. The # default value is json diff --git a/spec/system/rbeapi/api/system_spec.rb b/spec/system/rbeapi/api/system_spec.rb index f828f78..58df401 100644 --- a/spec/system/rbeapi/api/system_spec.rb +++ b/spec/system/rbeapi/api/system_spec.rb @@ -13,10 +13,14 @@ describe '#get' do let(:entity) do - { hostname: 'localhost', iprouting: true } + { hostname: 'localhost', iprouting: true, banner_motd: '', + banner_login: '' } end - before { node.config(['hostname localhost', 'ip routing']) } + before do + node.config(['hostname localhost', 'ip routing', 'no banner motd', + 'no banner login']) + end it 'returns the snmp resource' do expect(subject.get).to eq(entity) @@ -88,4 +92,44 @@ end end end + + describe '#set_banner' do + before { node.config(['no banner login', 'no banner motd']) } + + it 'configures the login value' do + expect(subject.get[:banner_login]).to eq('') + expect(subject.set_banner('login', value: 'foo')).to be_truthy + expect(subject.get[:banner_login]).to eq('foo') + end + + it 'negates the login value' do + expect(subject.get[:banner_login]).to eq('') + expect(subject.set_banner('login', enable: false)).to be_truthy + expect(subject.get[:banner_login]).to eq('') + end + + it 'defaults the login value' do + expect(subject.get[:banner_login]).to eq('') + expect(subject.set_banner('login', default: true)).to be_truthy + expect(subject.get[:banner_login]).to eq('') + end + + it 'configures the motd value' do + expect(subject.get[:banner_motd]).to eq('') + expect(subject.set_banner('motd', value: 'foo')).to be_truthy + expect(subject.get[:banner_motd]).to eq('foo') + end + + it 'negates the motd value' do + expect(subject.get[:banner_motd]).to eq('') + expect(subject.set_banner('motd', enable: false)).to be_truthy + expect(subject.get[:banner_motd]).to eq('') + end + + it 'defaults the motd value' do + expect(subject.get[:banner_motd]).to eq('') + expect(subject.set_banner('motd', default: true)).to be_truthy + expect(subject.get[:banner_motd]).to eq('') + end + end end diff --git a/spec/unit/rbeapi/api/system/default_spec.rb b/spec/unit/rbeapi/api/system/default_spec.rb index cb4ea8c..ef4e1fc 100644 --- a/spec/unit/rbeapi/api/system/default_spec.rb +++ b/spec/unit/rbeapi/api/system/default_spec.rb @@ -41,7 +41,9 @@ let(:node) { double('node') } let(:test) do - { hostname: 'localhost', iprouting: true } + { hostname: 'localhost', iprouting: true, + banner_motd: "MOTD Banner\nSecond Line\nEOF \n*\\v1?", + banner_login: "Login Banner\nSecond Line\n123456\n EOF" } end def system @@ -56,15 +58,15 @@ def system describe '#get' do it 'returns the username collection' do - expect(subject.get).to include(test) + expect(subject.get).to eq(test) end it 'returns a hash collection' do expect(subject.get).to be_a_kind_of(Hash) end - it 'has two entries' do - expect(subject.get.size).to eq(2) + it 'has four entries' do + expect(subject.get.size).to eq(4) end end @@ -99,4 +101,38 @@ def system expect(subject.set_iprouting(enable: false)).to be_truthy end end + + describe '#set_banner' do + it 'sets the login banner' do + expect(node).to receive(:config).with([{ cmd: 'banner login', + input: "login banner\n" }]) + expect(subject.set_banner('login', value: 'login banner')).to be_truthy + end + + it 'negates the login banner' do + expect(node).to receive(:config).with('no banner login') + expect(subject.set_banner('login', enable: false)).to be_truthy + end + + it 'defaults the login banner' do + expect(node).to receive(:config).with('default banner login') + expect(subject.set_banner('login', default: true)).to be_truthy + end + + it 'sets the motd banner' do + expect(node).to receive(:config).with([{ cmd: 'banner motd', + input: "motd banner\n" }]) + expect(subject.set_banner('motd', value: 'motd banner')).to be_truthy + end + + it 'negates the motd banner' do + expect(node).to receive(:config).with('no banner motd') + expect(subject.set_banner('motd', enable: false)).to be_truthy + end + + it 'defaults the motd banner' do + expect(node).to receive(:config).with('default banner motd') + expect(subject.set_banner('motd', default: true)).to be_truthy + end + end end diff --git a/spec/unit/rbeapi/api/system/fixture_system.text b/spec/unit/rbeapi/api/system/fixture_system.text index f84a0fc..df8459d 100644 --- a/spec/unit/rbeapi/api/system/fixture_system.text +++ b/spec/unit/rbeapi/api/system/fixture_system.text @@ -1,2 +1,16 @@ hostname localhost ip routing +banner login +Login Banner +Second Line +123456 + EOF +EOF +! +banner motd +MOTD Banner +Second Line +EOF +*\v1? +EOF +! From b0e77059d4ddabdd27c5bba36808caa571ea91c7 Mon Sep 17 00:00:00 2001 From: John Corbin Date: Fri, 15 Jan 2016 15:30:20 -0800 Subject: [PATCH 100/110] Added doc for trunk groups to get. --- lib/rbeapi/api/switchports.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/rbeapi/api/switchports.rb b/lib/rbeapi/api/switchports.rb index b10ed7b..dba8c8e 100644 --- a/lib/rbeapi/api/switchports.rb +++ b/lib/rbeapi/api/switchports.rb @@ -52,7 +52,8 @@ class Switchports < Entity # "mode": [access, trunk], # "trunk_allowed_vlans": array # "trunk_native_vlan": , - # "access_vlan": + # "access_vlan": , + # "trunk_groups": array # } # # @param [String] :name The full name of the interface to get. The From 6eb16a697ed4e7f4bd5c34b8cf51982c68398f5d Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Sun, 17 Jan 2016 19:27:18 -0700 Subject: [PATCH 101/110] Remove getter for timeouts and use attr_reader instead. --- lib/rbeapi/eapilib.rb | 10 ++-------- spec/system/rbeapi/client_spec.rb | 8 ++++---- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/lib/rbeapi/eapilib.rb b/lib/rbeapi/eapilib.rb index 9472e67..701411e 100644 --- a/lib/rbeapi/eapilib.rb +++ b/lib/rbeapi/eapilib.rb @@ -121,6 +121,8 @@ def initialize(message, connection_type = nil, commands = nil) # JSON-RPC. This class should not need to be directly instantiated. class EapiConnection attr_reader :error + attr_reader :open_timeout + attr_reader :read_timeout ## # The connection contains the transport. @@ -162,14 +164,6 @@ def timeouts(opts = {}) @read_timeout = opts.fetch(:read_timeout, DEFAULT_HTTP_READ_TIMEOUT) end - ## - # Gets values for open_timeout and read_timeout - # - # @return [Hash] open_timeout and read_timeout - def get_timeouts - { open_timeout: @open_timeout, read_timeout: @read_timeout } - end - ## # Generates the eAPI JSON request message. # diff --git a/spec/system/rbeapi/client_spec.rb b/spec/system/rbeapi/client_spec.rb index a05dd99..99c565c 100644 --- a/spec/system/rbeapi/client_spec.rb +++ b/spec/system/rbeapi/client_spec.rb @@ -348,8 +348,8 @@ def test_conf describe 'test timeouts' do it 'loads default timeout values' do - expect(node.connection.get_timeouts).to eq(open_timeout: 10, - read_timeout: 10) + expect(node.connection.open_timeout).to eq(10) + expect(node.connection.read_timeout).to eq(10) end describe 'loads veos05' do @@ -359,8 +359,8 @@ def test_conf end it 'loads timeout values from conf file' do - expect(node.connection.get_timeouts).to eq(open_timeout: 12, - read_timeout: 12) + expect(node.connection.open_timeout).to eq(12) + expect(node.connection.read_timeout).to eq(12) end end end From f11a1779631762cde4b08ed346032c4ec2a86d73 Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Tue, 19 Jan 2016 11:04:34 -0700 Subject: [PATCH 102/110] Merge in develop and fix conflicts. --- guide/.gitignore | 2 + guide/conf.py | 10 +- lib/rbeapi/api.rb | 73 ++-- lib/rbeapi/api/aaa.rb | 180 ++++----- lib/rbeapi/api/acl.rb | 123 +++--- lib/rbeapi/api/bgp.rb | 349 +++++++++-------- lib/rbeapi/api/dns.rb | 96 ++--- lib/rbeapi/api/interfaces.rb | 672 +++++++++++++++++---------------- lib/rbeapi/api/ipinterfaces.rb | 184 ++++----- lib/rbeapi/api/logging.rb | 64 ++-- lib/rbeapi/api/mlag.rb | 194 +++++----- lib/rbeapi/api/ntp.rb | 78 ++-- lib/rbeapi/api/ospf.rb | 116 +++--- lib/rbeapi/api/prefixlists.rb | 44 +-- lib/rbeapi/api/radius.rb | 126 ++++--- lib/rbeapi/api/routemaps.rb | 174 +++++---- lib/rbeapi/api/snmp.rb | 204 +++++----- lib/rbeapi/api/staticroutes.rb | 47 ++- lib/rbeapi/api/stp.rb | 184 ++++----- lib/rbeapi/api/switchports.rb | 172 +++++---- lib/rbeapi/api/tacacs.rb | 89 +++-- lib/rbeapi/api/users.rb | 136 +++---- lib/rbeapi/api/varp.rb | 103 ++--- lib/rbeapi/api/vlans.rb | 170 ++++----- lib/rbeapi/api/vrrp.rb | 383 ++++++++++--------- lib/rbeapi/utils.rb | 16 +- lib/rbeapi/version.rb | 2 +- 27 files changed, 2121 insertions(+), 1870 deletions(-) create mode 100644 guide/.gitignore diff --git a/guide/.gitignore b/guide/.gitignore new file mode 100644 index 0000000..ff16fe8 --- /dev/null +++ b/guide/.gitignore @@ -0,0 +1,2 @@ +# Sphinx build env +_build diff --git a/guide/conf.py b/guide/conf.py index 8335d42..878b37c 100644 --- a/guide/conf.py +++ b/guide/conf.py @@ -61,11 +61,11 @@ # built documents. # import re -p = re.compile("version\": \"(.*)\"") -with open("../metadata.json") as f: - data = f.read() - ver = p.search(data) - if ver: +p = re.compile("VERSION\s=\s'(.*)'") +with open("../lib/rbeapi/version.rb") as f: + data = f.read() + ver = p.search(data) + if ver: version = ver.group(1) #print "Version: {}".format(version) diff --git a/lib/rbeapi/api.rb b/lib/rbeapi/api.rb index 9693423..ce069ef 100644 --- a/lib/rbeapi/api.rb +++ b/lib/rbeapi/api.rb @@ -32,14 +32,14 @@ require 'rbeapi/eapilib' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## # Rbeapi::Api module Api ## # The Entity class provides a base class implementation for building - # API modules. The Entity class is typically not instantiated directly + # API modules. The Entity class is typically not instantiated directly # but serves as a super class with convenience methods used to # work with the node. class Entity @@ -50,56 +50,56 @@ class Entity ## # Construct the node. # - # @param [Node] :node An instance of Rbeapi::Client::Node used to - # send and receive eAPI messages + # @param node [Node] An instance of Rbeapi::Client::Node used to + # send and receive eAPI messages. def self.instance(node) new(node) end ## # The Entity class provides a base class implementation for building - # API modules. The Entity class is typically not instantiated directly + # API modules. The Entity class is typically not instantiated directly # but serves as a super class with convenience methods used to # work with the node. # - # @param [Node] :node This should be an instance of Rbeapi::Client::Node - # that is used to send and receive eAPI messages + # @param node [Node] This should be an instance of Rbeapi::Client::Node + # that is used to send and receive eAPI messages. # def initialize(node) @node = node end ## - # Returns the running configuration from the node instance. This is + # Returns the running configuration from the node instance. This is # a convenience method to easily access the current running config - # from an API module + # from an API module. # - # @return [String] The current running-config from the node + # @return [String] The current running-config from the node. def config @node.running_config end ## # Provides a convenience method for access the connection error (if - # one exists) of the node's connection instance + # one exists) of the node's connection instance. # # @return [Rbeapi::Eapilib::CommandError] An instance of CommandError - # that can be used to further evaluate the root cause of an error + # that can be used to further evaluate the root cause of an error. def error @node.connection.error end ## # Returns a block of configuration from the current running config - # as a string. The argument is used to search the config and return + # as a string. The argument is used to search the config and return # the text along with any child configuration statements. # - # @param [String] :text The text to be used to find the parent line + # @param text [String] The text to be used to find the parent line # in the nodes configuration. # - # @returns [nil, String] Returns the block of configuration based on - # the supplied argument. If the argument is not found in the - # configuration, nil is returned + # @return [nil, String] Returns the block of configuration based on + # the supplied argument. If the argument is not found in the + # configuration, nil is returned. def get_block(text) mdata = /^#{text}$/.match(config) return nil unless mdata @@ -115,16 +115,16 @@ def get_block(text) end ## - # Method called to send configuration commands to the node. This method + # Method called to send configuration commands to the node. This method # will send the commands to the node and rescue from CommandError or # ConnectionError. # - # @param [String, Array] :commands The commands to send to the node over - # the API connection to configure the system + # @param commands [String, Array] The commands to send to the node over + # the API connection to configure the system. # # @return [Boolean] Returns True if the commands were successful or # returns False if there was an error issuing the commands on the - # node. Use error to further investigate the cause of any errors + # node. Use error to further investigate the cause of any errors. def configure(commands) @node.config(commands) return true @@ -134,26 +134,27 @@ def configure(commands) ## # Method called to build the correct version of a command based on - # the modifier options. If value option is set then it is appended + # the modifier options. If value option is set then it is appended # to the command. If the enable option is false then the 'no' - # keyword is prefixed to the command. If the default value is - # provided and set to true, then the default keyword is used. If + # keyword is prefixed to the command. If the default value is + # provided and set to true, then the default keyword is used. If # both options are provided, then default option takes precedence. # - # @param [String, Array] :commands The commands to send to the node - # over the API connection to configure the system - # @param [Hash] :opts the options for the command + # @param cmd [String, Array] The commands to send to the node + # over the API connection to configure the system. # - # @option :opts [String] :value Optional value that is + # @param opts [Hash] The options for the command. + # + # @option opts value [String] Optional value that is # appended to the command if set. # - # @option :opts [Boolean] :enable Prefix the command with 'no'. + # @option opts enable [Boolean] Prefix the command with 'no'. # Default is true. # - # @option :opts [Boolean] :default Configure the command using + # @option opts default [Boolean] Configure the command using # the default keyword. Default is false. # - # @return [String] Returns built command string + # @return [String] Returns built command string. def command_builder(cmd, opts = {}) enable = opts.fetch(:enable, true) default = opts.fetch(:default, false) @@ -167,13 +168,13 @@ def command_builder(cmd, opts = {}) # configure_interface sends the commands over eAPI to the destination # node to configure a specific interface. # - # @param [String] :name The interface name to apply the configuration - # to. The name value must be the full interface identifier + # @param name [String] The interface name to apply the configuration + # to. The name value must be the full interface identifier. # - # @param [Array] :commands The list of commands to configure the - # interface + # @param commands [Array] The list of commands to configure the + # interface. # - # @return [Boolean] Returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def configure_interface(name, commands) commands = [*commands] commands.insert(0, "interface #{name}") diff --git a/lib/rbeapi/api/aaa.rb b/lib/rbeapi/api/aaa.rb index 16dd75b..956d325 100644 --- a/lib/rbeapi/api/aaa.rb +++ b/lib/rbeapi/api/aaa.rb @@ -32,17 +32,17 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Aaa class manages Authorization, Authentication and Accounting (AAA) # on an EOS node. class Aaa < Entity ## - # get returns a hash of all Aaa resources + # get returns a hash of all Aaa resources. # # @example # { @@ -105,12 +105,12 @@ class AaaGroups < Entity # servers: # } # - # @param [String] :name The server group name to return from the nodes - # current running configuration. If the name is not configured a nil + # @param name [String] The server group name to return from the nodes + # current running configuration. If the name is not configured a nil # object is returned. # - # @return [nil, Hash] returns the resource hash for the - # specified name. If the name does not exist, a nil object is returned + # @return [nil, Hash] Returns the resource hash for the + # specified name. If the name does not exist, a nil object is returned. def get(name) block = get_block("aaa group server ([^\s]+) #{name}") return nil unless block @@ -121,22 +121,22 @@ def get(name) end ## - # getall returns a aaa server groups hash + # getall returns a aaa server groups hash. # # @example - # { - # : { - # type: , - # servers: - # }, - # : { - # type: , - # servers: + # { + # : { + # type: , + # servers: + # }, + # : { + # type: , + # servers: + # } # } - # } # - # @return [Hash] returns the resource hashes for - # configured aaa groups. If none exist, a nil object is returned + # @return [Hash] Returns the resource hashes for + # configured aaa groups. If none exist, a nil object is returned. def getall cfg = config.scan(/aaa group server (?:radius|tacacs\+) (.+)$/) cfg.each_with_object({}) do |name, hsh| @@ -147,15 +147,15 @@ def getall ## # parse_type scans the specified configuration block and returns the - # server group type as either 'tacacs' or 'radius'. The type value is + # server group type as either 'tacacs' or 'radius'. The type value is # expected to always be present in the config. # # @api private # - # @param [String] :config The aaa server group block configuration for the - # group name to parse + # @param config [String] The aaa server group block configuration for the + # group name to parse. # - # @return [Hash] resource hash attribute + # @return [Hash] Resource hash attribute. def parse_type(config) value = config.scan(/aaa group server ([^\s]+)/).first { type: value.first } @@ -164,7 +164,7 @@ def parse_type(config) ## # parse_servers scans the specified configuraiton block and returns the - # list of servers configured for the group. If there are no servers + # list of servers configured for the group. If there are no servers # configured for the group the servers value will return an empty array. # # @api private @@ -172,13 +172,13 @@ def parse_type(config) # @see parse_radius_server # @see parse_tacacs_server # - # @param [String] :config The aaa server group block configuration for the - # group name to parse + # @param config [String] The aaa server group block configuration for the + # group name to parse. # - # @param [String] :type The aaa server block type. Valid values are + # @param type [String] The aaa server block type. Valid values are # either radius or tacacs+. # - # @return [Hash] resource hash attribute + # @return [Hash] Resource hash attribute def parse_servers(config, type) case type when 'radius' then parse_radius_server(config) @@ -189,13 +189,13 @@ def parse_servers(config, type) ## # parse_radius_server scans the provide configuration block and returns - # the list of servers configured. The configuration block is expected to - # be a radius configuration block. If there are no servers configured + # the list of servers configured. The configuration block is expected to + # be a radius configuration block. If there are no servers configured # for the group the servers value will return an empty array. # # @api private # - # @param [String] :config The aaa server group block configuration for the + # @param config [String] The aaa server group block configuration for the # group name to parse # # @return [Hash] resource hash attribute @@ -213,16 +213,16 @@ def parse_radius_server(config) ## # parse_tacacs_server scans the provided configuration block and returns - # the list of configured servers. The configuration block is expected to - # be a tacacs configuration block. If there are no servers configured + # the list of configured servers. The configuration block is expected to + # be a tacacs configuration block. If there are no servers configured # for the group the servers value will return an empty array. # # @api private # - # @param [String] :config The aaa server group block configuration for the - # group name to parse + # @param config [String] The aaa server group block configuration for the + # group name to parse. # - # @return [Hash] resource hash attribute + # @return [Hash] Resource hash attribute. def parse_tacacs_server(config) values = config.scan(TACACS_GROUP_SERVER).map do |(name, vrf, port)| { @@ -237,17 +237,17 @@ def parse_tacacs_server(config) ## # find_type is a utility method to find the type of aaa server group for - # the specified name. This method will scan the current running + # the specified name. This method will scan the current running # configuration on the node and return the server group type as either - # 'radius' or 'tacacs+'. If the server group is not configured, then nil + # 'radius' or 'tacacs+'. If the server group is not configured, then nil # will be returned. # # @api private # - # @param [String] :name The aaa server group name to find in the config - # and return the type value for + # @param name [String] The aaa server group name to find in the config + # and return the type value for. # - # @return [nil, String] returns either the type name as 'radius' or + # @return [nil, String] Returns either the type name as 'radius' or # 'tacacs+' or nil if the server group is not configured. def find_type(name) mdata = /aaa group server ([^\s]+) #{name}/.match(config) @@ -258,19 +258,19 @@ def find_type(name) ## # create adds a new aaa group server to the nodes current configuration. # If the specified name and type are already created then this method - # will return successfully. If the name is configured but the type is + # will return successfully. If the name is configured but the type is # different, this method will not return successfully (returns false). # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # aaa group server # - # @param [String] :name The name of the aaa group server to create in the + # @param name [String] The name of the aaa group server to create in the # nodes running configuration # - # @param [String] :type The type of aaa group server to create in the - # nodes running configuration. Valid values include 'radius' or + # @param type [String] The type of aaa group server to create in the + # nodes running configuration. Valid values include 'radius' or # 'tacacs+' # # @return [Boolean] returns true if the commands complete successfully @@ -280,19 +280,19 @@ def create(name, type) ## # delete removes a current aaa server group from the nodes current - # configuration. This method will automatically determine the server - # group type based on the name. If the name is not configured in the + # configuration. This method will automatically determine the server + # group type based on the name. If the name is not configured in the # nodes current configuration, this method will return successfully. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # no aaa group server [radius | tacacs+] # - # @param [String] :name The name of the aaa group server to create in the - # nodes running configuration + # @param name [String] The name of the aaa group server to create in the + # nodes running configuration. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def delete(name) type = find_type(name) return true unless type @@ -301,22 +301,20 @@ def delete(name) ## # set_servers configures the set of servers for a specified aaa server - # group. This is an atomic operation that first removes all current - # servers and then adds the new servers back. If any of the servers + # group. This is an atomic operation that first removes all current + # servers and then adds the new servers back. If any of the servers # failes to be removed or added, this method will return unsuccessfully. # # @see remove_server # @see add_server # - # @param [String] :name The name of the aaa group server to add the new + # @param name [String] The name of the aaa group server to add the new # server configuration to. # - # @param [String] :server The IP address or host name of the server to + # @param servers [String] The IP address or host name of the server to # add to the configuration # - # @param [Hash] :opts Optional configuration parameters - # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully def set_servers(name, servers) current = get(name) current[:servers].each do |srv| @@ -330,22 +328,22 @@ def set_servers(name, servers) end ## - # add_server adds a new server to the specified aaa server group. If + # add_server adds a new server to the specified aaa server group. If # the server is already configured in the list of servers, this method # will still return successfully. # # @see add_radius_server # @see add_tacacs_server # - # @param [String] :name The name of the aaa group server to add the new + # @param name [String] The name of the aaa group server to add the new # server configuration to. # - # @param [String] :server The IP address or host name of the server to - # add to the configuration + # @param server [String] The IP address or host name of the server to + # add to the configuration. # - # @param [Hash] :opts Optional configuration parameters + # @param opts [Hash] Optional configuration parameters. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def add_server(name, server, opts = {}) type = find_type(name) return false unless type @@ -359,24 +357,24 @@ def add_server(name, server, opts = {}) ## # add_radius_server adds a new radius server to the nodes current # configuration. If the server already exists in the specified group - # name this method will still return successfully + # name this method will still return successfully. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commmands + # commmands # aaa group server radius # server [acct-port ] [auth-port ] # [vrf ] # - # @param [String] :name The name of the aaa group server to add the new + # @param name [String] The name of the aaa group server to add the new # server configuration to. # - # @param [String] :server The IP address or host name of the server to - # add to the configuration + # @param server [String] The IP address or host name of the server to + # add to the configuration. # - # @param [Hash] :opts Optional configuration parameters + # @param opts [Hash] Optional configuration parameters. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def add_radius_server(name, server, opts = {}) # order of command options matter here! server = "server #{server} " @@ -388,25 +386,25 @@ def add_radius_server(name, server, opts = {}) ## # add_tacacs_server adds a new tacacs server to the nodes current - # configuration. If the server already exists in the specified group - # name this method will still return successfully + # configuration. If the server already exists in the specified group + # name this method will still return successfully. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commmands + # commmands # aaa group server tacacs+ # server [acct-port ] [auth-port ] # [vrf ] # - # @param [String] :name The name of the aaa group server to add the new + # @param name [String] The name of the aaa group server to add the new # server configuration to. # - # @param [String] :server The IP address or host name of the server to - # add to the configuration + # @param server [String] The IP address or host name of the server to + # add to the configuration. # - # @param [Hash] :opts Optional configuration parameters + # @param opts [Hash] Optional configuration parameters. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def add_tacacs_server(name, server, opts = {}) # order of command options matter here! server = "server #{server} " @@ -417,20 +415,22 @@ def add_tacacs_server(name, server, opts = {}) ## # remove_server deletes an existing server from the specified aaa server - # group. If the specified server is not configured in the specified + # group. If the specified server is not configured in the specified # server group, this method will still return true. # - # @eos_version 4.13.7M + # eos_version 4.13.7M # - # @commands + # commands # aaa group server [radius | tacacs+] # no server # - # @param [String] :name The name of the aaa group server to remove + # @param name [String] The name of the aaa group server to remove. # - # @param [String] :server The IP address or host name of the server + # @param server [String] The IP address or host name of the server. # - # @return [Boolean] returns true if the commands complete successfully + # @param opts [Hash] Optional configuration parameters. + # + # @return [Boolean] returns true if the commands complete successfully. def remove_server(name, server, opts = {}) type = find_type(name) return false unless type diff --git a/lib/rbeapi/api/acl.rb b/lib/rbeapi/api/acl.rb index dafd5f7..6124523 100644 --- a/lib/rbeapi/api/acl.rb +++ b/lib/rbeapi/api/acl.rb @@ -33,10 +33,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Acl class manages the set of standard ACLs. @@ -75,7 +75,7 @@ def initialize(node) # ... # } # - # @param [String] :name The ACL name. + # @param name [String] The ACL name. # # @return [nil, Hash] Returns the ACL resource as a # Hash. Returns nil if name does not exist. @@ -144,11 +144,11 @@ def getall ## # mask_to_prefixlen converts a subnet mask from dotted decimal to - # bit length + # bit length. # - # @param [String] :mask The dotted decimal subnet mask to convert + # @param mask [String] The dotted decimal subnet mask to convert. # - # @return [String] The subnet mask as a valid prefix length + # @return [String] The subnet mask as a valid prefix length. def mask_to_prefixlen(mask) mask = '255.255.255.255' unless mask NetAddr::CIDR.create('0.0.0.0/' + mask).netmask_ext @@ -160,9 +160,9 @@ def mask_to_prefixlen(mask) # # @api private # - # @param [String] :config The switch config. + # @param config [String] The switch config. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_entries(config) entries = {} @@ -187,38 +187,38 @@ def parse_entries(config) ## # create will create a new ACL resource in the nodes current - # configuration with the specified name. If the create method + # configuration with the specified name. If the create method # is called and the ACL already exists, this method will still # return true. The ACL will not have any entries. Use add_entry # to add entries to the ACL. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # ip access-list standard # - # @param [String] :name The ACL name to create on the node. Must + # @param name [String] The ACL name to create on the node. Must # begin with an alphabetic character. Cannot contain spaces or # quotation marks. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(name) configure("ip access-list standard #{name}") end ## # delete will delete an existing ACL resource from the nodes current - # running configuration. If the delete method is called and the ACL + # running configuration. If the delete method is called and the ACL # does not exist, this method will succeed. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # no ip access-list standard # - # @param [String] :name The ACL name to delete on the node. + # @param name [String] The ACL name to delete on the node. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete(name) configure("no ip access-list standard #{name}") end @@ -228,15 +228,15 @@ def delete(name) # command has the same effect as deleting the ACL from the nodes # running configuration. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # default no ip access-list standard # - # @param [String] :name The ACL name to set to the default value + # @param name [String] The ACL name to set to the default value # on the node. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully def default(name) configure("default ip access-list standard #{name}") end @@ -246,17 +246,22 @@ def default(name) # # @api private # - # @param [Hash] :opts the options for the entry - # @option :opts [String] :seqno The sequence number of the entry in + # @param entry [Hash] the options for the entry. + # + # @option entry seqno [String] The sequence number of the entry in # the ACL to add. Default is nil, will be assigned. - # @option :opts [String] :action The action triggered by the ACL. Valid - # values are 'permit', 'deny', or 'remark' - # @option :opts [String] :addr The IP address to permit or deny. - # @option :opts [String] :prefixlen The prefixlen for the IP address. - # @option :opts [Boolean] :log Triggers an informational log message + # + # @option entry action [String] The action triggered by the ACL. Valid + # values are 'permit', 'deny', or 'remark'. + # + # @option entry addr [String] The IP address to permit or deny. + # + # @option entry prefixlen [String] The prefixlen for the IP address. + # + # @option entry log [Boolean] Triggers an informational log message # to the console about the matching packet. # - # @return [String] returns commands to create an entry + # @return [String] Returns commands to create an entry. def build_entry(entry) cmds = "#{entry[:seqno]} " if entry[:seqno] cmds << "#{entry[:action]} #{entry[:srcaddr]}/#{entry[:srcprefixlen]}" @@ -269,20 +274,26 @@ def build_entry(entry) # update_entry will update an entry, identified by the seqno # in the ACL specified by name, with the passed in parameters. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The ACL name to update on the node. - # @param [Hash] :opts the options for the entry - # @option :opts [String] :seqno The sequence number of the entry in + # @param name [String] The ACL name to update on the node. + # + # @param entry [Hash] the options for the entry. + # + # @option entry seqno [String] The sequence number of the entry in # the ACL to update. - # @option :opts [String] :action The action triggered by the ACL. Valid - # values are 'permit', 'deny', or 'remark' - # @option :opts [String] :addr The IP address to permit or deny. - # @option :opts [String] :prefixlen The prefixlen for the IP address. - # @option :opts [Boolean] :log Triggers an informational log message + # + # @option entry action [String] The action triggered by the ACL. Valid + # values are 'permit', 'deny', or 'remark'. + # + # @option entry addr [String] The IP address to permit or deny. + # + # @option entry prefixlen [String] The prefixlen for the IP address. + # + # @option entry log [Boolean] Triggers an informational log message # to the console about the matching packet. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def update_entry(name, entry) cmds = ["ip access-list standard #{name}"] cmds << "no #{entry[:seqno]}" @@ -295,18 +306,23 @@ def update_entry(name, entry) # add_entry will add an entry to the specified ACL with the # passed in parameters. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M + # + # @param name [String] The ACL name to add an entry to on the node. + # + # @param entry [Hash] the options for the entry. # - # @param [String] :name The ACL name to add an entry to on the node. - # @param [Hash] :opts the options for the entry - # @option :opts [String] :action The action triggered by the ACL. Valid - # values are 'permit', 'deny', or 'remark' - # @option :opts [String] :addr The IP address to permit or deny. - # @option :opts [String] :prefixlen The prefixlen for the IP address. - # @option :opts [Boolean] :log Triggers an informational log message + # @option entry action [String] The action triggered by the ACL. Valid + # values are 'permit', 'deny', or 'remark'. + # + # @option entry addr [String] The IP address to permit or deny. + # + # @option entry prefixlen [String] The prefixlen for the IP address. + # + # @option entry log [Boolean] Triggers an informational log message # to the console about the matching packet. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def add_entry(name, entry) cmds = ["ip access-list standard #{name}"] cmds << build_entry(entry) @@ -318,13 +334,14 @@ def add_entry(name, entry) # remove_entry will remove the entry specified by the seqno for # the ACL specified by name. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M + # + # @param name [String] The ACL name to update on the node. # - # @param [String] :name The ACL name to update on the node. - # @param [String] :seqno The sequence number of the entry in + # @param seqno [String] The sequence number of the entry in # the ACL to remove. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def remove_entry(name, seqno) cmds = ["ip access-list standard #{name}", "no #{seqno}", 'exit'] configure(cmds) diff --git a/lib/rbeapi/api/bgp.rb b/lib/rbeapi/api/bgp.rb index 67d3a63..25d11b9 100644 --- a/lib/rbeapi/api/bgp.rb +++ b/lib/rbeapi/api/bgp.rb @@ -32,13 +32,13 @@ require 'rbeapi/api' ## -# Eos is the toplevel namespace for working with Arista EOS nodes +# Eos is the toplevel namespace for working with Arista EOS nodes. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## - # The Bgp class implements global BGP router configuration + # The Bgp class implements global BGP router configuration. class Bgp < Entity attr_reader :neighbors @@ -115,9 +115,9 @@ def get # AS number. Defined as a class method. Used by the BgpNeighbors # class below. # - # @param [String] :config The switch config. + # @param config [String] The switch config. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def self.parse_bgp_as(config) value = config.scan(/^router bgp (\d+)/).first { bgp_as: value[0] } @@ -129,9 +129,9 @@ def self.parse_bgp_as(config) # # @api private # - # @param [String] :config The switch config. + # @param config [String] The switch config. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_router_id(config) value = config.scan(/router-id ([^\s]+)/).first value = value ? value[0] : nil @@ -145,7 +145,7 @@ def parse_router_id(config) # # @api private # - # @param [String] :config The switch config. + # @param config [String] The switch config. # # @return [Hash] resource hash attribute. Returns # true if shutdown, false otherwise. @@ -161,9 +161,9 @@ def parse_shutdown(config) # # @api private # - # @param [String] :config The switch config. + # @param config [String] The switch config. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_maximum_paths(config) values = config.scan(/maximum-paths\s+(\d+)\s+ecmp\s+(\d+)/).first { maximum_paths: values[0].to_i, maximum_ecmp_paths: values[1].to_i } @@ -176,10 +176,9 @@ def parse_maximum_paths(config) # # @api private # - # @param [String] :config The switch config. + # @param config [String] The switch config. # - # @return [Hash] resource hash attribute - # @return [Array] Single element hash with Array of network hashes + # @return [Array] Single element hash with Array of network hashes. def parse_networks(config) networks = [] lines = config.scan(%r{network (.+)/(\d+)(?: route-map (\w+))*}) @@ -196,16 +195,15 @@ def parse_networks(config) # Optional parameters can be passed in to initialize BGP specific # settings. # - # @commands + # commands # router bgp # - # @param [String] :bgp_as The BGP autonomous system number to be + # @param bgp_as [String] The BGP autonomous system number to be # configured for the local BGP routing instance. # + # @param opts [hash] Optional keyword arguments. # - # @param [hash] :opts Optional keyword arguments - # - # @option :opts [String] :router_id The BGP routing process router-id + # @option opts router_id [String] The BGP routing process router-id # value. When no ID has been specified (i.e. value not set), the # local router ID is set to the following: # * The loopback IP address when a single loopback interface is @@ -215,17 +213,17 @@ def parse_networks(config) # * The highest IP address on a physical interface when no loopback # interfaces are configure # - # @option :opts [Integer] :maximum_paths Maximum number of equal cost + # @option opts maximum_paths [Integer] Maximum number of equal cost # paths. # - # @option :opts [Integer] :maximum_ecmp_paths Maximum number of installed + # @option opts maximum_ecmp_paths [Integer] Maximum number of installed # ECMP routes. The maximum_paths option must be set if # maximum_ecmp_paths is set. # - # @option :opts [Boolean] :enable If true then the BGP router is enabled. + # @option opts enable [Boolean] If true then the BGP router is enabled. # If false then the BGP router is disabled. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] returns true if the command completed successfully. def create(bgp_as, opts = {}) if opts[:maximum_ecmp_paths] && !opts[:maximum_paths] message = 'maximum_paths must be set if maximum_ecmp_paths is set' @@ -249,10 +247,10 @@ def create(bgp_as, opts = {}) ## # delete will delete the BGP routing instance from the node. # - # @commands + # commands # no router bgp # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete config = get return true unless config @@ -264,7 +262,7 @@ def delete # keyword. This command has the same effect as deleting the BGP # routine instance from the nodes running configuration. # - # @commands + # commands # default router bgp # # @return [Boolean] returns true if the command complete successfully @@ -281,9 +279,9 @@ def default # # @api private # - # @param [String] :cmd Command to run under BGP mode + # @param cmd [String] Command to run under BGP mode. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def configure_bgp(cmd) config = get_block('^router bgp .*') fail 'BGP router is not configured' unless config @@ -296,14 +294,14 @@ def configure_bgp(cmd) ## # set_router_id sets the router_id for the BGP routing instance. # - # @commands + # commands # router bgp # {no | default} router-id # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments # - # @option :opts [String] :value The BGP routing process router-id - # value. When no ID has been specified (i.e. value not set), the + # @option opts value [String] The BGP routing process router-id + # value. When no ID has been specified (i.e. value not set), the # local router ID is set to the following: # * The loopback IP address when a single loopback interface is # configured. @@ -312,13 +310,13 @@ def configure_bgp(cmd) # * The highest IP address on a physical interface when no loopback # interfaces are configure # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the router-id using - # the default keyword + # @option opts default [Boolean] Configure the router-id using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_router_id(opts = {}) configure_bgp(command_builder('router-id', opts)) end @@ -327,21 +325,21 @@ def set_router_id(opts = {}) # set_shutdown configures the administrative state for the global # BGP routing process. The value option is not used by this method. # - # @commands + # commands # router bgp # {no | default} shutdown # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If enable is true then the BGP + # @option opts enable [Boolean] If enable is true then the BGP # routing process is administratively enabled and if enable is # False then the BGP routing process is administratively # disabled. # - # @option :opts [Boolean] :default Configure the router-id using - # the default keyword + # @option opts default [Boolean] Configure the router-id using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_shutdown(opts = {}) fail 'set_shutdown has the value option set' if opts[:value] # Shutdown semantics are opposite of enable semantics so invert enable @@ -354,25 +352,25 @@ def set_shutdown(opts = {}) # set_maximum_paths sets the maximum number of equal cost paths and # the maximum number of installed ECMP routes. # - # @commands + # commands # router bgp # {no | default} # maximum-paths [ecmp ] # - # @param [Integer] :maximum_paths Maximum number of equal cost paths. + # @param maximum_paths [Integer] Maximum number of equal cost paths. # - # @param [Integer] :maximum_ecmp_paths Maximum number of installed ECMP + # @param maximum_ecmp_paths [Integer] Maximum number of installed ECMP # routes. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the maximum paths using - # the default keyword + # @option opts default [Boolean] Configure the maximum paths using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_maximum_paths(maximum_paths, maximum_ecmp_paths, opts = {}) enable = opts.fetch(:enable, true) default = opts[:default] || false @@ -393,19 +391,21 @@ def set_maximum_paths(maximum_paths, maximum_ecmp_paths, opts = {}) ## # add_network creates a new instance of a BGP network on the node. # - # @commands + # commands # router bgp # network / # route-map # - # @param [String] :prefix The IPv4 prefix to configure as part of - # the network statement. The value must be a valid IPv4 prefix. - # @param [String] :masklen The IPv4 subnet mask length in bits. + # @param prefix [String] The IPv4 prefix to configure as part of + # the network statement. The value must be a valid IPv4 prefix. + # + # @param masklen [String] The IPv4 subnet mask length in bits. # The masklen must be in the valid range of 1 to 32. - # @param [String] :route_map The route-map name to apply to the + # + # @param route_map [String] The route-map name to apply to the # network statement when configured. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def add_network(prefix, masklen, route_map = nil) cmd = "network #{prefix}/#{masklen}" cmd << " route-map #{route_map}" if route_map @@ -415,18 +415,20 @@ def add_network(prefix, masklen, route_map = nil) ## # remove_network removes the instance of a BGP network on the node. # - # @commands + # commands # router bgp # {no} shutdown # - # @param [String] :prefix The IPv4 prefix to configure as part of + # @param prefix [String] The IPv4 prefix to configure as part of # the network statement. The value must be a valid IPv4 prefix. - # @param [String] :masklen The IPv4 subnet mask length in bits. + # + # @param masklen [String] The IPv4 subnet mask length in bits. # The masklen must be in the valid range of 1 to 32. - # @param [String] :route_map The route-map name to apply to the + # + # @param route_map [String] The route-map name to apply to the # network statement when configured. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def remove_network(prefix, masklen, route_map = nil) cmd = "no network #{prefix}/#{masklen}" cmd << " route-map #{route_map}" if route_map @@ -453,7 +455,7 @@ class BgpNeighbors < Entity # route_map_out: # } # - # @param [String] :name The name of the BGP neighbor to manage. + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # @@ -525,12 +527,13 @@ def getall # # @api private # - # @param [String] :config The switch config. - # @param [String] :name The name of the BGP neighbor to manage. + # @param config [String] The switch config. + # + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_peer_group(config, name) value = config.scan(/neighbor #{name} peer-group ([^\s]+)/) peer_group = value[0] ? value[0][0] : nil @@ -544,12 +547,13 @@ def parse_peer_group(config, name) # # @api private # - # @param [String] :config The switch config. - # @param [String] :name The name of the BGP neighbor to manage. + # @param config [String] The switch config. + # + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute def parse_remote_as(config, name) value = config.scan(/neighbor #{name} remote-as (\d+)/) remote_as = value[0] ? value[0][0] : nil @@ -563,12 +567,13 @@ def parse_remote_as(config, name) # # @api private # - # @param [String] :config The switch config. - # @param [String] :name The name of the BGP neighbor to manage. + # @param config [String] The switch config. + # + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_send_community(config, name) value = config.scan(/no neighbor #{name} send-community/) enabled = value[0] ? false : true @@ -582,13 +587,14 @@ def parse_send_community(config, name) # # @api private # - # @param [String] :config The switch config. - # @param [String] :name The name of the BGP neighbor to manage. + # @param config [String] The switch config. + # + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Hash] resource hash attribute. Returns - # true if shutdown, false otherwise. + # @return [Hash] Resource hash attribute. Returns + # true if shutdown, false otherwise. def parse_shutdown(config, name) value = config.scan(/no neighbor #{name} shutdown/) shutdown = value[0] ? false : true @@ -602,12 +608,14 @@ def parse_shutdown(config, name) # # @api private # - # @param [String] :config The switch config. - # @param [String] :name The name of the BGP neighbor to manage. + # @param config [String] The switch config. + # + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash + # attribute. def parse_description(config, name) value = config.scan(/neighbor #{name} description (.*)$/) description = value[0] ? value[0][0] : nil @@ -621,12 +629,13 @@ def parse_description(config, name) # # @api private # - # @param [String] :config The switch config. - # @param [String] :name The name of the BGP neighbor to manage. + # @param config [String] The switch config. + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash + # attribute. def parse_next_hop_self(config, name) value = config.scan(/no neighbor #{name} next-hop-self/) enabled = value[0] ? false : true @@ -640,12 +649,14 @@ def parse_next_hop_self(config, name) # # @api private # - # @param [String] :config The switch config. - # @param [String] :name The name of the BGP neighbor to manage. + # @param config [String] The switch config. + # + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash + # attribute. def parse_route_map_in(config, name) value = config.scan(/neighbor #{name} route-map ([^\s]+) in/) route_map_in = value[0] ? value[0][0] : nil @@ -659,12 +670,14 @@ def parse_route_map_in(config, name) # # @api private # - # @param [String] :config The switch config. - # @param [String] :name The name of the BGP neighbor to manage. + # @param config [String] The switch config. + # + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash + # attribute. def parse_route_map_out(config, name) value = config.scan(/neighbor #{name} route-map ([^\s]+) out/) route_map_out = value[0] ? value[0][0] : nil @@ -679,9 +692,9 @@ def parse_route_map_out(config, name) # # @api private # - # @param [String] :cmd Command to run under BGP mode + # @param cmd [String] Command to run under BGP mode. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def configure_bgp(cmd) config = get_block('^router bgp .*') fail 'BGP router is not configured' unless config @@ -695,11 +708,11 @@ def configure_bgp(cmd) # create will create a new instance of a BGP neighbor on the node. # The neighbor is created in the shutdown state and then enabled. # - # @param [String] :name The name of the BGP neighbor to manage. + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(name) set_shutdown(name, enable: false) end @@ -707,16 +720,16 @@ def create(name) ## # delete will delete the BGP neighbor from the node. # - # @commands + # commands # no neighbor # or # no neighbor peer-group # - # @param [String] :name The name of the BGP neighbor to manage. + # @param name [String] The name of the BGP neighbor to manage. # This value can be either an IPv4 address or string (in the # case of managing a peer group). # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete(name) cmd = "no neighbor #{name}" response = configure_bgp(cmd) @@ -728,21 +741,23 @@ def delete(name) end ## - # neigh_command_builder for neighbors which calls command_builder + # neigh_command_builder for neighbors which calls command_builder. + # + # @param name [String] The name of the BGP neighbor to manage. # - # @param [String] :name The name of the BGP neighbor to manage. - # @param [String] :cmd The command portion of the neighbor command. - # @param [hash] :opts Optional keyword arguments + # @param cmd [String] The command portion of the neighbor command. # - # @option :opts [String] :value Value being set. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] Value being set. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the command using + # @option opts default [Boolean] Configure the command using # the default keyword. # - # @return [String] Returns built command string + # @return [String] Returns built command string. def neigh_command_builder(name, cmd, opts) command_builder("neighbor #{name} #{cmd}", opts) end @@ -750,22 +765,23 @@ def neigh_command_builder(name, cmd, opts) ## # set_peer_group creates a BGP static peer group name. # - # @commands + # commands # router bgp # {no | default} neighbor peer-group # - # @param [String] :name The IP address of the neighbor - # @param [hash] :opts Optional keyword arguments + # @param name [String] The IP address of the neighbor. + # + # @param opts [hash] Optional keyword arguments. # - # @option :opts [String] :value The group name. + # @option opts value [String] The group name. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the peer group using - # the default keyword + # @option opts default [Boolean] Configure the peer group using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_peer_group(name, opts = {}) configure_bgp(neigh_command_builder(name, 'peer-group', opts)) end @@ -774,22 +790,23 @@ def set_peer_group(name, opts = {}) # set_remote_as configures the expected AS number for a neighbor # (peer). # - # @commands + # commands # router bgp # {no | default} neighbor remote-as # - # @param [String] :name The IP address or name of the peer group. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The IP address or name of the peer group. # - # @option :opts [String] :value The remote as-id. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] The remote as-id. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the peer group using - # the default keyword + # @option opts default [Boolean] Configure the peer group using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_remote_as(name, opts = {}) configure_bgp(neigh_command_builder(name, 'remote-as', opts)) end @@ -798,23 +815,24 @@ def set_remote_as(name, opts = {}) # set_shutdown disables the specified neighbor. The value option is # not used by this method. # - # @commands + # commands # router bgp # {no | default} neighbor shutdown # - # @param [String] :name The IP address or name of the peer group. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The IP address or name of the peer group. # - # @option :opts [String] :enable True enables the specified neighbor. + # @param opts [hash] Optional keyword arguments. + # + # @option opts enable [String] True enables the specified neighbor. # False disables the specified neighbor. # - # @option :opts [Boolean] :default Configure the peer group using - # the default keyword + # @option opts default [Boolean] Configure the peer group using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_shutdown(name, opts = {}) fail 'set_shutdown has value option set' if opts[:value] - # Shutdown semantics are opposite of enable semantics so invert enable + # Shutdown semantics are opposite of enable semantics so invert enable. value = !opts[:enable] opts.merge!(enable: value) configure_bgp(neigh_command_builder(name, 'shutdown', opts)) @@ -825,20 +843,21 @@ def set_shutdown(name, opts = {}) # attributes to the specified BGP neighbor. The value option is # not used by this method. # - # @commands + # commands # router bgp # {no | default} neighbor send-community # - # @param [String] :name The IP address or name of the peer group. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The IP address or name of the peer group. + # + # @param opts [hash] Optional keyword arguments. # - # @option :opts [String] :enable True enables the feature. False + # @option opts enable [String] True enables the feature. False # disables the feature. # - # @option :opts [Boolean] :default Configure the peer group using - # the default keyword + # @option opts default [Boolean] Configure the peer group using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_send_community(name, opts = {}) fail 'send_community has the value option set' if opts[:value] configure_bgp(neigh_command_builder(name, 'send-community', opts)) @@ -850,20 +869,21 @@ def set_send_community(name, opts = {}) # BGP-speaking neighbor or neighbors in the specified peer group. # The value option is not used by this method. # - # @commands + # commands # router bgp # {no | default} neighbor next-hop-self # - # @param [String] :name The IP address or name of the peer group. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The IP address or name of the peer group. + # + # @param opts [hash] Optional keyword arguments. # - # @option :opts [String] :enable True enables the feature. False + # @option opts enable [String] True enables the feature. False # disables the feature. # - # @option :opts [Boolean] :default Configure the peer group using - # the default keyword + # @option opts default [Boolean] Configure the peer group using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_next_hop_self(name, opts = {}) fail 'set_next_hop_self has the value option set' if opts[:value] configure_bgp(neigh_command_builder(name, 'next-hop-self', opts)) @@ -873,22 +893,23 @@ def set_next_hop_self(name, opts = {}) # set_route_map_in command applies a route map to inbound BGP # routes. # - # @commands + # commands # router bgp # {no | default} neighbor route-map in # - # @param [String] :name The IP address or name of the peer group. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The IP address or name of the peer group. # - # @option :opts [String] :value Name of a route map. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] Name of a route map. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the peer group using - # the default keyword + # @option opts default [Boolean] Configure the peer group using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_route_map_in(name, opts = {}) cmd = neigh_command_builder(name, 'route-map', opts) + ' in' configure_bgp(cmd) @@ -898,22 +919,23 @@ def set_route_map_in(name, opts = {}) # set_route_map_out command applies a route map to outbound BGP # routes. # - # @commands + # commands # router bgp # {no | default} neighbor route-map out # - # @param [String] :name The IP address or name of the peer group. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The IP address or name of the peer group. # - # @option :opts [String] :value Name of a route map. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] Name of a route map. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the peer group using - # the default keyword + # @option opts default [Boolean] Configure the peer group using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_route_map_out(name, opts = {}) cmd = neigh_command_builder(name, 'route-map', opts) + ' out' configure_bgp(cmd) @@ -923,22 +945,23 @@ def set_route_map_out(name, opts = {}) # set_description associates descriptive text with the specified # peer or peer group. # - # @commands + # commands # router bgp # {no | default} neighbor description # - # @param [String] :name The IP address or name of the peer group. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The IP address or name of the peer group. # - # @option :opts [String] :value The description string. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] The description string. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the peer group using - # the default keyword + # @option opts default [Boolean] Configure the peer group using + # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_description(name, opts = {}) configure_bgp(neigh_command_builder(name, 'description', opts)) end diff --git a/lib/rbeapi/api/dns.rb b/lib/rbeapi/api/dns.rb index f3777cb..2072ccf 100644 --- a/lib/rbeapi/api/dns.rb +++ b/lib/rbeapi/api/dns.rb @@ -32,16 +32,16 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Dns class manages DNS settings on an EOS node. class Dns < Entity ## - # get returns the DNS resource + # get returns the DNS resource. # # @example # { @@ -50,7 +50,7 @@ class Dns < Entity # "domain_list": array # } # - # @return [Hash] A Ruby hash object that provides the SNMP settings as + # @return [Hash] A Ruby hash object that provides the SNMP settings as # key / value pairs. def get response = {} @@ -61,11 +61,11 @@ def get end ## - # parse_domain_name parses the domain-name from config + # parse_domain_name parses the domain-name from config. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_domain_name mdata = /ip domain-name ([\w.]+)/.match(config) { domain_name: mdata.nil? ? '' : mdata[1] } @@ -74,11 +74,11 @@ def parse_domain_name ## # parse_name_servers parses the name-server values from - # config + # config. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_name_servers servers = config.scan(/(?:ip name-server vrf )(?:\w+)\s(.+)/) values = servers.each_with_object([]) { |srv, arry| arry << srv.first } @@ -87,11 +87,11 @@ def parse_name_servers private :parse_name_servers ## - # parse_domain_list parses the domain-list from config + # parse_domain_list parses the domain-list from config. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_domain_list search = config.scan(/(?<=^ip\sdomain-list\s).+$/) { domain_list: search } @@ -99,15 +99,18 @@ def parse_domain_list private :parse_domain_list ## - # Configure the domain-name value in the running-config + # Configure the domain-name value in the running-config. # - # @param [Hash] opts The configuration parameters - # @option opts [string] :value The value to set the domain-name to - # @option :opts [Boolean] :enable If false then the command is + # @param opts [Hash] The configuration parameters. + # + # @option opts value [string] The value to set the domain-name to. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default # - # @return [Boolean] returns true if the command completed successfully + # @option opts default [Boolean] The value should be set to default. + # + # @return [Boolean] Returns true if the command completed successfully. def set_domain_name(opts = {}) cmds = command_builder('ip domain-name', opts) configure(cmds) @@ -118,26 +121,29 @@ def set_domain_name(opts = {}) # to resolve dns queries. If the enable option is false, then the # name-server list will be configured using the no keyword. If the # default option is specified, then the name server list will be - # configured using the default keyword. If both options are provided the - # keyword option will take precedence + # configured using the default keyword. If both options are provided the + # keyword option will take precedence. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # ip name-server # no ip name-server # default ip name-server # - # @param [Hash] opts The configuration parameters - # @option opts [string] :value The set of name servers to configure on the - # node. The list of name servers will be replace in the nodes running - # configuration by the list provided in value - # @option :opts [Boolean] :enable If false then the command is + # @param [Hash] opts The configuration parameters. + # + # @option opts value [string] The set of name servers to configure on the + # node. The list of name servers will be replace in the nodes running + # configuration by the list provided in value. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option [Boolean] :default Configures the ip name-servers using the + # + # @option default [Boolean] Configures the ip name-servers using the # default keyword argument. Default takes precedence over enable. # - # @return [Boolean] returns true if the commands completed successfully + # @return [Boolean] Returns true if the commands completed successfully. def set_name_servers(opts = {}) value = opts[:value] enable = opts.fetch(:enable, true) @@ -160,9 +166,9 @@ def set_name_servers(opts = {}) ## # add_name_server adds an ip name-server. # - # @param [String] :server The name of the ip name-server to create + # @param server [String] The name of the ip name-server to create. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_name_server(server) configure "ip name-server #{server}" end @@ -170,36 +176,36 @@ def add_name_server(server) ## # remove_name_server removes the specified ip name-server. # - # @param [String] :server The name of the ip name-server to remove + # @param server [String] The name of the ip name-server to remove. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def remove_name_server(server) configure "no ip name-server #{server}" end ## # set_domain_list configures the set of domain names to search when - # making dns queries for the FQDN. If the enable option is set to false, + # making dns queries for the FQDN. If the enable option is set to false, # then the domain-list will be configured using the no keyword. If the # default option is specified, then the domain list will be configured - # using the default keyword. If both options are provided the default + # using the default keyword. If both options are provided the default # keyword option will take precedence. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # ip domain-list # no ip domain-list # default ip domain-list # - # @option [Array] :value The set of domain names to configure on the - # node. The list of domain names will be replace in the nodes running - # configuration by the list provided in value + # @option value [Array] The set of domain names to configure on the + # node. The list of domain names will be replace in the nodes running + # configuration by the list provided in value. # - # @option [Boolean] :default Configures the ip domain-list using the - # default keyword argument + # @option default [Boolean] Configures the ip domain-list using the + # default keyword argument. # - # @return [Boolean] returns true if the commands completed successfully + # @return [Boolean] Returns true if the commands completed successfully. def set_domain_list(opts = {}) value = opts[:value] enable = opts.fetch(:enable, true) @@ -227,9 +233,9 @@ def set_domain_list(opts = {}) ## # add_domain_list adds an ip domain-list. # - # @param [String] :name The name of the ip domain-list to add + # @param name [String] The name of the ip domain-list to add. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_domain_list(name) configure "ip domain-list #{name}" end @@ -237,9 +243,9 @@ def add_domain_list(name) ## # remove_domain_list removes a specified ip domain-list. # - # @param [String] :name The name of the ip domain-list to remove + # @param name [String] The name of the ip domain-list to remove. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def remove_domain_list(name) configure "no ip domain-list #{name}" end diff --git a/lib/rbeapi/api/interfaces.rb b/lib/rbeapi/api/interfaces.rb index f2e2de3..9efc667 100644 --- a/lib/rbeapi/api/interfaces.rb +++ b/lib/rbeapi/api/interfaces.rb @@ -33,10 +33,10 @@ require 'rbeapi/utils' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Interfaces class manages all physical and logical interfaces on an @@ -48,7 +48,7 @@ def initialize(node) end ## - # get returns a hash of interface configurations for the given name + # get returns a hash of interface configurations for the given name. # # @example # { @@ -58,18 +58,18 @@ def initialize(node) # shutdown: # } # - # @param [String] :name The interface name to return a resource for from - # the nodes configuration + # @param name [String] The interface name to return a resource for from + # the nodes configuration. # # @return [nil, Hash] Returns the interface resource as a # Hash. If the specified name is not found in the nodes current - # configuration a nil object is returned + # configuration a nil object is returned. def get(name) get_instance(name).get(name) end ## - # getall returns a hash of interface configurations + # getall returns a hash of interface configurations. # # @example # { @@ -91,8 +91,8 @@ def get(name) # } # # @return [Hash] Returns the interface resources as a - # Hash. If none exist in the nodes current - # configuration an empty hash is returned + # Hash. If none exist in the nodes current configuration an empty + # hash is returned. def getall interfaces = config.scan(/(?<=^interface\s).+$/) @@ -103,12 +103,11 @@ def getall end ## - # get_instance returns an interface instance for the given name + # get_instance returns an interface instance for the given name. # - # @param [String] :name The interface name to return an instance for + # @param name [String] The interface name to return an instance for. # - # @return [Object] Returns the interface instance as an - # Object. + # @return [Object] Returns the interface instance as an Object. def get_instance(name) name = name[0, 2].upcase case name @@ -148,9 +147,9 @@ class BaseInterface < Entity ## # get returns the specified interface resource hash that represents the - # node's current interface configuration. The BaseInterface class + # node's current interface configuration. The BaseInterface class # provides all the set of attributes that are common to all interfaces - # in EOS. This method will return an interface type of generic + # in EOS. This method will return an interface type of generic. # # @example # { @@ -160,12 +159,12 @@ class BaseInterface < Entity # shutdown: [true, false] # } # - # @param [String] :name The name of the interface to return from the - # running-configuration + # @param name [String] The name of the interface to return from the + # running-configuration. # # @return [nil, Hash] Returns a hash of the interface # properties if the interface name was found in the running - # configuration. If the interface was not found, nil is returned + # configuration. If the interface was not found, nil is returned. def get(name) config = get_block("^interface #{name}") return nil unless config @@ -185,7 +184,10 @@ def get(name) # # @api private # - # @return [Hash] resource hash attribute + # @param config [String] The configuration block retrieved from the + # nodes current running configuration. + # + # @return [Hash] Returns the resource hash attribute. def parse_description(config) mdata = /^\s{3}description\s(.+)$/.match(config) { description: mdata.nil? ? DEFAULT_INTF_DESCRIPTION : mdata[1] } @@ -201,7 +203,10 @@ def parse_description(config) # # @api private # - # @return [Hash] resource hash attribute + # @param config [String] The configuration block retrieved from the + # nodes current running configuration. + # + # @return [Hash] Returns the resource hash attribute. def parse_shutdown(config) value = /no shutdown/ =~ config { shutdown: value.nil? } @@ -210,80 +215,80 @@ def parse_shutdown(config) ## # create will create a new interface resource in the node's current - # configuration with the specified interface name. If the create + # configuration with the specified interface name. If the create # method is called and the interface already exists, this method will - # return successful + # return successful. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :value The interface name to create on the node. The + # @param value [String] The interface name to create on the node. The # interface name must be the full interface identifier (ie Loopback, - # not Lo) + # not Lo). # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(value) configure("interface #{value}") end ## # delete will delete an existing interface resource in the node's - # current configuration with the specified interface name. If the + # current configuration with the specified interface name. If the # delete method is called and interface does not exist, this method - # will return successful + # will return successful. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :value The interface name to delete from the node. + # @param value [String] The interface name to delete from the node. # The interface name must be the full interface identifier - # (ie Loopback, no Lo) + # (ie Loopback, no Lo). # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete(value) configure("no interface #{value}") end ## - # default will configure the interface using the default keyword. For + # default will configure the interface using the default keyword. For # virtual interfaces this is equivalent to deleting the interface. For # physical interfaces, the entire interface configuration will be set # to defaults. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :value The interface name to default in the node. The + # @param value [String] The interface name to default in the node. The # interface name must be the full interface identifier (ie Loopback, - # not Lo) + # not Lo). # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def default(value) configure("default interface #{value}") end ## # set_description configures the description value for the specified - # interface name in the nodes running configuration. If the enable + # interface name in the nodes running configuration. If the enable # keyword is false then the description value is negated using the no - # keyword. If the default keyword is set to true, then the description - # value is defaulted using the default keyword. The default keyword takes + # keyword. If the default keyword is set to true, then the description + # value is defaulted using the default keyword. The default keyword takes # precedence over the enable keyword if both are provided. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # to. The name value must be the full interface identifier + # @param name [String] The interface name to apply the configuration + # to. The name value must be the full interface identifier. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the description + # @option opts value [String] The value to configure the description # to in the node's configuration. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the interface description - # using the default keyword + # @option opts default [Boolean] Configure the interface description + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_description(name, opts = {}) commands = command_builder('description', opts) configure_interface(name, commands) @@ -291,31 +296,31 @@ def set_description(name, opts = {}) ## # set_shutdown configures the administrative state of the specified - # interface in the node. If the enable keyword is false, then the - # interface is administratively disabled. If the enable keyword is - # true, then the interface is administratively enabled. If the default + # interface in the node. If the enable keyword is false, then the + # interface is administratively disabled. If the enable keyword is + # true, then the interface is administratively enabled. If the default # keyword is set to true, then the interface shutdown value is configured - # using the default keyword. The default keyword takes precedence + # using the default keyword. The default keyword takes precedence # over the enable keyword if both are provided. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # to. The name value must be the full interface identifier + # @param name [String] The interface name to apply the configuration + # to. The name value must be the full interface identifier. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable True if the interface should be + # @option opts enable [Boolean] True if the interface should be # administratively enabled or false if the interface should be # administratively disabled. # - # @option :opts [Boolean] :default Configure the interface shutdown - # using the default keyword + # @option opts default [Boolean] Configure the interface shutdown + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_shutdown(name, opts = {}) fail 'set_shutdown has the value option set' if opts[:value] - # Shutdown semantics are opposite of enable semantics so invert enable + # Shutdown semantics are opposite of enable semantics so invert enable. value = !opts[:enable] opts.merge!(enable: value) commands = command_builder('shutdown', opts) @@ -349,12 +354,12 @@ class EthernetInterface < BaseInterface # flowcontrol_receive: # } # - # @param [String] :name The interface name to return a resource hash - # for from the node's running configuration + # @param name [String] The interface name to return a resource hash + # for from the node's running configuration. # # @return [nil, Hash] Returns the interface resource as - # a hash. If the specified interface name is not found in the node's - # configuration a nil object is returned + # a hash. If the specified interface name is not found in the node's + # configuration a nil object is returned. def get(name) config = get_block("^interface #{name}") return nil unless config @@ -372,12 +377,14 @@ def get(name) ## # parse_speed scans the provided configuration block and parses the speed # value. If the speed value is not found in the interface configuration - # block provided, DEFAULT_SPEED and DEFAULT_FORCED are used. The - # returned hash is intended to be merged into the interface resource hash + # block provided, DEFAULT_SPEED and DEFAULT_FORCED are used. The + # returned hash is intended to be merged into the interface resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @param config [String] The configuration block to parse. + # + # @return [Hash] Returns the resource hash attribute. def parse_speed(config) value = config.scan(/speed (forced)?[ ]?(\w+)/).first return { speed: DEFAULT_SPEED, forced: DEFAULT_FORCED } unless value @@ -388,13 +395,15 @@ def parse_speed(config) ## # parse_sflow scans the provided configuration block and parse the - # sflow value. The sflow values true if sflow is enabled on the - # interface or returns false if it is not enabled. The hash returned + # sflow value. The sflow values true if sflow is enabled on the + # interface or returns false if it is not enabled. The hash returned # is intended to be merged into the interface hash. # # @api private # - # @return [Hash] resource hash attribute + # @param config [String] The configuration block to parse. + # + # @return [Hash] Returns the resource hash attribute. def parse_sflow(config) value = /no sflow enable/ =~ config { sflow: value.nil? } @@ -403,14 +412,16 @@ def parse_sflow(config) ## # parse_flowcontrol_send scans the provided configuration block and - # parses the flowcontrol send value. If the interface flowcontrol value + # parses the flowcontrol send value. If the interface flowcontrol value # is not configured, then this method will return the value of - # DEFAULT_ETH_FLOWC_TX. The hash returned is intended to be merged into + # DEFAULT_ETH_FLOWC_TX. The hash returned is intended to be merged into # the interface resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @param config [String] The configuration block to parse. + # + # @return [Hash] Returns the resource hash attribute. def parse_flowcontrol_send(config) mdata = /flowcontrol send (\w+)$/.match(config) { flowcontrol_send: mdata.nil? ? DEFAULT_ETH_FLOWC_TX : mdata[1] } @@ -419,14 +430,16 @@ def parse_flowcontrol_send(config) ## # parse_flowcontrol_receive scans the provided configuration block and - # parse the flowcontrol receive value. If the interface flowcontrol + # parse the flowcontrol receive value. If the interface flowcontrol # value is not configured, then this method will return the value of - # DEFAULT_ETH_FLOWC_RX. The hash returned is intended to be merged into + # DEFAULT_ETH_FLOWC_RX. The hash returned is intended to be merged into # the interface resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @param config [String] The configuration block to parse. + # + # @return [Hash] Returns the resource hash attribute. def parse_flowcontrol_receive(config) mdata = /flowcontrol receive (\w+)$/.match(config) { flowcontrol_receive: mdata.nil? ? DEFAULT_ETH_FLOWC_RX : mdata[1] } @@ -437,10 +450,10 @@ def parse_flowcontrol_receive(config) # create overrides the create method from the BaseInterface and raises # an exception because Ethernet interface creation is not supported. # - # @param [String] :name The name of the interface + # @param _name [String] The name of the interface. # # @raise [NotImplementedError] Creation of physical Ethernet interfaces - # is not supported + # is not supported. def create(_name) fail NotImplementedError, 'creating Ethernet interfaces is '\ 'not supported' @@ -451,10 +464,10 @@ def create(_name) # raises an exception because Ethernet interface deletion is not # supported. # - # @param [String] :name The name of the interface + # @param _name [String] The name of the interface. # # @raise [NotImplementedError] Deletion of physical Ethernet interfaces - # is not supported + # is not supported. def delete(_name) fail NotImplementedError, 'deleting Ethernet interfaces is '\ 'not supported' @@ -462,32 +475,32 @@ def delete(_name) ## # set_speed configures the interface speed and negotiation values on the - # specified interface. If the enable option is false the speed - # setting is configured using the no keyword. If the default options is + # specified interface. If the enable option is false the speed + # setting is configured using the no keyword. If the default options is # set to true, then the speed setting is configured using the default - # keyword. If both options are specified, the default keyword takes + # keyword. If both options are specified, the default keyword takes # precedence. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # values to. The name must be the full interface identifier. + # @param name [String] The interface name to apply the configuration + # values to. The name must be the full interface identifier. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option [String] :value The value to configure the speed setting to in - # the nodes running configuration + # @option opts value [String] The value to configure the speed setting to + # in the nodes running configuration. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option [Boolean] :forced Specifies if auto negotiation should be - # enabled (true) or disabled (false) + # @option opts forced [Boolean] Specifies if auto negotiation should be + # enabled (true) or disabled (false). # - # @option :opts [Boolean] :default Configures the sflow value on the - # interface using the default keyword + # @option opts default [Boolean] Configures the sflow value on the + # interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_speed(name, opts = {}) value = opts[:value] forced = opts.fetch(:forced, false) @@ -509,26 +522,26 @@ def set_speed(name, opts = {}) ## # set_sflow configures the administrative state of sflow on the - # interface. Setting the enable keyword to true enables sflow on the + # interface. Setting the enable keyword to true enables sflow on the # interface and setting enable to false disables sflow on the interface. # If the default keyword is set to true, then the sflow value is - # defaulted using the default keyword. The default keyword takes + # defaulted using the default keyword. The default keyword takes # precedence over the enable keyword # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # values to. The name must be the full interface identifier. + # @param name [String] The interface name to apply the configuration + # values to. The name must be the full interface identifier. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable Enables sflow if the value is true or + # @option opts enable [Boolean] Enables sflow if the value is true or # disables sflow on the interface if false. Default is true. # - # @option :opts [Boolean] :default Configures the sflow value on the - # interface using the default keyword + # @option opts default [Boolean] Configures the sflow value on the + # interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_sflow(name, opts = {}) commands = command_builder('sflow enable', opts) configure_interface(name, commands) @@ -537,31 +550,31 @@ def set_sflow(name, opts = {}) ## # set_flowcontrol configures the flowcontrol value either on or off for # the for the specified interface in the specified direction (either send - # or receive). If the enable keyword is false then the configuration is - # negated using the no keyword. If the default keyword is set to true, - # then the state value is defaulted using the default keyword. The + # or receive). If the enable keyword is false then the configuration is + # negated using the no keyword. If the default keyword is set to true, + # then the state value is defaulted using the default keyword. The # default keyword takes precedence over the enable keyword # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # values to. The name must be the full interface identifier. + # @param name [String] The interface name to apply the configuration + # values to. The name must be the full interface identifier. # - # @param [String] :direction Specifies the flowcontrol direction to - # configure. Valid values include send and receive. + # @param direction [String] Specifies the flowcontrol direction to + # configure. Valid values include send and receive. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value Specifies the value to configure the - # flowcontrol setting for. Valid values include on or off + # @option opts value [String] Specifies the value to configure the + # flowcontrol setting for. Valid values include on or off. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configures the flowcontrol value on - # the interface using the default keyword + # @option opts default [Boolean] Configures the flowcontrol value on + # the interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_flowcontrol(name, direction, opts = {}) commands = command_builder("flowcontrol #{direction}", opts) configure_interface(name, commands) @@ -573,50 +586,50 @@ def set_flowcontrol(name, direction, opts = {}) # # @see set_flowcontrol # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # values to. The name must be the full interface identifier. + # @param name [String] The interface name to apply the configuration + # values to. The name must be the full interface identifier. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value Specifies the value to configure the - # flowcontrol setting for. Valid values include on or off + # @option opts value [String] Specifies the value to configure the + # flowcontrol setting for. Valid values include on or off. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configures the flowcontrol value on - # the interface using the default keyword + # @option opts default [Boolean] Configures the flowcontrol value on + # the interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_flowcontrol_send(name, opts = {}) set_flowcontrol(name, 'send', opts) end ## - # set_flowcontrol_receive is a convenience function for configuring th e - # value of interface flowcontrol + # set_flowcontrol_receive is a convenience function for configuring the + # value of interface flowcontrol. # # @see set_flowcontrol # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # values to. The name must be the full interface identifier. + # @param name [String] The interface name to apply the configuration + # values to. The name must be the full interface identifier. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value Specifies the value to configure the - # flowcontrol setting for. Valid values include on or off + # @option opts value [String] Specifies the value to configure the + # flowcontrol setting for. Valid values include on or off. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configures the flowcontrol value on - # the interface using the default keyword + # @option opts default [Boolean] Configures the flowcontrol value on + # the interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_flowcontrol_receive(name, opts = {}) set_flowcontrol(name, 'receive', opts) end @@ -632,7 +645,7 @@ class PortchannelInterface < BaseInterface ## # get returns the specified port-channel interface configuration from - # the nodes running configuration as a resource hash. The resource + # the nodes running configuration as a resource hash. The resource # hash returned extends the BaseInterface resource hash, sets the type # value to portchannel and adds the portchannel specific attributes # @@ -650,13 +663,13 @@ class PortchannelInterface < BaseInterface # # @see BaseInterface Interface get example # - # @param [String] :name The name of the portchannel interface to return - # a resource hash for. The name must be the full interface name of + # @param name [String] The name of the portchannel interface to return + # a resource hash for. The name must be the full interface name of # the desired interface. # - # @return [nil, Hash] returns the interface resource as - # a hash object. If the specified interface does not exist in the - # running configuration, a nil object is returned + # @return [nil, Hash] Returns the interface resource as + # a hash object. If the specified interface does not exist in the + # running configuration, a nil object is returned. def get(name) config = get_block("^interface #{name}") return nil unless config @@ -672,17 +685,17 @@ def get(name) ## # parse_members scans the nodes running config and returns all of the - # Ethernet members for the port-channel interface specified. If the + # Ethernet members for the port-channel interface specified. If the # port-channel interface has no members configured, then this method will - # assign an empty array as the value for members. The hash returned is - # intended to be merged into the interface resource hash + # assign an empty array as the value for members. The hash returned is + # intended to be merged into the interface resource hash. # # @api private # - # @param [String] :name The name of the portchannel interface to extract - # the members for + # @param name [String] The name of the portchannel interface to extract + # the members for. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_members(name) grpid = name.scan(/(?<=Port-Channel)\d+/)[0] command = "show port-channel #{grpid} all-ports" @@ -694,17 +707,17 @@ def parse_members(name) ## # parse_lacp_mode scans the member interfaces and returns the configured - # lacp mode. The lacp mode value must be common across every member - # in the port channel interface. If no members are configured, the value - # for lacp_mode will be set using DEFAULT_LACP_MODE. The hash returned is + # lacp mode. The lacp mode value must be common across every member + # in the port channel interface. If no members are configured, the value + # for lacp_mode will be set using DEFAULT_LACP_MODE. The hash returned is # intended to be merged into the interface resource hash # # @api private # - # @param [String] :name The name of the portchannel interface to extract - # the members from in order to get the configured lacp_mode + # @param name [String] The name of the portchannel interface to extract + # the members from in order to get the configured lacp_mode. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_lacp_mode(name) members = parse_members(name)[:members] return { lacp_mode: DEFAULT_LACP_MODE } unless members @@ -716,17 +729,17 @@ def parse_lacp_mode(name) ## # parse_minimum_links scans the port-channel configuration and returns - # the value for port-channel minimum-links. If the value is not found + # the value for port-channel minimum-links. If the value is not found # in the interface configuration, then DEFAULT_MIN_LINKS value is used. # The hash returned is intended to be merged into the interface - # resource hash + # resource hash. # # @api private # - # @param [String] :config The interface configuration block to extract - # the minimum links value from + # @param config [String] The interface configuration block to extract + # the minimum links value from. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_minimum_links(config) mdata = /port-channel min-links (\d+)$/.match(config) { minimum_links: mdata ? mdata[1] : DEFAULT_MIN_LINKS } @@ -735,17 +748,17 @@ def parse_minimum_links(config) ## # parse_lacp_fallback scans the interface config block and returns the - # configured value of the lacp fallback attribute. If the value is not + # configured value of the lacp fallback attribute. If the value is not # configured, then the method will return the value of - # DEFAULT_LACP_FALLBACK. The hash returned is intended to be merged into - # the interface resource hash + # DEFAULT_LACP_FALLBACK. The hash returned is intended to be merged into + # the interface resource hash. # # @api private # - # @param [String] :config The interface configuration block to extract - # the lacp fallback value from + # @param config [String] The interface configuration block to extract + # the lacp fallback value from. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_lacp_fallback(config) mdata = /lacp fallback (static|individual)/.match(config) { lacp_fallback: mdata ? mdata[1] : DEFAULT_LACP_FALLBACK } @@ -754,16 +767,16 @@ def parse_lacp_fallback(config) ## # parse_lacp_timeout scans the interface config block and returns the - # value of the lacp fallback timeout value. The value is expected to be - # found in the interface configuration block. The hash returned is - # intended to be merged into the interface resource hash + # value of the lacp fallback timeout value. The value is expected to be + # found in the interface configuration block. The hash returned is + # intended to be merged into the interface resource hash. # # @api private # - # @param [String] :config The interface configuration block to extract - # the lacp timeout value from + # @param config [String] The interface configuration block to extract + # the lacp timeout value from. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_lacp_timeout(config) mdata = /lacp fallback timeout (\d+)$/.match(config) { lacp_timeout: mdata[1] } @@ -772,31 +785,31 @@ def parse_lacp_timeout(config) ## # set_minimum_links configures the minimum physical links up required to - # consider the logical portchannel interface operationally up. If the + # consider the logical portchannel interface operationally up. If the # enable keyword is false then the minimum-links is configured using the - # no keyword argument. If the default keyword argument is provided and + # no keyword argument. If the default keyword argument is provided and # set to true, the minimum-links value is defaulted using the default - # keyword. The default keyword takes precedence over the enable keyword + # keyword. The default keyword takes precedence over the enable keyword # argument if both are provided. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration + # @param name [String] The interface name to apply the configuration # values to. The name must be the full interface identifier. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String, Integer] :value Specifies the value to - # configure the minimum-links to in the configuration. Valid values + # @option opts value [String, Integer] Specifies the value to + # configure the minimum-links to in the configuration. Valid values # are in the range of 1 to 16. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configures the minimum links value on - # the interface using the default keyword + # @option opts default [Boolean] Configures the minimum links value on + # the interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_minimum_links(name, opts = {}) commands = command_builder('port-channel min-links', opts) configure_interface(name, commands) @@ -804,22 +817,23 @@ def set_minimum_links(name, opts = {}) ## # set_members configures the set of physical interfaces that comprise the - # logical port-channel interface. The members value passed should be an + # logical port-channel interface. The members value passed should be an # array of physical interface names that comprise the port-channel - # interface. This method will add and remove individual members as - # required to sync the provided members array + # interface. This method will add and remove individual members as + # required to sync the provided members array. + # + # @see add_member Adds member links to the port-channel interface. # - # @see add_member Adds member links to the port-channel interface - # @see remove_member Removes member links from the port-channel interface + # @see remove_member Removes member links from the port-channel interface. # - # @param [String] :name The name of the port-channel interface to apply - # the members to. If the port-channel interface does not already exist - # it will be created + # @param name [String] The name of the port-channel interface to apply + # the members to. If the port-channel interface does not already exist + # it will be created. # - # @param [Array] :members The array of physical interface members to add + # @param members [Array] The array of physical interface members to add # to the port-channel logical interface. # - # @param [str] :mode The LACP mode to configure the member interfaces to. + # @param mode [str] The LACP mode to configure the member interfaces to. # Valid values are 'on, 'passive', 'active'. When there are # existing channel-group members and their lacp mode differs # from this attribute, all of those members will be removed and @@ -827,7 +841,7 @@ def set_minimum_links(name, opts = {}) # is omitted, the existing lacp mode will be used for new # member additions. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_members(name, members, mode = nil) current_members = Set.new parse_members(name)[:members] members = Set.new members @@ -841,13 +855,13 @@ def set_members(name, members, mode = nil) cmds = [] grpid = /(\d+)/.match(name)[0] - # remove members from the current port-channel interface + # remove members from the current port-channel interface. current_members.difference(members).each do |intf| cmds << "interface #{intf}" cmds << "no channel-group #{grpid}" end - # add new member interfaces to the port-channel + # add new member interfaces to the port-channel. members.difference(current_members).each do |intf| cmds << "interface #{intf}" cmds << "channel-group #{grpid} mode #{lacp_mode}" @@ -858,18 +872,18 @@ def set_members(name, members, mode = nil) ## # add_member adds the interface specified in member to the port-channel - # interface specified by name in the nodes running-configuration. If + # interface specified by name in the nodes running-configuration. If # the port-channel interface does not already exist, it will be created. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The name of the port-channel interface to apply + # @param name [String] The name of the port-channel interface to apply # the configuration to. # - # @param [String] :member The name of the physical Ethernet interface to + # @param member [String] The name of the physical Ethernet interface to # add to the logical port-channel interface. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_member(name, member) lacp = parse_lacp_mode(name)[:lacp_mode] grpid = /(\d+)/.match(name)[0] @@ -881,15 +895,15 @@ def add_member(name, member) # port-channel interface specified by name in the nodes # running-configuration. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The name of the port-channel interface to apply + # @param name [String] The name of the port-channel interface to apply # the configuration to. # - # @param [String] :member The name of the physical Ethernet interface to + # @param member [String] The name of the physical Ethernet interface to # remove from the logical port-channel interface. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def remove_member(name, member) grpid = /(\d+)/.match(name)[0] configure_interface(member, "no channel-group #{grpid}") @@ -897,20 +911,20 @@ def remove_member(name, member) ## # set_lacp_mode configures the lacp mode on the port-channel interface - # by configuring the lacp mode value for each member interface. This + # by configuring the lacp mode value for each member interface. This # method will find all member interfaces for a port-channel and # reconfigure them using the mode argument. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # values to. The name must be the full interface identifier. + # @param name [String] The interface name to apply the configuration + # values to. The name must be the full interface identifier. # - # @param [String] :mode The lacp mode to configure on the member - # interfaces for the port-channel. Valid values include active, - # passive or on + # @param mode [String] The lacp mode to configure on the member + # interfaces for the port-channel. Valid values include active, + # passive or on. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_lacp_mode(name, mode) return false unless %w(on passive active).include?(mode) grpid = /(\d+)/.match(name)[0] @@ -930,29 +944,29 @@ def set_lacp_mode(name, mode) ## # set_lacp_fallback configures the lacp fallback mode for the # port-channel interface. If the enable keyword is false, lacp fallback - # is configured using the no keyword argument. If the default option is + # is configured using the no keyword argument. If the default option is # specified and set to true, the lacp fallback value is configured using - # the default keyword. The default keyword takes precedence over the + # the default keyword. The default keyword takes precedence over the # enable keyword if both options are provided. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # values to. The name must be the full interface identifier. + # @param name [String] The interface name to apply the configuration + # values to. The name must be the full interface identifier. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value Specifies the value to configure for - # the port-channel lacp fallback. Valid values are individual and - # static + # @option opts value [String] Specifies the value to configure for + # the port-channel lacp fallback. Valid values are individual and + # static. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configures the lacp fallback value on - # the interface using the default keyword + # @option opts default [Boolean] Configures the lacp fallback value on + # the interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_lacp_fallback(name, opts = {}) commands = command_builder('port-channel lacp fallback', opts) configure_interface(name, commands) @@ -960,29 +974,29 @@ def set_lacp_fallback(name, opts = {}) ## # set_lacp_timeout configures the lacp fallback timeout for the - # port-channel interface. If the enable keyword is false, lacp fallback - # timeout is configured using the no keyword argument. If the default + # port-channel interface. If the enable keyword is false, lacp fallback + # timeout is configured using the no keyword argument. If the default # option is specified and set to true, the lacp fallback timeout value is - # configured using the default keyword. The default keyword takes + # configured using the default keyword. The default keyword takes # precedence over the enable keyword if both options are provided. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The interface name to apply the configuration - # values to. The name must be the full interface identifier. + # @param name [String] The interface name to apply the configuration + # values to. The name must be the full interface identifier. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value Specifies the value to configure for + # @option opts value [String] Specifies the value to configure for # the port-channel lacp fallback timeout. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configures the lacp fallback timeout - # value on the interface using the default keyword + # @option opts default [Boolean] Configures the lacp fallback timeout + # value on the interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_lacp_timeout(name, opts = {}) commands = command_builder('port-channel lacp fallback timeout', opts) configure_interface(name, commands) @@ -999,7 +1013,7 @@ class VxlanInterface < BaseInterface # Returns the Vxlan interface configuration as a Ruby hash of key/value # pairs from the nodes running configuration. This method extends the # BaseInterface get method and adds the Vxlan specific attributes to - # the hash + # the hash. # # @example # { @@ -1014,12 +1028,12 @@ class VxlanInterface < BaseInterface # vlans: # } # - # @param [String] :name The interface name to return from the nodes - # configuration. This optional parameter defaults to Vxlan1 + # @param name [String] The interface name to return from the nodes + # configuration. This optional parameter defaults to Vxlan1. # # @return [nil, Hash] Returns the interface configuration - # as a Ruby hash object. If the provided interface name is not found - # then this method will return nil + # as a Ruby hash object. If the provided interface name is not found + # then this method will return nil. def get(name = 'Vxlan1') config = get_block("interface #{name}") return nil unless config @@ -1036,14 +1050,14 @@ def get(name = 'Vxlan1') ## # parse_source_interface scans the interface config block and returns the - # value of the vxlan source-interface. If the source-interface is not - # configured then the value of DEFAULT_SRC_INTF is used. The hash + # value of the vxlan source-interface. If the source-interface is not + # configured then the value of DEFAULT_SRC_INTF is used. The hash # returned is intended to be merged into the interface resource hash # # @api private # - # @param [String] :config The interface configuration block to extract - # the vxlan source-interface value from + # @param config [String] The interface configuration block to extract + # the vxlan source-interface value from. # # @return [Hash] def parse_source_interface(config) @@ -1054,14 +1068,14 @@ def parse_source_interface(config) ## # parse_multicast_group scans the interface config block and returns the - # value of the vxlan multicast-group. If the multicast-group is not - # configured then the value of DEFAULT_MCAST_GRP is used. The hash - # returned is intended to be merged into the interface resource hash + # value of the vxlan multicast-group. If the multicast-group is not + # configured then the value of DEFAULT_MCAST_GRP is used. The hash + # returned is intended to be merged into the interface resource hash. # # @api private # - # @param [String] :config The interface configuration block to extract - # the vxlan multicast-group value from + # @param config [String] The interface configuration block to extract + # the vxlan multicast-group value from. # # @return [Hash] def parse_multicast_group(config) @@ -1072,14 +1086,14 @@ def parse_multicast_group(config) ## # parse_udp_port scans the interface config block and returns the value - # of the vxlan udp-port setting. The vxlan udp-port value is expected to - # always be present in the configuration. The returned value is intended - # to be merged into the interface resource Hash + # of the vxlan udp-port setting. The vxlan udp-port value is expected to + # always be present in the configuration. The returned value is intended + # to be merged into the interface resource Hash. # # @api private # - # @param [String] :config The interface configuration block to parse the - # vxlan udp-port value from + # @param config [String] The interface configuration block to parse the + # vxlan udp-port value from. # # @return [Hash] def parse_udp_port(config) @@ -1090,15 +1104,15 @@ def parse_udp_port(config) ## # parse_flood_list scans the interface config block and returns the list - # of configured VTEPs that comprise the flood list. If there are no + # of configured VTEPs that comprise the flood list. If there are no # flood list values configured, the value will return DEFAULT_FLOOD_LIST. # The returned value is intended to be merged into the interface resource # Hash. # # @api private # - # @param [String] :config The interface configuration block to parse the - # vxlan flood list values from + # @param config [String] The interface configuration block to parse the + # vxlan flood list values from. # # @return [Hash] def parse_flood_list(config) @@ -1110,13 +1124,13 @@ def parse_flood_list(config) ## # parse_vlans scans the interface config block and returns the set of - # configured vlan to vni mappings. If there are no vlans configured, the - # value will return an empty Hash + # configured vlan to vni mappings. If there are no vlans configured, the + # value will return an empty Hash. # # @api private # - # @param [String] :config The interface configuration block to parse the - # vxlan flood list values from + # @param config [String] The interface configuration block to parse the + # vxlan flood list values from. # # @return [Hash] def parse_vlans(config) @@ -1129,26 +1143,26 @@ def parse_vlans(config) private :parse_vlans ## - # Configures the vxlan source-interface to the specified value. This + # Configures the vxlan source-interface to the specified value. This # parameter should be the interface identifier of the interface to act - # as the source for all Vxlan traffic + # as the source for all Vxlan traffic. # - # @param [String] :name The name of the interface to apply the - # configuration values to + # @param name [String] The name of the interface to apply the + # configuration values to. # - # @param [Hash] :opt Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value Configures the vxlan source-interface to - # the specified value + # @option opts value [String] Configures the vxlan source-interface to + # the specified value. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Specifies whether or not the - # multicast-group command is configured as default. The value of this - # option has a higher precedence than :enable + # @option opts default [Boolean] Specifies whether or not the + # multicast-group command is configured as default. The value of this + # option has a higher precedence than :enable. # - # @return [Boolean] Returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def set_source_interface(name = 'Vxlan1', opts = {}) commands = command_builder('vxlan source-interface', opts) configure_interface(name, commands) @@ -1156,24 +1170,24 @@ def set_source_interface(name = 'Vxlan1', opts = {}) ## # Configures the vxlan multicast-group flood address to the specified - # value. The value should be a valid multicast address + # value. The value should be a valid multicast address. # - # @param [String] :name The name of the interface to apply the - # configuration values to + # @param name [String] The name of the interface to apply the + # configuration values to. # - # @param [Hash] :opt Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value Configures the multicast-group flood + # @option opts value [String] Configures the multicast-group flood # address to the specified value. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Specifies whether or not the - # multicast-group command is configured as default. The value of this - # option has a higher precedence than :value + # @option opts default [Boolean] Specifies whether or not the + # multicast-group command is configured as default. The value of this + # option has a higher precedence than :value. # - # @return [Boolean] Returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def set_multicast_group(name = 'Vxlan1', opts = {}) commands = command_builder('vxlan multicast-group', opts) configure_interface(name, commands) @@ -1181,28 +1195,28 @@ def set_multicast_group(name = 'Vxlan1', opts = {}) ## # set_udp_port configures the Vxlan udp-port value in EOS for the - # specified interface name. If the enable keyword is false then the - # no keyword is used to configure the value. If the default option is - # provided and set to true, then the default keyword is used. If both + # specified interface name. If the enable keyword is false then the + # no keyword is used to configure the value. If the default option is + # provided and set to true, then the default keyword is used. If both # options are provided, the default keyword will take precedence. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name The name of the vxlan interface to configure + # @param name [String] The name of the vxlan interface to configure. # - # @param [Hash] :opts optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value Specifies the value to configure the - # udp-port setting to. Valid values are in the range of 1024 to - # 65535 + # @option opts value [String] Specifies the value to configure the + # udp-port setting to. Valid values are in the range of 1024 to + # 65535. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configures the udp-port value on - # the interface using the default keyword + # @option opts default [Boolean] Configures the udp-port value on + # the interface using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_udp_port(name, opts = {}) commands = command_builder('vxlan udp-port', opts) configure_interface(name, commands) @@ -1210,47 +1224,49 @@ def set_udp_port(name, opts = {}) ## # add_vtep adds a new VTEP endpoint to the global flood list for the - # specified interface. If the VTEP endpoint is already configured, this + # specified interface. If the VTEP endpoint is already configured, this # method will still return successfully. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M + # + # @param name [String] The name of the interface to configure. # - # @param [String] :name The name of the interface to configure - # @param [String] :vtep The IP address of the remote VTEP endpoint + # @param vtep [String] The IP address of the remote VTEP endpoint. # - # @return [Boolean] Returns true if the commands completed successfully + # @return [Boolean] Returns true if the commands completed successfully. def add_vtep(name, vtep) configure_interface(name, "vxlan flood vtep add #{vtep}") end ## # remove_vtep deletes a VTEP endpoint from the global flood list for the - # specified interface. If the VTEP endpoint specified is not configured, + # specified interface. If the VTEP endpoint specified is not configured, # this method will still return successfully. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M + # + # @param name [String] The name of the interface to configure. # - # @param [String] :name The name of the interface to configure - # @param [String] :vtep The IP address of the remote VTEP endpoint + # @param vtep [String] The IP address of the remote VTEP endpoint. # - # @return [Boolean] Returns true if the commands completed successfully + # @return [Boolean] Returns true if the commands completed successfully. def remove_vtep(name, vtep) configure_interface(name, "vxlan flood vtep remove #{vtep}") end ## # update_vlan creates a new vlan to vni mapping for the specified - # interface in the nodes current configuration + # interface in the nodes current configuration. # - # @eos_verson 4.13.7M + # @since eos_verson 4.13.7M # - # @param [String] :name The name of the interface to configure + # @param name [String] The name of the interface to configure. # - # @param [Fixnum] :vlan The VLAN ID to configure. + # @param vlan [Fixnum] The VLAN ID to configure. # - # @param [Fixnum] :vni The VNI value to map the VLAN into + # @param vni [Fixnum] The VNI value to map the VLAN into. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def update_vlan(name, vlan, vni) configure_interface(name, "vxlan vlan #{vlan} vni #{vni}") end @@ -1259,15 +1275,15 @@ def update_vlan(name, vlan, vni) # remove_vlan deletes a previously configured VLAN to VNI mapping on the # specified interface. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @param [String] :name the name of the interface to configure + # @param name [String] the name of the interface to configure. # - # @param [Fixnum] :vlan The VLAN ID to remove from the configuration. If + # @param vlan [Fixnum] The VLAN ID to remove from the configuration. If # the VLAN ID does not exist, this method will still return - # successfully + # successfully. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def remove_vlan(name, vlan) configure_interface(name, "no vxlan vlan #{vlan} vni") end diff --git a/lib/rbeapi/api/ipinterfaces.rb b/lib/rbeapi/api/ipinterfaces.rb index ddeb80c..7b270a4 100644 --- a/lib/rbeapi/api/ipinterfaces.rb +++ b/lib/rbeapi/api/ipinterfaces.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api # # The Ipinterface class provides an instance for managing logical @@ -49,17 +49,17 @@ class Ipinterfaces < Entity # # @example # { - # address: - # mtu: + # address: , + # mtu: , # helper_addresses: array # } # - # @param [String] :name The full interface identifier of the interface to - # return the resource configuration hash for. The name must be the - # full name (Ethernet, not Et) + # @param name [String] The full interface identifier of the interface to + # return the resource configuration hash for. The name must be the + # full name (Ethernet, not Et). # - # @return [nil, Hash] returns the ip interface - # configuration as a hash. If the provided interface name is not a + # @return [nil, Hash] Returns the ip interface + # configuration as a hash. If the provided interface name is not a # configured ip address, nil is returned. def get(name) config = get_block("interface #{name}") @@ -80,13 +80,13 @@ def get(name) # @example # { # : { - # address: - # mtu: + # address: , + # mtu: , # helper_addresses: array # }, # : { - # address: - # mtu: + # address: , + # mtu: , # helper_addresses: array # }, # ... @@ -94,9 +94,9 @@ def get(name) # # @see get Ipaddress resource example # - # @return [Hash] returns a hash object that - # represents all of the configured IP addresses found. If no IP - # addresses are configured, then an empty hash is returned + # @return [Hash] Returns a hash object that + # represents all of the configured IP addresses found. If no IP + # addresses are configured, then an empty hash is returned. def getall interfaces = config.scan(/(?<=^interface\s).+/) interfaces.each_with_object({}) do |name, hsh| @@ -107,17 +107,17 @@ def getall ## # parse_address scans the provided configuration block and extracts - # the interface address, if configured, and returns it. If there is + # the interface address, if configured, and returns it. If there is # no IP address configured, then this method will return the - # DEFAULT_ADDRESS. The return value is intended to be merged into the + # DEFAULT_ADDRESS. The return value is intended to be merged into the # ipaddress resource hash. # # @api private # - # @param [String] :config The IP interface configuration block returned - # from the node's running configuration + # @param config [String] The IP interface configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_address(config) mdata = /(?<=^\s{3}ip\saddress\s)(.+)$/.match(config) { address: mdata.nil? ? DEFAULT_ADDRESS : mdata[1] } @@ -126,16 +126,16 @@ def parse_address(config) ## # parse_mtu scans the provided configuration block and extracts the IP - # interface MTU value. The MTU value is expected to always be present in - # the configuration blcok. The return value is intended to be merged - # into the ipaddress resource hash + # interface MTU value. The MTU value is expected to always be present in + # the configuration blcok. The return value is intended to be merged + # into the ipaddress resource hash. # # @api private # - # @param [String] :config The IP interface configuration block returned - # from the node's running configuration + # @param config [String] The IP interface configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_mtu(config) mdata = /(?<=mtu\s)(\d+)$/.match(config) { mtu: mdata.nil? ? '' : mdata[1] } @@ -144,18 +144,18 @@ def parse_mtu(config) ## # parse_helper_addresses scans the provided configuration block and - # extracts any configured IP helper address values. The interface could - # be configured with one or more helper addresses. If no helper + # extracts any configured IP helper address values. The interface could + # be configured with one or more helper addresses. If no helper # addresses are configured, then an empty array is set in the return - # hash. The return value is intended to be merged into the ipaddress - # resource hash + # hash. The return value is intended to be merged into the ipaddress + # resource hash. # # @api private # - # @param [String] :config The IP interface configuration block returned - # from the node's running configuration + # @param config [String] The IP interface configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_helper_addresses(config) helpers = config.scan(/(?<=\s{3}ip\shelper-address\s).+$/) { helper_addresses: helpers } @@ -163,80 +163,80 @@ def parse_helper_addresses(config) private :parse_helper_addresses ## - # create will create a new IP interface on the node. If the ip interface + # create will create a new IP interface on the node. If the ip interface # already exists in the configuration, this method will still return - # successful. This method will cause an existing layer 2 interface + # successful. This method will cause an existing layer 2 interface # (switchport) to be deleted if it exists in the node's configuration. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # no switchport # - # @param [String] :name The full interface name of the port to create the - # logical interface on. The name must be the full interface - # identifier + # @param name [String] The full interface name of the port to create the + # logical interface on. The name must be the full interface + # identifier. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def create(name) configure(["interface #{name}", 'no switchport']) end ## # delete will delete an existing IP interface in the node's current - # configuration. If the IP interface does not exist on the specified - # interface, this method will still return success. This command will + # configuration. If the IP interface does not exist on the specified + # interface, this method will still return success. This command will # default the interface back to being a switchport. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # no ip address # switchport # - # @param [String] :name The full interface name of the port to delete the - # logical interface from. The name must be the full interface name + # @param name [String] The full interface name of the port to delete the + # logical interface from. The name must be the full interface name # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def delete(name) configure(["interface #{name}", 'no ip address', 'switchport']) end ## # set_address configures a logical IP interface with an address. - # The address value must be in the form of A.B.C.D/E. If the enable + # The address value must be in the form of A.B.C.D/E. If the enable # keyword is false, then the interface address is negated using the - # config no keyword. If the default option is set to true, then the - # ip address # value is defaulted using the default keyword. The + # config no keyword. If the default option is set to true, then the + # ip address # value is defaulted using the default keyword. The # default keyword has precedence over the enable keyword if both - # options are specified + # options are specified. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # ip address # no ip address # default ip address # - # @param [String] :name The name of the interface to configure the - # address in the node. The name must be the full interface name. + # @param name [String] The name of the interface to configure the + # address in the node. The name must be the full interface name. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the address to - # for the specified interface name. The value must be in the form - # of A.B.C.D/E + # @option opts value [String] The value to configure the address to + # for the specified interface name. The value must be in the form + # of A.B.C.D/E. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the ip address value using - # the default keyword + # @option opts default [Boolean] Configure the ip address value using + # the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns True if the command completed successfully. def set_address(name, opts = {}) cmds = command_builder('ip address', opts) configure_interface(name, cmds) @@ -244,36 +244,36 @@ def set_address(name, opts = {}) ## # set_mtu configures the IP mtu value of the ip interface in the nodes - # configuration. If the enable option is false, then the ip mtu value is - # configured using the no keyword. If the default keyword option is + # configuration. If the enable option is false, then the ip mtu value is + # configured using the no keyword. If the default keyword option is # provided and set to true then the ip mtu value is configured using the - # default keyword. The default keyword has precedence over the enable + # default keyword. The default keyword has precedence over the enable # keyword if both options are specified. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # mtu # no mtu # default mtu # - # @param [String] :name The name of the interface to configure the - # address in the node. The name must be the full interface name. + # @param name [String] The name of the interface to configure the + # address in the node. The name must be the full interface name. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the IP MTU to in - # the nodes configuration. Valid values are in the range of 68 to 9214 - # bytes. The default is 1500 bytes + # @option opts value [String] The value to configure the IP MTU to in + # the nodes configuration. Valid values are in the range of 68 to 9214 + # bytes. The default is 1500 bytes. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the ip mtu value using - # the default keyword + # @option opts default [Boolean] Configure the ip mtu value using + # the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_mtu(name, opts = {}) cmds = command_builder('mtu', opts) configure_interface(name, cmds) @@ -281,31 +281,31 @@ def set_mtu(name, opts = {}) ## # set_helper_addresses configures the list of helper addresses on the ip - # interface. An IP interface can have one or more helper addresses - # configured. If no value is provided, the helper address configuration - # is set using the no keyword. If the default option is specified and + # interface. An IP interface can have one or more helper addresses + # configured. If no value is provided, the helper address configuration + # is set using the no keyword. If the default option is specified and # set to true, then the helper address values are defaulted using the # default keyword. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # ip helper-address # no ip helper-address # default ip helper-address # - # @param [String] :name The name of the interface to configure the - # address in the node. The name must be the full interface name. + # @param name [String] The name of the interface to configure the + # address in the node. The name must be the full interface name. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [Array] :value The list of IP addresses to configure as - # helper address on the interface. The helper addresses must be valid + # @option opts value [Array] The list of IP addresses to configure as + # helper address on the interface. The helper addresses must be valid # addresses in the main interface's subnet. # - # @option :opts [Boolean] :default Configure the ip helper address values - # using the default keyword + # @option opts default [Boolean] Configure the ip helper address values + # using the default keyword. # def set_helper_addresses(name, opts = {}) value = opts[:value] diff --git a/lib/rbeapi/api/logging.rb b/lib/rbeapi/api/logging.rb index f5b18c1..1c09a9a 100644 --- a/lib/rbeapi/api/logging.rb +++ b/lib/rbeapi/api/logging.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Logging class manages logging settings on an EOS node. @@ -50,8 +50,8 @@ class Logging < Entity # hosts: array # } # - # @return [Hash] returns the logging resource as a hash - # object from the nodes current configuration + # @return [Hash] Returns the logging resource as a hash + # object from the nodes current configuration. def get response = {} response.merge!(parse_enable) @@ -61,14 +61,14 @@ def get ## # parse_enable scans the nodes current running configuration and extracts - # the current enabled state of the logging facility. The logging enable - # command is expected to always be in the node's configuration. This + # the current enabled state of the logging facility. The logging enable + # command is expected to always be in the node's configuration. This # methods return value is intended to be merged into the logging resource # hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_enable value = /no logging on/ !~ config { enable: value } @@ -76,14 +76,14 @@ def parse_enable ## # parse_hosts scans the nodes current running configuration and extracts - # the configured logging host destinations if any are configured. If no + # the configured logging host destinations if any are configured. If no # logging hosts are configured, then the value for hosts will be an empty - # array. The return value is intended to be merged into the logging + # array. The return value is intended to be merged into the logging # resource hash # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_hosts hosts = config.scan(/(?<=^logging\shost\s)[^\s]+/) { hosts: hosts } @@ -92,28 +92,28 @@ def parse_hosts ## # set_enable configures the global logging instance on the node as either - # enabled or disabled. If the enable keyword is set to true then logging - # is globally enabled and if set to false, it is globally disabled. If + # enabled or disabled. If the enable keyword is set to true then logging + # is globally enabled and if set to false, it is globally disabled. If # the default keyword is specified and set to true, then the configuration - # is defaulted using the default keyword. The default keyword option + # is defaulted using the default keyword. The default keyword option # takes precedence over the enable keyword if both options are specified. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # logging on # no logging on # default logging on # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments # - # @option :opts [Boolean] :enable Enables logging globally if value is - # true or disabled logging globally if value is false + # @option opts enable [Boolean] Enables logging globally if value is + # true or disabled logging globally if value is false. # - # @option :opts [Boolean] :default Configure the ip address value using - # the default keyword + # @option opts default [Boolean] Configure the ip address value using + # the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_enable(opts = {}) cmd = command_builder('logging on', opts) configure cmd @@ -121,36 +121,36 @@ def set_enable(opts = {}) ## # add_host configures a new logging destination host address or hostname - # to the list of logging destinations. If the host is already configured + # to the list of logging destinations. If the host is already configured # in the list of destinations, this method will return successfully. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # logging host # - # @param [String] :name The host name or ip address of the destination + # @param name [String] The host name or ip address of the destination # node to send logging information to. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_host(name) configure "logging host #{name}" end ## # remove_host deletes a logging destination host name or address form the - # list of logging destinations. If the host is not in the list of + # list of logging destinations. If the host is not in the list of # configured hosts, this method will still return successfully. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # no logging host # - # @param [String] :name The host name or ip address of the destination - # host to remove from the nodes current configuration + # @param name [String] The host name or ip address of the destination + # host to remove from the nodes current configuration. # - # @return [Boolean] returns true if the commands completed successfully + # @return [Boolean] Returns true if the commands completed successfully. def remove_host(name) configure "no logging host #{name}" end diff --git a/lib/rbeapi/api/mlag.rb b/lib/rbeapi/api/mlag.rb index e88a67f..b57ccd0 100644 --- a/lib/rbeapi/api/mlag.rb +++ b/lib/rbeapi/api/mlag.rb @@ -32,14 +32,14 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Mlag class provides a configuration instance for working with - # the global MLAG configuration of the node + # the global MLAG configuration of the node. class Mlag < Entity DEFAULT_DOMAIN_ID = '' DEFAULT_LOCAL_INTF = '' @@ -73,8 +73,8 @@ class Mlag < Entity # @see parse_interfaces # # @return [nil, Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_domain_id(config) mdata = /(?<=\s{3}domain-id\s)(.+)$/.match(config) { domain_id: mdata.nil? ? DEFAULT_DOMAIN_ID : mdata[1] } @@ -108,16 +108,16 @@ def parse_domain_id(config) ## # parse_local_interface scans the current nodes running configuration and - # extracts the mlag local-interface value. If the mlag local-interface + # extracts the mlag local-interface value. If the mlag local-interface # has not been configured, this method will return DEFAULT_LOCAL_INTF. - # The return value is intended to be merged into the resource hash + # The return value is intended to be merged into the resource hash. # # @api private # - # @param [String] :config The mlag configuration block retrieved from the + # @param config [String] The mlag configuration block retrieved from the # nodes current running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_local_interface(config) mdata = /(?<=\s{3}local-interface\s)(.+)$/.match(config) { local_interface: mdata.nil? ? DEFAULT_LOCAL_INTF : mdata[1] } @@ -126,16 +126,16 @@ def parse_local_interface(config) ## # parse_peer_address scans the current nodes running configuration and - # extracts the mlag peer-address value. If the mlag peer-address has not - # been configured, this method will return DEFAULT_PEER_ADDR. The return + # extracts the mlag peer-address value. If the mlag peer-address has not + # been configured, this method will return DEFAULT_PEER_ADDR. The return # value is intended to be merged into the resource hash. # # @api private # - # @param [String] :config The mlag configuration block retrieved from the + # @param config [String] The mlag configuration block retrieved from the # nodes current running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_peer_address(config) mdata = /(?<=\s{3}peer-address\s)(.+)$/.match(config) { peer_address: mdata.nil? ? DEFAULT_PEER_ADDR : mdata[1] } @@ -144,16 +144,16 @@ def parse_peer_address(config) ## # parse_peer_link scans the current nodes running configuration and - # extracts the mlag peer-link value. If the mlag peer-link hash not been - # configure, this method will return DEFAULT_PEER_LINK. The return value + # extracts the mlag peer-link value. If the mlag peer-link hash not been + # configure, this method will return DEFAULT_PEER_LINK. The return value # is intended to be merged into the resource hash. # # @api private # - # @param [String] :config The mlag configuration block retrieved from the + # @param config [String] The mlag configuration block retrieved from the # nodes current running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute def parse_peer_link(config) mdata = /(?<=\s{3}peer-link\s)(.+)$/.match(config) { peer_link: mdata.nil? ? DEFAULT_PEER_LINK : mdata[1] } @@ -162,16 +162,16 @@ def parse_peer_link(config) ## # parse_shutdown scans the current nodes mlag configuration and extracts - # the mlag shutdown value. The mlag configuration should always return - # the value of shutdown from the configuration block. Ths return value + # the mlag shutdown value. The mlag configuration should always return + # the value of shutdown from the configuration block. The return value # is intended to be merged into the resource hash. # # @api private # - # @param [String] :config The mlag configuration block retrieved from the + # @param config [String] The mlag configuration block retrieved from the # nodes current running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_shutdown(config) value = /\s{3}no shutdown/ !~ config { shutdown: value } @@ -180,16 +180,16 @@ def parse_shutdown(config) ## # parse_interfaces scans the global configuration and returns all of the - # configured MLAG interfaces. Each interface returns the configured MLAG - # identifier for establishing a MLAG peer. The return value is intended - # to be merged into the resource Hash + # configured MLAG interfaces. Each interface returns the configured MLAG + # identifier for establishing a MLAG peer. The return value is intended + # to be merged into the resource Hash. # # The resource Hash attribute returned contains: - # * mlag_id: (Fixnum) The configured MLAG identifier + # * mlag_id: (Fixnum) The configured MLAG identifier. # # @api private # - # @return [Hash] resource Hash attribute + # @return [Hash] Returns the resource Hash attribute. def parse_interfaces names = config.scan(/(?<=^interface\s)Po.+/) names.each_with_object({}) do |name, hsh| @@ -204,31 +204,31 @@ def parse_interfaces ## # set_domain_id configures the mlag domain-id value in the current nodes # running configuration. If the enable keyword is false, the the - # domain-id is configured with the no keyword. If the default keyword + # domain-id is configured with the no keyword. If the default keyword # is provided, the configuration is defaulted using the default keyword. # The default keyword takes precedence over the enable keyword if both - # options are specified + # options are specified. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # mlag configuration # domain-id # no domain-id # default domain-id # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments # - # @option :opts [String] :value The value to configure the mlag + # @option opts value [String] The value to configure the mlag # domain-id to. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the domain-id value using - # the default keyword + # @option opts default [Boolean] Configure the domain-id value using + # the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_domain_id(opts = {}) cmd = command_builder('domain-id', opts) cmds = ['mlag configuration', cmd] @@ -238,32 +238,32 @@ def set_domain_id(opts = {}) ## # set_local_interface configures the mlag local-interface value in the # current nodes running configuration. If the enable keyword is false, - # the local-interface is configured with the no keyword. If + # the local-interface is configured with the no keyword. If # the default keyword is provided, the configuration is defaulted using - # the default keyword. The default keyword takes precedence over the + # the default keyword. The default keyword takes precedence over the # enable keyword if both options are specified # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # mlag configuration # local-interface # no local-interface # default local-interface # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments # - # @option :opts [String] :value The value to configure the mlag - # local-interface to. The local-interface accepts full interface + # @option opts value [String] The value to configure the mlag + # local-interface to. The local-interface accepts full interface # identifiers and expects a Vlan interface # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the local-interface value - # using the default keyword + # @option opts default [Boolean] Configure the local-interface value + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_local_interface(opts = {}) cmd = command_builder('local-interface', opts) cmds = ['mlag configuration', cmd] @@ -273,32 +273,32 @@ def set_local_interface(opts = {}) ## # set_peer_link configures the mlag peer-link value in the current nodes # running configuration. If enable keyword is false, then the - # peer-link is configured with the no keyword. If the default keyword + # peer-link is configured with the no keyword. If the default keyword # is provided, the configuration is defaulted using the default keyword. # The default keyword takes precedence over the enable keyword if both - # options are specified + # options are specified. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # mlag configuration # peer-link # no peer-link # default peer-link # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the mlag - # peer-link to. The peer-link accepts full interface identifiers - # and expects an Ethernet or Port-Channel interface + # @option opts value [String] The value to configure the mlag + # peer-link to. The peer-link accepts full interface identifiers + # and expects an Ethernet or Port-Channel interface. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the peer-link using the - # default keyword + # @option opts default [Boolean] Configure the peer-link using the + # default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_peer_link(opts = {}) cmd = command_builder('peer-link', opts) cmds = ['mlag configuration', cmd] @@ -308,32 +308,32 @@ def set_peer_link(opts = {}) ## # set_peer_address configures the mlag peer-address value in the current # nodes running configuration. If the enable keyword is false, then the - # peer-address is configured with the no keyword. If the default keyword + # peer-address is configured with the no keyword. If the default keyword # is provided, the configuration is defaulted using the default keyword. # The default keyword takes precedence over the enable keyword if both # options are specified # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # mlag configuration # peer-address # no peer-address # default peer-address # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the mlag - # peer-address to. The peer-address accepts an IP address in the form - # of A.B.C.D/E + # @option opts value [String] The value to configure the mlag + # peer-address to. The peer-address accepts an IP address in the form + # of A.B.C.D/E. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the peer-address using the - # default keyword + # @option opts default [Boolean] Configure the peer-address using the + # default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_peer_address(opts = {}) cmd = command_builder('peer-address', opts) cmds = ['mlag configuration', cmd] @@ -342,30 +342,30 @@ def set_peer_address(opts = {}) ## # set_shutdown configures the administrative state of the mlag process on - # the current node. If the enable keyword is true, then mlag is enabled + # the current node. If the enable keyword is true, then mlag is enabled # and if the enable keyword is false, then mlag is disabled. If the # default keyword is provided, the configuration is defaulted using # the default keyword. The default keyword takes precedence over the # enable keyword if both options are specified # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # mlag configuration # shutdown # no shutdown # default shutdown # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable True if the interface should be + # @option opts enable [Boolean] True if the interface should be # administratively enabled or false if the interface should be # administratively disabled. # - # @option :opts [Boolean] :default Configure the shutdown value using the - # default keyword + # @option opts default [Boolean] Configure the shutdown value using the + # default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_shutdown(opts = {}) fail 'set_shutdown has the value option set' if opts[:value] # Shutdown semantics are opposite of enable semantics so invert enable @@ -378,36 +378,36 @@ def set_shutdown(opts = {}) ## # set_mlag_id configures the mlag id on the interface in the nodes - # current running configuration. If the enable keyword is false, then the - # interface mlag id is configured using the no keyword. If the default + # current running configuration. If the enable keyword is false, then the + # interface mlag id is configured using the no keyword. If the default # keyword is provided and set to true, the interface mlag id is - # configured using the default keyword. The default keyword takes + # configured using the default keyword. The default keyword takes # precedence over the enable keyword if both options are specified # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # mlag # no mlag # default mlag # - # @param [String] :name The full interface identifier of the interface + # @param name [String] The full interface identifier of the interface # to configure th mlag id for. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String, Integer] :value The value to configure the - # interface mlag to. The mlag id should be in the valid range of 1 to - # 2000 + # @option opts value [String, Integer] The value to configure the + # interface mlag to. The mlag id should be in the valid range of 1 to + # 2000. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the mlag value using the - # default keyword + # @option opts default [Boolean] Configure the mlag value using the + # default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_mlag_id(name, opts = {}) cmd = command_builder('mlag', opts) configure_interface(name, cmd) diff --git a/lib/rbeapi/api/ntp.rb b/lib/rbeapi/api/ntp.rb index 2b1e78d..4ae0058 100644 --- a/lib/rbeapi/api/ntp.rb +++ b/lib/rbeapi/api/ntp.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Ntp class provides an instance for working with the nodes @@ -44,7 +44,7 @@ class Ntp < Entity DEFAULT_SRC_INTF = '' ## - # get returns the nodes current ntp configure as a resource hash + # get returns the nodes current ntp configure as a resource hash. # # @example # { @@ -65,13 +65,13 @@ def get ## # parse_source_interface scans the nodes configurations and parses - # the ntp source interface if configured. If the source interface + # the ntp source interface if configured. If the source interface # is not configured, this method will return DEFAULT_SRC_INTF as the - # value. The return hash is intended to be merged into the resource hash + # value. The return hash is intended to be merged into the resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_source_interface mdata = /(?<=^ntp\ssource\s)(.+)$/.match(config) { source_interface: mdata.nil? ? DEFAULT_SRC_INTF : mdata[1] } @@ -80,14 +80,14 @@ def parse_source_interface ## # parse_servers scans the nodes configuration and parses the configured - # ntp server host names and/or addresses. This method will also return - # the value of prefer. If no servers are configured, the value will be - # set to an empty array. The return hash is intended to be merged into - # the resource hash + # ntp server host names and/or addresses. This method will also return + # the value of prefer. If no servers are configured, the value will be + # set to an empty array. The return hash is intended to be merged into + # the resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_servers servers = config.scan(/(?:ntp server\s)([^\s]+)\s(prefer)?/) values = servers.each_with_object({}) do |(srv, prefer), hsh| @@ -99,31 +99,31 @@ def parse_servers ## # set_source_interface configures the ntp source value in the nodes - # running configuration. If the enable keyword is false, then - # the ntp source is configured with the no keyword argument. If the + # running configuration. If the enable keyword is false, then + # the ntp source is configured with the no keyword argument. If the # default keyword argument is provided and set to true, the value is - # configured used the default keyword. The default keyword takes + # configured used the default keyword. The default keyword takes # precedence over the enable keyword if both options are specified. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # ntp source # no ntp source # default ntp source # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the ntp source - # in the nodes configuration + # @option opts value [String] The value to configure the ntp source + # in the nodes configuration. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the ntp source value using - # the default keyword + # @option opts default [Boolean] Configure the ntp source value using + # the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_source_interface(opts = {}) cmd = command_builder('ntp source', opts) configure(cmd) @@ -131,17 +131,17 @@ def set_source_interface(opts = {}) ## # add_server configures a new ntp server destination hostname or ip - # address to the list of ntp destinations. The optional prefer argument + # address to the list of ntp destinations. The optional prefer argument # configures the server as a preferred (true) or not (false) ntp # destination. # - # @param [String] :server The IP address or FQDN of the NTP server to - # be removed from the configuration + # @param server [String] The IP address or FQDN of the NTP server to + # be removed from the configuration. # - # @param [Boolean] :prefer Appends the prefer keyword argument to the - # command if this value is true + # @param prefer [Boolean] Appends the prefer keyword argument to the + # command if this value is true. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_server(server, prefer = false) cmd = "ntp server #{server}" cmd << ' prefer' if prefer @@ -150,13 +150,13 @@ def add_server(server, prefer = false) ## # remove_server deletes the provided server destination from the list of - # ntp server destinations. If the ntp server does not exist in the list + # ntp server destinations. If the ntp server does not exist in the list # of servers, this method will return successful # - # @param [String] :server The IP address or FQDN of the NTP server to - # be removed from the configuration + # @param server [String] The IP address or FQDN of the NTP server to + # be removed from the configuration. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def remove_server(server) configure("no ntp server #{server}") end @@ -166,20 +166,20 @@ def remove_server(server) # If the server does not already exist in the configuration, it will be # added and the prefer keyword will be set. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # ntp server prefer # no ntp server prefer # - # @param [String] :srv The IP address or hostname of the ntp server to - # configure with the prefer value + # @param srv [String] The IP address or hostname of the ntp server to + # configure with the prefer value. # - # @param [Boolean] :value The value to configure for prefer. If true + # @param value [Boolean] The value to configure for prefer. If true # the prefer value is configured for the server. If false, then the # prefer value is removed. # - # @return [Boolean] returns true if the commands completed successfully + # @return [Boolean] Returns true if the commands completed successfully. def set_prefer(srv, value) case value when true diff --git a/lib/rbeapi/api/ospf.rb b/lib/rbeapi/api/ospf.rb index 8f4fea4..9e21c70 100644 --- a/lib/rbeapi/api/ospf.rb +++ b/lib/rbeapi/api/ospf.rb @@ -32,17 +32,17 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Ospf class is a global class that provides an instance for working - # with the node's OSPF configuration + # with the node's OSPF configuration. class Ospf < Entity ## - # Returns the global OSPF configuration from the node + # Returns the global OSPF configuration from the node. # # rubocop:disable Metrics/MethodLength # @@ -55,9 +55,9 @@ class Ospf < Entity # redistribute: {} # } # - # @param [String] :inst The ospf instance name + # @param inst [String] The ospf instance name. # - # @return [Hash] A Ruby hash object that provides the OSPF settings as + # @return [Hash] A Ruby hash object that provides the OSPF settings as # key / value pairs. def get(inst) config = get_block("router ospf #{inst}") @@ -88,19 +88,19 @@ def get(inst) end ## - # Returns the OSPF configuration from the node as a Ruby hash + # Returns the OSPF configuration from the node as a Ruby hash. # # @example - # { - # : { - # router_id: , - # areas: {}, - # redistribute: {} - # }, - # interfaces: {} - # } + # { + # : { + # router_id: , + # areas: {}, + # redistribute: {} + # }, + # interfaces: {} + # } # - # @return [Hash] A Ruby hash object that provides the OSPF settings as + # @return [Hash] A Ruby hash object that provides the OSPF settings as # key / value pairs. def getall instances = config.scan(/(?<=^router\sospf\s)\d+$/) @@ -118,38 +118,38 @@ def interfaces end ## - # create will create a router ospf with the specified pid + # create will create a router ospf with the specified pid. # - # @param [String] :pid The router ospf to create + # @param pid [String] The router ospf to create. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(pid) configure "router ospf #{pid}" end ## - # delete will remove the specified router ospf + # delete will remove the specified router ospf. # - # @param [String] :pid The router ospf to remove + # @param pid [String] The router ospf to remove. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete(pid) configure "no router ospf #{pid}" end ## - # set_router_id sets router ospf router-id with pid and options + # set_router_id sets router ospf router-id with pid and options. # - # @param [String] :pid The router ospf name + # @param pid [String] The router ospf name. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the router-id to default. + # @option opts default [Boolean] Configure the router-id to default. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_router_id(pid, opts = {}) cmd = command_builder('router-id', opts) cmds = ["router ospf #{pid}", cmd] @@ -159,13 +159,13 @@ def set_router_id(pid, opts = {}) ## # add_network adds network settings for router ospf and network area. # - # @param [String] :pid The pid for router ospf + # @param pid [String] The pid for router ospf. # - # @param [String] :net The network name + # @param net [String] The network name. # - # @param [String] :area The network area name + # @param area [String] The network area name. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_network(pid, net, area) configure ["router ospf #{pid}", "network #{net} area #{area}"] end @@ -174,34 +174,34 @@ def add_network(pid, net, area) # remove_network removes network settings for router ospf and network # area. # - # @param [String] :pid The pid for router ospf + # @param pid [String] The pid for router ospf. # - # @param [String] :net The network name + # @param net [String] The network name. # - # @param [String] :area The network area name + # @param area [String] The network area name. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def remove_network(pid, net, area) configure ["router ospf #{pid}", "no network #{net} area #{area}"] end ## - # set_redistribute sets router ospf router-id with pid and options + # set_redistribute sets router ospf router-id with pid and options. # - # @param [String] :pid The router ospf name + # @param pid [String] The router ospf name. # - # @param [String] :proto The redistribute value + # @param proto [String] The redistribute value. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [String] :routemap The route-map value + # @option opts routemap [String] The route-map value. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the router-id to default. + # @option opts default [Boolean] Configure the router-id to default. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_redistribute(pid, proto, opts = {}) routemap = opts[:routemap] cmds = ["router ospf #{pid}", "redistribute #{proto}"] @@ -212,21 +212,21 @@ def set_redistribute(pid, proto, opts = {}) ## # The OspfInterfaces class is a global class that provides an instance - # for working with the node's OSPF interface configuration + # for working with the node's OSPF interface configuration. class OspfInterfaces < Entity ## - # Returns a single MLAG interface configuration + # Returns a single MLAG interface configuration. # # Example # { # network_type: # } # - # @param [String] :name The interface name to return the configuration - # values for. This must be the full interface identifier. + # @param name [String] The interface name to return the configuration + # values for. This must be the full interface identifier. # # @return [nil, Hash] A Ruby hash that represents the - # MLAG interface configuration. A nil object is returned if the + # MLAG interface configuration. A nil object is returned if the # specified interface is not configured def get(name) config = get_block("interface #{name}") @@ -241,7 +241,7 @@ def get(name) ## # Returns the collection of MLAG interfaces as a hash index by the - # interface name + # interface name. # # Example # { @@ -255,7 +255,7 @@ def get(name) # } # # @return [nil, Hash] A Ruby hash that represents the - # MLAG interface configuration. A nil object is returned if no + # MLAG interface configuration. A nil object is returned if no # interfaces are configured. def getall interfaces = config.scan(/(?<=interface\s)[Et|Po|Lo|Vl].+/) @@ -266,21 +266,21 @@ def getall end ## - # set_network_type sets network type with options + # set_network_type sets network type with options. # - # @param [String] :name The name of the interface + # @param name [String] The name of the interface. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [String] :value The point-to-point value + # @option opts value [String] The point-to-point value. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the ip ospf network + # @option opts default [Boolean] Configure the ip ospf network # to default. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_network_type(name, opts = {}) value = opts[:value] return false unless [nil, 'point-to-point'].include?(value) diff --git a/lib/rbeapi/api/prefixlists.rb b/lib/rbeapi/api/prefixlists.rb index 0a2435d..d0583aa 100644 --- a/lib/rbeapi/api/prefixlists.rb +++ b/lib/rbeapi/api/prefixlists.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Prefixlists class provides a configuration instance for working @@ -43,7 +43,7 @@ module Api # class Prefixlists < Entity ## - # Returns the static routes configured on the node + # Returns the static routes configured on the node. # # @example # { @@ -53,12 +53,12 @@ class Prefixlists < Entity # } # } # - # @param [String] :name The name of the prefix-list to return + # @param name [String] The name of the prefix-list to return. # - # @returns [Hash The method will return all of the - # configured static routes on the node as a Ruby hash object. If + # @return [Hash The method will return all of the + # configured static routes on the node as a Ruby hash object. If # there are no static routes configured, this method will return - # an empty hash + # an empty hash. def get(name) config = get_block("ip prefix-list #{name}") return nil unless config @@ -71,7 +71,7 @@ def get(name) end ## - # Returns the static routes configured on the node + # Returns the static routes configured on the node. # # @example # { @@ -81,10 +81,10 @@ def get(name) # } # } # - # @returns [Hash The method will return all of the - # configured static routes on the node as a Ruby hash object. If + # @return [Hash The method will return all of the + # configured static routes on the node as a Ruby hash object. If # there are no static routes configured, this method will return - # an empty hash + # an empty hash. def getall lists = config.scan(/(?<=^ip\sprefix-list\s).+/) lists.each_with_object({}) do |name, hsh| @@ -96,9 +96,9 @@ def getall ## # create will create a new ip prefix-list with designated name. # - # @param [String] :name The name of the ip prefix-list + # @param name [String] The name of the ip prefix-list. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(name) configure "ip prefix-list #{name}" end @@ -107,15 +107,15 @@ def create(name) # add_rule will create an ip prefix-list with the designated name, # seqno, action and prefix. # - # @param [String] :name The name of the ip prefix-list + # @param name [String] The name of the ip prefix-list. # - # @param [String] :seq The seq value + # @param seq [String] The seq value. # - # @param [String] :action The action value + # @param action [String] The action value. # - # @param [String] :prefix The prefix value + # @param prefix [String] The prefix value. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_rule(name, action, prefix, seq = nil) cmd = "ip prefix-list #{name}" cmd << " seq #{seq}" if seq @@ -124,13 +124,13 @@ def add_rule(name, action, prefix, seq = nil) end ## - # delete will remove the designated prefix-list + # delete will remove the designated prefix-list. # - # @param [String] :name The name of the ip prefix-list + # @param name [String] The name of the ip prefix-list. # - # @param [String] :seq The seq value + # @param seq [String] The seq value. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete(name, seq = nil) cmd = "no ip prefix-list #{name}" cmd << " seq #{seq}" if seq diff --git a/lib/rbeapi/api/radius.rb b/lib/rbeapi/api/radius.rb index 33b449a..c2e73f7 100644 --- a/lib/rbeapi/api/radius.rb +++ b/lib/rbeapi/api/radius.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # Radius provides instance methods to retrieve and set radius configuration @@ -70,7 +70,7 @@ class Radius < Entity # servers: # } # - # @return [Array] Single element Array of resource hashes + # @return [Array] Single element Array of resource hashes. def get global = {} global.merge!(parse_global_timeout) @@ -82,12 +82,12 @@ def get ## # parse_time scans the nodes current configuration and parse the - # radius-server timeout value. The timeout value is expected to always - # be present in the config + # radius-server timeout value. The timeout value is expected to always + # be present in the config. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_global_timeout value = config.scan(/radius-server timeout (\d+)/).first { timeout: value.first.to_i } @@ -96,12 +96,12 @@ def parse_global_timeout ## # parse_retransmit scans the cnodes current configuration and parses the - # radius-server retransmit value. the retransmit value is expected to - # always be present in the config + # radius-server retransmit value. The retransmit value is expected to + # always be present in the config. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_global_retransmit value = config.scan(/radius-server retransmit (\d+)/).first { retransmit: value.first.to_i } @@ -110,13 +110,13 @@ def parse_global_retransmit ## # parse_key scans the current nodes running configuration and parse the - # global radius-server key and format value. If the key is not + # global radius-server key and format value. If the key is not # configured this method will return DEFAULT_KEY and DEFAULT_KEY_FORMAT # for the resource hash values. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_global_key rsrc_hsh = {} (key_format, key) = config.scan(/radius-server key (\d+) (\w+)/).first @@ -127,9 +127,9 @@ def parse_global_key private :parse_global_key ## - # parse_servers returns an Array of radius server resource hashes. Each + # parse_servers returns an Array of radius server resource hashes. Each # hash describes the current state of the radius server and is intended - # to be merged into the radius resource hash + # to be merged into the radius resource hash. # # The resource hash returned contains the following information: # * hostname: hostname or ip address @@ -145,7 +145,7 @@ def parse_global_key # # @api private # - # @return [Array>] Array of resource hashes + # @return [Array>] Array of resource hashes. def parse_servers tuples = config.scan(SERVER_REGEXP) tuples.map do |(host, vrf, authp, acctp, tout, tries, keyfm, key)| @@ -164,33 +164,33 @@ def parse_servers private :parse_servers ## - # set_global_key configures the global radius-server key. If the enable + # set_global_key configures the global radius-server key. If the enable # option is false, radius-server key is configured using the no # keyword. If the default option is specified, radius-server key is # configured using the default keyword. If both options are specified, # the default keyword option takes precedence. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # radius-server key # no radius-server key # default radius-server key # - # @option [String] :value The value to configure the radius-server key to - # in the nodes running configuration + # @option value [String] The value to configure the radius-server key to + # in the nodes running configuration. # - # @option [Fixnum] :key_format The format of the key to be passed to the - # nodes running configuration. Valid values are 0 (clear text) or 7 - # (encrypted). The default value is 0 if format is not provided. + # @option key_format [Fixnum] The format of the key to be passed to the + # nodes running configuration. Valid values are 0 (clear text) or 7 + # (encrypted). The default value is 0 if format is not provided. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option [Boolean] :default Configures the radius-server key using the - # default keyword argument + # @option default [Boolean] Configures the radius-server key using the + # default keyword argument. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def set_global_key(opts = {}) value = opts[:value] enable = opts.fetch(:enable, true) @@ -211,30 +211,30 @@ def set_global_key(opts = {}) end ## - # set_global_timeout configures the radius-server timeout value. If the + # set_global_timeout configures the radius-server timeout value. If the # enable option is false, then radius-server timeout is configured - # using the no keyword. If the default option is specified, radius-server - # timeout is configured using the default keyword. If both options are + # using the no keyword. If the default option is specified, radius-server + # timeout is configured using the default keyword. If both options are # specified then the default keyword takes precedence. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # radius-server timeout # no radius-server timeout # default radius-server timeout # - # @option [String, Fixnum] :value The value to set the global - # radius-server timeout value to. This value should be in the range of - # 1 to 1000 + # @option value [String, Fixnum] The value to set the global + # radius-server timeout value to. This value should be in the range of + # 1 to 1000. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option [Boolean] :default Configures the radius-server timeout value + # @option default [Boolean] Configures the radius-server timeout value # using the default keyword. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def set_global_timeout(opts = {}) cmd = command_builder('radius-server timeout', opts) configure cmd @@ -246,26 +246,26 @@ def set_global_timeout(opts = {}) # value is configured using the no keyword. If the default option is # specified, the radius-server retransmit value is configured using the # default keyword. If both options are specified then the default keyword - # takes precedence + # takes precedence. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # radius-server retransmit # no radius-server retransmit # default radius-server retransmit # - # @option [String, Fixnum] :value The value to set the global - # radius-server retransmit value to. This value should be in the range + # @option value [String, Fixnum] The value to set the global + # radius-server retransmit value to. This value should be in the range # of 1 to 100 # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option [Boolean] :default Configures the radius-server retransmit - # value using the default keyword + # @option default [Boolean] Configures the radius-server retransmit + # value using the default keyword. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def set_global_retransmit(opts = {}) cmd = command_builder('radius-server retransmit', opts) configure cmd @@ -275,11 +275,29 @@ def set_global_retransmit(opts = {}) # update_server configures a radius server resource on the target device. # This API method maps to the `radius server host` command, e.g. # `radius-server host 10.11.12.13 auth-port 1024 acct-port 2048 timeout - # 30 retransmit 5 key 7 011204070A5955` + # 30 retransmit 5 key 7 011204070A5955`. # # @api public # - # @return [Boolean] true if there are no errors + # @param opts [Hash] The configuration options. + # + # @option opts key_format [Integer] The key format value. + # + # @option opts hostname [String] The host value. + # + # @option opts vrf [String] The vrf value. + # + # @option opts auth_port [String] The auth-port value. + # + # @option opts acct_port [String] The acct-port value. + # + # @option opts timeout [String] The timeout value. + # + # @option opts retransmit [String] The retransmit value. + # + # @option opts key [String] The key value. + # + # @return [Boolean] Returns true if there are no errors. def update_server(opts = {}) # beware: order of cli keyword options counts key_format = opts[:key_format] || 7 @@ -299,7 +317,17 @@ def update_server(opts = {}) # # @api public # - # @return [Boolean] true if no errors + # @param opts [Hash] The configuration options. + # + # @option opts hostname [String] The host value. + # + # @option opts vrf [String] The vrf value. + # + # @option opts auth_port [String] The auth-port value. + # + # @option opts acct_port [String] The acct-port value. + # + # @return [Boolean] Returns true if there are no errors. def remove_server(opts = {}) cmd = "no radius-server host #{opts[:hostname]}" cmd << " vrf #{opts[:vrf]}" if opts[:vrf] diff --git a/lib/rbeapi/api/routemaps.rb b/lib/rbeapi/api/routemaps.rb index 7be95b3..9f75b43 100644 --- a/lib/rbeapi/api/routemaps.rb +++ b/lib/rbeapi/api/routemaps.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Routemaps class manages routemaps. A route map is a list of rules @@ -47,7 +47,7 @@ module Api # class Routemaps < Entity ## - # get returns a hash of routemap configurations for the given name + # get returns a hash of routemap configurations for the given name. # # @example # { @@ -81,12 +81,12 @@ class Routemaps < Entity # } # } # - # @param [String] :name The routemap name to return a resource for from - # the nodes configuration + # @param name [String] The routemap name to return a resource for from + # the nodes configuration. # # @return [nil, Hash] Returns the routemap resource as a # Hash. If the specified name is not found in the nodes current - # configuration a nil object is returned + # configuration a nil object is returned. def get(name) parse_entries(name) end @@ -160,8 +160,8 @@ def get(name) # } # } # - # @return [nil, Hash] returns a hash that represents the - # entire routemap collection from the nodes running configuration. If + # @return [nil, Hash] Returns a hash that represents the + # entire routemap collection from the nodes running configuration. If # there are no routemap names configured, this method will return nil. def getall routemaps = config.scan(/(?<=^route-map\s)[^\s]+/) @@ -176,8 +176,10 @@ def getall # # @api private # - # @return [nil, Hash] returns a hash that represents the - # rules for routemaps from the nodes running configuration. If + # @param name [String] The routemap name. + # + # @return [nil, Hash] Returns a hash that represents the + # rules for routemaps from the nodes running configuration. If # there are no routemaps configured, this method will return nil. def parse_entries(name) entries = config.scan(/^route-map\s#{name}\s.+$/) @@ -199,10 +201,20 @@ def parse_entries(name) # # @api private # - # @return [Hash] returns a hash that represents the - # rules for routemaps from the nodes running configuration. If + # @param rules [Hash] Rules configuration options. + # + # @option rules match [Array] The match options. + # + # @option rules set [Array] The set options. + # + # @option rules continue [String] The continue value. + # + # @option rules description [String] The description value. + # + # @return [Hash] Returns a hash that represents the + # rules for routemaps from the nodes running configuration. If # there are no routemaps configured, this method will return an empty - # hash. + # hash. def parse_rules(rules) rules.split("\n").each_with_object({}) do |rule, rule_hsh| mdata = /\s{3}(\w+)\s/.match(rule) @@ -225,7 +237,21 @@ def parse_rules(rules) private :parse_rules ## - # name_commands is utilized to initially prepare the routemap + # name_commands is utilized to initially prepare the routemap. + # + # @param name [String] The routemap name. + # + # @param action [String] The action value. + # + # @param seqno [String] The seqno value. + # + # @param opts [Hash] The configuration options. + # + # @option opts default [Boolean] The default value. + # + # @option opts enable [Boolean] The enable value. + # + # @return [Array] Returns the prepared eos command. def name_commands(name, action, seqno, opts = {}) if opts[:default] == true cmd = "default route-map #{name}" @@ -245,35 +271,35 @@ def name_commands(name, action, seqno, opts = {}) # # rubocop:disable Metrics/MethodLength # - # @commands + # commands # route-map action seqno description # match set continue # - # @param [String] :name The name of the routemap to create + # @param name [String] The name of the routemap to create. # - # @param [String] :action Either permit or deny + # @param action [String] Either permit or deny. # - # @param [Integer] :seqno The sequence number + # @param seqno [Integer] The sequence number value. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :default Set routemap to default + # @option opts default [Boolean] Set routemap to default. # - # @option :opts [String] :description A description for the routemap + # @option opts description [String] A description for the routemap. # - # @option :opts [Array] :match routemap match rule + # @option opts match [Array] routemap match rule. # - # @option :opts [String] :set Sets route attribute + # @option opts set [String] Sets route attribute. # - # @option :opts [String] :continue The routemap sequence number to + # @option opts continue [String] The routemap sequence number to # continue on. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the routemap to default. + # @option opts default [Boolean] Configure the routemap to default. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(name, action, seqno, opts = {}) if opts.empty? cmds = name_commands(name, action, seqno) @@ -306,6 +332,16 @@ def create(name, action, seqno, opts = {}) ## # remove_match_statemements removes all match rules for the # specified routemap + # + # @param name [String] The routemap name. + # + # @param action [String] The action value. + # + # @param seqno [String] The seqno value. + # + # @param cmds [Array] Array of eos commands. + # + # @return [Boolean] Returns true if the command completed successfully. def remove_match_statements(name, action, seqno, cmds) entries = parse_entries(name) return nil unless entries @@ -322,6 +358,16 @@ def remove_match_statements(name, action, seqno, cmds) ## # remove_set_statemements removes all set rules for the # specified routemap + # + # @param name [String] The routemap name. + # + # @param action [String] The action value. + # + # @param seqno [String] The seqno value. + # + # @param cmds [Array] Array of eos commands. + # + # @return [Boolean] Returns true if the command completed successfully. def remove_set_statements(name, action, seqno, cmds) entries = parse_entries(name) return nil unless entries @@ -340,16 +386,16 @@ def remove_set_statements(name, action, seqno, cmds) # running configuration. If the delete method is called and the # routemap name does not exist, this method will succeed. # - # @commands + # commands # no route-map # - # @param [String] :name The routemap name to delete from the node. + # @param name [String] The routemap name to delete from the node. # - # @param [String] :action Either permit or deny + # @param action [String] Either permit or deny. # - # @param [Integer] :seqno The sequence number + # @param seqno [Integer] The sequence number. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete(name, action, seqno) configure(["no route-map #{name} #{action} #{seqno}"]) end @@ -358,20 +404,20 @@ def delete(name, action, seqno) # This method will attempt to default the routemap from the nodes # operational config. Since routemaps do not exist by default, # the default action is essentially a negation and the result will - # be the removal of the routemap clause. - # If the routemap does not exist then this - # method will not perform any changes but still return True + # be the removal of the routemap clause. If the routemap does not + # exist then this method will not perform any changes but still + # return True. # - # @commands + # commands # no route-map # - # @param [String] :name The routemap name to set to default. + # @param name [String] The routemap name to set to default. # - # @param [String] :action Either permit or deny + # @param action [String] Either permit or deny. # - # @param [Integer] :seqno The sequence number + # @param seqno [Integer] The sequence number. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def default(name, action, seqno) configure(["default route-map #{name} #{action} #{seqno}"]) end @@ -380,18 +426,18 @@ def default(name, action, seqno) # set_match_statements will set the match values for a specified routemap. # If the specified routemap does not exist, it will be created. # - # @commands + # commands # route-map action seqno match # - # @param [String] :name The name of the routemap to create + # @param name [String] The name of the routemap to create. # - # @param [String] :action Either permit or deny + # @param action [String] Either permit or deny. # - # @param [Integer] :seqno The sequence number + # @param seqno [Integer] The sequence number. # - # @param [Array] :value The routemap match rules + # @param value [Array] The routemap match rules. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_match_statements(name, action, seqno, value) cmds = ["route-map #{name} #{action} #{seqno}"] remove_match_statements(name, action, seqno, cmds) @@ -405,18 +451,18 @@ def set_match_statements(name, action, seqno, value) # set_set_statements will set the set values for a specified routemap. # If the specified routemap does not exist, it will be created. # - # @commands + # commands # route-map action seqno set # - # @param [String] :name The name of the routemap to create + # @param name [String] The name of the routemap to create. # - # @param [String] :action Either permit or deny + # @param action [String] Either permit or deny. # - # @param [Integer] :seqno The sequence number + # @param seqno [Integer] The sequence number. # - # @param [Array] :value The routemap set rules + # @param value [Array] The routemap set rules. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_set_statements(name, action, seqno, value) cmds = ["route-map #{name} #{action} #{seqno}"] remove_set_statements(name, action, seqno, cmds) @@ -430,18 +476,18 @@ def set_set_statements(name, action, seqno, value) # set_continue will set the continue value for a specified routemap. # If the specified routemap does not exist, it will be created. # - # @commands + # commands # route-map action seqno continue # - # @param [String] :name The name of the routemap to create + # @param name [String] The name of the routemap to create. # - # @param [String] :action Either permit or deny + # @param action [String] Either permit or deny. # - # @param [Integer] :seqno The sequence number + # @param seqno [Integer] The sequence number. # - # @param [Integer] :value The continue value + # @param value [Integer] The continue value. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_continue(name, action, seqno, value) cmds = ["route-map #{name} #{action} #{seqno}"] cmds << 'no continue' @@ -453,18 +499,18 @@ def set_continue(name, action, seqno, value) # set_description will set the description for a specified routemap. # If the specified routemap does not exist, it will be created. # - # @commands + # commands # route-map action seqno description # - # @param [String] :name The name of the routemap to create + # @param name [String] The name of the routemap to create. # - # @param [String] :action Either permit or deny + # @param action [String] Either permit or deny. # - # @param [Integer] :seqno The sequence number + # @param seqno [Integer] The sequence number. # - # @param [String] :value The description value + # @param value [String] The description value. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_description(name, action, seqno, value) cmds = ["route-map #{name} #{action} #{seqno}"] cmds << 'no description' diff --git a/lib/rbeapi/api/snmp.rb b/lib/rbeapi/api/snmp.rb index 3006260..f4d38fe 100644 --- a/lib/rbeapi/api/snmp.rb +++ b/lib/rbeapi/api/snmp.rb @@ -32,17 +32,17 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Snmp class provides a class implementation for working with the - # nodes SNMP configuration entity. This class presents an abstraction + # nodes SNMP configuration entity. This class presents an abstraction # of the node's snmp configuration from the running config. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M class Snmp < Entity DEFAULT_SNMP_LOCATION = '' DEFAULT_SNMP_CONTACT = '' @@ -63,7 +63,7 @@ class Snmp < Entity # source_interface: # } # - # @return[Hash] Returns the snmp resource as a Hash + # @return[Hash] Returns the snmp resource as a Hash. def get response = {} response.merge!(parse_location) @@ -77,14 +77,14 @@ def get ## # parse_location scans the running config from the node and parses - # the snmp location value if it exists in the configuration. If the + # the snmp location value if it exists in the configuration. If the # snmp location is not configure, then the DEFAULT_SNMP_LOCATION string - # is returned. The Hash returned by this method is merged into the + # is returned. The Hash returned by this method is merged into the # snmp resource Hash returned by the get method. # # @api private # - # @return [Hash] resource Hash attribute + # @return [Hash] Returns the resource Hash attribute. def parse_location mdata = /snmp-server location (.+)$/.match(config) { location: mdata.nil? ? DEFAULT_SNMP_LOCATION : mdata[1] } @@ -93,14 +93,14 @@ def parse_location ## # parse_contact scans the running config form the node and parses - # the snmp contact value if it exists in the configuration. If the + # the snmp contact value if it exists in the configuration. If the # snmp contact is not configured, then the DEFAULT_SNMP_CONTACT value - # is returned. The Hash returned by this method is merged into the + # is returned. The Hash returned by this method is merged into the # snmp resource Hash returned by the get method. # # @api private # - # @return [Hash] resource Hash attribute + # @return [Hash] Returns the resource Hash attribute. def parse_chassis_id mdata = /snmp-server chassis-id (.+)$/.match(config) { chassis_id: mdata.nil? ? DEFAULT_SNMP_CHASSIS_ID : mdata[1] } @@ -126,14 +126,14 @@ def parse_chassis_id ## # parse_source_interface scans the running config from the node and # parses the snmp source interface value if it exists in the - # configuration. If the snmp source interface is not configured, then - # the DEFAULT_SNMP_SOURCE_INTERFACE value is returned. The Hash + # configuration. If the snmp source interface is not configured, then + # the DEFAULT_SNMP_SOURCE_INTERFACE value is returned. The Hash # returned by this method is intended to be merged into the snmmp - # resource Hash + # resource Hash. # # @api private # - # @return [Hash] resource Hash attribute + # @return [Hash] Returns the resource Hash attribute. def parse_source_interface mdata = /snmp-server source-interface (.+)$/.match(config) { source_interface: mdata.nil? ? '' : mdata[1] } @@ -142,14 +142,14 @@ def parse_source_interface ## # parse_communities scans the running config from the node and parses all - # of the configure snmp community strings. If there are no configured + # of the configure snmp community strings. If there are no configured # snmp community strings, the community value is set to an empty array. # The returned hash is intended to be merged into the global snmp - # resource hash + # resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_communities values = config.scan(/snmp-server community (\w+) (ro|rw)[ ]?(.+)?$/) communities = values.each_with_object({}) do |value, hsh| @@ -162,9 +162,9 @@ def parse_communities ## # parse_notifications scans the running configuration and parses all of - # the snmp trap notifications configuration. It is expected the trap - # configuration is in the running config. The returned hash is intended - # to be merged into the resource hash + # the snmp trap notifications configuration. It is expected the trap + # configuration is in the running config. The returned hash is intended + # to be merged into the resource hash. def parse_notifications traps = config.scan(/(default|no)?[ ]?snmp-server enable traps (.+)$/) all = config.scan(/(default|no)?[ ]?snmp-server enable traps$/).first @@ -180,24 +180,26 @@ def parse_notifications ## # set_notification configures the snmp trap notification for the - # specified trap. The name option accepts the snmp trap name to + # specified trap. The name option accepts the snmp trap name to # configure or the keyword all to globally enable or disable - # notifications. If the optional state argument is not provided then the + # notifications. If the optional state argument is not provided then the # default state is default. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # snmp-server enable traps # no snmp-server enable traps # default snmp-server enable traps # - # @param [String] :name The name of the trap to configure or the keyword - # all. If this option is not specified, then the value of 'all' is - # used as the default. + # @param opts [Hash] The configuration parameters. # - # @param [String] :state The state to configure the trap notification. - # Valid values include 'on', 'off' or 'default' + # @option opts name [String] The name of the trap to configure or the + # keyword all. If this option is not specified, then the value of + # 'all' is used as the default. + # + # @option opts state [String] The state to configure the trap + # notification. Valid values include 'on', 'off' or 'default'. def set_notification(opts = {}) name = opts[:name] name = nil if name == 'all' @@ -208,29 +210,29 @@ def set_notification(opts = {}) ## # set_location updates the snmp location value in the nodes running - # configuration. If enable is false, then the snmp location value is - # negated using the no keyword. If the default keyword is set to true, + # configuration. If enable is false, then the snmp location value is + # negated using the no keyword. If the default keyword is set to true, # then the snmp location value is defaulted using the default keyword. # The default parameter takes precedence over the enable keyword. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # snmp-server location # no snmp-server location # default snmp-server location # - # @param [Hash] opts The configuration parameters + # @param opts [Hash] The configuration parameters. # - # @option opts [string] :value The snmp location value to configure + # @option opts value [string] The snmp location value to configure. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option opts [Boolean] :default Configure the snmp location value - # using the default keyword + # @option opts default [Boolean] Configure the snmp location value + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_location(opts = {}) cmd = command_builder('snmp-server location', opts) configure(cmd) @@ -238,30 +240,30 @@ def set_location(opts = {}) ## # set_contact updates the snmp contact value in the nodes running - # configuration. If enable is false in the opts Hash then - # the snmp contact value is negated using the no keyword. If the + # configuration. If enable is false in the opts Hash then + # the snmp contact value is negated using the no keyword. If the # default keyword is set to true, then the snmp contact value is - # defaulted using the default keyword. The default parameter takes + # defaulted using the default keyword. The default parameter takes # precedence over the enable keyword. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # snmp-server contact # no snmp-server contact # default snmp-server contact # - # @param [Hash] opts The configuration parameters + # @param opts [Hash] The configuration parameters. # - # @option opts [string] :value The snmp contact value to configure + # @option opts value [string] The snmp contact value to configure. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option opts [Boolean] :default Configures the snmp contact value - # using the default keyword + # @option opts default [Boolean] Configures the snmp contact value + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_contact(opts = {}) cmd = command_builder('snmp-server contact', opts) configure(cmd) @@ -269,30 +271,30 @@ def set_contact(opts = {}) ## # set_chassis_id updates the snmp chassis id value in the nodes - # running configuration. If enable is false in the opts + # running configuration. If enable is false in the opts # Hash then the snmp chassis id value is negated using the no - # keyword. If the default keyword is set to true, then the snmp - # chassis id value is defaulted using the default keyword. The default + # keyword. If the default keyword is set to true, then the snmp + # chassis id value is defaulted using the default keyword. The default # keyword takes precedence over the enable keyword. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # snmp-server chassis-id # no snmp-server chassis-id # default snmp-server chassis-id # - # @param [Hash] opts The configuration parameters + # @param opts [Hash] The configuration parameters # - # @option opts [string] :value The snmp chassis id value to configure + # @option opts value [string] The snmp chassis id value to configure # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option opts [Boolean] :default Configures the snmp chassis id value - # using the default keyword + # @option opts default [Boolean] Configures the snmp chassis id value + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_chassis_id(opts = {}) cmd = command_builder('snmp-server chassis-id', opts) configure(cmd) @@ -300,30 +302,30 @@ def set_chassis_id(opts = {}) ## # set_source_interface updates the snmp source interface value in the - # nodes running configuration. If enable is false in the opts + # nodes running configuration. If enable is false in the opts # Hash then the snmp source interface is negated using the no keyword. # If the default keyword is set to true, then the snmp source interface - # value is defaulted using the default keyword. The default keyword + # value is defaulted using the default keyword. The default keyword # takes precedence over the enable keyword. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # snmp-server source-interface # no snmp-server source-interface # default snmp-server source-interface # - # @param [Hash] opts The configuration parameters + # @param opts [Hash] The configuration parameters. # - # @option opts [string] :value The snmp source interface value to - # configure. This method will not ensure the interface is present - # in the configuration - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [string] The snmp source interface value to + # configure. This method will not ensure the interface is present + # in the configuration. + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default Configures the snmp source interface - # value using the default keyword + # @option opts default [Boolean] Configures the snmp source interface + # value using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_source_interface(opts = {}) cmd = command_builder('snmp-server source-interface', opts) configure(cmd) @@ -331,65 +333,67 @@ def set_source_interface(opts = {}) ## # add_community adds a new snmp community to the nodes running - # configuration. This function is a convenience function that passes the + # configuration. This function is a convenience function that passes the # message to set_community_access. # # @see set_community_access # - # @param [String] :name The name of the snmp community to add to the + # @param name [String] The name of the snmp community to add to the # nodes running configuration. # - # @param [String] :access Specifies the access level to assign to the - # new snmp community. Valid values are 'rw' or 'ro' + # @param access [String] Specifies the access level to assign to the + # new snmp community. Valid values are 'rw' or 'ro'. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_community(name, access = 'ro') set_community_access(name, access) end ## # remove_community removes the specified community from the nodes running - # configuration. If the specified name is not configured, this method + # configuration. If the specified name is not configured, this method # will still return successfully. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # no snmp-server community # - # @param [String] :name The name of the snmp community to add to the + # @param name [String] The name of the snmp community to add to the # nodes running configuration. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def remove_community(name) configure "no snmp-server community #{name}" end ## # set_community_acl configures the acl to apply to the specified - # community name. When enable is true, it will remove the + # community name. When enable is true, it will remove the # the named community and then add the new acl entry. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # no snmp-server [ro|rw] # snmp-server [ro|rw] # - # @param [String] :name The name of the snmp community to add to the + # @param name [String] The name of the snmp community to add to the # nodes running configuration. # - # @param [Hash] opts The configuration parameters + # @param opts [Hash] The configuration parameters. # - # @option opts [String] :value The name of the acl to apply to the snmp + # @option opts value [String] The name of the acl to apply to the snmp # community in the nodes config. If nil, then the community name # allows access to all objects. - # @option opts [Boolean] :enable If false then the command is + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default Configure the snmp community name + # + # @option opts default [Boolean] Configure the snmp community name # using the default keyword. Default takes precedence over enable. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_community_acl(name, opts = {}) value = opts[:value] enable = opts.fetch(:enable, true) @@ -407,11 +411,11 @@ def set_community_acl(name, opts = {}) # set_community_access configures snmp-server community with designated # name and access values. # - # @param [String] :name The snmp-server community name value + # @param name [String] The snmp-server community name value. # - # @param [String] :access The snmp-server community access value + # @param access [String] The snmp-server community access value. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_community_access(name, access) configure "snmp-server community #{name} #{access}" end diff --git a/lib/rbeapi/api/staticroutes.rb b/lib/rbeapi/api/staticroutes.rb index 1efe459..313b0a7 100644 --- a/lib/rbeapi/api/staticroutes.rb +++ b/lib/rbeapi/api/staticroutes.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Staticroutes class provides a configuration instance for working @@ -43,7 +43,7 @@ module Api # class Staticroutes < Entity ## - # Returns the static routes configured on the node + # Returns the static routes configured on the node. # # @example # { @@ -59,9 +59,9 @@ class Staticroutes < Entity # ] # } # - # @returns [Array] The method will return all of the + # @return [Array] The method will return all of the # configured static routes on the node as a Ruby array object - # containing a list of hashes with each hash describing a route. If + # containing a list of hashes with each hash describing a route. If # there are no static routes configured, this method will return # an empty array. def getall @@ -88,22 +88,28 @@ def getall ## # Creates a static route in EOS. May add or overwrite an existing route. # - # @commands + # commands # ip route [router_ip] [distance] [tag ] # [name ] # - # @param [String] :destination The destination and prefix matching the + # @param destination [String] The destination and prefix matching the # route(s). Ex '192.168.0.2/24'. - # @param [String] :nexthop The nexthop for this entry, which may an IP + # + # @param nexthop [String] The nexthop for this entry, which may an IP # address or interface name. - # @param [Hash] :opts Additional options for the route entry. - # @option :opts [String] :router_ip If nexthop is an egress interface, - # router_ip specifies the router to which traffic will be forwarded - # @option :opts [String] :distance The administrative distance (metric) - # @option :opts [String] :tag The route tag - # @option :opts [String] :name A route name # - # @return [Boolean] returns true on success + # @param opts [Hash] Additional options for the route entry. + # + # @option opts router_ip [String] If nexthop is an egress interface, + # router_ip specifies the router to which traffic will be forwarded. + # + # @option opts distance [String] The administrative distance (metric). + # + # @option opts tag [String] The route tag. + # + # @option opts name [String] A route name. + # + # @return [Boolean] Returns True on success, otherwise False. def create(destination, nexthop, opts = {}) cmd = "ip route #{destination} #{nexthop}" cmd << " #{opts[:router_ip]}" if opts[:router_ip] @@ -114,18 +120,19 @@ def create(destination, nexthop, opts = {}) end ## - # Removes a given route from EOS. May remove multiple routes if nexthop + # Removes a given route from EOS. May remove multiple routes if nexthop # is not specified. # - # @commands + # commands # no ip route [nexthop] # - # @param [String] :destination The destination and prefix matching the + # @param destination [String] The destination and prefix matching the # route(s). Ex '192.168.0.2/24'. - # @param [String] :nexthop The nexthop for this entry, which may an IP + # + # @param nexthop [String] The nexthop for this entry, which may an IP # address or interface name. # - # @return [Boolean] returns true on success + # @return [Boolean] Returns True on success, otherwise False. def delete(destination, nexthop = nil) cmd = "no ip route #{destination}" cmd << " #{nexthop}" if nexthop diff --git a/lib/rbeapi/api/stp.rb b/lib/rbeapi/api/stp.rb index bd2a25f..20e5b9c 100644 --- a/lib/rbeapi/api/stp.rb +++ b/lib/rbeapi/api/stp.rb @@ -31,14 +31,14 @@ # ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Stp class provides a base class instance for working with - # the EOS spanning-tree configuration + # the EOS spanning-tree configuration. # class Stp < Entity ## @@ -62,7 +62,7 @@ class Stp < Entity # } # } # - # @return [Hash] returns a Hash of attributes derived from eAPI + # @return [Hash] returns a Hash of attributes derived from eAPI. def get response = {} response.merge!(parse_mode) @@ -73,13 +73,13 @@ def get ## # parse_mode scans the nodes running configuration and extracts the - # value of the spanning-tree mode. The spanning tree mode is - # expected to be always be available in the running config. The return - # value is intended to be merged into the stp resource hash + # value of the spanning-tree mode. The spanning tree mode is + # expected to be always be available in the running config. The return + # value is intended to be merged into the stp resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Resource hash attribute. def parse_mode mdata = /(?<=spanning-tree\smode\s)(\w+)$/.match(config) { mode: mdata[1] } @@ -89,7 +89,7 @@ def parse_mode # instances returns a memoized instance of StpInstances for configuring # individual stp instances. # - # @return [StpInstances] an instance of StpInstances class + # @return [StpInstances] an instance of StpInstances class. def instances return @instances if @instances @instances = StpInstances.new(node) @@ -98,9 +98,9 @@ def instances ## # interfaces returns a memoized instance of StpInterfaces for - # configuring individual stp interfaces + # configuring individual stp interfaces. # - # @return [StpInterfaces] an instance of StpInterfaces class + # @return [StpInterfaces] an instance of StpInterfaces class. def interfaces return @interfaces if @interfaces @interfaces = StpInterfaces.new(node) @@ -113,27 +113,27 @@ def interfaces # mode is configured with the no keyword argument. If the default option # is specified then the mode is configured with the default keyword # argument. The default keyword argument takes precedence over the enable - # option if both are provided + # option if both are provided. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # spanning-tree mode # no spanning-tree mode # default spanning-tree mode # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the stp mode to - # in the nodes current running configuration + # @option opts value [String] The value to configure the stp mode to + # in the nodes current running configuration. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the stp mode value using - # the default keyword + # @option opts default [Boolean] Configure the stp mode value using + # the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] returns true if the command completed successfully. # def set_mode(opts = {}) cmd = command_builder('spanning-tree mode', opts) @@ -157,11 +157,11 @@ class StpInstances < Entity # priority: # } # - # @param [String] :inst The named stp instance to return + # @param inst [String] The named stp instance to return. # - # @return [nil, Hash] returns all configured stp instances - # found in the nodes running configuration + # @return [Hash] Returns all configured stp instances + # found in the nodes running configuration. def getall parse_instances.each_with_object({}) do |inst, hsh| values = get(inst) @@ -196,12 +196,12 @@ def getall ## # parse_instances will scan the nodes current configuration and extract - # the list of configured mst instances. If no instances are configured - # then this method will return an empty array + # the list of configured mst instances. If no instances are configured + # then this method will return an empty array. # # @api private # - # @return [Array] returns an Array of configured stp instances + # @return [Array] Returns an Array of configured stp instances. def parse_instances config = get_block('spanning-tree mst configuration') config.scan(/(?<=^\s{3}instance\s)\d+/) @@ -210,14 +210,14 @@ def parse_instances ## # parse_priority will scan the nodes current configuration and extract - # the stp priority value for the given stp instance. If the stp + # the stp priority value for the given stp instance. If the stp # instance priority is not configured, the priority value will be set - # using DEFAULT_STP_PRIORITY. The returned hash is intended to be merged - # into the resource hash + # using DEFAULT_STP_PRIORITY. The returned hash is intended to be merged + # into the resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Resource hash attribute. def parse_priority(inst) priority_re = /(?<=^spanning-tree\smst\s#{inst}\spriority\s)(.+$)/x mdata = priority_re.match(config) @@ -226,27 +226,31 @@ def parse_priority(inst) private :parse_priority ## - # Deletes a configured MST instance + # Deletes a configured MST instance. # - # @param [String] inst The MST instance to delete + # @param inst [String] The MST instance to delete. # - # @return [Boolean] True if the commands succeed otherwise False + # @return [Boolean] True if the commands succeed otherwise False. def delete(inst) configure ['spanning-tree mst configuration', "no instance #{inst}", 'exit'] end ## - # Configures the spanning-tree MST priority + # Configures the spanning-tree MST priority. # - # @param [String] inst The MST instance to configure - # @param [Hash] opts The configuration parameters for the priority - # @option opts [string] :value The value to set the priority to - # @option :opts [Boolean] :enable If false then the command is + # @param inst [String] The MST instance to configure. + # + # @param opts [Hash] The configuration parameters for the priority. + # + # @option opts value [string] The value to set the priority to. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default # - # @return [Boolean] True if the commands succeed otherwise False + # @option opts default [Boolean] The value should be set to default. + # + # @return [Boolean] True if the commands succeed otherwise False. def set_priority(inst, opts = {}) value = opts[:value] enable = opts.fetch(:enable, true) @@ -268,13 +272,13 @@ def set_priority(inst, opts = {}) ## # The StpInterfaces class provides a class instance for working with - # spanning-tree interfaces in EOS + # spanning-tree interfaces in EOS. # class StpInterfaces < Entity ## # get returns the configured stp interfaces from the nodes running - # configuration as a resource hash. If the specified interface is not - # configured as a switchport then this method will return nil + # configuration as a resource hash. If the specified interface is not + # configured as a switchport then this method will return nil. # # @example # { @@ -283,11 +287,11 @@ class StpInterfaces < Entity # bpduguard: # } # - # @param [String] :name The interface name to return a resource for from - # the nodes configuration + # @param name [String] The interface name to return a resource for from + # the nodes configuration. # - # @return [nil, Hash] returns the stp interface as a - # resource hash + # @return [nil, Hash] Returns the stp interface as a + # resource hash. def get(name) config = get_block("interface #{name}") return nil unless config @@ -301,8 +305,8 @@ def get(name) ## # getall returns all of the configured stp interfaces parsed from the - # nodes current running configuration. The returned hash is keyed by the - # interface name + # nodes current running configuration. The returned hash is keyed by the + # interface name. # # @example # { @@ -319,8 +323,8 @@ def get(name) # ... # } # - # @return [Hash] returns the stp interfaces config as a - # resource hash from the nodes running configuration + # @return [Hash] Returns the stp interfaces config as a + # resource hash from the nodes running configuration. def getall interfaces = config.scan(/(?<=^interface\s)[Et|Po].+/) resp = interfaces.each_with_object({}) do |name, hsh| @@ -332,12 +336,12 @@ def getall ## # parse_portfast scans the supplied interface configuration block and - # parses the value stp portfast. The value of portfast is either enabled - # (true) or disabled (false) + # parses the value stp portfast. The value of portfast is either enabled + # (true) or disabled (false). # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Resource hash attribute. def parse_portfast(config) val = /no spanning-tree portfast/ =~ config { portfast: val.nil? } @@ -346,12 +350,12 @@ def parse_portfast(config) ## # parse_portfast_type scans the supplied interface configuration block - # and parses the value stp portfast type. The value of portfast type + # and parses the value stp portfast type. The value of portfast type # is either not set which implies normal (default), edge, or network. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Resource hash attribute. def parse_portfast_type(config) if /spanning-tree portfast network/ =~ config value = 'network' @@ -366,12 +370,12 @@ def parse_portfast_type(config) ## # parse_bpduguard scans the supplied interface configuration block and - # parses the value of stp bpduguard. The value of bpduguard is either - # disabled (false) or enabled (true) + # parses the value of stp bpduguard. The value of bpduguard is either + # disabled (false) or enabled (true). # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Resource hash attribute. def parse_bpduguard(config) val = /spanning-tree bpduguard enable/ =~ config { bpduguard: !val.nil? } @@ -379,16 +383,20 @@ def parse_bpduguard(config) private :parse_bpduguard ## - # Configures the interface portfast value + # Configures the interface portfast value. # - # @param [String] name The name of the interface to configure - # @param [Hash] opts The configuration parameters for portfast - # @option opts [Boolean] :value The value to set portfast - # @option :opts [Boolean] :enable If false then the command is + # @param name [String] The name of the interface to configure. + # + # @param opts [Hash] The configuration parameters for portfast. + # + # @option opts value [Boolean] The value to set portfast. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default # - # @return [Boolean] True if the commands succeed otherwise False + # @option opts default [Boolean] The value should be set to default. + # + # @return [Boolean] True if the commands succeed otherwise False. def set_portfast(name, opts = {}) cmd = command_builder('spanning-tree portfast', opts) configure_interface(name, cmd) @@ -397,15 +405,19 @@ def set_portfast(name, opts = {}) ## # Configures the interface portfast type value # - # @param [String] name The name of the interface to configure - # @param [Hash] opts The configuration parameters for portfast type - # @option opts [String] :value The value to set portfast type to. + # @param name [String] The name of the interface to configure. + # + # @param opts [Hash] The configuration parameters for portfast type. + # + # @option opts value [String] The value to set portfast type to. # The value must be set for calls to this method. - # @option opts [Boolean] :enable If false then the command is + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default # - # @return [Boolean] True if the commands succeed otherwise False + # @option opts default [Boolean] The value should be set to default. + # + # @return [Boolean] True if the commands succeed otherwise False. def set_portfast_type(name, opts = {}) value = opts[:value] fail ArgumentError, 'value must be set' unless value @@ -428,14 +440,18 @@ def set_portfast_type(name, opts = {}) ## # Configures the interface bpdu guard value # - # @param [String] name The name of the interface to configure - # @param [Hash] opts The configuration parameters for bpduguard - # @option opts [Boolean] :value The value to set bpduguard - # @option opts [Boolean] :enable If false then the bpduguard is + # @param name [String] The name of the interface to configure. + # + # @param opts [Hash] The configuration parameters for bpduguard. + # + # @option opts value [Boolean] The value to set bpduguard. + # + # @option opts enable [Boolean] If false then the bpduguard is # disabled. If true then the bpduguard is enabled. Default is true. - # @option opts [Boolean] :default The value should be set to default # - # @return [Boolean] True if the commands succeed otherwise False + # @option opts default [Boolean] The value should be set to default. + # + # @return [Boolean] True if the commands succeed otherwise False. def set_bpduguard(name, opts = {}) enable = opts.fetch(:enable, true) default = opts[:default] || false diff --git a/lib/rbeapi/api/switchports.rb b/lib/rbeapi/api/switchports.rb index dba8c8e..45c9b15 100644 --- a/lib/rbeapi/api/switchports.rb +++ b/lib/rbeapi/api/switchports.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Switchport class provides a base class instance for working with @@ -44,7 +44,7 @@ module Api class Switchports < Entity ## # Retrieves the properties for a logical switchport from the - # running-config using eAPI + # running-config using eAPI. # # Example # { @@ -56,10 +56,10 @@ class Switchports < Entity # "trunk_groups": array # } # - # @param [String] :name The full name of the interface to get. The - # interface name must be the full interface (ie Ethernet, not Et) + # @param name [String] The full name of the interface to get. The + # interface name must be the full interface (ie Ethernet, not Et). # - # @return [Hash] a hash that includes the switchport properties + # @return [Hash] Returns a hash that includes the switchport properties. def get(name) config = get_block("interface #{name}") return nil unless config @@ -75,14 +75,14 @@ def get(name) end ## - # parse_mode parses switchport mode from the provided config + # parse_mode parses switchport mode from the provided config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_mode(config) mdata = /(?<=\s{3}switchport\smode\s)(.+)$/.match(config) { mode: mdata[1] } @@ -91,14 +91,14 @@ def parse_mode(config) ## # parse_access_vlan parses access vlan from the provided - # config + # config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_access_vlan(config) mdata = /(?<=access\svlan\s)(.+)$/.match(config) { access_vlan: mdata[1] } @@ -107,14 +107,14 @@ def parse_access_vlan(config) ## # parse_trunk_native_vlan parses trunk native vlan from - # the provided config + # the provided config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_trunk_native_vlan(config) mdata = /(?<=trunk\snative\svlan\s)(.+)$/.match(config) { trunk_native_vlan: mdata[1] } @@ -123,14 +123,14 @@ def parse_trunk_native_vlan(config) ## # parse_trunk_allowed_vlans parses trunk allowed vlan from - # the provided config + # the provided config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_trunk_allowed_vlans(config) mdata = /(?<=trunk\sallowed\svlan\s)(.+)$/.match(config) return { trunk_allowed_vlans: [] } unless mdata[1] != 'none' @@ -149,14 +149,14 @@ def parse_trunk_allowed_vlans(config) ## # parse_trunk_groups parses trunk group values from the - # provided config + # provided config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_trunk_groups(config) mdata = config.scan(/(?<=trunk\sgroup\s)(.+)$/) mdata = mdata.flatten if mdata.length > 0 @@ -165,7 +165,7 @@ def parse_trunk_groups(config) private :parse_trunk_groups ## - # Retrieves all switchport interfaces from the running-config + # Retrieves all switchport interfaces from the running-config. # # @example # { @@ -186,7 +186,7 @@ def parse_trunk_groups(config) # ... # } # - # @return [Array] an array of switchport hashes + # @return [Array] Returns an array of switchport hashes. def getall interfaces = config.scan(/(?<=^interface\s)([Et|Po].+)$/) interfaces.each_with_object({}) do |port, hsh| @@ -196,31 +196,31 @@ def getall end ## - # Creates a new logical switchport interface in EOS + # Creates a new logical switchport interface in EOS. # - # @param [String] name The name of the logical interface + # @param name [String] The name of the logical interface. # - # @return [Boolean] True if it succeeds otherwise False + # @return [Boolean] Returns True if it succeeds otherwise False. def create(name) configure ["interface #{name}", 'no ip address', 'switchport'] end ## - # Deletes a logical switchport interface from the running-config + # Deletes a logical switchport interface from the running-config. # - # @param [String] name The name of the logical interface + # @param name [String] The name of the logical interface. # - # @return [Boolean] True if it succeeds otherwise False + # @return [Boolean] Returns True if it succeeds otherwise False. def delete(name) configure ["interface #{name}", 'no switchport'] end ## - # Defaults a logical switchport interface in the running-config + # Defaults a logical switchport interface in the running-config. # - # @param [String] name The name of the logical interface + # @param name [String] The name of the logical interface. # - # @return [Boolean] True if it succeeds otherwise False + # @return [Boolean] Returns True if it succeeds otherwise False. def default(name) configure ["interface #{name}", 'default switchport'] end @@ -228,14 +228,18 @@ def default(name) ## # Configures the switchport mode for the specified interface. # - # @param [String] name The name of the interface to configure - # @param [Hash] opts The configuration parameters for the interface - # @option opts [string] :value The value to set the mode to - # @option opts [Boolean] :enable If false then the command is + # @param name [String] The name of the interface to configure. + # + # @param opts [Hash] The configuration parameters for the interface. + # + # @option opts value [string] The value to set the mode to. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default # - # @return [Boolean] True if the commands succeed otherwise False + # @option opts default [Boolean] The value should be set to default. + # + # @return [Boolean] Returns True if the commands succeed otherwise False. def set_mode(name, opts = {}) cmd = command_builder('switchport mode', opts) configure_interface(name, cmd) @@ -243,31 +247,35 @@ def set_mode(name, opts = {}) ## # set_trunk_allowed_vlans configures the list of vlan ids that are - # allowed on the specified trunk port. If the enable option is set to + # allowed on the specified trunk port. If the enable option is set to # false, then the allowed trunks is configured using the no keyword. # If the default keyword is provided then the allowed trunks is configured - # using the default keyword The default option takes precedence over the - # enable option if both are specified + # using the default keyword. The default option takes precedence over the + # enable option if both are specified. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # switchport trunk allowed vlan add # no switchport trunk allowed vlan # default switchport trunk allowed vlan # - # @param [String] name The name of the interface to configure - # @param [Hash] opts The configuration parameters for the interface - # @option pts [Array] :value The list of vlan ids to configure on the - # switchport to be allowed. This value must be an array of valid vlan - # ids - # @option opts [Boolean] :enable If false then the command is + # @param name [String] The name of the interface to configure. + # + # @param opts [Hash] The configuration parameters for the interface. + # + # @option ots value [Array] The list of vlan ids to configure on the + # switchport to be allowed. This value must be an array of valid vlan + # ids. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option [Boolean] :default Configures the switchport trunk allowed + # + # @option default [Boolean] Configures the switchport trunk allowed # vlans command using the default keyword. Default takes precedence # over enable. # - # @return [Boolean] returns true if the commands complete successfully + # @return [Boolean] Returns true if the commands complete successfully. def set_trunk_allowed_vlans(name, opts = {}) value = opts[:value] enable = opts.fetch(:enable, true) @@ -297,15 +305,19 @@ def set_trunk_allowed_vlans(name, opts = {}) # This value is only valid if the switchport mode is configure as # trunk. # - # @param [String] name The name of the interface to configure - # @param [Hash] opts The configuration parameters for the interface - # @option opts [string] :value The value of the trunk native vlan - # @option :opts [Boolean] :enable If false then the command is + # @param name [String] The name of the interface to configure. + # + # @param opts [Hash] The configuration parameters for the interface. + # + # @option opts value [string] The value of the trunk native vlan. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default. + # + # @option opts default [Boolean] The value should be set to default. # Default takes precedence over enable. # - # @return [Boolean] True if the commands succeed otherwise False + # @return [Boolean] Returns True if the commands succeed otherwise False. def set_trunk_native_vlan(name, opts = {}) cmd = command_builder('switchport trunk native vlan', opts) configure_interface(name, cmd) @@ -316,15 +328,19 @@ def set_trunk_native_vlan(name, opts = {}) # This value is only valid if the switchport mode is configure # in access mode. # - # @param [String] name The name of the interface to configure - # @param [Hash] opts The configuration parameters for the interface - # @option opts [string] :value The value of the access vlan - # @option opts [Boolean] :enable If false then the command is + # @param name [String] The name of the interface to configure. + # + # @param opts [Hash] The configuration parameters for the interface. + # + # @option opts value [string] The value of the access vlan. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default + # + # @option opts default [Boolean] The value should be set to default # Default takes precedence over enable. # - # @return [Boolean] True if the commands succeed otherwise False + # @return [Boolean] Returns True if the commands succeed otherwise False. def set_access_vlan(name, opts = {}) cmd = command_builder('switchport access vlan', opts) configure_interface(name, cmd) @@ -335,15 +351,19 @@ def set_access_vlan(name, opts = {}) # Trunk groups not currently set are added and trunk groups # currently configured but not in the passed in value array are removed. # - # @param [String] name The name of the interface to configure - # @param [Hash] opts The configuration parameters for the interface - # @option opts [string] :value Set of values to configure the trunk group - # @option opts [Boolean] :enable If false then the command is + # @param name [String] The name of the interface to configure. + # + # @param opts [Hash] The configuration parameters for the interface. + # + # @option opts value [string] Set of values to configure the trunk group. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default + # + # @option opts default [Boolean] The value should be set to default # Default takes precedence over enable. # - # @return [Boolean] True if the commands succeed otherwise False + # @return [Boolean] Returns True if the commands succeed otherwise False. def set_trunk_groups(name, opts = {}) default = opts.fetch(:default, false) if default @@ -362,12 +382,12 @@ def set_trunk_groups(name, opts = {}) current_value = Set.new get(name)[:trunk_groups] cmds = [] - # Add trunk groups that are not currently in the list + # Add trunk groups that are not currently in the list. value.difference(current_value).each do |group| cmds << "switchport trunk group #{group}" end - # Remove trunk groups that are not in the new list + # Remove trunk groups that are not in the new list. current_value.difference(value).each do |group| cmds << "no switchport trunk group #{group}" end diff --git a/lib/rbeapi/api/tacacs.rb b/lib/rbeapi/api/tacacs.rb index 4b34ae5..308376b 100644 --- a/lib/rbeapi/api/tacacs.rb +++ b/lib/rbeapi/api/tacacs.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # Tacacs provides instance methods to retrieve and set tacacs configuration @@ -45,7 +45,7 @@ class Tacacs < Entity DEFAULT_KEY = nil # Regular expression to extract a tacacs server's attributes from the - # running-configuration text. The explicit [ ] spaces enable line + # running-configuration text. The explicit [ ] spaces enable line # wrapping and indentation with the /x flag. SERVER_REGEXP = /tacacs-server[ ]host[ ]([^\s]+) (?:[ ](single-connection))? @@ -72,7 +72,7 @@ class Tacacs < Entity # timeout: # } # - # @return [Array] Single element Array of resource hashes + # @return [Array] Single element Array of resource hashes. def get global = {} global.merge!(parse_global_timeout) @@ -84,15 +84,13 @@ def get ## # parse_global_key takes a running configuration as a string and # parses out the radius global key and global key format if it exists in - # the configuration. An empty Hash is returned if there is no global key - # configured. The intent of the Hash is to be merged into a property + # the configuration. An empty Hash is returned if there is no global key + # configured. The intent of the Hash is to be merged into a property # hash. # - # @param [String] config The running configuration as a single string. - # # @api private # - # @return [Hash] resource hash attributes + # @return [Hash] Returns the resource hash attributes. def parse_global_key rsrc_hsh = {} (key_format, key) = config.scan(/tacacs-server key (\d+) (\w+)/).first @@ -105,15 +103,13 @@ def parse_global_key ## # parse_global_timeout takes a running configuration as a string # and parses out the tacacs global timeout if it exists in the - # configuration. An empty Hash is returned if there is no global timeout - # value configured. The intent of the Hash is to be merged into a + # configuration. An empty Hash is returned if there is no global timeout + # value configured. The intent of the Hash is to be merged into a # property hash. # - # @param [String] config The running configuration as a single string. - # # @api private # - # @return [Hash] resource hash attributes + # @return [Hash] Returns the resource hash attributes. def parse_global_timeout timeout = config.scan(/tacacs-server timeout (\d+)/).first { timeout: timeout.first.to_i } @@ -127,17 +123,17 @@ def parse_global_timeout # # The resource hash returned contains the following information: # - # * hostname: hostname or ip address, part of the identifier - # * port: (Fixnum) TCP port of the server, part of the identifier - # * key: (String) the key either in plain text or hashed format - # * key_format: (Fixnum) e.g. 0 or 7 - # * timeout: (Fixnum) seconds before the timeout period ends + # * hostname: hostname or ip address, part of the identifier. + # * port: (Fixnum) TCP port of the server, part of the identifier. + # * key: (String) the key either in plain text or hashed format. + # * key_format: (Fixnum) e.g. 0 or 7. + # * timeout: (Fixnum) seconds before the timeout period ends. # * multiplex: (Boolean) true when configured to make requests through a - # single connection + # single connection. # # @api public # - # @return [Array>] Array of resource hashes + # @return [Array>] Array of resource hashes. def servers tuples = config.scan(SERVER_REGEXP) tuples.map do |(host, mplex, vrf, port, tout, keyfm, key)| @@ -154,19 +150,19 @@ def servers end ## - # set_global_key configures the tacacs default key. This method maps to + # set_global_key configures the tacacs default key. This method maps to # the `tacacs-server key` EOS configuration command, e.g. `tacacs-server # key 7 070E234F1F5B4A`. # - # @option opts [String] :key ('070E234F1F5B4A') The key value + # @option opts key [String] ('070E234F1F5B4A') The key value. # - # @option opts [Fixnum] :key_format (7) The key format, 0 for plain text - # and 7 for a hashed value. 7 will be assumed if this option is not + # @option opts key_format [Fixnum] (7) The key format, 0 for plain text + # and 7 for a hashed value. 7 will be assumed if this option is not # provided. # # @api public # - # @return [Boolean] true if no errors + # @return [Boolean] Returns true if no errors. def set_global_key(opts = {}) format = opts[:key_format] key = opts[:key] @@ -176,18 +172,21 @@ def set_global_key(opts = {}) end ## - # set_timeout configures the tacacs default timeout. This method maps to + # set_timeout configures the tacacs default timeout. This method maps to # the `tacacs-server timeout` setting. # - # @param [Hash] opts The configuration parameters - # @option opts [string] :value The value to set the timeout to - # @option :opts [Boolean] :enable If false then the command is + # @param opts [Hash] The configuration parameters. + # + # @option opts value [string] The value to set the timeout to. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default + # + # @option opts default [Boolean] The value should be set to default. # # @api public # - # @return [Boolean] true if no errors + # @return [Boolean] Returns true if no errors. def set_global_timeout(opts = {}) cmd = command_builder('tacacs-server timeout', opts) configure cmd @@ -197,11 +196,25 @@ def set_global_timeout(opts = {}) # update_server configures a tacacs server resource on the target device. # This API method maps to the `tacacs server host` command, e.g. # `tacacs-server host 1.2.3.4 single-connection port 4949 timeout 6 key 7 - # 06070D221D1C5A` + # 06070D221D1C5A`. # # @api public # - # @return [Boolean] true if there are no errors + # @param opts [Hash] The configuration parameters. + # + # @option opts key_format [Integer] The format for the key. + # + # @option opts hostname [String] The host value. + # + # @option opts multiplex [String] Defines single-connection. + # + # @option opts port [String] The port value. + # + # @option opts timeout [String] The timeout value. + # + # @option opts key [String] The key value. + # + # @return [Boolean] Returns true if there are no errors. def update_server(opts = {}) key_format = opts[:key_format] || 7 cmd = "tacacs-server host #{opts[:hostname]}" @@ -218,7 +231,13 @@ def update_server(opts = {}) # # @api public # - # @return [Boolean] true if no errors + # @param opts [Hash] The configuration parameters. + # + # @option hostname [String] The host value. + # + # @option port [String] The port value. + # + # @return [Boolean] Returns true if there are no errors. def remove_server(opts = {}) cmd = "no tacacs-server host #{opts[:hostname]}" cmd << " port #{opts[:port]}" if opts[:port] diff --git a/lib/rbeapi/api/users.rb b/lib/rbeapi/api/users.rb index 593157e..ca0f8d1 100644 --- a/lib/rbeapi/api/users.rb +++ b/lib/rbeapi/api/users.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Users class provides configuration of local user resources for @@ -63,7 +63,7 @@ def initialize(node) end ## - # get returns the local user configuration + # get returns the local user configuration. # # @example # { @@ -76,12 +76,12 @@ def initialize(node) # sshkey: # } # - # @param [String] :name The user name to return a resource for from the + # @param name [String] The user name to return a resource for from the # nodes configuration # # @return [nil, Hash] Returns the user resource as a # Hash. If the specified user name is not found in the nodes current - # configuration a nil object is returned + # configuration a nil object is returned. def get(name) # The regex used here parses the running configuration to find one # username entry. @@ -100,7 +100,7 @@ def get(name) ## # getall returns a collection of user resource hashes from the nodes - # running configuration. The user resource collection hash is keyed + # running configuration. The user resource collection hash is keyed # by the unique user name. # # @example @@ -126,7 +126,7 @@ def get(name) # ... # ] # - # @return [Hash] returns a hash that represents the + # @return [Hash] Returns a hash that represents the # entire user collection from the nodes running configuration. If # there are no user names configured, this method will return an empty # hash. @@ -144,10 +144,10 @@ def getall # # @api private # - # @param [Array] :user An array of values returned from the regular + # @param user [Array] An array of values returned from the regular # expression scan of the nodes configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_user_entry(user) hsh = {} hsh[:name] = user[0] @@ -178,34 +178,34 @@ def parse_user_entry(user) # Optional parameters can be passed in to initialize user name specific # settings. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # username nopassword privilege role # username secret [0,5,sha512] ... # - # @param [String] :name The name of the user to create + # @param name [String] The name of the user to create. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :nopassword Configures the user to be able to - # authenticate without a password challenge + # @option opts nopassword [Boolean] Configures the user to be able to + # authenticate without a password challenge. # - # @option :opts [String] :secret The secret (password) to assign to this - # user + # @option opts secret [String] The secret (password) to assign to this + # user. # - # @option :opts [String] :encryption Specifies how the secret is encoded. + # @option opts encryption [String] Specifies how the secret is encoded. # Valid values are "cleartext", "md5", "sha512". The default is - # "cleartext" + # "cleartext". # - # @option :opts [String] :privilege The privilege value to assign to - # the user + # @option opts privilege [String] The privilege value to assign to + # the user. # - # @option :opts [String] :role The role value to assign to the user + # @option opts role [String] The role value to assign to the user. # - # @option :opts [String] :sshkey The sshkey value to assign to the user + # @option opts sshkey [String] The sshkey value to assign to the user. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(name, opts = {}) cmd = "username #{name}" cmd << " privilege #{opts[:privilege]}" if opts[:privilege] @@ -234,134 +234,134 @@ def create(name, opts = {}) ## # delete will delete an existing user name from the nodes current - # running configuration. If the delete method is called and the user + # running configuration. If the delete method is called and the user # name does not exist, this method will succeed. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # no username # - # @param [String] :name The user name to delete from the node. + # @param name [String] The user name to delete from the node. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete(name) configure("no username #{name}") end ## - # default will configure the user name using the default keyword. This + # default will configure the user name using the default keyword. This # command has the same effect as deleting the user name from the nodes # running configuration. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # default username # - # @param [String] :name The user name to default in the nodes + # @param name [String] The user name to default in the nodes # configuration. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def default(name) configure("default username #{name}") end ## # set_privilege configures the user privilege value for the specified user - # name in the nodes running configuration. If enable is false in the + # name in the nodes running configuration. If enable is false in the # opts keyword Hash then the name value is negated using the no # keyword. If the default keyword is set to true, then the privilege value - # is defaulted using the default keyword. The default keyword takes + # is defaulted using the default keyword. The default keyword takes # precedence over the enable keyword # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # username privilege # no username privilege # default username privilege # - # @param [String] :name The user name to default in the nodes + # @param name [String] The user name to default in the nodes # configuration. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The privilege value to assign to the user + # @option opts value [String] The privilege value to assign to the user. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the user privilege value - # using the default keyword + # @option opts default [Boolean] Configure the user privilege value + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_privilege(name, opts = {}) configure(command_builder("username #{name} privilege", opts)) end ## # set_role configures the user role value for the specified user - # name in the nodes running configuration. If enable is false in the + # name in the nodes running configuration. If enable is false in the # opts keyword Hash then the name value is negated using the no # keyword. If the default keyword is set to true, then the role value - # is defaulted using the default keyword. The default keyword takes + # is defaulted using the default keyword. The default keyword takes # precedence over the enable keyword # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # username role # no username role # default username role # - # @param [String] :name The user name to default in the nodes + # @param name [String] The user name to default in the nodes # configuration. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The role value to assign to the user + # @option opts value [String] The role value to assign to the user. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the user role value - # using the default keyword + # @option opts default [Boolean] Configure the user role value + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_role(name, opts = {}) configure(command_builder("username #{name} role", opts)) end ## # set_sshkey configures the user sshkey value for the specified user - # name in the nodes running configuration. If enable is false in the + # name in the nodes running configuration. If enable is false in the # opts keyword Hash then the name value is negated using the no # keyword. If the default keyword is set to true, then the sshkey value - # is defaulted using the default keyword. The default keyword takes - # precedence over the enable keyword + # is defaulted using the default keyword. The default keyword takes + # precedence over the enable keyword. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # username sshkey # no username sshkey # default username sshkey # - # @param [String] :name The user name to default in the nodes + # @param name [String] The user name to default in the nodes # configuration. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments # - # @option :opts [String] :value The sshkey value to assign to the user + # @option opts value [String] The sshkey value to assign to the user # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the user sshkey value - # using the default keyword + # @option opts default [Boolean] Configure the user sshkey value + # using the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_sshkey(name, opts = {}) configure(command_builder("username #{name} sshkey", opts)) end diff --git a/lib/rbeapi/api/varp.rb b/lib/rbeapi/api/varp.rb index 45a4dcd..69b6292 100644 --- a/lib/rbeapi/api/varp.rb +++ b/lib/rbeapi/api/varp.rb @@ -32,17 +32,17 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Varp class provides an instance for working with the global - # VARP configuration of the node + # VARP configuration of the node. class Varp < Entity ## - # Returns the global VARP configuration from the node + # Returns the global VARP configuration from the node. # # @example # { @@ -58,7 +58,7 @@ class Varp < Entity # } # } # - # @return [Hash] A Ruby hash object that provides the Varp settings as + # @return [Hash] A Ruby hash object that provides the Varp settings as # key / value pairs. def get response = {} @@ -68,17 +68,17 @@ def get end ## - # parse_mac_address parses mac-address values from the provided config + # parse_mac_address parses mac-address values from the provided config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_mac_address(config) # ip virtual-router mac-address value will always - # be stored in aa:bb:cc:dd:ee:ff format + # be stored in aa:bb:cc:dd:ee:ff format. regex = /mac-address ((?:[a-f0-9]{2}:){5}[a-f0-9]{2})$/ mdata = regex.match(config) { mac_address: mdata.nil? ? '' : mdata[1] } @@ -92,15 +92,18 @@ def interfaces end ## - # Configure the VARP virtual-router mac-address value + # Configure the VARP virtual-router mac-address value. # - # @param [Hash] opts The configuration parameters - # @option opts [string] :value The value to set the mac-address to - # @option opts [Boolean] :enable If false then the command is + # @param opts [Hash] The configuration parameters. + # + # @option opts value [string] The value to set the mac-address to. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default # - # @return [Boolean] returns true if the command completed successfully + # @option opts default [Boolean] The value should be set to default. + # + # @return [Boolean] Returns true if the command completed successfully. def set_mac_address(opts = {}) cmd = command_builder('ip virtual-router mac-address', opts) configure(cmd) @@ -109,21 +112,21 @@ def set_mac_address(opts = {}) ## # The VarpInterfaces class provides an instance for working with the global - # VARP interface configuration of the node + # VARP interface configuration of the node. class VarpInterfaces < Entity ## - # Returns a single VARP interface configuration + # Returns a single VARP interface configuration. # # @example # { # "addresses": array # } # - # @param [String] :name The interface name to return the configuration - # values for. This must be the full interface identifier. + # @param name [String] The interface name to return the configuration + # values for. This must be the full interface identifier. # # @return [nil, Hash] A Ruby hash that represents the - # VARP interface configuration. A nil object is returned if the + # VARP interface configuration. A nil object is returned if the # specified interface is not configured def get(name) config = get_block("^interface #{name}") @@ -134,7 +137,7 @@ def get(name) ## # Returns the collection of MLAG interfaces as a hash index by the - # interface name + # interface name. # # @example # { @@ -148,7 +151,7 @@ def get(name) # } # # @return [nil, Hash] A Ruby hash that represents the - # MLAG interface configuration. A nil object is returned if no + # MLAG interface configuration. A nil object is returned if no # interfaces are configured. def getall interfaces = config.scan(/(?<=^interface\s)(Vl.+)$/) @@ -162,14 +165,14 @@ def getall ## # parse_addresses parses ip virtual-router address from the provided - # config + # config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_addresses(config) addrs = config.scan(/(?<=\s{3}ip\svirtual-router\saddress\s).+$/) { addresses: addrs } @@ -181,17 +184,21 @@ def parse_addresses(config) # to the specified VLAN interface. All existing addresses are # removed before the ones in value are added. # - # @param [String] :name The name of the interface. The - # name argument must be the full interface name. Valid interfaces - # are restricted to VLAN interfaces - # @param [Hash] opts The configuration parameters - # @option opts [Array] :value Array of IPv4 addresses to add to + # @param name [String] The name of the interface. The + # name argument must be the full interface name. Valid interfaces + # are restricted to VLAN interfaces. + # + # @param opts [Hash] The configuration parameters. + # + # @option opts value [Array] Array of IPv4 addresses to add to # the virtual router. - # @option opts [Boolean] :enable If false then the command is + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option opts [Boolean] :default The value should be set to default # - # @return [Boolean] True if the commands succeeds otherwise False + # @option opts default [Boolean] The value should be set to default. + # + # @return [Boolean] True if the commands succeeds otherwise False. def set_addresses(name, opts = {}) value = opts[:value] enable = opts.fetch(:enable, true) @@ -215,27 +222,29 @@ def set_addresses(name, opts = {}) end ## - # The add_address method assigns one virtual IPv4 address + # The add_address method assigns one virtual IPv4 address. # - # @param [String] :name The name of the interface. The - # name argument must be the full interface name. Valid interfaces - # are restricted to VLAN interfaces - # @param [string] :address The virtual router address to add + # @param name [String] The name of the interface. The + # name argument must be the full interface name. Valid interfaces + # are restricted to VLAN interfaces. # - # @return [Boolean] True if the commands succeeds otherwise False + # @param value [string] The virtual router address to add. + # + # @return [Boolean] True if the commands succeeds otherwise False. def add_address(name, value) configure(["interface #{name}", "ip virtual-router address #{value}"]) end ## - # The remove_address method removes one virtual IPv4 address + # The remove_address method removes one virtual IPv4 address. + # + # @param name [String] The name of the interface. The + # name argument must be the full interface name. Valid interfaces + # are restricted to VLAN interfaces. # - # @param [String] :name The name of the interface. The - # name argument must be the full interface name. Valid interfaces - # are restricted to VLAN interfaces - # @param [string] :address The virtual router address to remove + # @param value [string] The virtual router address to remove. # - # @return [Boolean] True if the commands succeeds otherwise False + # @return [Boolean] True if the commands succeeds otherwise False. def remove_address(name, value) configure(["interface #{name}", "no ip virtual-router address #{value}"]) diff --git a/lib/rbeapi/api/vlans.rb b/lib/rbeapi/api/vlans.rb index 5567030..ef02a23 100644 --- a/lib/rbeapi/api/vlans.rb +++ b/lib/rbeapi/api/vlans.rb @@ -32,17 +32,17 @@ require 'rbeapi/api' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Vlan class provides a class implementation for working with the - # collection of Vlans on the node. This class presents an abstraction + # collection of Vlans on the node. This class presents an abstraction # of the nodes configured vlan id's from the running configuration. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M class Vlans < Entity ## # get returns the specified vlan resource Hash that represents the @@ -55,12 +55,12 @@ class Vlans < Entity # trunk_groups: array[] Returns the vlan resource as a - # Hash. If the specified vlan id is not found in the nodes current - # configuration a nil object is returned + # Hash. If the specified vlan id is not found in the nodes current + # configuration a nil object is returned. def get(id) config = get_block("vlan #{id}") return nil unless config @@ -73,8 +73,8 @@ def get(id) ## # getall returns the collection of vlan resources from the nodes - # running configuration as a hash. The vlan resource collection - # hash is keyed by the unique vlan id + # running configuration as a hash. The vlan resource collection + # hash is keyed by the unique vlan id. # # @example # { @@ -93,10 +93,10 @@ def get(id) # # @see get Vlan resource example # - # @return [Hash] returns a hash that represents the - # entire vlan collection from the nodes running configuration. If + # @return [Hash] Returns a hash that represents the + # entire vlan collection from the nodes running configuration. If # there are no vlans configured, this method will return an empty - # hash + # hash. def getall vlans = config.scan(/(?<=^vlan\s)\d+$/) vlans.each_with_object({}) do |vid, hsh| @@ -107,13 +107,13 @@ def getall ## # parse_name scans the provided configuration block and parses the - # vlan name value. The vlan name should always return a value - # from the running configuration. The return value is intended to - # be merged into the resource hash + # vlan name value. The vlan name should always return a value + # from the running configuration. The return value is intended to + # be merged into the resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_name(config) mdata = /name ([^\s]+)$/.match(config) { name: mdata[1] } @@ -123,12 +123,12 @@ def parse_name(config) ## # parse_state scans the provided configuration block and parses the # vlan state value. The vlan state should always return a value from - # the nodes running configuration. The return hash is intended to be - # merged into the resource hash + # the nodes running configuration. The return hash is intended to be + # merged into the resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_state(config) mdata = /state (\w+)$/.match(config) { state: mdata[1] } @@ -137,13 +137,13 @@ def parse_state(config) ## # parse_trunk_groups scans the provided configuration block and parses - # the trunk groups. If no trunk groups are found in the nodes + # the trunk groups. If no trunk groups are found in the nodes # running configuration then an empty array is returned as the value. # The return hash is intended to be merged into the resource hash. # # @api private # - # @return [Hash] resource hash attribute + # @return [Hash] Returns the resource hash attribute. def parse_trunk_groups(config) values = config.scan(/trunk group (.+)$/).first values = [] unless values @@ -153,92 +153,92 @@ def parse_trunk_groups(config) ## # create will create a new vlan resource in the nodes current - # configuration with the specified vlan id. If the create method + # configuration with the specified vlan id. If the create method # is called and the vlan id already exists, this method will still # return true. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # vlan # - # @param [String, Integer] :id The vlan id to create on the node. The - # vlan id must be in the valid range of 1 to 4094 + # @param id [String, Integer] The vlan id to create on the node. The + # vlan id must be in the valid range of 1 to 4094. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(id) configure("vlan #{id}") end ## # delete will delete an existing vlan resource from the nodes current - # running configuration. If the delete method is called and the vlan + # running configuration. If the delete method is called and the vlan # id does not exist, this method will succeed. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # no vlan # - # @param [String, Integer] :id The vlan id to delete from the node. The - # id value should be in the valid range of 1 to 4094 + # @param id [String, Integer] The vlan id to delete from the node. The + # id value should be in the valid range of 1 to 4094. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def delete(id) configure("no vlan #{id}") end ## - # default will configure the vlan using the default keyword. This + # default will configure the vlan using the default keyword. This # command has the same effect as deleting the vlan from the nodes # running configuration. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # default vlan # - # @param [String, Integer] :id The vlan id to default in the nodes - # configuration. Ths vid value should be in the valid range of 1 - # to 4094 + # @param id [String, Integer] The vlan id to default in the nodes + # configuration. Ths vid value should be in the valid range of 1 + # to 4094. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def default(id) configure("default vlan #{id}") end ## # set_name configures the name value for the specified vlan id in the - # nodes running configuration. If enable is false in the + # nodes running configuration. If enable is false in the # opts keyword Hash then the name value is negated using the no - # keyword. If the default keyword is set to true, then the name value - # is defaulted using the default keyword. The default keyword takes - # precedence over the enable keyword + # keyword. If the default keyword is set to true, then the name value + # is defaulted using the default keyword. The default keyword takes + # precedence over the enable keyword. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # vlan # name # no name # default name # - # @param [String, Integer] :id The vlan id to apply the configuration - # to. The id value should be in the valid range of 1 to 4094 + # @param id [String, Integer] The vlan id to apply the configuration + # to. The id value should be in the valid range of 1 to 4094. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the vlan name - # to in the node configuration. The name parameter accepts a-z, 0-9 + # @option opts value [String] The value to configure the vlan name + # to in the node configuration. The name parameter accepts a-z, 0-9 # and _. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the vlan name value using - # the default keyword + # @option opts default [Boolean] Configure the vlan name value using + # the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_name(id, opts = {}) cmd = command_builder('name', opts) cmds = ["vlan #{id}", cmd] @@ -247,39 +247,39 @@ def set_name(id, opts = {}) ## # set_state configures the state value for the specified vlan id in - # the nodes running configuration. If enable is set to false in + # the nodes running configuration. If enable is set to false in # the opts keyword Hash then the state value is negated using the no # keyword. If the default keyword is set to true, then the state - # value is defaulted using the default keyword. The default keyword + # value is defaulted using the default keyword. The default keyword # takes precedence over the enable keyword # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # vlan # state [active, suspend] # no state # default state # - # @param [String, Integer] :id The vlan id to apply the configuration - # to. The id value should be in the valid range of 1 to 4094 + # @param id [String, Integer] The vlan id to apply the configuration + # to. The id value should be in the valid range of 1 to 4094. # - # @param [Hash] :opts Optional keyword arguments + # @param opts [Hash] Optional keyword arguments. # - # @option :opts [String] :value The value to configure the vlan state - # to in the node's configuration. Accepted values are 'active' or - # 'suspend' + # @option opts value [String] The value to configure the vlan state + # to in the node's configuration. Accepted values are 'active' or + # 'suspend'. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the vlan state value using - # the default keyword + # @option opts default [Boolean] Configure the vlan state value using + # the default keyword. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. # # @raise [ArgumentError] if the value is not in the accept list of - # values + # values. def set_state(id, opts = {}) value = opts[:value] unless ['active', 'suspend', nil].include?(value) @@ -294,41 +294,41 @@ def set_state(id, opts = {}) ## # add_trunk_group adds a new trunk group value to the specified vlan # id in the nodes running configuration. The trunk group name value - # accepts a-z 0-9 and _ + # accepts a-z 0-9 and _. # - # @version 4.13.7M + # @since version 4.13.7M # - # @commands + # commands # vlan # trunk group # - # @param [String, Integer] :id The vlan id to apply the configuration - # to. the id value should be in the range of 1 to 4094 + # @param id [String, Integer] The vlan id to apply the configuration + # to. the id value should be in the range of 1 to 4094 # - # @param [String] :value The value to add to the vlan id configuration + # @param value [String] The value to add to the vlan id configuration # on the node. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def add_trunk_group(id, value) configure(["vlan #{id}", "trunk group #{value}"]) end ## # remove_trunk_group removes the specified trunk group value from the - # specified vlan id in the node's configuration. If the trunk group + # specified vlan id in the node's configuration. If the trunk group # name does not exist, this method will return success # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # vlan # no trunk group # - # @param [String, Integer] :id The vlan id to apply the configuration - # to. the id value should be in the range of 1 to 4094 + # @param id [String, Integer] The vlan id to apply the configuration + # to. the id value should be in the range of 1 to 4094. # - # @param [String] :value The value to remove from the list of trunk - # group names configured for the specified vlan + # @param value [String] The value to remove from the list of trunk + # group names configured for the specified vlan. # def remove_trunk_group(id, value) configure(["vlan #{id}", "no trunk group #{value}"]) diff --git a/lib/rbeapi/api/vrrp.rb b/lib/rbeapi/api/vrrp.rb index 69cf370..90d3fa0 100644 --- a/lib/rbeapi/api/vrrp.rb +++ b/lib/rbeapi/api/vrrp.rb @@ -32,10 +32,10 @@ require 'rbeapi/api' ## -# Eos is the toplevel namespace for working with Arista EOS nodes +# Eos is the toplevel namespace for working with Arista EOS nodes. module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The Vrrp class manages the set of virtual routers. @@ -74,7 +74,7 @@ def initialize(node) # } # } # - # @param [String] :name The layer 3 interface name. + # @param name [String] The layer 3 interface name. # # @return [nil, Hash] Returns the VRRP resource as a # Hash with the virtual router ID as the key. If the interface name @@ -128,7 +128,7 @@ def get(name) # # @return [nil, Hash] Returns a hash that represents # the entire virtual router IPs collection for all the layer 3 - # interfaces from the nodes running configuration. If there are no + # interfaces from the nodes running configuration. If there are no # virtual routers configured, this method will return an empty hash. def getall interfaces = config.scan(/(?<=^interface\s).+$/) @@ -144,8 +144,9 @@ def getall # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [Hash<'primary_ip', String>] Where string is the IPv4 # address or nil if the value is not set. @@ -166,8 +167,9 @@ def parse_primary_ip(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [Hash<'priority', Integer>] The priority is between # <1-255> or nil if the value is not set. @@ -188,8 +190,9 @@ def parse_priority(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [nil, Hash<'timers_advertise', Integer>] The timers_advertise # is between <1-255> or nil if the value is not set. @@ -210,8 +213,9 @@ def parse_timers_advertise(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [nil, Hash<'preempt', Integer>] The preempt is # between <1-255> or nil if the value is not set. @@ -232,8 +236,9 @@ def parse_preempt(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [Hash<'enable', Boolean>] def parse_enable(config, vrid) @@ -253,8 +258,9 @@ def parse_enable(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [nil, Hash<'secondary_ip', Array>] Returns an empty # array if the value is not set. @@ -275,8 +281,9 @@ def parse_secondary_ip(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [nil, Hash<'secondary_ip', String>] Returns nil if the # value is not set. @@ -297,8 +304,9 @@ def parse_description(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [Hash<'track', Array] Returns an empty array if the # value is not set. An example array of hashes follows: @@ -325,8 +333,9 @@ def parse_track(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [Hash<'ip_version', Integer>] Returns nil if the # value is not set. @@ -348,8 +357,9 @@ def parse_ip_version(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [Hash<'mac_addr_adv_interval', Integer>] Returns nil if the # value is not set. @@ -368,12 +378,13 @@ def parse_mac_addr_adv_interval(config, vrid) ## # parse_preempt_delay_min scans the nodes configurations for the given - # virtual router id and extracts the preempt delay minimum value.. + # virtual router id and extracts the preempt delay minimum value. # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [Hash<'preempt_delay_min', Integer>] Returns nil if the # value is not set. @@ -394,8 +405,9 @@ def parse_preempt_delay_min(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # # @return [Hash<'preempt_delay_reload', Integer>] Returns nil if the # value is not set. @@ -416,10 +428,11 @@ def parse_preempt_delay_reload(config, vrid) # # @api private # - # @param [String] :config The interface config. - # @param [String] :vrid The virtual router id. + # @param config [String] The interface config. + # + # @param vrid [String] The virtual router id. # - # @return [Hash<'delay_reload', Integer>] Returns empty hash if the + # @return [Hash<'delay_reload', Integer>] Returns empty hash if the # value is not set. def parse_delay_reload(config, vrid) match = config.scan(/^\s+vrrp #{vrid} delay reload (\d+)$/) @@ -434,69 +447,69 @@ def parse_delay_reload(config, vrid) ## # create will create a new virtual router ID resource for the interface - # in the nodes current. If the create method is called and the virtual + # in the nodes current. If the create method is called and the virtual # router ID already exists for the interface, this method will still - # return true. Create takes optional parameters, but at least one + # return true. Create takes optional parameters, but at least one # parameter needs to be set or the command will fail. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # vrrp ... # - # @param [String] :name The layer 3 interface name. + # @param name [String] The layer 3 interface name. # - # @param [String] :vrid The virtual router id. + # @param vrid [String] The virtual router id. # - # @param [hash] :opts Optional keyword arguments + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable Enable the virtual router. + # @option opts enable [Boolean] Enable the virtual router. # - # @option :opts [String] :primary_ip The primary IPv4 address. + # @option opts primary_ip [String] The primary IPv4 address. # - # @option :opts [Integer] :priority The priority setting for a virtual + # @option opts priority [Integer] The priority setting for a virtual # router. # - # @option :opts [String] :description Associates a text string to a + # @option opts description [String] Associates a text string to a # virtual router. # - # @option :opts [Array] :secondary_ip The secondary IPv4 + # @option opts secondary_ip [Array] The secondary IPv4 # address to the specified virtual router. # - # @option :opts [Integer] :ip_version Configures the VRRP version for + # @option opts ip_version [Integer] Configures the VRRP version for # the VRRP router. # - # @option :opts [Integer] :timers_advertise The interval between + # @option opts timers_advertise [Integer] The interval between # successive advertisement messages that the switch sends to routers # in the specified virtual router ID. # - # @option :opts [Integer] :mac_addr_adv_interval Specifies interval in + # @option opts mac_addr_adv_interval [Integer] Specifies interval in # seconds between advertisement packets sent to VRRP group members. # - # @option :opts [Boolean] :preempt A virtual router preempt mode + # @option opts preempt [Boolean] A virtual router preempt mode # setting. When preempt mode is enabled, if the switch has a higher # priority it will preempt the current master virtual router. When # preempt mode is disabled, the switch can become the master virtual # router only when a master virtual router is not present on the # subnet, regardless of priority settings. # - # @option :opts [Integer] :preempt_delay_min Interval in seconds between + # @option opts preempt_delay_min [Integer] Interval in seconds between # VRRP preempt event and takeover. Minimum delays takeover when VRRP # is fully implemented. # - # @option :opts [Integer] :preempt_delay_reload Interval in seconds + # @option opts preempt_delay_reload [Integer] Interval in seconds # between VRRP preempt event and takeover. Reload delays takeover # after initialization following a switch reload. # - # @option :opts [Integer] :delay_reload Delay between system reboot and + # @option opts delay_reload [Integer] Delay between system reboot and # VRRP initialization. # - # @option :opts [Array] :track The track hash contains the + # @option opts track [Array] The track hash contains the # name of an interface to track, the action to take on state-change # of the tracked interface, and the amount to decrement the priority. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def create(name, vrid, opts = {}) fail ArgumentError, 'create has no options set' if opts.empty? cmds = [] @@ -555,16 +568,17 @@ def create(name, vrid, opts = {}) # and the virtual router id does not exist on the interface, this # method will succeed. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # no vrrp # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. + # @param name [String] The layer 3 interface name. # - # @return [Boolean] returns true if the command completed successfully + # @param vrid [Integer] The virtual router ID. + # + # @return [Boolean] Returns true if the command completed successfully. def delete(name, vrid) configure_interface(name, "no vrrp #{vrid}") end @@ -577,16 +591,17 @@ def delete(name, vrid) # virtual router id does not exist on the interface, this method will # succeed. # - # @eos_version 4.13.7M + # @since eos_version 4.13.7M # - # @commands + # commands # interface # default vrrp # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def default(name, vrid) configure_interface(name, "default vrrp #{vrid}") end @@ -594,26 +609,28 @@ def default(name, vrid) ## # set_shutdown enables and disables the virtual router. # - # @commands + # commands # interface # {no | default} vrrp shutdown # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. # - # @option :opts [Boolean] :enable If enable is true then the virtual + # @param vrid [Integer] The virtual router ID. + # + # @param opts [hash] Optional keyword arguments. + # + # @option opts enable [Boolean] If enable is true then the virtual # router is administratively enabled for the interface and if enable # is false then the virtual router is administratively disabled # for the interface. Default is true. # - # @option :opts [Boolean] :default Configure shutdown using + # @option opts default [Boolean] Configure shutdown using # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_shutdown(name, vrid, opts = {}) fail 'set_shutdown has the value option set' if opts[:value] - # Shutdown semantics are opposite of enable semantics so invert enable + # Shutdown semantics are opposite of enable semantics so invert enable. enable = opts.fetch(:enable, true) opts.merge!(enable: !enable) cmd = "vrrp #{vrid} shutdown" @@ -623,23 +640,25 @@ def set_shutdown(name, vrid, opts = {}) ## # set_primary_ip sets the primary IP address for the virtual router. # - # @commands + # commands # interface # {no | default} vrrp ip # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. + # + # @param opts [hash] Optional keyword arguments. # - # @option :opts [String] :value The primary IPv4 address. + # @option opts value [String] The primary IPv4 address. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the primary IP address using + # @option opts default [Boolean] Configure the primary IP address using # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_primary_ip(name, vrid, opts = {}) cmd = "vrrp #{vrid} ip" configure_interface(name, command_builder(cmd, opts)) @@ -648,23 +667,25 @@ def set_primary_ip(name, vrid, opts = {}) ## # set_priority sets the priority for a virtual router. # - # @commands + # commands # interface # {no | default} vrrp priority # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. # - # @option :opts [String] :value The priority value. + # @param vrid [Integer] The virtual router ID. # - # @option :opts [Boolean] :enable If false then the command is + # @param opts [hash] Optional keyword arguments. + # + # @option opts value [String] The priority value. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the priority using + # @option opts default [Boolean] Configure the priority using # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_priority(name, vrid, opts = {}) cmd = "vrrp #{vrid} priority" configure_interface(name, command_builder(cmd, opts)) @@ -673,23 +694,25 @@ def set_priority(name, vrid, opts = {}) ## # set_description sets the description for a virtual router. # - # @commands + # commands # interface # {no | default} vrrp description # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. # - # @option :opts [String] :value The description value. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] The description value. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the description using + # @option opts default [Boolean] Configure the description using # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_description(name, vrid, opts = {}) cmd = "vrrp #{vrid} description" configure_interface(name, command_builder(cmd, opts)) @@ -702,11 +725,11 @@ def set_description(name, vrid, opts = {}) # # @api private # - # @param [String] :name The layer 3 interface name. + # @param name [String] The layer 3 interface name. # - # @param [Integer] :vrid The virtual router ID. + # @param vrid [Integer] The virtual router ID. # - # @param [Array] :ip_addrs Array of secondary IPv4 address. + # @param ip_addrs [Array] Array of secondary IPv4 address. # An empty array will remove all secondary IPv4 addresses set for # the virtual router on the specified layer 3 interface. # @@ -744,27 +767,27 @@ def build_secondary_ip_cmd(name, vrid, ip_addrs) private :build_secondary_ip_cmd # set_secondary_ips configures the set of secondary IP addresses - # associated with the virtual router. The ip_addrs value passed - # should be an array of IP Addresses. This method will remove + # associated with the virtual router. The ip_addrs value passed + # should be an array of IP Addresses. This method will remove # secondary IP addresses that are currently set for the virtual # router but not included in the ip_addrs array value passed in. # The method will then add secondary IP addresses that are not # currently set for the virtual router but are included in the # ip_addrs array value passed in. # - # @commands + # commands # interface # {no} vrrp ip secondary # - # @param [String] :name The layer 3 interface name. + # @param name [String] The layer 3 interface name. # - # @param [Integer] :vrid The virtual router ID. + # @param vrid [Integer] The virtual router ID. # - # @param [Array] :ip_addrs Array of secondary IPv4 address. + # @param ip_addrs [Array] Array of secondary IPv4 address. # An empty array will remove all secondary IPv4 addresses set for # the virtual router on the specified layer 3 interface. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_secondary_ip(name, vrid, ip_addrs) cmds = build_secondary_ip_cmd(name, vrid, ip_addrs) return true if cmds.empty? @@ -774,23 +797,25 @@ def set_secondary_ip(name, vrid, ip_addrs) ## # set_ip_version sets the VRRP version for a virtual router. # - # @commands + # commands # interface # {no | default} vrrp ip version # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. # - # @option :opts [String] :value The VRRP version. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] The VRRP version. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the VRRP version using + # @option opts default [Boolean] Configure the VRRP version using # the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_ip_version(name, vrid, opts = {}) cmd = "vrrp #{vrid} ip version" configure_interface(name, command_builder(cmd, opts)) @@ -801,23 +826,25 @@ def set_ip_version(name, vrid, opts = {}) # advertisement messages that the switch sends to routers in the # specified virtual router ID. # - # @commands + # commands # interface # {no | default} vrrp timers advertise # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. + # + # @param opts [hash] Optional keyword arguments. # - # @option :opts [String] :value The timer value in seconds. + # @option opts value [String] The timer value in seconds. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the timer advertise value + # @option opts default [Boolean] Configure the timer advertise value # using the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_timers_advertise(name, vrid, opts = {}) cmd = "vrrp #{vrid} timers advertise" configure_interface(name, command_builder(cmd, opts)) @@ -828,24 +855,26 @@ def set_timers_advertise(name, vrid, opts = {}) # advertisement packets sent to VRRP group members for the # specified virtual router ID. # - # @commands + # commands # interface # {no | default} vrrp mac-address advertisement-interval # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. + # + # @param opts [hash] Optional keyword arguments # - # @option :opts [String] :value The mac address advertisement interval + # @option opts value [String] The mac address advertisement interval # value in seconds. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the timer advertise value + # @option opts default [Boolean] Configure the timer advertise value # using the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_mac_addr_adv_interval(name, vrid, opts = {}) cmd = "vrrp #{vrid} mac-address advertisement-interval" configure_interface(name, command_builder(cmd, opts)) @@ -859,23 +888,25 @@ def set_mac_addr_adv_interval(name, vrid, opts = {}) # when a master virtual router is not present on the subnet, # regardless of priority settings. # - # @commands + # commands # interface # {no | default} vrrp preempt # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. # - # @option :opts [Boolean] :enable If enable is true then the virtual + # @param vrid [Integer] The virtual router ID. + # + # @param opts [hash] Optional keyword arguments. + # + # @option opts enable [Boolean] If enable is true then the virtual # router preempt mode is administratively enabled for the interface # and if enable is false then the virtual router preempt mode is # administratively disabled for the interface. Default is true. # - # @option :opts [Boolean] :default Configure the timer advertise value + # @option opts default [Boolean] Configure the timer advertise value # using the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_preempt(name, vrid, opts = {}) fail 'set_preempt has the value option set' if opts[:value] cmd = "vrrp #{vrid} preempt" @@ -886,23 +917,25 @@ def set_preempt(name, vrid, opts = {}) # set_preempt_delay_min sets the minimum time in seconds for the # virtual router to wait before taking over the active role. # - # @commands + # commands # interface # {no | default} vrrp preempt delay minimum # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. # - # @option :opts [String] :value The preempt delay minimum value. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] The preempt delay minimum value. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the preempt delay minimum + # @option opts default [Boolean] Configure the preempt delay minimum # value using the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_preempt_delay_min(name, vrid, opts = {}) cmd = "vrrp #{vrid} preempt delay minimum" configure_interface(name, command_builder(cmd, opts)) @@ -913,23 +946,25 @@ def set_preempt_delay_min(name, vrid, opts = {}) # only. This delay period applies only to the first interface-up # event after the virtual router has reloaded. # - # @commands + # commands # interface # {no | default} vrrp preempt delay reload # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. # - # @option :opts [String] :value The preempt delay reload value. + # @param opts [hash] Optional keyword arguments. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts value [String] The preempt delay reload value. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the preempt delay reload - # value using the default keyword. + # @option opts default [Boolean] :default Configure the preempt delay + # reload value using the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_preempt_delay_reload(name, vrid, opts = {}) cmd = "vrrp #{vrid} preempt delay reload" configure_interface(name, command_builder(cmd, opts)) @@ -939,23 +974,25 @@ def set_preempt_delay_reload(name, vrid, opts = {}) # set_delay_reload sets the delay between system reboot and VRRP # initialization for the virtual router. # - # @commands + # commands # interface # {no | default} vrrp delay reload # - # @param [String] :name The layer 3 interface name. - # @param [Integer] :vrid The virtual router ID. - # @param [hash] :opts Optional keyword arguments + # @param name [String] The layer 3 interface name. + # + # @param vrid [Integer] The virtual router ID. + # + # @param opts [hash] Optional keyword arguments # - # @option :opts [String] :value The delay reload value. + # @option opts value [String] The delay reload value. # - # @option :opts [Boolean] :enable If false then the command is + # @option opts enable [Boolean] If false then the command is # negated. Default is true. # - # @option :opts [Boolean] :default Configure the delay reload + # @option opts default [Boolean] Configure the delay reload # value using the default keyword. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_delay_reload(name, vrid, opts = {}) cmd = "vrrp #{vrid} delay reload" configure_interface(name, command_builder(cmd, opts)) @@ -968,11 +1005,11 @@ def set_delay_reload(name, vrid, opts = {}) # # @api private # - # @param [String] :name The layer 3 interface name. + # @param name [String] The layer 3 interface name. # - # @param [Integer] :vrid The virtual router ID. + # @param vrid [Integer] The virtual router ID. # - # @param [Array] :tracks Array of a hash of track information. + # @param tracks [Array] Array of a hash of track information. # Hash format: { name: 'Eth2', action: 'decrement', amount: 33 }, # The name and action key are required. The amount key should only # be specified if the action is shutdown. The valid actions are @@ -1010,7 +1047,7 @@ def build_tracks_cmd(name, vrid, tracks) tracks = Set.new tracks - # Get the current tracks set for the virtual router + # Get the current tracks set for the virtual router. # A return of nil means that nothing has been configured for # the virtual router. vrrp = get(name) @@ -1041,27 +1078,27 @@ def build_tracks_cmd(name, vrid, tracks) private :build_tracks_cmd # set_tracks configures the set of track settings associated with - # the virtual router. The tracks value passed should be an array of - # hashes, each hash containing a track entry. This method will remove + # the virtual router. The tracks value passed should be an array of + # hashes, each hash containing a track entry. This method will remove # tracks that are currently set for the virtual router but not included - # in the tracks array value passed in. The method will then add + # in the tracks array value passed in. The method will then add # tracks that are not currently set for the virtual router but are # included in the tracks array value passed in. # - # @commands + # commands # interface # {no} vrrp track [] # - # @param [String] :name The layer 3 interface name. + # @param name [String] The layer 3 interface name. # - # @param [Integer] :vrid The virtual router ID. + # @param vrid [Integer] The virtual router ID. # - # @param [Array] :tracks Array of a hash of track information. + # @param tracks [Array] Array of a hash of track information. # Hash format: { name: 'Eth2', action: 'decrement', amount: 33 }, # An empty array will remove all tracks set for # the virtual router on the specified layer 3 interface. # - # @return [Boolean] returns true if the command complete successfully + # @return [Boolean] Returns true if the command complete successfully. def set_tracks(name, vrid, tracks) cmds = build_tracks_cmd(name, vrid, tracks) return true if cmds.empty? diff --git a/lib/rbeapi/utils.rb b/lib/rbeapi/utils.rb index d5337ab..663b001 100644 --- a/lib/rbeapi/utils.rb +++ b/lib/rbeapi/utils.rb @@ -33,19 +33,19 @@ require 'syslog' ## -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi ## - # Utils module + # Utils module. module Utils ## # Iterates through a hash structure and converts all of the keys # to symbols. # - # @param [Hash] :value The hash structure to convert the keys + # @param value [Hash] The hash structure to convert the keys. # # @return [Hash] An updated hash structure with all keys converted to - # symboles + # symboles. def self.transform_keys_to_symbols(value) return value unless value.is_a?(Hash) hash = value.each_with_object({}) do |(k, v), hsh| @@ -56,11 +56,11 @@ def self.transform_keys_to_symbols(value) end ## - # Returns a class object from a string capable of being instatiated + # Returns a class object from a string capable of being instatiated. # - # @param [String] :name The name of the class to return a constant for + # @param name [String] The name of the class to return a constant for. # - # @return [Object] Returns a a class object that can be instatiated + # @return [Object] Returns a a class object that can be instatiated. def self.class_from_string(name) name.split('::').inject(Object) do |mod, cls| mod.const_get(cls) @@ -70,7 +70,7 @@ def self.class_from_string(name) ## # Syslogs a warning message. # - # @param [String] :message The message to log. + # @param message [String] The message to log. def self.syslog_warning(message) Syslog.open('rbeapi', Syslog::LOG_PID) { |s| s.warning message } end diff --git a/lib/rbeapi/version.rb b/lib/rbeapi/version.rb index 53c83dc..9c4cb0b 100644 --- a/lib/rbeapi/version.rb +++ b/lib/rbeapi/version.rb @@ -31,7 +31,7 @@ # # # -# Rbeapi toplevel namespace +# Rbeapi toplevel namespace. module Rbeapi VERSION = '0.5.0' end From 84d7320c247ce2549fae5b40080374d77350683e Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Tue, 19 Jan 2016 17:10:38 -0700 Subject: [PATCH 103/110] Update doc. --- lib/rbeapi/api/system.rb | 77 +++++++------ lib/rbeapi/client.rb | 233 ++++++++++++++++++++++----------------- lib/rbeapi/eapilib.rb | 125 ++++++++++++--------- 3 files changed, 243 insertions(+), 192 deletions(-) diff --git a/lib/rbeapi/api/system.rb b/lib/rbeapi/api/system.rb index 1d9abfd..db775f4 100644 --- a/lib/rbeapi/api/system.rb +++ b/lib/rbeapi/api/system.rb @@ -35,11 +35,11 @@ # Rbeapi toplevel namespace module Rbeapi ## - # Api is module namespace for working with the EOS command API + # Api is module namespace for working with the EOS command API. module Api ## # The System class configures the node system services such as - # hostname and domain name + # hostname and domain name. class System < Entity def initialize(node) super(node) @@ -47,7 +47,7 @@ def initialize(node) end ## - # Returns the system settings for hostname, iprouting, and banners + # Returns the system settings for hostname, iprouting, and banners. # # @example # { @@ -57,7 +57,7 @@ def initialize(node) # banner_login: # } # - # @return [Hash] A Ruby hash object that provides the system settings as + # @return [Hash] A Ruby hash object that provides the system settings as # key/value pairs. def get response = {} @@ -68,14 +68,14 @@ def get end ## - # parse_hostname parses hostname values from the provided config + # parse_hostname parses hostname values from the provided config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] The resource hash attribute. def parse_hostname(config) mdata = /(?<=^hostname\s)(.+)$/.match(config) { hostname: mdata.nil? ? '' : mdata[1] } @@ -83,14 +83,14 @@ def parse_hostname(config) private :parse_hostname ## - # parse_iprouting parses ip routing from the provided config + # parse_iprouting parses ip routing from the provided config. # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute + # @return [Hash] The resource hash attribute. def parse_iprouting(config) mdata = /no\sip\srouting/.match(config) { iprouting: mdata.nil? ? true : false } @@ -103,10 +103,10 @@ def parse_iprouting(config) # # @api private # - # @param [String] :config The configuration block returned - # from the node's running configuration + # @param config [String] The configuration block returned + # from the node's running configuration. # - # @return [Hash] resource hash attribute. If the + # @return [Hash] The resource hash attribute. If the # banner is not set it will return a value of None for that key. def parse_banners(config) motd_value = login_value = '' @@ -123,49 +123,58 @@ def parse_banners(config) private :parse_banners ## - # Configures the system hostname value in the running-config + # Configures the system hostname value in the running-config. # - # @param [Hash] opts The configuration parameters - # @option opts [string] :value The value to set the hostname to - # @option :opts [Boolean] :enable If false then the command is + # @param opts [Hash] The configuration parameters. + # + # @option opts value [string] The value to set the hostname to. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option :opts [Boolean] :default If true configure the command using + # + # @option opts default [Boolean] If true configure the command using # the default keyword. Default is false. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_hostname(opts = {}) cmd = command_builder('hostname', opts) configure(cmd) end ## - # Configures the state of global ip routing + # Configures the state of global ip routing. # - # @param [Hash] opts The configuration parameters - # @option :opts [Boolean] :enable True if ip routing should be enabled + # @param opts [Hash] The configuration parameters. + # + # @option opts enable [Boolean] True if ip routing should be enabled # or False if ip routing should be disabled. Default is true. - # @option :opts [Boolean] :default If true configure the command using + # + # @option opts default [Boolean] If true configure the command using # the default keyword. Default is false. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_iprouting(opts = {}) cmd = command_builder('ip routing', opts) configure(cmd) end ## - # Configures system banners + # Configures system banners. # - # @param [String] :banner_type banner to be changed (likely either - # login or motd) - # @param [Hash] opts The configuration parameters - # @option opts [string] :value The value to set for the banner. - # @option :opts [Boolean] :enable If false then the command is + # @param banner_type [String] Banner to be changed (likely either + # login or motd). + # + # @param opts [Hash] The configuration parameters. + # + # @option opts value [string] The value to set for the banner. + # + # @option opts enable [Boolean] If false then the command is # negated. Default is true. - # @option :opts [Boolean] :default If true configure the command using + # + # @option opts default [Boolean] If true configure the command using # the default keyword. Default is false. # - # @return [Boolean] returns true if the command completed successfully + # @return [Boolean] Returns true if the command completed successfully. def set_banner(banner_type, opts = {}) value = opts[:value] cmd_string = "banner #{banner_type}" diff --git a/lib/rbeapi/client.rb b/lib/rbeapi/client.rb index e11c53a..fe5ebb8 100644 --- a/lib/rbeapi/client.rb +++ b/lib/rbeapi/client.rb @@ -50,12 +50,12 @@ class << self 'socket' => 'Rbeapi::Eapilib::SocketEapiConnection' } ## - # Returns the currently loaded config object. This function will + # Returns the currently loaded config object. This function will # create a new instance of the config object if one doesn't already - # exist + # exist. # # @return [Config] Returns an instance of Config used for working - # with the eapi.conf file + # with the eapi.conf file. def config return @config if @config @config = Config.new @@ -64,11 +64,11 @@ def config ## # load_config overrides the default conf file loaded in the config - # instances using the supplied conf argument as the conf file. This + # instances using the supplied conf argument as the conf file. This # method will clear out an previously loaded configuration and replace # all entries with the contents of the supplied file. # - # @param [String] :conf The full path to the conf file to load into + # @param conf [String] The full path to the conf file to load into # the config instance. def load_config(conf) config.read(conf) @@ -76,15 +76,15 @@ def load_config(conf) ## # Returns the configuration options for the named connection from - # the loaded configuration. The configuration name is specified as + # the loaded configuration. The configuration name is specified as # the string right of the colon in the section name. # - # @param [String] :name The connection name to return from the loaded - # configuration + # @param name [String] The connection name to return from the loaded + # configuration. # # @return [Hash, nil] This method will return the configuration hash for - # the named configuration if found. If the name is not found, then - # nil is returned + # the named configuration if found. If the name is not found, then + # nil is returned. def config_for(name) config.get_connection(name) end @@ -93,11 +93,11 @@ def config_for(name) # Retrieves the node config from the loaded configuration file and # returns a Rbeapi::Node instance for working with the remote node. # - # @param [String] :name The named configuration to use for creating the - # connection to the remote node + # @param name [String] The named configuration to use for creating the + # connection to the remote node. # - # @return [Rbeapi::Node, nil] Returns an instance of Rbeapi::Node. If - # the named configuration is not found then nil is returned + # @return [Rbeapi::Node, nil] Returns an instance of Rbeapi::Node. If + # the named configuration is not found then nil is returned. def connect_to(name) config_entry = config_for(name) return nil unless config_entry @@ -114,26 +114,32 @@ def connect_to(name) ## # Builds a connection object to a remote node using the specified - # options and return an instance of Rbeapi::Connection. All + # options and return an instance of Rbeapi::Connection. All # configuration options can be passed via the :opts param. # - # @param [Hash] :opts the options to create a message with - # @option :opts [String] :host The IP address or hostname of the remote - # eAPI endpoint - # @option :opts [String] :username The username to use to authenticate - # the eAPI connection with - # @option :opts [String] :password The password to use to authenticate - # the eAPI connection with - # @option :opts [String] :enablepwd The enable password (if defined) to - # pass to the remote node to enter privilege mode - # @option :opts [String] :use_ssl Specifies whether or not to use the - # HTTP or HTTPS protocol - # @option :opts [String] :port The port to connect to. If not specified + # @param opts [Hash] the options to create a message with. + # + # @option opts host [String] The IP address or hostname of the remote + # eAPI endpoint. + # + # @option opts username [String] The username to use to authenticate + # the eAPI connection with. + # + # @option opts password [String] The password to use to authenticate + # the eAPI connection with. + # + # @option opts enablepwd [String] The enable password (if defined) to + # pass to the remote node to enter privilege mode. + # + # @option opts use_ssl [String] Specifies whether or not to use the + # HTTP or HTTPS protocol. + # + # @option opts port [String] The port to connect to. If not specified # The port is automatically determined based on the protocol used - # (443 for https, 80 for http) + # (443 for https, 80 for http). # # @return [Rbeapi::Connection] Returns an instance of Rbeapi::Connection - # using the specified configuration options + # using the specified configuration options. def connect(opts = {}) transport = opts.fetch(:transport, DEFAULT_TRANSPORT) make_connection(transport, opts) @@ -143,10 +149,11 @@ def connect(opts = {}) # Creates a connection instance that can either be used directly or # passed to a Node instance. # - # @params [String] :transport The name of the transport to create. - # @params [Hash] :opts The options used to create the transport + # @param transport [String] The name of the transport to create. # - # @return [Rbeapi::EapiConnection] A instance of a connection object + # @param opts [Hash] The options used to create the transport. + # + # @return [Rbeapi::EapiConnection] A instance of a connection object. def make_connection(transport, opts = {}) klass = TRANSPORTS.fetch(transport) cls = Rbeapi::Utils.class_from_string(klass) @@ -155,7 +162,7 @@ def make_connection(transport, opts = {}) end ## - # The Config class holds the loaded configuration file data. It is a + # The Config class holds the loaded configuration file data. It is a # subclass of IniFile. class Config < IniFile CONFIG_SEARCH_PATH = ['/mnt/flash/eapi.conf'] @@ -164,7 +171,9 @@ class Config < IniFile # The Config class will automatically search for a filename to load # (if none provided) and load the data when the object is instantiated. # - # @param [String] :filename The full path to the filename to load. If + # @param opts [Hash] The initialization parameters. + # + # @option opts filename [String] The full path to the filename to load. If # the filename is not provided, then this class will attempt to find # a valid conf file using the CONFIG_SEARCH_PATH. def initialize(opts = {}) @@ -175,13 +184,14 @@ def initialize(opts = {}) ## # This private method automatically finds and loads the conf file - # into the instance using the class variable CONFIG_SEARCH_PATH. The - # connections should be retrieved using the get_connection method + # into the instance using the class variable CONFIG_SEARCH_PATH. The + # connections should be retrieved using the get_connection method. + # + # @param opts [Hash] The options for specifying the message. # - # @param [Hash] :opts The options for specifying the message - # @option :opts [String] :filename The full path to the filename - # to load. Using this option eliminates the use of the - # search path + # @option opts filename [String] The full path to the filename + # to load. Using this option eliminates the use of the + # search path. def autoload(opts = {}) search_path = CONFIG_SEARCH_PATH.dup # Add the home directory path if the HOME environement var is defined. @@ -202,10 +212,10 @@ def autoload(opts = {}) ## # This method will read the specified filename and load its contents - # into the instance. It will also add the default localhost entry - # if it doesn't exist in the conf file + # into the instance. It will also add the default localhost entry + # if it doesn't exist in the conf file. # - # @param [String] :filename The full path to the filename to load + # @param filename [String] The full path to the filename to load. def read(filename) begin super(filename: filename) @@ -215,7 +225,7 @@ def read(filename) end # For each section, if the host parameter is omitted then the - # connection name is used + # connection name is used. sections.each do |name| if name.start_with?('connection:') conn = self["#{name}"] @@ -228,13 +238,14 @@ def read(filename) end ## - # This method will cause the config to be loaded. The process of + # This method will cause the config to be loaded. The process of # finding the configuration will be repeated so it is possible a # different conf file could be chosen if the original file was - # removed or a new file added higher on the search priority list + # removed or a new file added higher on the search priority list. # - # @param [Hash] :opts The options for specifying the message - # @opton :opts [String] :filename The full path to the file to load + # @param opts [Hash] The options for specifying the message. + # + # @option opts filename [String] The full path to the file to load. def reload(opts = {}) autoload opts end @@ -244,12 +255,12 @@ def reload(opts = {}) # connection is not found matching the name and if a default # connection has been specified then return the default connection. # - # @param [String] :name The name of the connection to return from - # the configuration. This should be the string right of the : - # in the config section header + # @param name [String] The name of the connection to return from + # the configuration. This should be the string right of the : + # in the config section header. # # @return [nil, Hash Returns a hash of the connection - # properties from the loaded config. This method will return nil + # properties from the loaded config. This method will return nil # if the connection name is not found. def get_connection(name) return self["connection:#{name}"] \ @@ -259,11 +270,12 @@ def get_connection(name) end ## - # Adds a new connection section to the current configuration + # Adds a new connection section to the current configuration. # - # @param [String] :name The name of the connection to add to the + # @param name [String] The name of the connection to add to the # configuration. - # @param [Hash] :values The properties for the connection + # + # @param values [Hash] The properties for the connection. def add_connection(name, values) self["connection:#{name}"] = values nil @@ -273,7 +285,7 @@ def add_connection(name, values) ## # The Node object provides an instance for sending and receiving messages # with a specific EOS device. The methods provided in this class allow - # for handling both enable mode and config mode commands + # for handling both enable mode and config mode commands. class Node attr_reader :connection attr_accessor :dry_run @@ -281,7 +293,7 @@ class Node ## # Save the connection and set autorefresh to true. # - # @param [Rbeapi::Eapilib::EapiConnection] :connection An instance of + # @param connection [Rbeapi::Eapilib::EapiConnection] An instance of # EapiConnection used to send and receive eAPI formatted messages def initialize(connection) @connection = connection @@ -291,55 +303,58 @@ def initialize(connection) ## # Provides access the nodes running-configuration. This is a lazily - # loaded memoized property for working with the node configuration + # loaded memoized property for working with the node configuration. # - # @return [String] The node's running-config as a string + # @return [String] The node's running-config as a string. def running_config return @running_config if @running_config @running_config = get_config(params: 'all', as_string: true) end ## - # Provides access to the nodes startup-configuration. This is a lazily - # loaded memoized property for working with the nodes startup config + # Provides access to the nodes startup-configuration. This is a lazily + # loaded memoized property for working with the nodes startup config. # - # @return [String] The node's startup-config as a string + # @return [String] The node's startup-config as a string. def startup_config return @startup_config if @startup_config @startup_config = get_config(config: 'startup-config', as_string: true) end ## - # Configures the node instance to use an enable password. EOS can be + # Configures the node instance to use an enable password. EOS can be # configured to require a second layer of authentication when putting - # the session into enable mode. The password supplied will be used to + # the session into enable mode. The password supplied will be used to # authenticate the session to enable mode if necessary. # - # @param [String] :password The value of the enable password + # @param password [String] The value of the enable password. def enable_authentication(password) @enablepwd = password end ## # The config method is a convenience method that will handling putting - # the switch into config mode prior to executing commands. The method + # the switch into config mode prior to executing commands. The method # will insert 'config' at the top of the command stack and then pop # the empty hash from the response output before return the array - # to the caller + # to the caller. # - # @param [Array] :commands An ordered list of commands to + # @param commands [Array] An ordered list of commands to # execute. A string in the list is an eapi command. A Hash entry in the # array consists of the following key value pairs: # { cmd: 'eapi command', input: 'text passed into stdin for command' } - # @option :opts [String] :encoding The encoding scheme to use for sending - # and receive eAPI messages. Valid values are json and text. The - # default value is json - # @option :opts [Float] :open_timeout Number of seconds to wait for the + # + # @option opts encoding [String] The encoding scheme to use for sending + # and receive eAPI messages. Valid values are json and text. The + # default value is json. + # + # @option opts open_timeout [Float] Number of seconds to wait for the # eAPI connection to open. - # @option :opts [Float] :read_timeout Number of seconds to wait for one + # + # @option opts read_timeout [Float] Number of seconds to wait for one # block of eAPI results to be read (via one read(2) call). # - # @return [Array] ordered list of output from commands + # @return [Array] Ordered list of output from commands. def config(commands, opts = {}) commands = [*commands] unless commands.respond_to?('each') @@ -364,19 +379,22 @@ def config(commands, opts = {}) # # rubocop:disable Metrics/MethodLength # - # @param [Array] :commands An ordered list of commands to + # @param commands [Array] An ordered list of commands to # execute. A string in the list is an eapi command. A Hash entry in the # array consists of the following key value pairs: # { cmd: 'eapi command', input: 'text passed into stdin for command' } - # @option :opts [String] :encoding The encoding scheme to use for sending - # and receive eAPI messages. Valid values are json and text. The - # default value is json - # @option :opts [Float] :open_timeout Number of seconds to wait for the + # + # @option opts encoding [String] The encoding scheme to use for sending + # and receive eAPI messages. Valid values are json and text. The + # default value is json. + # + # @option opts open_timeout [Float] Number of seconds to wait for the # eAPI connection to open. - # @option :opts [Float] :read_timeout Number of seconds to wait for one + # + # @option opts read_timeout [Float] Number of seconds to wait for one # block of eAPI results to be read (via one read(2) call). # - # @return [Array] ordered list of output from commands + # @return [Array] Ordered list of output from commands. def enable(commands, opts = {}) commands = [*commands] unless commands.respond_to?('each') @@ -407,16 +425,18 @@ def enable(commands, opts = {}) end ## - # Returns a response object from a call to the enable method. This + # Returns a response object from a call to the enable method. This # private method is an internal method to ensure consistency in the - # return message format + # return message format. + # + # @param command [String] The command send to the node. # - # @param [String] :command The command send to the node - # @param [Hash] :response The response returned from the eAPI call - # @param [String] :encoding The encoding scheme used in the response - # which should be either json or text + # @param result [Hash] The response returned from the eAPI call. # - # @return [Hash] A Ruby hash object + # @param encoding [String] The encoding scheme used in the response + # which should be either json or text. + # + # @return [Hash] A Ruby hash object. def make_response(command, result, encoding) { command: command, result: result, encoding: encoding } end @@ -424,17 +444,20 @@ def make_response(command, result, encoding) ## # This method will send the ordered list of commands to the destination - # node using the transport. It is also response for inserting enable - # onto the command stack and popping the enable result on the response + # node using the transport. It is also response for inserting enable + # onto the command stack and popping the enable result on the response. # - # @param [Array] :commands The ordered list of commands to send to the + # @param commands [Array] The ordered list of commands to send to the # destination node. - # @option :opts [String] :encoding The encoding scheme to use for - # sending and receive eAPI requests. This argument is optional. - # Valid values include json or text. The default is json - # @option :opts [Float] :open_timeout Number of seconds to wait for the + # + # @option opts encoding [String] The encoding scheme to use for + # sending and receive eAPI requests. This argument is optional. + # Valid values include json or text. The default is json. + # + # @option opts open_timeout [Float] Number of seconds to wait for the # eAPI connection to open. - # @option :opts [Float] :read_timeout Number of seconds to wait for one + # + # @option opts read_timeout [Float] Number of seconds to wait for one # block of eAPI results to be read (via one read(2) call). def run_commands(commands, opts = {}) encoding = opts.fetch(:encoding, 'json') @@ -458,12 +481,14 @@ def run_commands(commands, opts = {}) # and return it in full text. # # @param [Hash] opts the options to create a message with - # @option :opts [String] :config The configuration instance to return from - # the node. Valid values are 'running-config' and 'startup-config'. If - # no value is specified, then 'running-config' is used - # @ :opts [String] :param Additional parameters to append to the - # retrieving the configuration. Valid values depend on the config - # file requested + # + # @option opts config [String] The configuration instance to return from + # the node. Valid values are 'running-config' and 'startup-config'. If + # no value is specified, then 'running-config' is used. + # + # @option opts param [String] Additional parameters to append to the + # retrieving the configuration. Valid values depend on the config + # file requested. # # running-config params # all Configuration with defaults @@ -478,7 +503,7 @@ def run_commands(commands, opts = {}) # interfaces Filter config to include only the given interfaces # section Display sections containing matching commands # - # @return [String] the specified configuration as text + # @return [String] The specified configuration as text. def get_config(opts = {}) config = opts.fetch(:config, 'running-config') params = opts.fetch(:params, '') @@ -490,7 +515,7 @@ def get_config(opts = {}) ## # Returns an API module for working with the active configuration - # of the node + # of the node. def api(name, opts = {}) path = opts.fetch(:path, 'rbeapi/api') namespace = opts.fetch(:namespace, 'Rbeapi::Api') diff --git a/lib/rbeapi/eapilib.rb b/lib/rbeapi/eapilib.rb index 701411e..e548887 100644 --- a/lib/rbeapi/eapilib.rb +++ b/lib/rbeapi/eapilib.rb @@ -58,8 +58,8 @@ class EapiError < StandardError # The EapiError class provides one property for holding the set of # commands issued when the error was generated. # - # @param [String] :message The error message to return from raising - # the exception + # @param message [String] The error message to return from raising + # the exception. def initalize(message) @message = message @commands = nil @@ -77,12 +77,14 @@ class CommandError < EapiError ## # The exception contains the eAPI error code and error text. # - # @param [String] :message The error message to return from raising - # this exception - # @param [Integer] :code The error code associated with the error - # message to be raised - # @param [Array] :commands The list of commands that were used in the - # eAPI request message + # @param message [String] The error message to return from raising + # this exception. + # + # @param code [Integer] The error code associated with the error + # message to be raised. + # + # @param commands [Array] The list of commands that were used in the + # eAPI request message. def initialize(message, code, commands = nil) @error_code = code @error_text = message @@ -101,12 +103,14 @@ class ConnectionError < EapiError ## # The exception contains the eAPI error code and error text. # - # @param [String] :message The error message to return from raising - # this exception - # @param [String] :connection_type The optional connection_type of - # the instance - # @param [Array] :commands The list of commands that were used in the - # eAPI request message + # @param message [String] The error message to return from raising + # this exception. + # + # @param connection_type [String] The optional connection_type of + # the instance. + # + # @param commands [Array] The list of commands that were used in the + # eAPI request message. def initialize(message, connection_type = nil, commands = nil) @connection_type = connection_type @commands = commands @@ -117,8 +121,8 @@ def initialize(message, connection_type = nil, commands = nil) ## # The EapiConnection provides a base class for building eAPI connection # instances with a specific transport for connecting to Arista EOS - # devices. This class handles sending and receiving eAPI calls using - # JSON-RPC. This class should not need to be directly instantiated. + # devices. This class handles sending and receiving eAPI calls using + # JSON-RPC. This class should not need to be directly instantiated. class EapiConnection attr_reader :error attr_reader :open_timeout @@ -127,8 +131,8 @@ class EapiConnection ## # The connection contains the transport. # - # @param [Net::HTTP] :transport The HTTP transport to use for sending - # and receive eAPI request and response messages + # @param transport [Net::HTTP] The HTTP transport to use for sending + # and receive eAPI request and response messages. def initialize(transport) @transport = transport @error = nil @@ -136,13 +140,16 @@ def initialize(transport) ## # Configures the connection authentication values (username and - # password). The authentication values are used to authenticate - # the eAPI connection. Using authentication is only required for - # connections that use Http or Https transports + # password). The authentication values are used to authenticate + # the eAPI connection. Using authentication is only required for + # connections that use Http or Https transports. # - # @options :opts [String] :username The username to use to + # @param opts [Hash] The authentication parameters. + # + # @option opts username [String] The username to use to # authenticate with eAPI. Default is 'admin'. - # @options :opts [String] :password The password to use to + # + # @option opts password [String] The password to use to # authenticate with eAPI. Default is ''. def authentication(opts = {}) @username = opts.fetch(:username, 'admin') @@ -151,12 +158,13 @@ def authentication(opts = {}) ## # Configures the connection timeout values (open_timeout and - # read_timeout). The timeout values are used for the eAPI + # read_timeout). The timeout values are used for the eAPI # connection. # - # @option :opts [Float] :open_timeout Number of seconds to wait for the + # @option opts open_timeout [Float] Number of seconds to wait for the # eAPI connection to open. Default is DEFAULT_HTTP_OPEN_TIMEOUT. - # @option :opts [Float] :read_timeout Number of seconds to wait for one + # + # @option opts read_timeout [Float] Number of seconds to wait for one # block of eAPI results to be read (via one read(2) call). Default # is DEFAULT_HTTP_READ_TIMEOUT. def timeouts(opts = {}) @@ -181,18 +189,21 @@ def timeouts(opts = {}) # "id": # } # - # @param [Array] :commands The ordered set of commands that should - # be included in the eAPI request - # @param [Hash] :opts Optional keyword arguments - # @option :opts [String] :id The value to use for the eAPI request - # id. If not provided,the object_id for the connection instance - # will be used - # @option :opts [String] :format The encoding formation to pass in - # the eAPI request. Valid values are json or text. The default - # value is json + # @param commands [Array] The ordered set of commands that should + # be included in the eAPI request. + # + # @param opts [Hash] Optional keyword arguments. + # + # @option opts id [String] The value to use for the eAPI request + # id. If not provided,the object_id for the connection instance + # will be used. + # + # @option opts format [String] The encoding formation to pass in + # the eAPI request. Valid values are json or text. The default + # value is json. # # @return [Hash] Returns a Ruby hash of the request message that is - # suitable to be JSON encoded and sent to the destination node + # suitable to be JSON encoded and sent to the destination node. def request(commands, opts = {}) id = opts.fetch(:reqid, object_id) format = opts.fetch(:format, 'json') @@ -205,7 +216,7 @@ def request(commands, opts = {}) ## # This method will send the request to the node over the specified # transport and return a response message with the contents from - # the eAPI response. eAPI responds to request messages with either + # the eAPI response. eAPI responds to request messages with either # a success message or failure message. # # @example eAPI Response - success @@ -242,16 +253,18 @@ def request(commands, opts = {}) # "id": # } # - # @param [Hash] :data A hash containing the body of the request - # message. This should be a valid eAPI request message. - # @option :opts [Float] :open_timeout Number of seconds to wait for the + # @param data [Hash] A hash containing the body of the request + # message. This should be a valid eAPI request message. + # + # @option opts open_timeout [Float] Number of seconds to wait for the # eAPI connection to open. - # @option :opts [Float] :read_timeout Number of seconds to wait for one + # + # @option opts read_timeout [Float] Number of seconds to wait for one # block of eAPI results to be read (via one read(2) call). # - # @return [Hash] returns the response message as a Ruby hash object + # @return [Hash] Returns the response message as a Ruby hash object. # - # @raises [CommandError] Raised if an eAPI failure response is return + # @raise [CommandError] Raised if an eAPI failure response is return # from the destination node. def send(data, opts) request = Net::HTTP::Post.new('/command-api') @@ -283,24 +296,28 @@ def send(data, opts) # Executes the commands on the destination node and returns the # response from the node. # - # @param [Array] :commands The ordered list of commands to execute + # @param commands [Array] The ordered list of commands to execute # on the destination node. - # @param [Hash] :opts Optional keyword arguments - # @option :opts [String] :encoding Used to specify the encoding to be - # used for the response. Valid encoding values are json or text - # @option :opts [Float] :open_timeout Number of seconds to wait for the + # + # @param opts [Hash] Optional keyword arguments. + # + # @option opts encoding [String] Used to specify the encoding to be + # used for the response. Valid encoding values are json or text. + # + # @option opts open_timeout [Float] Number of seconds to wait for the # eAPI connection to open. - # @option :opts [Float] :read_timeout Number of seconds to wait for one + # + # @option opts read_timeout [Float] Number of seconds to wait for one # block of eAPI results to be read (via one read(2) call). # - # @returns [Array] This method will return the array of responses + # @return [Array] This method will return the array of responses # for each command executed on the node. # - # @raises [CommandError] Raises a CommandError if rescued from the - # send method and adds the list of commands to the exception message + # @raise [CommandError] Raises a CommandError if rescued from the + # send method and adds the list of commands to the exception message. # - # @raises [ConnectionError] Raises a ConnectionError if rescued and - # adds the list of commands to the exception message + # @raise [ConnectionError] Raises a ConnectionError if rescued and + # adds the list of commands to the exception message. def execute(commands, opts = {}) @error = nil request = request(commands, opts) From aac94863ea9a4c39888a4a2144aa277099cf719b Mon Sep 17 00:00:00 2001 From: Hunt Burdick Date: Fri, 22 Jan 2016 18:11:07 -0700 Subject: [PATCH 104/110] Update documentation. --- guide/api.rst | 5894 ++++++++++++++++++++++++++++++++ guide/contributing.rst | 6 + guide/cookbook.rst | 4 - guide/developing.rst | 4 - guide/faq.rst | 4 - guide/getting-started.rst | 134 + guide/index.rst | 8 +- guide/installation.rst | 57 +- guide/license.rst | 15 +- guide/overview.rst | 7 +- guide/quickstart.rst | 4 - guide/testing.rst | 6 +- guide/troubleshooting.rst | 1 - guide/upgrading.rst | 10 + lib/rbeapi/api/aaa.rb | 6 +- lib/rbeapi/api/acl.rb | 6 +- lib/rbeapi/api/bgp.rb | 34 +- lib/rbeapi/api/dns.rb | 4 +- lib/rbeapi/api/ipinterfaces.rb | 10 +- lib/rbeapi/api/logging.rb | 6 +- lib/rbeapi/api/mlag.rb | 12 +- lib/rbeapi/api/ntp.rb | 4 +- lib/rbeapi/api/radius.rb | 6 +- lib/rbeapi/api/routemaps.rb | 14 +- lib/rbeapi/api/snmp.rb | 14 +- lib/rbeapi/api/staticroutes.rb | 4 +- lib/rbeapi/api/stp.rb | 2 +- lib/rbeapi/api/switchports.rb | 2 +- lib/rbeapi/api/users.rb | 12 +- lib/rbeapi/api/vlans.rb | 14 +- lib/rbeapi/api/vrrp.rb | 32 +- 31 files changed, 6214 insertions(+), 122 deletions(-) create mode 100644 guide/api.rst create mode 100644 guide/contributing.rst delete mode 100644 guide/cookbook.rst delete mode 100644 guide/developing.rst delete mode 100644 guide/faq.rst create mode 100644 guide/getting-started.rst delete mode 100644 guide/quickstart.rst delete mode 100644 guide/troubleshooting.rst create mode 100644 guide/upgrading.rst diff --git a/guide/api.rst b/guide/api.rst new file mode 100644 index 0000000..ef1f8dd --- /dev/null +++ b/guide/api.rst @@ -0,0 +1,5894 @@ +Copyright (c) 2014, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Aaa class manages Authorization, Authentication and Accounting (AAA) +on an EOS node. + +get returns a hash of all Aaa resources. + +@example { : { : { type: , servers: }, : { type: , servers: } } } + +@return [Hash] Returns the Aaa resources as a Hash. If +no Aaa resources are found, an empty hash is returned. + +Returns an object node for working with AaaGroups class. + +The AaaGroups class manages the server groups on an EOS node. Regular +expression that parses the radius servers from the aaa group server +radius configuration block. Regular expression that parses the tacacs +servers from the aaa group server tacacs+ configuration block. + +get returns the aaa server group resource hash that describes the +current configuration for the specified server group name. + +@example { type: , servers: } + +@param name [String] The server group name to return from the nodes +current running configuration. If the name is not configured a nil +object is returned. + +@return [nil, Hash] Returns the resource hash for the +specified name. If the name does not exist, a nil object is returned. +block = get\_block("aaa group server ([^\\s]+) {name}") + +getall returns a aaa server groups hash. + +@example { : { type: , servers: }, : { type: , servers: } } + +@return [Hash] Returns the resource hashes for +configured aaa groups. If none exist, a nil object is returned. + +parse\_type scans the specified configuration block and returns the +server group type as either 'tacacs' or 'radius'. The type value is +expected to always be present in the config. + +@api private + +@param config [String] The aaa server group block configuration for the +group name to parse. + +@return [Hash] Resource hash attribute. + +parse\_servers scans the specified configuraiton block and returns the +list of servers configured for the group. If there are no servers +configured for the group the servers value will return an empty array. + +@api private + +@see parse\_radius\_server @see parse\_tacacs\_server + +@param config [String] The aaa server group block configuration for the +group name to parse. + +@param type [String] The aaa server block type. Valid values are either +radius or tacacs+. + +@return [Hash] Resource hash attribute + +parse\_radius\_server scans the provide configuration block and returns +the list of servers configured. The configuration block is expected to +be a radius configuration block. If there are no servers configured for +the group the servers value will return an empty array. + +@api private + +@param config [String] The aaa server group block configuration for the +group name to parse + +@return [Hash] resource hash attribute + +parse\_tacacs\_server scans the provided configuration block and returns +the list of configured servers. The configuration block is expected to +be a tacacs configuration block. If there are no servers configured for +the group the servers value will return an empty array. + +@api private + +@param config [String] The aaa server group block configuration for the +group name to parse. + +@return [Hash] Resource hash attribute. + +find\_type is a utility method to find the type of aaa server group for +the specified name. This method will scan the current running +configuration on the node and return the server group type as either +'radius' or 'tacacs+'. If the server group is not configured, then nil +will be returned. + +@api private + +@param name [String] The aaa server group name to find in the config and +return the type value for. + +@return [nil, String] Returns either the type name as 'radius' or +'tacacs+' or nil if the server group is not configured. mdata = /aaa +group server ([^\\s]+) {name}/.match(config) + +create adds a new aaa group server to the nodes current configuration. +If the specified name and type are already created then this method will +return successfully. If the name is configured but the type is +different, this method will not return successfully (returns false). + +@since eos\_version 4.13.7M + +commands aaa group server + +@param name [String] The name of the aaa group server to create in the +nodes running configuration + +@param type [String] The type of aaa group server to create in the nodes +running configuration. Valid values include 'radius' or 'tacacs+' + +@return [Boolean] returns true if the commands complete successfully +configure ["aaa group server {type} {name}", 'exit'] + +delete removes a current aaa server group from the nodes current +configuration. This method will automatically determine the server group +type based on the name. If the name is not configured in the nodes +current configuration, this method will return successfully. + +@since eos\_version 4.13.7M + +commands no aaa group server [radius \| tacacs+] + +@param name [String] The name of the aaa group server to create in the +nodes running configuration. + +@return [Boolean] Returns true if the commands complete successfully. +configure "no aaa group server {type} {name}" + +set\_servers configures the set of servers for a specified aaa server +group. This is an atomic operation that first removes all current +servers and then adds the new servers back. If any of the servers failes +to be removed or added, this method will return unsuccessfully. + +@see remove\_server @see add\_server + +@param name [String] The name of the aaa group server to add the new +server configuration to. + +@param servers [String] The IP address or host name of the server to add +to the configuration + +@return [Boolean] Returns true if the commands complete successfully + +add\_server adds a new server to the specified aaa server group. If the +server is already configured in the list of servers, this method will +still return successfully. + +@see add\_radius\_server @see add\_tacacs\_server + +@param name [String] The name of the aaa group server to add the new +server configuration to. + +@param server [String] The IP address or host name of the server to add +to the configuration. + +@param opts [Hash] Optional configuration parameters. + +@return [Boolean] Returns true if the commands complete successfully. + +add\_radius\_server adds a new radius server to the nodes current +configuration. If the server already exists in the specified group name +this method will still return successfully. + +@since eos\_version 4.13.7M + +commmands aaa group server radius server [acct-port ] [auth-port ] [vrf +] + +@param name [String] The name of the aaa group server to add the new +server configuration to. + +@param server [String] The IP address or host name of the server to add +to the configuration. + +@param opts [Hash] Optional configuration parameters. + +@return [Boolean] Returns true if the commands complete successfully. +order of command options matter here! server = "server {server} " server +<< "auth-port {opts[:auth\_port]} " if opts[:auth\_port] server << +"acct-port {opts[:acct\_port]} " if opts[:acct\_port] server << "vrf +{opts[:vrf]}" if opts[:vrf] configure ["aaa group server radius {name}", +server, 'exit'] + +add\_tacacs\_server adds a new tacacs server to the nodes current +configuration. If the server already exists in the specified group name +this method will still return successfully. + +@since eos\_version 4.13.7M + +commmands aaa group server tacacs+ server [acct-port ] [auth-port ] [vrf +] + +@param name [String] The name of the aaa group server to add the new +server configuration to. + +@param server [String] The IP address or host name of the server to add +to the configuration. + +@param opts [Hash] Optional configuration parameters. + +@return [Boolean] Returns true if the commands complete successfully. +order of command options matter here! server = "server {server} " server +<< "vrf {opts[:vrf]} " if opts[:vrf] server << "port {opts[:port]} " if +opts[:port] configure ["aaa group server tacacs+ {name}", server, +'exit'] + +remove\_server deletes an existing server from the specified aaa server +group. If the specified server is not configured in the specified server +group, this method will still return true. + +eos\_version 4.13.7M + +commands aaa group server [radius \| tacacs+] no server + +@param name [String] The name of the aaa group server to remove. + +@param server [String] The IP address or host name of the server. + +@param opts [Hash] Optional configuration parameters. + +@return [Boolean] returns true if the commands complete successfully. +server = "no server {server} " server << "vrf {opts[:vrf]}" if +opts[:vrf] configure ["aaa group server {type} {name}", server, 'exit'] + +Copyright (c) 2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Acl class manages the set of standard ACLs. + +get returns the specified ACL from the nodes current configuration. + +@example { : { seqno: , action: , srcaddr: , srcprefixle: , log: }, : { +seqno: , action: , srcaddr: , srcprefixle: , log: }, ... } + +@param name [String] The ACL name. + +@return [nil, Hash] Returns the ACL resource as a Hash. +Returns nil if name does not exist. config = get\_block("ip access-list +standard {name}") + +getall returns the collection of ACLs from the nodes running +configuration as a hash. The ACL resource collection hash is keyed by +the ACL name. + +@example { : { : { seqno: , action: , srcaddr: , srcprefixle: , log: }, +: { seqno: , action: , srcaddr: , srcprefixle: , log: }, ... }, : { : { +seqno: , action: , srcaddr: , srcprefixle: , log: }, : { seqno: , +action: , srcaddr: , srcprefixle: , log: }, ... }, ... } + +@return [nil, Hash] Returns a hash that represents the +entire ACL collection from the nodes running configuration. If there are +no ACLs configured, this method will return an empty hash. + +mask\_to\_prefixlen converts a subnet mask from dotted decimal to bit +length. + +@param mask [String] The dotted decimal subnet mask to convert. + +@return [String] The subnet mask as a valid prefix length. + +parse\_entries scans the nodes configurations and parses the entries +within an ACL. + +@api private + +@param config [String] The switch config. + +@return [Hash] Returns the resource hash attribute. + +create will create a new ACL resource in the nodes current configuration +with the specified name. If the create method is called and the ACL +already exists, this method will still return true. The ACL will not +have any entries. Use add\_entry to add entries to the ACL. + +@since eos\_version 4.13.7M + +commands ip access-list standard + +@param name [String] The ACL name to create on the node. Must begin with +an alphabetic character. Cannot contain spaces or quotation marks. + +@return [Boolean] Returns true if the command completed successfully. +configure("ip access-list standard {name}") + +delete will delete an existing ACL resource from the nodes current +running configuration. If the delete method is called and the ACL does +not exist, this method will succeed. + +@since eos\_version 4.13.7M + +commands no ip access-list standard + +@param name [String] The ACL name to delete on the node. + +@return [Boolean] Returns true if the command completed successfully. +configure("no ip access-list standard {name}") + +default will configure the ACL using the default keyword. This command +has the same effect as deleting the ACL from the nodes running +configuration. + +@since eos\_version 4.13.7M + +commands default no ip access-list standard + +@param name [String] The ACL name to set to the default value on the +node. + +@return [Boolean] Returns true if the command complete successfully +configure("default ip access-list standard {name}") + +build\_entry will build the commands to add an entry. + +@api private + +@param entry [Hash] the options for the entry. + +@option entry seqno [String] The sequence number of the entry in the ACL +to add. Default is nil, will be assigned. + +@option entry action [String] The action triggered by the ACL. Valid +values are 'permit', 'deny', or 'remark'. + +@option entry addr [String] The IP address to permit or deny. + +@option entry prefixlen [String] The prefixlen for the IP address. + +@option entry log [Boolean] Triggers an informational log message to the +console about the matching packet. + +@return [String] Returns commands to create an entry. cmds = +"{entry[:seqno]} " if entry[:seqno] cmds << "{entry[:action]} +{entry[:srcaddr]}/{entry[:srcprefixlen]}" + +update\_entry will update an entry, identified by the seqno in the ACL +specified by name, with the passed in parameters. + +@since eos\_version 4.13.7M + +@param name [String] The ACL name to update on the node. + +@param entry [Hash] the options for the entry. + +@option entry seqno [String] The sequence number of the entry in the ACL +to update. + +@option entry action [String] The action triggered by the ACL. Valid +values are 'permit', 'deny', or 'remark'. + +@option entry addr [String] The IP address to permit or deny. + +@option entry prefixlen [String] The prefixlen for the IP address. + +@option entry log [Boolean] Triggers an informational log message to the +console about the matching packet. + +@return [Boolean] Returns true if the command complete successfully. +cmds = ["ip access-list standard {name}"] cmds << "no {entry[:seqno]}" + +add\_entry will add an entry to the specified ACL with the passed in +parameters. + +@since eos\_version 4.13.7M + +@param name [String] The ACL name to add an entry to on the node. + +@param entry [Hash] the options for the entry. + +@option entry action [String] The action triggered by the ACL. Valid +values are 'permit', 'deny', or 'remark'. + +@option entry addr [String] The IP address to permit or deny. + +@option entry prefixlen [String] The prefixlen for the IP address. + +@option entry log [Boolean] Triggers an informational log message to the +console about the matching packet. + +@return [Boolean] Returns true if the command complete successfully. +cmds = ["ip access-list standard {name}"] + +remove\_entry will remove the entry specified by the seqno for the ACL +specified by name. + +@since eos\_version 4.13.7M + +@param name [String] The ACL name to update on the node. + +@param seqno [String] The sequence number of the entry in the ACL to +remove. + +@return [Boolean] Returns true if the command complete successfully. +cmds = ["ip access-list standard {name}", "no {seqno}", 'exit'] + +Copyright (c) 2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Eos is the toplevel namespace for working with Arista EOS nodes. + +Api is module namespace for working with the EOS command API. + +The Bgp class implements global BGP router configuration. + +get returns the BGP routing configuration from the nodes current +configuration. + +@example { bgp\_as: , router\_id: , shutdown: , maximum\_paths: , +maximum\_ecmp\_paths: networks: [ { prefix: , masklen: , route\_map: }, +{ prefix: , masklen: , route\_map: } ], neighbors: { name: { +peer\_group: , remote\_as: , send\_community: , shutdown: , description: +, next\_hop\_selp: , route\_map\_in: , route\_map\_out: }, name: { +peer\_group: , remote\_as: , send\_community: , shutdown: , description: +, next\_hop\_selp: , route\_map\_in: , route\_map\_out: }, ... } } + +@return [nil, Hash] Returns the BGP resource as a Hash. + +parse\_bgp\_as scans the BGP routing configuration for the AS number. +Defined as a class method. Used by the BgpNeighbors class below. + +@param config [String] The switch config. + +@return [Hash] Returns the resource hash attribute. + +parse\_router\_id scans the BGP routing configuration for the router ID. + +@api private + +@param config [String] The switch config. + +@return [Hash] Returns the resource hash attribute. + +parse\_shutdown scans the BGP routing configuration for the shutdown +status. + +@api private + +@param config [String] The switch config. + +@return [Hash] resource hash attribute. Returns true if +shutdown, false otherwise. + +parse\_maximum\_paths scans the BGP routing configuration for the +maximum paths and maximum ecmp paths. + +@api private + +@param config [String] The switch config. + +@return [Hash] Returns the resource hash attribute. + +parse\_networks scans the BGP routing configuration for all the network +entries. + +@api private + +@param config [String] The switch config. + +@return [Array] Single element hash with Array of network hashes. + +create will create a new instance of BGP routing on the node. Optional +parameters can be passed in to initialize BGP specific settings. + +commands router bgp + +@param bgp\_as [String] The BGP autonomous system number to be +configured for the local BGP routing instance. + +@param opts [hash] Optional keyword arguments. + +@option opts router\_id [String] The BGP routing process router-id +value. When no ID has been specified (i.e. value not set), the local +router ID is set to the following: \* The loopback IP address when a +single loopback interface is configured. \* The loopback with the +highest IP address when multiple loopback interfaces are configured. \* +The highest IP address on a physical interface when no loopback +interfaces are configure + +@option opts maximum\_paths [Integer] Maximum number of equal cost +paths. + +@option opts maximum\_ecmp\_paths [Integer] Maximum number of installed +ECMP routes. The maximum\_paths option must be set if +maximum\_ecmp\_paths is set. + +@option opts enable [Boolean] If true then the BGP router is enabled. If +false then the BGP router is disabled. + +@return [Boolean] returns true if the command completed successfully. +cmds = ["router bgp {bgp\_as}"] cmds << "router-id {opts[:router\_id]}" +if opts.key?(:router\_id) cmd = "maximum-paths {opts[:maximum\_paths]}" +cmd << " ecmp {opts[:maximum\_ecmp\_paths]}" + +delete will delete the BGP routing instance from the node. + +commands no router bgp + +@return [Boolean] Returns true if the command completed successfully. +configure("no router bgp {config[:bgp\_as]}") + +default will configure the BGP routing using the default keyword. This +command has the same effect as deleting the BGP routine instance from +the nodes running configuration. + +commands default router bgp + +@return [Boolean] returns true if the command complete successfully +configure("default router bgp {config[:bgp\_as]}") + +configure\_bgp adds the command to go to BGP config mode. Then it adds +the passed in command. The commands are then passed on to configure. + +@api private + +@param cmd [String] Command to run under BGP mode. + +@return [Boolean] Returns true if the command complete successfully. +cmds = ["router bgp {bgp\_as[:bgp\_as]}", cmd] + +set\_router\_id sets the router\_id for the BGP routing instance. + +commands router bgp {no \| default} router-id + +@param opts [hash] Optional keyword arguments + +@option opts value [String] The BGP routing process router-id value. +When no ID has been specified (i.e. value not set), the local router ID +is set to the following: \* The loopback IP address when a single +loopback interface is configured. \* The loopback with the highest IP +address when multiple loopback interfaces are configured. \* The highest +IP address on a physical interface when no loopback interfaces are +configure + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the router-id using the default +keyword. + +@return [Boolean] Returns true if the command complete successfully. + +set\_shutdown configures the administrative state for the global BGP +routing process. The value option is not used by this method. + +commands router bgp {no \| default} shutdown + +@param opts [hash] Optional keyword arguments. + +@option opts enable [Boolean] If enable is true then the BGP routing +process is administratively enabled and if enable is False then the BGP +routing process is administratively disabled. + +@option opts default [Boolean] Configure the router-id using the default +keyword. + +@return [Boolean] Returns true if the command complete successfully. +Shutdown semantics are opposite of enable semantics so invert enable + +set\_maximum\_paths sets the maximum number of equal cost paths and the +maximum number of installed ECMP routes. + +commands router bgp {no \| default} maximum-paths [ecmp ] + +@param maximum\_paths [Integer] Maximum number of equal cost paths. + +@param maximum\_ecmp\_paths [Integer] Maximum number of installed ECMP +routes. + +@param opts [hash] Optional keyword arguments + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the maximum paths using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "maximum-paths {maximum\_paths} ecmp {maximum\_ecmp\_paths}" + +add\_network creates a new instance of a BGP network on the node. + +commands router bgp network / route-map + +@param prefix [String] The IPv4 prefix to configure as part of the +network statement. The value must be a valid IPv4 prefix. + +@param masklen [String] The IPv4 subnet mask length in bits. The masklen +must be in the valid range of 1 to 32. + +@param route\_map [String] The route-map name to apply to the network +statement when configured. + +@return [Boolean] Returns true if the command complete successfully. cmd += "network {prefix}/{masklen}" cmd << " route-map {route\_map}" if +route\_map + +remove\_network removes the instance of a BGP network on the node. + +commands router bgp {no} shutdown + +@param prefix [String] The IPv4 prefix to configure as part of the +network statement. The value must be a valid IPv4 prefix. + +@param masklen [String] The IPv4 subnet mask length in bits. The masklen +must be in the valid range of 1 to 32. + +@param route\_map [String] The route-map name to apply to the network +statement when configured. + +@return [Boolean] Returns true if the command complete successfully. cmd += "no network {prefix}/{masklen}" cmd << " route-map {route\_map}" if +route\_map + +The BgpNeighbors class implements BGP neighbor configuration + +get returns a single BGP neighbor entry from the nodes current +configuration. + +@example { peer\_group: , remote\_as: , send\_community: , shutdown: , +description: next\_hop\_self: route\_map\_in: route\_map\_out: } + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [nil, Hash] Returns the BGP neighbor resource as +a Hash. + +getall returns the collection of all neighbor entries for the BGP router +instance. + +@example { : { peer\_group: , remote\_as: , send\_community: , shutdown: +, description: next\_hop\_self: route\_map\_in: route\_map\_out: }, : { +peer\_group: , remote\_as: , send\_community: , shutdown: , description: +next\_hop\_self: route\_map\_in: route\_map\_out: }, ... } + +@return [nil, Hash] Returns a hash that represents the +entire BGP neighbor collection from the nodes running configuration. If +there a BGP router is not configured or contains no neighbor entries +then this method will return an empty hash. + +parse\_peer\_group scans the BGP neighbor entries for the peer group. + +@api private + +@param config [String] The switch config. + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Hash] Returns the resource hash attribute. +value = config.scan(/neighbor {name} peer-group ([^\\s]+)/) + +parse\_remote\_as scans the BGP neighbor entries for the remote AS. + +@api private + +@param config [String] The switch config. + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Hash] Returns the resource hash attribute value += config.scan(/neighbor {name} remote-as (:raw-latex:`\d`+)/) + +parse\_send\_community scans the BGP neighbor entries for the remote AS. + +@api private + +@param config [String] The switch config. + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Hash] Returns the resource hash attribute. +value = config.scan(/no neighbor {name} send-community/) + +parse\_shutdown scans the BGP neighbor entries for the remote AS. + +@api private + +@param config [String] The switch config. + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Hash] Resource hash attribute. Returns true if +shutdown, false otherwise. value = config.scan(/no neighbor {name} +shutdown/) + +parse\_description scans the BGP neighbor entries for the description. + +@api private + +@param config [String] The switch config. + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Hash] Returns the resource hash attribute. +value = config.scan(/neighbor {name} description (.\*)$/) + +parse\_next\_hop\_self scans the BGP neighbor entries for the next hop +self. + +@api private + +@param config [String] The switch config. @param name [String] The name +of the BGP neighbor to manage. This value can be either an IPv4 address +or string (in the case of managing a peer group). + +@return [Hash] Returns the resource hash attribute. +value = config.scan(/no neighbor {name} next-hop-self/) + +parse\_route\_map\_in scans the BGP neighbor entries for the route map +in. + +@api private + +@param config [String] The switch config. + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Hash] Returns the resource hash attribute. +value = config.scan(/neighbor {name} route-map ([^\\s]+) in/) + +parse\_route\_map\_out scans the BGP neighbor entries for the route map +in. + +@api private + +@param config [String] The switch config. + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Hash] Returns the resource hash attribute. +value = config.scan(/neighbor {name} route-map ([^\\s]+) out/) + +configure\_bgp adds the command to go to BGP config mode. Then it adds +the passed in command. The commands are then passed on to configure. + +@api private + +@param cmd [String] Command to run under BGP mode. + +@return [Boolean] Returns true if the command complete successfully. +cmds = ["router bgp {bgp\_as[:bgp\_as]}", cmd] + +create will create a new instance of a BGP neighbor on the node. The +neighbor is created in the shutdown state and then enabled. + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Boolean] Returns true if the command completed successfully. + +delete will delete the BGP neighbor from the node. + +commands no neighbor or no neighbor peer-group + +@param name [String] The name of the BGP neighbor to manage. This value +can be either an IPv4 address or string (in the case of managing a peer +group). + +@return [Boolean] Returns true if the command completed successfully. +cmd = "no neighbor {name}" cmd = "no neighbor {name} peer-group" + +neigh\_command\_builder for neighbors which calls command\_builder. + +@param name [String] The name of the BGP neighbor to manage. + +@param cmd [String] The command portion of the neighbor command. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] Value being set. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the command using the default +keyword. + +@return [String] Returns built command string. +command\_builder("neighbor {name} {cmd}", opts) + +set\_peer\_group creates a BGP static peer group name. + +commands router bgp {no \| default} neighbor peer-group + +@param name [String] The IP address of the neighbor. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The group name. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the peer group using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. + +set\_remote\_as configures the expected AS number for a neighbor (peer). + +commands router bgp {no \| default} neighbor remote-as + +@param name [String] The IP address or name of the peer group. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The remote as-id. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the peer group using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. + +set\_shutdown disables the specified neighbor. The value option is not +used by this method. + +commands router bgp {no \| default} neighbor shutdown + +@param name [String] The IP address or name of the peer group. + +@param opts [hash] Optional keyword arguments. + +@option opts enable [String] True enables the specified neighbor. False +disables the specified neighbor. + +@option opts default [Boolean] Configure the peer group using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. +Shutdown semantics are opposite of enable semantics so invert enable. + +set\_send\_community configures the switch to send community attributes +to the specified BGP neighbor. The value option is not used by this +method. + +commands router bgp {no \| default} neighbor send-community + +@param name [String] The IP address or name of the peer group. + +@param opts [hash] Optional keyword arguments. + +@option opts enable [String] True enables the feature. False disables +the feature. + +@option opts default [Boolean] Configure the peer group using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. + +set\_next\_hop\_self configures the switch to list its address as the +next hop in routes that it advertises to the specified BGP-speaking +neighbor or neighbors in the specified peer group. The value option is +not used by this method. + +commands router bgp {no \| default} neighbor next-hop-self + +@param name [String] The IP address or name of the peer group. + +@param opts [hash] Optional keyword arguments. + +@option opts enable [String] True enables the feature. False disables +the feature. + +@option opts default [Boolean] Configure the peer group using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. + +set\_route\_map\_in command applies a route map to inbound BGP routes. + +commands router bgp {no \| default} neighbor route-map in + +@param name [String] The IP address or name of the peer group. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] Name of a route map. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the peer group using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. + +set\_route\_map\_out command applies a route map to outbound BGP routes. + +commands router bgp {no \| default} neighbor route-map out + +@param name [String] The IP address or name of the peer group. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] Name of a route map. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the peer group using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. + +set\_description associates descriptive text with the specified peer or +peer group. + +commands router bgp {no \| default} neighbor description + +@param name [String] The IP address or name of the peer group. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The description string. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the peer group using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Dns class manages DNS settings on an EOS node. + +get returns the DNS resource. + +@example { "domain\_name": , "name\_servers": array, "domain\_list": +array } + +@return [Hash] A Ruby hash object that provides the SNMP settings as key +/ value pairs. + +parse\_domain\_name parses the domain-name from config. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_name\_servers parses the name-server values from config. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_domain\_list parses the domain-list from config. + +@api private + +@return [Hash] Returns the resource hash attribute. + +Configure the domain-name value in the running-config. + +@param opts [Hash] The configuration parameters. + +@option opts value [string] The value to set the domain-name to. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. + +@return [Boolean] Returns true if the command completed successfully. + +set\_name\_servers configures the set of name servers that eos will use +to resolve dns queries. If the enable option is false, then the +name-server list will be configured using the no keyword. If the default +option is specified, then the name server list will be configured using +the default keyword. If both options are provided the keyword option +will take precedence. + +@since eos\_version 4.13.7M + +commands ip name-server no ip name-server default ip name-server + +@param [Hash] opts The configuration parameters. + +@option opts value [string] The set of name servers to configure on the +node. The list of name servers will be replace in the nodes running +configuration by the list provided in value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option default [Boolean] Configures the ip name-servers using the +default keyword argument. Default takes precedence over enable. + +@return [Boolean] Returns true if the commands completed successfully. +cmds << "ip name-server {srv}" + +add\_name\_server adds an ip name-server. + +@param server [String] The name of the ip name-server to create. + +@return [Boolean] Returns true if the command completed successfully. +configure "ip name-server {server}" + +remove\_name\_server removes the specified ip name-server. + +@param server [String] The name of the ip name-server to remove. + +@return [Boolean] Returns true if the command completed successfully. +configure "no ip name-server {server}" + +set\_domain\_list configures the set of domain names to search when +making dns queries for the FQDN. If the enable option is set to false, +then the domain-list will be configured using the no keyword. If the +default option is specified, then the domain list will be configured +using the default keyword. If both options are provided the default +keyword option will take precedence. + +@since eos\_version 4.13.7M + +commands ip domain-list no ip domain-list default ip domain-list + +@option value [Array] The set of domain names to configure on the node. +The list of domain names will be replace in the nodes running +configuration by the list provided in value. + +@option default [Boolean] Configures the ip domain-list using the +default keyword argument. + +@return [Boolean] Returns true if the commands completed successfully. +cmds << "default ip domain-list {name}" cmds << "no ip domain-list +{name}" cmds << "ip domain-list {name}" + +add\_domain\_list adds an ip domain-list. + +@param name [String] The name of the ip domain-list to add. + +@return [Boolean] Returns true if the command completed successfully. +configure "ip domain-list {name}" + +remove\_domain\_list removes a specified ip domain-list. + +@param name [String] The name of the ip domain-list to remove. + +@return [Boolean] Returns true if the command completed successfully. +configure "no ip domain-list {name}" + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Interfaces class manages all physical and logical interfaces on an +EOS node. + +get returns a hash of interface configurations for the given name. + +@example { name: , type: , description: , shutdown: } + +@param name [String] The interface name to return a resource for from +the nodes configuration. + +@return [nil, Hash] Returns the interface resource as a +Hash. If the specified name is not found in the nodes current +configuration a nil object is returned. + +getall returns a hash of interface configurations. + +@example { : { name: , type: , description: , shutdown: , ... }, : { +name: , type: , description: , shutdown: , ... }, ... } + +@return [Hash] Returns the interface resources as a +Hash. If none exist in the nodes current configuration an empty hash is +returned. + +get\_instance returns an interface instance for the given name. + +@param name [String] The interface name to return an instance for. + +@return [Object] Returns the interface instance as an Object. + +The BaseInterface class extends Entity and provides an implementation +that is common to all interfaces configured in EOS. + +get returns the specified interface resource hash that represents the +node's current interface configuration. The BaseInterface class provides +all the set of attributes that are common to all interfaces in EOS. This +method will return an interface type of generic. + +@example { name: type: 'generic' description: shutdown: [true, false] } + +@param name [String] The name of the interface to return from the +running-configuration. + +@return [nil, Hash] Returns a hash of the interface +properties if the interface name was found in the running configuration. +If the interface was not found, nil is returned. config = +get\_block("^interface {name}") + +parse\_description scans the provided configuration block and parses the +description value if it exists in the configuration. If the description +value is not configured, then the DEFALT\_INTF\_DESCRIPTION value is +returned. The hash returned by this method is intended to be merged into +the interface resource hash returned by the get method. + +@api private + +@param config [String] The configuration block retrieved from the nodes +current running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_shutdown scans the provided configuration block and parses the +shutdown value. If the shutdown value is configured then true is +returned as its value otherwise false is returned. The hash returned by +this method is intended to be merged into the interface resource hash +returned by the get method. + +@api private + +@param config [String] The configuration block retrieved from the nodes +current running configuration. + +@return [Hash] Returns the resource hash attribute. + +create will create a new interface resource in the node's current +configuration with the specified interface name. If the create method is +called and the interface already exists, this method will return +successful. + +@since eos\_version 4.13.7M + +@param value [String] The interface name to create on the node. The +interface name must be the full interface identifier (ie Loopback, not +Lo). + +@return [Boolean] Returns true if the command completed successfully. +configure("interface {value}") + +delete will delete an existing interface resource in the node's current +configuration with the specified interface name. If the delete method is +called and interface does not exist, this method will return successful. + +@since eos\_version 4.13.7M + +@param value [String] The interface name to delete from the node. The +interface name must be the full interface identifier (ie Loopback, no +Lo). + +@return [Boolean] Returns true if the command completed successfully. +configure("no interface {value}") + +default will configure the interface using the default keyword. For +virtual interfaces this is equivalent to deleting the interface. For +physical interfaces, the entire interface configuration will be set to +defaults. + +@since eos\_version 4.13.7M + +@param value [String] The interface name to default in the node. The +interface name must be the full interface identifier (ie Loopback, not +Lo). + +@return [Boolean] Returns true if the command completed successfully. +configure("default interface {value}") + +set\_description configures the description value for the specified +interface name in the nodes running configuration. If the enable keyword +is false then the description value is negated using the no keyword. If +the default keyword is set to true, then the description value is +defaulted using the default keyword. The default keyword takes +precedence over the enable keyword if both are provided. + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration to. +The name value must be the full interface identifier. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The value to configure the description to in +the node's configuration. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the interface description using +the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_shutdown configures the administrative state of the specified +interface in the node. If the enable keyword is false, then the +interface is administratively disabled. If the enable keyword is true, +then the interface is administratively enabled. If the default keyword +is set to true, then the interface shutdown value is configured using +the default keyword. The default keyword takes precedence over the +enable keyword if both are provided. + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration to. +The name value must be the full interface identifier. + +@param opts [hash] Optional keyword arguments. + +@option opts enable [Boolean] True if the interface should be +administratively enabled or false if the interface should be +administratively disabled. + +@option opts default [Boolean] Configure the interface shutdown using +the default keyword. + +@return [Boolean] Returns true if the command completed successfully. +Shutdown semantics are opposite of enable semantics so invert enable. + +The EthernetInterface class manages all Ethernet interfaces on an EOS +node. + +get returns the specified Ethernet interface resource hash that +represents the interface's current configuration in the node. + +@example { name: , type: , description: , shutdown: , speed: , forced: , +sflow: , flowcontrol\_send: , flowcontrol\_receive: } + +@param name [String] The interface name to return a resource hash for +from the node's running configuration. + +@return [nil, Hash] Returns the interface resource as a +hash. If the specified interface name is not found in the node's +configuration a nil object is returned. config = get\_block("^interface +{name}") + +parse\_speed scans the provided configuration block and parses the speed +value. If the speed value is not found in the interface configuration +block provided, DEFAULT\_SPEED and DEFAULT\_FORCED are used. The +returned hash is intended to be merged into the interface resource hash. + +@api private + +@param config [String] The configuration block to parse. + +@return [Hash] Returns the resource hash attribute. + +parse\_sflow scans the provided configuration block and parse the sflow +value. The sflow values true if sflow is enabled on the interface or +returns false if it is not enabled. The hash returned is intended to be +merged into the interface hash. + +@api private + +@param config [String] The configuration block to parse. + +@return [Hash] Returns the resource hash attribute. + +parse\_flowcontrol\_send scans the provided configuration block and +parses the flowcontrol send value. If the interface flowcontrol value is +not configured, then this method will return the value of +DEFAULT\_ETH\_FLOWC\_TX. The hash returned is intended to be merged into +the interface resource hash. + +@api private + +@param config [String] The configuration block to parse. + +@return [Hash] Returns the resource hash attribute. + +parse\_flowcontrol\_receive scans the provided configuration block and +parse the flowcontrol receive value. If the interface flowcontrol value +is not configured, then this method will return the value of +DEFAULT\_ETH\_FLOWC\_RX. The hash returned is intended to be merged into +the interface resource hash. + +@api private + +@param config [String] The configuration block to parse. + +@return [Hash] Returns the resource hash attribute. + +create overrides the create method from the BaseInterface and raises an +exception because Ethernet interface creation is not supported. + +@param \_name [String] The name of the interface. + +@raise [NotImplementedError] Creation of physical Ethernet interfaces is +not supported. + +delete overrides the delete method fro the BaseInterface instance and +raises an exception because Ethernet interface deletion is not +supported. + +@param \_name [String] The name of the interface. + +@raise [NotImplementedError] Deletion of physical Ethernet interfaces is +not supported. + +set\_speed configures the interface speed and negotiation values on the +specified interface. If the enable option is false the speed setting is +configured using the no keyword. If the default options is set to true, +then the speed setting is configured using the default keyword. If both +options are specified, the default keyword takes precedence. + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the speed setting to +in the nodes running configuration. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts forced [Boolean] Specifies if auto negotiation should be +enabled (true) or disabled (false). + +@option opts default [Boolean] Configures the sflow value on the +interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. +cmds = ["interface {name}"] cmds << enable ? "speed {forced} {value}" : +'no speed' + +set\_sflow configures the administrative state of sflow on the +interface. Setting the enable keyword to true enables sflow on the +interface and setting enable to false disables sflow on the interface. +If the default keyword is set to true, then the sflow value is defaulted +using the default keyword. The default keyword takes precedence over the +enable keyword + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param opts [Hash] Optional keyword arguments. + +@option opts enable [Boolean] Enables sflow if the value is true or +disables sflow on the interface if false. Default is true. + +@option opts default [Boolean] Configures the sflow value on the +interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_flowcontrol configures the flowcontrol value either on or off for +the for the specified interface in the specified direction (either send +or receive). If the enable keyword is false then the configuration is +negated using the no keyword. If the default keyword is set to true, +then the state value is defaulted using the default keyword. The default +keyword takes precedence over the enable keyword + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param direction [String] Specifies the flowcontrol direction to +configure. Valid values include send and receive. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] Specifies the value to configure the +flowcontrol setting for. Valid values include on or off. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the flowcontrol value on the +interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. +commands = command\_builder("flowcontrol {direction}", opts) + +set\_flowcontrol\_send is a convenience function for configuring the +value of interface flowcontrol. + +@see set\_flowcontrol + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] Specifies the value to configure the +flowcontrol setting for. Valid values include on or off. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the flowcontrol value on the +interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_flowcontrol\_receive is a convenience function for configuring the +value of interface flowcontrol. + +@see set\_flowcontrol + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] Specifies the value to configure the +flowcontrol setting for. Valid values include on or off. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the flowcontrol value on the +interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +The PortchannelInterface class manages all port channel interfaces on an +EOS node. + +get returns the specified port-channel interface configuration from the +nodes running configuration as a resource hash. The resource hash +returned extends the BaseInterface resource hash, sets the type value to +portchannel and adds the portchannel specific attributes + +@example { type: 'portchannel' description: shutdown: [true, false] +members: array[] lacp\_mode: [active, passive, on] minimum\_links: +lacp\_timeout: lacp\_fallback: [static, individual, disabled] } + +@see BaseInterface Interface get example + +@param name [String] The name of the portchannel interface to return a +resource hash for. The name must be the full interface name of the +desired interface. + +@return [nil, Hash] Returns the interface resource as a +hash object. If the specified interface does not exist in the running +configuration, a nil object is returned. config = get\_block("^interface +{name}") + +parse\_members scans the nodes running config and returns all of the +Ethernet members for the port-channel interface specified. If the +port-channel interface has no members configured, then this method will +assign an empty array as the value for members. The hash returned is +intended to be merged into the interface resource hash. + +@api private + +@param name [String] The name of the portchannel interface to extract +the members for. + +@return [Hash] Returns the resource hash attribute. +command = "show port-channel {grpid} all-ports" + +parse\_lacp\_mode scans the member interfaces and returns the configured +lacp mode. The lacp mode value must be common across every member in the +port channel interface. If no members are configured, the value for +lacp\_mode will be set using DEFAULT\_LACP\_MODE. The hash returned is +intended to be merged into the interface resource hash + +@api private + +@param name [String] The name of the portchannel interface to extract +the members from in order to get the configured lacp\_mode. + +@return [Hash] Returns the resource hash attribute. +config = get\_block("interface {members.first}") + +parse\_minimum\_links scans the port-channel configuration and returns +the value for port-channel minimum-links. If the value is not found in +the interface configuration, then DEFAULT\_MIN\_LINKS value is used. The +hash returned is intended to be merged into the interface resource hash. + +@api private + +@param config [String] The interface configuration block to extract the +minimum links value from. + +@return [Hash] Returns the resource hash attribute. + +parse\_lacp\_fallback scans the interface config block and returns the +configured value of the lacp fallback attribute. If the value is not +configured, then the method will return the value of +DEFAULT\_LACP\_FALLBACK. The hash returned is intended to be merged into +the interface resource hash. + +@api private + +@param config [String] The interface configuration block to extract the +lacp fallback value from. + +@return [Hash] Returns the resource hash attribute. + +parse\_lacp\_timeout scans the interface config block and returns the +value of the lacp fallback timeout value. The value is expected to be +found in the interface configuration block. The hash returned is +intended to be merged into the interface resource hash. + +@api private + +@param config [String] The interface configuration block to extract the +lacp timeout value from. + +@return [Hash] Returns the resource hash attribute. + +set\_minimum\_links configures the minimum physical links up required to +consider the logical portchannel interface operationally up. If the +enable keyword is false then the minimum-links is configured using the +no keyword argument. If the default keyword argument is provided and set +to true, the minimum-links value is defaulted using the default keyword. +The default keyword takes precedence over the enable keyword argument if +both are provided. + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String, Integer] Specifies the value to configure +the minimum-links to in the configuration. Valid values are in the range +of 1 to 16. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the minimum links value on the +interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_members configures the set of physical interfaces that comprise the +logical port-channel interface. The members value passed should be an +array of physical interface names that comprise the port-channel +interface. This method will add and remove individual members as +required to sync the provided members array. + +@see add\_member Adds member links to the port-channel interface. + +@see remove\_member Removes member links from the port-channel +interface. + +@param name [String] The name of the port-channel interface to apply the +members to. If the port-channel interface does not already exist it will +be created. + +@param members [Array] The array of physical interface members to add to +the port-channel logical interface. + +@param mode [str] The LACP mode to configure the member interfaces to. +Valid values are 'on, 'passive', 'active'. When there are existing +channel-group members and their lacp mode differs from this attribute, +all of those members will be removed and then re-added using the +specified lacp mode. If this attribute is omitted, the existing lacp +mode will be used for new member additions. + +@return [Boolean] Returns true if the command completed successfully. +remove members from the current port-channel interface. cmds << +"interface {intf}" cmds << "no channel-group {grpid}" add new member +interfaces to the port-channel. cmds << "interface {intf}" cmds << +"channel-group {grpid} mode {lacp\_mode}" + +add\_member adds the interface specified in member to the port-channel +interface specified by name in the nodes running-configuration. If the +port-channel interface does not already exist, it will be created. + +@since eos\_version 4.13.7M + +@param name [String] The name of the port-channel interface to apply the +configuration to. + +@param member [String] The name of the physical Ethernet interface to +add to the logical port-channel interface. + +@return [Boolean] Returns true if the command completed successfully. +configure\_interface(member, "channel-group {grpid} mode {lacp}") + +remove\_member removes the interface specified in member from the +port-channel interface specified by name in the nodes +running-configuration. + +@since eos\_version 4.13.7M + +@param name [String] The name of the port-channel interface to apply the +configuration to. + +@param member [String] The name of the physical Ethernet interface to +remove from the logical port-channel interface. + +@return [Boolean] Returns true if the command completed successfully. +configure\_interface(member, "no channel-group {grpid}") + +set\_lacp\_mode configures the lacp mode on the port-channel interface +by configuring the lacp mode value for each member interface. This +method will find all member interfaces for a port-channel and +reconfigure them using the mode argument. + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param mode [String] The lacp mode to configure on the member interfaces +for the port-channel. Valid values include active, passive or on. + +@return [Boolean] Returns true if the command completed successfully. +remove\_commands << "interface {member}" remove\_commands << "no +channel-group {grpid}" add\_commands << "interface {member}" +add\_commands << "channel-group {grpid} mode {mode}" + +set\_lacp\_fallback configures the lacp fallback mode for the +port-channel interface. If the enable keyword is false, lacp fallback is +configured using the no keyword argument. If the default option is +specified and set to true, the lacp fallback value is configured using +the default keyword. The default keyword takes precedence over the +enable keyword if both options are provided. + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] Specifies the value to configure for the +port-channel lacp fallback. Valid values are individual and static. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the lacp fallback value on the +interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_lacp\_timeout configures the lacp fallback timeout for the +port-channel interface. If the enable keyword is false, lacp fallback +timeout is configured using the no keyword argument. If the default +option is specified and set to true, the lacp fallback timeout value is +configured using the default keyword. The default keyword takes +precedence over the enable keyword if both options are provided. + +@since eos\_version 4.13.7M + +@param name [String] The interface name to apply the configuration +values to. The name must be the full interface identifier. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] Specifies the value to configure for the +port-channel lacp fallback timeout. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the lacp fallback timeout +value on the interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +The VxlanInterface class manages all Vxlan interfaces on an EOS node. + +Returns the Vxlan interface configuration as a Ruby hash of key/value +pairs from the nodes running configuration. This method extends the +BaseInterface get method and adds the Vxlan specific attributes to the +hash. + +@example { name: , type: , description: , shutdown: , source\_interface: +, multicast\_group: , udp\_port: , flood\_list: , vlans: } + +@param name [String] The interface name to return from the nodes +configuration. This optional parameter defaults to Vxlan1. + +@return [nil, Hash] Returns the interface configuration +as a Ruby hash object. If the provided interface name is not found then +this method will return nil. config = get\_block("interface {name}") + +parse\_source\_interface scans the interface config block and returns +the value of the vxlan source-interface. If the source-interface is not +configured then the value of DEFAULT\_SRC\_INTF is used. The hash +returned is intended to be merged into the interface resource hash + +@api private + +@param config [String] The interface configuration block to extract the +vxlan source-interface value from. + +@return [Hash] + +parse\_multicast\_group scans the interface config block and returns the +value of the vxlan multicast-group. If the multicast-group is not +configured then the value of DEFAULT\_MCAST\_GRP is used. The hash +returned is intended to be merged into the interface resource hash. + +@api private + +@param config [String] The interface configuration block to extract the +vxlan multicast-group value from. + +@return [Hash] + +parse\_udp\_port scans the interface config block and returns the value +of the vxlan udp-port setting. The vxlan udp-port value is expected to +always be present in the configuration. The returned value is intended +to be merged into the interface resource Hash. + +@api private + +@param config [String] The interface configuration block to parse the +vxlan udp-port value from. + +@return [Hash] + +parse\_flood\_list scans the interface config block and returns the list +of configured VTEPs that comprise the flood list. If there are no flood +list values configured, the value will return DEFAULT\_FLOOD\_LIST. The +returned value is intended to be merged into the interface resource +Hash. + +@api private + +@param config [String] The interface configuration block to parse the +vxlan flood list values from. + +@return [Hash] + +parse\_vlans scans the interface config block and returns the set of +configured vlan to vni mappings. If there are no vlans configured, the +value will return an empty Hash. + +@api private + +@param config [String] The interface configuration block to parse the +vxlan flood list values from. + +@return [Hash] + +Configures the vxlan source-interface to the specified value. This +parameter should be the interface identifier of the interface to act as +the source for all Vxlan traffic. + +@param name [String] The name of the interface to apply the +configuration values to. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] Configures the vxlan source-interface to the +specified value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Specifies whether or not the +multicast-group command is configured as default. The value of this +option has a higher precedence than :enable. + +@return [Boolean] Returns true if the commands complete successfully. + +Configures the vxlan multicast-group flood address to the specified +value. The value should be a valid multicast address. + +@param name [String] The name of the interface to apply the +configuration values to. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] Configures the multicast-group flood address +to the specified value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Specifies whether or not the +multicast-group command is configured as default. The value of this +option has a higher precedence than :value. + +@return [Boolean] Returns true if the commands complete successfully. + +set\_udp\_port configures the Vxlan udp-port value in EOS for the +specified interface name. If the enable keyword is false then the no +keyword is used to configure the value. If the default option is +provided and set to true, then the default keyword is used. If both +options are provided, the default keyword will take precedence. + +@since eos\_version 4.13.7M + +@param name [String] The name of the vxlan interface to configure. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] Specifies the value to configure the +udp-port setting to. Valid values are in the range of 1024 to 65535. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the udp-port value on the +interface using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +add\_vtep adds a new VTEP endpoint to the global flood list for the +specified interface. If the VTEP endpoint is already configured, this +method will still return successfully. + +@since eos\_version 4.13.7M + +@param name [String] The name of the interface to configure. + +@param vtep [String] The IP address of the remote VTEP endpoint. + +@return [Boolean] Returns true if the commands completed successfully. +configure\_interface(name, "vxlan flood vtep add {vtep}") + +remove\_vtep deletes a VTEP endpoint from the global flood list for the +specified interface. If the VTEP endpoint specified is not configured, +this method will still return successfully. + +@since eos\_version 4.13.7M + +@param name [String] The name of the interface to configure. + +@param vtep [String] The IP address of the remote VTEP endpoint. + +@return [Boolean] Returns true if the commands completed successfully. +configure\_interface(name, "vxlan flood vtep remove {vtep}") + +update\_vlan creates a new vlan to vni mapping for the specified +interface in the nodes current configuration. + +@since eos\_verson 4.13.7M + +@param name [String] The name of the interface to configure. + +@param vlan [Fixnum] The VLAN ID to configure. + +@param vni [Fixnum] The VNI value to map the VLAN into. + +@return [Boolean] Returns true if the command completed successfully. +configure\_interface(name, "vxlan vlan {vlan} vni {vni}") + +remove\_vlan deletes a previously configured VLAN to VNI mapping on the +specified interface. + +@since eos\_version 4.13.7M + +@param name [String] the name of the interface to configure. + +@param vlan [Fixnum] The VLAN ID to remove from the configuration. If +the VLAN ID does not exist, this method will still return successfully. + +@return [Boolean] Returns true if the command completed successfully. +configure\_interface(name, "no vxlan vlan {vlan} vni") + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Ipinterface class provides an instance for managing logical IP +interfaces configured using eAPI. + +get returns a resource hash that represents the configuration of the IP +interface from the nodes running configuration. + +@example { address: , mtu: , helper\_addresses: array } + +@param name [String] The full interface identifier of the interface to +return the resource configuration hash for. The name must be the full +name (Ethernet, not Et). + +@return [nil, Hash] Returns the ip interface +configuration as a hash. If the provided interface name is not a +configured ip address, nil is returned. config = get\_block("interface +{name}") + +getall returns a hash object that represents all ip interfaces +configured on the node from the current running configuration. + +@example { : { address: , mtu: , helper\_addresses: array }, : { +address: , mtu: , helper\_addresses: array }, ... } + +@see get Ipaddress resource example + +@return [Hash] Returns a hash object that represents all +of the configured IP addresses found. If no IP addresses are configured, +then an empty hash is returned. + +parse\_address scans the provided configuration block and extracts the +interface address, if configured, and returns it. If there is no IP +address configured, then this method will return the DEFAULT\_ADDRESS. +The return value is intended to be merged into the ipaddress resource +hash. + +@api private + +@param config [String] The IP interface configuration block returned +from the node's running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_mtu scans the provided configuration block and extracts the IP +interface MTU value. The MTU value is expected to always be present in +the configuration blcok. The return value is intended to be merged into +the ipaddress resource hash. + +@api private + +@param config [String] The IP interface configuration block returned +from the node's running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_helper\_addresses scans the provided configuration block and +extracts any configured IP helper address values. The interface could be +configured with one or more helper addresses. If no helper addresses are +configured, then an empty array is set in the return hash. The return +value is intended to be merged into the ipaddress resource hash. + +@api private + +@param config [String] The IP interface configuration block returned +from the node's running configuration. + +@return [Hash] Returns the resource hash attribute. + +create will create a new IP interface on the node. If the ip interface +already exists in the configuration, this method will still return +successful. This method will cause an existing layer 2 interface +(switchport) to be deleted if it exists in the node's configuration. + +@since eos\_version 4.13.7M + +commands interface no switchport + +@param name [String] The full interface name of the port to create the +logical interface on. The name must be the full interface identifier. + +@return [Boolean] Returns true if the commands complete successfully. +configure(["interface {name}", 'no switchport']) + +delete will delete an existing IP interface in the node's current +configuration. If the IP interface does not exist on the specified +interface, this method will still return success. This command will +default the interface back to being a switchport. + +@since eos\_version 4.13.7M + +commands interface no ip address switchport + +@param name [String] The full interface name of the port to delete the +logical interface from. The name must be the full interface name + +@return [Boolean] Returns true if the commands complete successfully. +configure(["interface {name}", 'no ip address', 'switchport']) + +set\_address configures a logical IP interface with an address. The +address value must be in the form of A.B.C.D/E. If the enable keyword is +false, then the interface address is negated using the config no +keyword. If the default option is set to true, then the ip address value +is defaulted using the default keyword. The default keyword has +precedence over the enable keyword if both options are specified. + +@since eos\_version 4.13.7M + +commands interface ip address no ip address default ip address + +@param name [String] The name of the interface to configure the address +in the node. The name must be the full interface name. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the address to for +the specified interface name. The value must be in the form of +A.B.C.D/E. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the ip address value using the +default keyword. + +@return [Boolean] Returns True if the command completed successfully. + +set\_mtu configures the IP mtu value of the ip interface in the nodes +configuration. If the enable option is false, then the ip mtu value is +configured using the no keyword. If the default keyword option is +provided and set to true then the ip mtu value is configured using the +default keyword. The default keyword has precedence over the enable +keyword if both options are specified. + +@since eos\_version 4.13.7M + +commands interface mtu no mtu default mtu + +@param name [String] The name of the interface to configure the address +in the node. The name must be the full interface name. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the IP MTU to in the +nodes configuration. Valid values are in the range of 68 to 9214 bytes. +The default is 1500 bytes. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the ip mtu value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_helper\_addresses configures the list of helper addresses on the ip +interface. An IP interface can have one or more helper addresses +configured. If no value is provided, the helper address configuration is +set using the no keyword. If the default option is specified and set to +true, then the helper address values are defaulted using the default +keyword. + +@since eos\_version 4.13.7M + +commands interface ip helper-address no ip helper-address default ip +helper-address + +@param name [String] The name of the interface to configure the address +in the node. The name must be the full interface name. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [Array] The list of IP addresses to configure as +helper address on the interface. The helper addresses must be valid +addresses in the main interface's subnet. + +@option opts default [Boolean] Configure the ip helper address values +using the default keyword. + +value.each { \|addr\| cmds << "ip helper-address {addr}" } if enable + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Logging class manages logging settings on an EOS node. + +get returns the current logging configuration hash extracted from the +nodes running configuration. + +@example { enable: [true, false], hosts: array } + +@return [Hash] Returns the logging resource as a hash +object from the nodes current configuration. + +parse\_enable scans the nodes current running configuration and extracts +the current enabled state of the logging facility. The logging enable +command is expected to always be in the node's configuration. This +methods return value is intended to be merged into the logging resource +hash. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_hosts scans the nodes current running configuration and extracts +the configured logging host destinations if any are configured. If no +logging hosts are configured, then the value for hosts will be an empty +array. The return value is intended to be merged into the logging +resource hash + +@api private + +@return [Hash] Returns the resource hash attribute. + +set\_enable configures the global logging instance on the node as either +enabled or disabled. If the enable keyword is set to true then logging +is globally enabled and if set to false, it is globally disabled. If the +default keyword is specified and set to true, then the configuration is +defaulted using the default keyword. The default keyword option takes +precedence over the enable keyword if both options are specified. + +@since eos\_version 4.13.7M + +commands logging on no logging on default logging on + +@param opts [Hash] Optional keyword arguments + +@option opts enable [Boolean] Enables logging globally if value is true +or disabled logging globally if value is false. + +@option opts default [Boolean] Configure the ip address value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +add\_host configures a new logging destination host address or hostname +to the list of logging destinations. If the host is already configured +in the list of destinations, this method will return successfully. + +@since eos\_version 4.13.7M + +commands logging host + +@param name [String] The host name or ip address of the destination node +to send logging information to. + +@return [Boolean] Returns true if the command completed successfully. +configure "logging host {name}" + +remove\_host deletes a logging destination host name or address form the +list of logging destinations. If the host is not in the list of +configured hosts, this method will still return successfully. + +@since eos\_version 4.13.7M + +commands no logging host + +@param name [String] The host name or ip address of the destination host +to remove from the nodes current configuration. + +@return [Boolean] Returns true if the commands completed successfully. +configure "no logging host {name}" + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Mlag class provides a configuration instance for working with the +global MLAG configuration of the node. + +get scans the current nodes configuration and returns the values as a +Hash describing the current state. + +@example { global: { domain\_id: , local\_interface: , peer\_address: , +peer\_link: , shutdown: }, interfaces: { : { mlag\_id: }, : { mlag\_id: +}, ... } } + +@see parse\_interfaces + +@return [nil, Hash] Returns the resource hash attribute. + +parse\_local\_interface scans the current nodes running configuration +and extracts the mlag local-interface value. If the mlag local-interface +has not been configured, this method will return DEFAULT\_LOCAL\_INTF. +The return value is intended to be merged into the resource hash. + +@api private + +@param config [String] The mlag configuration block retrieved from the +nodes current running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_peer\_address scans the current nodes running configuration and +extracts the mlag peer-address value. If the mlag peer-address has not +been configured, this method will return DEFAULT\_PEER\_ADDR. The return +value is intended to be merged into the resource hash. + +@api private + +@param config [String] The mlag configuration block retrieved from the +nodes current running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_peer\_link scans the current nodes running configuration and +extracts the mlag peer-link value. If the mlag peer-link hash not been +configure, this method will return DEFAULT\_PEER\_LINK. The return value +is intended to be merged into the resource hash. + +@api private + +@param config [String] The mlag configuration block retrieved from the +nodes current running configuration. + +@return [Hash] Returns the resource hash attribute + +parse\_shutdown scans the current nodes mlag configuration and extracts +the mlag shutdown value. The mlag configuration should always return the +value of shutdown from the configuration block. The return value is +intended to be merged into the resource hash. + +@api private + +@param config [String] The mlag configuration block retrieved from the +nodes current running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_interfaces scans the global configuration and returns all of the +configured MLAG interfaces. Each interface returns the configured MLAG +identifier for establishing a MLAG peer. The return value is intended to +be merged into the resource Hash. + +The resource Hash attribute returned contains: \* mlag\_id: (Fixnum) The +configured MLAG identifier. + +@api private + +@return [Hash] Returns the resource Hash attribute. +config = get\_block("^interface {name}") + +set\_domain\_id configures the mlag domain-id value in the current nodes +running configuration. If the enable keyword is false, the the domain-id +is configured with the no keyword. If the default keyword is provided, +the configuration is defaulted using the default keyword. The default +keyword takes precedence over the enable keyword if both options are +specified. + +@since eos\_version 4.13.7M + +commands mlag configuration domain-id no domain-id default domain-id + +@param opts [Hash] Optional keyword arguments + +@option opts value [String] The value to configure the mlag domain-id +to. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the domain-id value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_local\_interface configures the mlag local-interface value in the +current nodes running configuration. If the enable keyword is false, the +local-interface is configured with the no keyword. If the default +keyword is provided, the configuration is defaulted using the default +keyword. The default keyword takes precedence over the enable keyword if +both options are specified + +@since eos\_version 4.13.7M + +commands mlag configuration local-interface no local-interface default +local-interface + +@param opts [Hash] Optional keyword arguments + +@option opts value [String] The value to configure the mlag +local-interface to. The local-interface accepts full interface +identifiers and expects a Vlan interface + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the local-interface value using +the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_peer\_link configures the mlag peer-link value in the current nodes +running configuration. If enable keyword is false, then the peer-link is +configured with the no keyword. If the default keyword is provided, the +configuration is defaulted using the default keyword. The default +keyword takes precedence over the enable keyword if both options are +specified. + +@since eos\_version 4.13.7M + +commands mlag configuration peer-link no peer-link default peer-link + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the mlag peer-link +to. The peer-link accepts full interface identifiers and expects an +Ethernet or Port-Channel interface. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the peer-link using the default +keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_peer\_address configures the mlag peer-address value in the current +nodes running configuration. If the enable keyword is false, then the +peer-address is configured with the no keyword. If the default keyword +is provided, the configuration is defaulted using the default keyword. +The default keyword takes precedence over the enable keyword if both +options are specified + +@since eos\_version 4.13.7M + +commands mlag configuration peer-address no peer-address default +peer-address + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the mlag peer-address +to. The peer-address accepts an IP address in the form of A.B.C.D/E. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the peer-address using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_shutdown configures the administrative state of the mlag process on +the current node. If the enable keyword is true, then mlag is enabled +and if the enable keyword is false, then mlag is disabled. If the +default keyword is provided, the configuration is defaulted using the +default keyword. The default keyword takes precedence over the enable +keyword if both options are specified + +@since eos\_version 4.13.7M + +commands mlag configuration shutdown no shutdown default shutdown + +@param opts [Hash] Optional keyword arguments. + +@option opts enable [Boolean] True if the interface should be +administratively enabled or false if the interface should be +administratively disabled. + +@option opts default [Boolean] Configure the shutdown value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. +Shutdown semantics are opposite of enable semantics so invert enable + +set\_mlag\_id configures the mlag id on the interface in the nodes +current running configuration. If the enable keyword is false, then the +interface mlag id is configured using the no keyword. If the default +keyword is provided and set to true, the interface mlag id is configured +using the default keyword. The default keyword takes precedence over the +enable keyword if both options are specified + +@since eos\_version 4.13.7M + +commands interface mlag no mlag default mlag + +@param name [String] The full interface identifier of the interface to +configure th mlag id for. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String, Integer] The value to configure the +interface mlag to. The mlag id should be in the valid range of 1 to +2000. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the mlag value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Ntp class provides an instance for working with the nodes NTP +configuration. + +get returns the nodes current ntp configure as a resource hash. + +@example { source\_interface: , servers: { prefer: [true, false] } } + +@return [nil, Hash] Returns the ntp resource as a Hash. + +parse\_source\_interface scans the nodes configurations and parses the +ntp source interface if configured. If the source interface is not +configured, this method will return DEFAULT\_SRC\_INTF as the value. The +return hash is intended to be merged into the resource hash. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_servers scans the nodes configuration and parses the configured +ntp server host names and/or addresses. This method will also return the +value of prefer. If no servers are configured, the value will be set to +an empty array. The return hash is intended to be merged into the +resource hash. + +@api private + +@return [Hash] Returns the resource hash attribute. + +set\_source\_interface configures the ntp source value in the nodes +running configuration. If the enable keyword is false, then the ntp +source is configured with the no keyword argument. If the default +keyword argument is provided and set to true, the value is configured +used the default keyword. The default keyword takes precedence over the +enable keyword if both options are specified. + +@since eos\_version 4.13.7M + +commands ntp source no ntp source default ntp source + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the ntp source in the +nodes configuration. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the ntp source value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +add\_server configures a new ntp server destination hostname or ip +address to the list of ntp destinations. The optional prefer argument +configures the server as a preferred (true) or not (false) ntp +destination. + +@param server [String] The IP address or FQDN of the NTP server to be +removed from the configuration. + +@param prefer [Boolean] Appends the prefer keyword argument to the +command if this value is true. + +@return [Boolean] Returns true if the command completed successfully. +cmd = "ntp server {server}" + +remove\_server deletes the provided server destination from the list of +ntp server destinations. If the ntp server does not exist in the list of +servers, this method will return successful + +@param server [String] The IP address or FQDN of the NTP server to be +removed from the configuration. + +@return [Boolean] Returns true if the command completed successfully. +configure("no ntp server {server}") + +set\_prefer will set the prefer keyword for the specified ntp server. If +the server does not already exist in the configuration, it will be added +and the prefer keyword will be set. + +@since eos\_version 4.13.7M + +commands ntp server prefer no ntp server prefer + +@param srv [String] The IP address or hostname of the ntp server to +configure with the prefer value. + +@param value [Boolean] The value to configure for prefer. If true the +prefer value is configured for the server. If false, then the prefer +value is removed. + +@return [Boolean] Returns true if the commands completed successfully. +cmds = "ntp server {srv} prefer" cmds = ["no ntp server {srv} prefer", +"ntp server {srv}"] + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Ospf class is a global class that provides an instance for working +with the node's OSPF configuration. + +Returns the global OSPF configuration from the node. + +rubocop:disable Metrics/MethodLength + +@example { router\_id: areas: { : array }, redistribute: {} } + +@param inst [String] The ospf instance name. + +@return [Hash] A Ruby hash object that provides the OSPF settings as key +/ value pairs. config = get\_block("router ospf {inst}") + +Returns the OSPF configuration from the node as a Ruby hash. + +@example { : { router\_id: , areas: {}, redistribute: {} }, interfaces: +{} } + +@return [Hash] A Ruby hash object that provides the OSPF settings as key +/ value pairs. + +create will create a router ospf with the specified pid. + +@param pid [String] The router ospf to create. + +@return [Boolean] Returns true if the command completed successfully. +configure "router ospf {pid}" + +delete will remove the specified router ospf. + +@param pid [String] The router ospf to remove. + +@return [Boolean] Returns true if the command completed successfully. +configure "no router ospf {pid}" + +set\_router\_id sets router ospf router-id with pid and options. + +@param pid [String] The router ospf name. + +@param opts [hash] Optional keyword arguments. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the router-id to default. + +@return [Boolean] Returns true if the command completed successfully. +cmds = ["router ospf {pid}", cmd] + +add\_network adds network settings for router ospf and network area. + +@param pid [String] The pid for router ospf. + +@param net [String] The network name. + +@param area [String] The network area name. + +@return [Boolean] Returns true if the command completed successfully. +configure ["router ospf {pid}", "network {net} area {area}"] + +remove\_network removes network settings for router ospf and network +area. + +@param pid [String] The pid for router ospf. + +@param net [String] The network name. + +@param area [String] The network area name. + +@return [Boolean] Returns true if the command completed successfully. +configure ["router ospf {pid}", "no network {net} area {area}"] + +set\_redistribute sets router ospf router-id with pid and options. + +@param pid [String] The router ospf name. + +@param proto [String] The redistribute value. + +@param opts [hash] Optional keyword arguments. + +@option opts routemap [String] The route-map value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the router-id to default. + +@return [Boolean] Returns true if the command completed successfully. +cmds = ["router ospf {pid}", "redistribute {proto}"] cmds[1] << " +route-map {routemap}" if routemap + +The OspfInterfaces class is a global class that provides an instance for +working with the node's OSPF interface configuration. + +Returns a single MLAG interface configuration. + +Example { network\_type: } + +@param name [String] The interface name to return the configuration +values for. This must be the full interface identifier. + +@return [nil, Hash] A Ruby hash that represents the MLAG +interface configuration. A nil object is returned if the specified +interface is not configured config = get\_block("interface {name}") + +Returns the collection of MLAG interfaces as a hash index by the +interface name. + +Example { : { network\_type: }, : { network\_type: }, ... } + +@return [nil, Hash] A Ruby hash that represents the MLAG +interface configuration. A nil object is returned if no interfaces are +configured. + +set\_network\_type sets network type with options. + +@param name [String] The name of the interface. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The point-to-point value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the ip ospf network to default. + +@return [Boolean] Returns true if the command completed successfully. + +Copyright (c) 2014, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Prefixlists class provides a configuration instance for working with +static routes in EOS. + +Returns the static routes configured on the node. + +@example { : { next\_hop: , name: } } + +@param name [String] The name of the prefix-list to return. + +@return [Hash The method will return all of the configured static routes +on the node as a Ruby hash object. If there are no static routes +configured, this method will return an empty hash. config = +get\_block("ip prefix-list {name}") + +Returns the static routes configured on the node. + +@example { : { next\_hop: , name: } } + +@return [Hash The method will return all of the configured static routes +on the node as a Ruby hash object. If there are no static routes +configured, this method will return an empty hash. + +create will create a new ip prefix-list with designated name. + +@param name [String] The name of the ip prefix-list. + +@return [Boolean] Returns true if the command completed successfully. +configure "ip prefix-list {name}" + +add\_rule will create an ip prefix-list with the designated name, seqno, +action and prefix. + +@param name [String] The name of the ip prefix-list. + +@param seq [String] The seq value. + +@param action [String] The action value. + +@param prefix [String] The prefix value. + +@return [Boolean] Returns true if the command completed successfully. +cmd = "ip prefix-list {name}" cmd << " seq {seq}" if seq cmd << " +{action} {prefix}" + +delete will remove the designated prefix-list. + +@param name [String] The name of the ip prefix-list. + +@param seq [String] The seq value. + +@return [Boolean] Returns true if the command completed successfully. +cmd = "no ip prefix-list {name}" cmd << " seq {seq}" if seq + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +Radius provides instance methods to retrieve and set radius +configuration values. Regular expression to extract a radius server's +attributes from the running-configuration text. The explicit [ ] spaces +enable line wrapping and indentation with the /x flag. + +get Returns an Array with a single resource Hash describing the current +state of the global radius configuration on the target device. This +method is intended to be used by a provider's instances class method. + +@example { key: , key\_format: , timeout: , retransmit: , servers: } + +@return [Array] Single element Array of resource hashes. + +parse\_time scans the nodes current configuration and parse the +radius-server timeout value. The timeout value is expected to always be +present in the config. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_retransmit scans the cnodes current configuration and parses the +radius-server retransmit value. The retransmit value is expected to +always be present in the config. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_key scans the current nodes running configuration and parse the +global radius-server key and format value. If the key is not configured +this method will return DEFAULT\_KEY and DEFAULT\_KEY\_FORMAT for the +resource hash values. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_servers returns an Array of radius server resource hashes. Each +hash describes the current state of the radius server and is intended to +be merged into the radius resource hash. + +The resource hash returned contains the following information: \* +hostname: hostname or ip address \* vrf: (String) vrf name \* key: +(String) the key either in plain text or hashed format \* key\_format: +(Fixnum) e.g. 0 or 7 \* timeout: (Fixnum) seconds before the timeout +period ends \* retransmit: (Integer), e.g. 3, attempts after first +timeout expiry. \* group: (String) Server group associated with this +server. \* acct\_port: (Fixnum) Port number to use for accounting. \* +accounting\_only: (Boolean) Enable this server for accounting only. \* +auth\_port: (Fixnum) Port number to use for authentication + +@api private + +@return [Array>] Array of resource hashes. + +set\_global\_key configures the global radius-server key. If the enable +option is false, radius-server key is configured using the no keyword. +If the default option is specified, radius-server key is configured +using the default keyword. If both options are specified, the default +keyword option takes precedence. + +@since eos\_version 4.13.7M + +commands radius-server key no radius-server key default radius-server +key + +@option value [String] The value to configure the radius-server key to +in the nodes running configuration. + +@option key\_format [Fixnum] The format of the key to be passed to the +nodes running configuration. Valid values are 0 (clear text) or 7 +(encrypted). The default value is 0 if format is not provided. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option default [Boolean] Configures the radius-server key using the +default keyword argument. + +@return [Boolean] Returns true if the commands complete successfully. +cmds = "radius-server key {key\_format} {value}" + +set\_global\_timeout configures the radius-server timeout value. If the +enable option is false, then radius-server timeout is configured using +the no keyword. If the default option is specified, radius-server +timeout is configured using the default keyword. If both options are +specified then the default keyword takes precedence. + +@since eos\_version 4.13.7M + +commands radius-server timeout no radius-server timeout default +radius-server timeout + +@option value [String, Fixnum] The value to set the global radius-server +timeout value to. This value should be in the range of 1 to 1000. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option default [Boolean] Configures the radius-server timeout value +using the default keyword. + +@return [Boolean] Returns true if the commands complete successfully. + +set\_global\_retransmit configures the global radius-server retransmit +value. If the enable option is false, then the radius-server retransmit +value is configured using the no keyword. If the default option is +specified, the radius-server retransmit value is configured using the +default keyword. If both options are specified then the default keyword +takes precedence. + +@since eos\_version 4.13.7M + +commands radius-server retransmit no radius-server retransmit default +radius-server retransmit + +@option value [String, Fixnum] The value to set the global radius-server +retransmit value to. This value should be in the range of 1 to 100 + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option default [Boolean] Configures the radius-server retransmit value +using the default keyword. + +@return [Boolean] Returns true if the commands complete successfully. + +update\_server configures a radius server resource on the target device. +This API method maps to the ``radius server host`` command, e.g. +``radius-server host 10.11.12.13 auth-port 1024 acct-port 2048 timeout 30 retransmit 5 key 7 011204070A5955``. + +@api public + +@param opts [Hash] The configuration options. + +@option opts key\_format [Integer] The key format value. + +@option opts hostname [String] The host value. + +@option opts vrf [String] The vrf value. + +@option opts auth\_port [String] The auth-port value. + +@option opts acct\_port [String] The acct-port value. + +@option opts timeout [String] The timeout value. + +@option opts retransmit [String] The retransmit value. + +@option opts key [String] The key value. + +@return [Boolean] Returns true if there are no errors. beware: order of +cli keyword options counts cmd = "radius-server host {opts[:hostname]}" +cmd << " vrf {opts[:vrf]}" if opts[:vrf] cmd << " auth-port +{opts[:auth\_port]}" if opts[:auth\_port] cmd << " acct-port +{opts[:acct\_port]}" if opts[:acct\_port] cmd << " timeout +{opts[:timeout]}" if opts[:timeout] cmd << " retransmit +{opts[:retransmit]}" if opts[:retransmit] cmd << " key {key\_format} +{opts[:key]}" if opts[:key] + +remove\_server removes the SNMP server identified by the hostname, +auth\_port, and acct\_port attributes. + +@api public + +@param opts [Hash] The configuration options. + +@option opts hostname [String] The host value. + +@option opts vrf [String] The vrf value. + +@option opts auth\_port [String] The auth-port value. + +@option opts acct\_port [String] The acct-port value. + +@return [Boolean] Returns true if there are no errors. cmd = "no +radius-server host {opts[:hostname]}" cmd << " vrf {opts[:vrf]}" if +opts[:vrf] cmd << " auth-port {opts[:auth\_port]}" if opts[:auth\_port] +cmd << " acct-port {opts[:acct\_port]}" if opts[:acct\_port] + +Copyright (c) 2014, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Routemaps class manages routemaps. A route map is a list of rules +that control the redistribution of IP routes into a protocol domain on +the basis of such criteria as route metrics, access control lists, next +hop addresses, and route tags. + +rubocop:disable Metrics/ClassLength + +get returns a hash of routemap configurations for the given name. + +@example { : { : { match: , set: , continue: , description: }, : { +match: , set: , continue: , description: } }, : { : { match: , set: , +continue: , description: }, : { match: , set: , continue: , description: +} } } + +@param name [String] The routemap name to return a resource for from the +nodes configuration. + +@return [nil, Hash] Returns the routemap resource as a +Hash. If the specified name is not found in the nodes current +configuration a nil object is returned. + +getall returns a collection of routemap resource hashes from the nodes +running configuration. The routemap resource collection hash is keyed by +the unique routemap name. + +@example { : { : { : { match: , set: , continue: , description: }, : { +match: , set: , continue: , description: } }, : { : { match: , set: , +continue: , description: }, : { match: , set: , continue: , description: +} } }, : { : { : { match: , set: , continue: , description: }, : { +match: , set: , continue: , description: } }, : { : { match: , set: , +continue: , description: }, : { match: , set: , continue: , description: +} } } } + +@return [nil, Hash] Returns a hash that represents the +entire routemap collection from the nodes running configuration. If +there are no routemap names configured, this method will return nil. + +parse entries is a private method to get the routemap rules. + +@api private + +@param name [String] The routemap name. + +@return [nil, Hash] Returns a hash that represents the +rules for routemaps from the nodes running configuration. If there are +no routemaps configured, this method will return nil. entries = +config.scan(/^route-map:raw-latex:`\s{name}`:raw-latex:`\s`.+$/) + +parse rule is a private method to parse a rule. + +@api private + +@param rules [Hash] Rules configuration options. + +@option rules match [Array] The match options. + +@option rules set [Array] The set options. + +@option rules continue [String] The continue value. + +@option rules description [String] The description value. + +@return [Hash] Returns a hash that represents the rules +for routemaps from the nodes running configuration. If there are no +routemaps configured, this method will return an empty hash. + +name\_commands is utilized to initially prepare the routemap. + +@param name [String] The routemap name. + +@param action [String] The action value. + +@param seqno [String] The seqno value. + +@param opts [Hash] The configuration options. + +@option opts default [Boolean] The default value. + +@option opts enable [Boolean] The enable value. + +@return [Array] Returns the prepared eos command. cmd = "default +route-map {name}" cmd = "no route-map {name}" cmd = "route-map {name}" +cmd << " {action}" cmd << " {seqno}" + +create will create a new routemap with the specified name. + +rubocop:disable Metrics/MethodLength + +commands route-map action seqno description match set continue + +@param name [String] The name of the routemap to create. + +@param action [String] Either permit or deny. + +@param seqno [Integer] The sequence number value. + +@param opts [hash] Optional keyword arguments. + +@option opts default [Boolean] Set routemap to default. + +@option opts description [String] A description for the routemap. + +@option opts match [Array] routemap match rule. + +@option opts set [String] Sets route attribute. + +@option opts continue [String] The routemap sequence number to continue +on. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the routemap to default. + +@return [Boolean] Returns true if the command completed successfully. +cmds << "description {opts[:description]}" cmds << "continue +{opts[:continue]}" cmds << "match {options}" cmds << "set {options}" + +remove\_match\_statemements removes all match rules for the specified +routemap + +@param name [String] The routemap name. + +@param action [String] The action value. + +@param seqno [String] The seqno value. + +@param cmds [Array] Array of eos commands. + +@return [Boolean] Returns true if the command completed successfully. +cmds << "no match {options}" + +remove\_set\_statemements removes all set rules for the specified +routemap + +@param name [String] The routemap name. + +@param action [String] The action value. + +@param seqno [String] The seqno value. + +@param cmds [Array] Array of eos commands. + +@return [Boolean] Returns true if the command completed successfully. +cmds << "no set {options}" + +delete will delete an existing routemap name from the nodes current +running configuration. If the delete method is called and the routemap +name does not exist, this method will succeed. + +commands no route-map + +@param name [String] The routemap name to delete from the node. + +@param action [String] Either permit or deny. + +@param seqno [Integer] The sequence number. + +@return [Boolean] Returns true if the command completed successfully. +configure(["no route-map {name} {action} {seqno}"]) + +This method will attempt to default the routemap from the nodes +operational config. Since routemaps do not exist by default, the default +action is essentially a negation and the result will be the removal of +the routemap clause. If the routemap does not exist then this method +will not perform any changes but still return True. + +commands no route-map + +@param name [String] The routemap name to set to default. + +@param action [String] Either permit or deny. + +@param seqno [Integer] The sequence number. + +@return [Boolean] Returns true if the command completed successfully. +configure(["default route-map {name} {action} {seqno}"]) + +set\_match\_statements will set the match values for a specified +routemap. If the specified routemap does not exist, it will be created. + +commands route-map action seqno match + +@param name [String] The name of the routemap to create. + +@param action [String] Either permit or deny. + +@param seqno [Integer] The sequence number. + +@param value [Array] The routemap match rules. + +@return [Boolean] Returns true if the command completed successfully. +cmds = ["route-map {name} {action} {seqno}"] cmds << "match {options}" + +set\_set\_statements will set the set values for a specified routemap. +If the specified routemap does not exist, it will be created. + +commands route-map action seqno set + +@param name [String] The name of the routemap to create. + +@param action [String] Either permit or deny. + +@param seqno [Integer] The sequence number. + +@param value [Array] The routemap set rules. + +@return [Boolean] Returns true if the command completed successfully. +cmds = ["route-map {name} {action} {seqno}"] cmds << "set {options}" + +set\_continue will set the continue value for a specified routemap. If +the specified routemap does not exist, it will be created. + +commands route-map action seqno continue + +@param name [String] The name of the routemap to create. + +@param action [String] Either permit or deny. + +@param seqno [Integer] The sequence number. + +@param value [Integer] The continue value. + +@return [Boolean] Returns true if the command completed successfully. +cmds = ["route-map {name} {action} {seqno}"] cmds << "continue {value}" + +set\_description will set the description for a specified routemap. If +the specified routemap does not exist, it will be created. + +commands route-map action seqno description + +@param name [String] The name of the routemap to create. + +@param action [String] Either permit or deny. + +@param seqno [Integer] The sequence number. + +@param value [String] The description value. + +@return [Boolean] Returns true if the command completed successfully. +cmds = ["route-map {name} {action} {seqno}"] cmds << "description +{value}" + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Snmp class provides a class implementation for working with the +nodes SNMP configuration entity. This class presents an abstraction of +the node's snmp configuration from the running config. + +@since eos\_version 4.13.7M + +get returns the snmp resource Hash that represents the nodes snmp +configuration abstraction from the running config. + +@example { location: , contact: , chassis\_id: , source\_interface: } + +@return [Hash] Returns the snmp resource as a Hash. + +parse\_location scans the running config from the node and parses the +snmp location value if it exists in the configuration. If the snmp +location is not configure, then the DEFAULT\_SNMP\_LOCATION string is +returned. The Hash returned by this method is merged into the snmp +resource Hash returned by the get method. + +@api private + +@return [Hash] Returns the resource Hash attribute. + +parse\_contact scans the running config form the node and parses the +snmp contact value if it exists in the configuration. If the snmp +contact is not configured, then the DEFAULT\_SNMP\_CONTACT value is +returned. The Hash returned by this method is merged into the snmp +resource Hash returned by the get method. + +@api private + +@return [Hash] Returns the resource Hash attribute. + +parse\_source\_interface scans the running config from the node and +parses the snmp source interface value if it exists in the +configuration. If the snmp source interface is not configured, then the +DEFAULT\_SNMP\_SOURCE\_INTERFACE value is returned. The Hash returned by +this method is intended to be merged into the snmmp resource Hash. + +@api private + +@return [Hash] Returns the resource Hash attribute. + +parse\_communities scans the running config from the node and parses all +of the configure snmp community strings. If there are no configured snmp +community strings, the community value is set to an empty array. The +returned hash is intended to be merged into the global snmp resource +hash. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_notifications scans the running configuration and parses all of +the snmp trap notifications configuration. It is expected the trap +configuration is in the running config. The returned hash is intended to +be merged into the resource hash. + +set\_notification configures the snmp trap notification for the +specified trap. The name option accepts the snmp trap name to configure +or the keyword all to globally enable or disable notifications. If the +optional state argument is not provided then the default state is +default. + +@since eos\_version 4.13.7M + +commands snmp-server enable traps no snmp-server enable traps default +snmp-server enable traps + +@param opts [Hash] The configuration parameters. + +@option opts name [String] The name of the trap to configure or the +keyword all. If this option is not specified, then the value of 'all' is +used as the default. + +@option opts state [String] The state to configure the trap +notification. Valid values include 'on', 'off' or 'default'. configure +"{state} snmp-server enable traps {name}" + +set\_location updates the snmp location value in the nodes running +configuration. If enable is false, then the snmp location value is +negated using the no keyword. If the default keyword is set to true, +then the snmp location value is defaulted using the default keyword. The +default parameter takes precedence over the enable keyword. + +@since eos\_version 4.13.7M + +commands snmp-server location no snmp-server location default +snmp-server location + +@param opts [Hash] The configuration parameters. + +@option opts value [string] The snmp location value to configure. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the snmp location value using +the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_contact updates the snmp contact value in the nodes running +configuration. If enable is false in the opts Hash then the snmp contact +value is negated using the no keyword. If the default keyword is set to +true, then the snmp contact value is defaulted using the default +keyword. The default parameter takes precedence over the enable keyword. + +@since eos\_version 4.13.7M + +commands snmp-server contact no snmp-server contact default snmp-server +contact + +@param opts [Hash] The configuration parameters. + +@option opts value [string] The snmp contact value to configure. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the snmp contact value using +the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_chassis\_id updates the snmp chassis id value in the nodes running +configuration. If enable is false in the opts Hash then the snmp chassis +id value is negated using the no keyword. If the default keyword is set +to true, then the snmp chassis id value is defaulted using the default +keyword. The default keyword takes precedence over the enable keyword. + +@since eos\_version 4.13.7M + +commands snmp-server chassis-id no snmp-server chassis-id default +snmp-server chassis-id + +@param opts [Hash] The configuration parameters + +@option opts value [string] The snmp chassis id value to configure + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configures the snmp chassis id value +using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +set\_source\_interface updates the snmp source interface value in the +nodes running configuration. If enable is false in the opts Hash then +the snmp source interface is negated using the no keyword. If the +default keyword is set to true, then the snmp source interface value is +defaulted using the default keyword. The default keyword takes +precedence over the enable keyword. + +@since eos\_version 4.13.7M + +commands snmp-server source-interface no snmp-server source-interface +default snmp-server source-interface + +@param opts [Hash] The configuration parameters. + +@option opts value [string] The snmp source interface value to +configure. This method will not ensure the interface is present in the +configuration. @option opts enable [Boolean] If false then the command +is negated. Default is true. @option opts default [Boolean] Configures +the snmp source interface value using the default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +add\_community adds a new snmp community to the nodes running +configuration. This function is a convenience function that passes the +message to set\_community\_access. + +@see set\_community\_access + +@param name [String] The name of the snmp community to add to the nodes +running configuration. + +@param access [String] Specifies the access level to assign to the new +snmp community. Valid values are 'rw' or 'ro'. + +@return [Boolean] Returns true if the command completed successfully. + +remove\_community removes the specified community from the nodes running +configuration. If the specified name is not configured, this method will +still return successfully. + +@since eos\_version 4.13.7M + +commands no snmp-server community + +@param name [String] The name of the snmp community to add to the nodes +running configuration. + +@return [Boolean] Returns true if the command completed successfully. +configure "no snmp-server community {name}" + +set\_community\_acl configures the acl to apply to the specified +community name. When enable is true, it will remove the the named +community and then add the new acl entry. + +@since eos\_version 4.13.7M + +commands no snmp-server [ro\|rw] snmp-server [ro\|rw] + +@param name [String] The name of the snmp community to add to the nodes +running configuration. + +@param opts [Hash] The configuration parameters. + +@option opts value [String] The name of the acl to apply to the snmp +community in the nodes config. If nil, then the community name allows +access to all objects. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the snmp community name using +the default keyword. Default takes precedence over enable. + +@return [Boolean] Returns true if the command completed successfully. +Default is same as negate for this command cmds = ["no snmp-server +community {name}"] cmds << "snmp-server community {name} {access} +{value}" if enable + +set\_community\_access configures snmp-server community with designated +name and access values. + +@param name [String] The snmp-server community name value. + +@param access [String] The snmp-server community access value. + +@return [Boolean] Returns true if the command completed successfully. +configure "snmp-server community {name} {access}" + +Copyright (c) 2014, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Staticroutes class provides a configuration instance for working +with static routes in EOS. + +Returns the static routes configured on the node. + +@example { [ { destination: , nexthop: next\_hop>, +distance: , tag: , name: }, ... ] } + +@return [Array] The method will return all of the configured +static routes on the node as a Ruby array object containing a list of +hashes with each hash describing a route. If there are no static routes +configured, this method will return an empty array. +([^\\s]+):raw-latex:`\s `capture destination ([^\\s$]+) +capture next hop IP or egress interface `:raw-latex:`\s`\|$ <\d+>`__ +capture metric (distance) +[:raw-latex:`\s`\|$]{1}(?:tag:raw-latex:`\s`(:raw-latex:`\d`+))? catpure +route tag [:raw-latex:`\s`\|$]{1}(?:name:raw-latex:`\s`(.+))? capture +route name + +Creates a static route in EOS. May add or overwrite an existing route. + +commands ip route [router\_ip] [distance] [tag ][name ] + +@param destination [String] The destination and prefix matching the +route(s). Ex '192.168.0.2/24'. + +@param nexthop [String] The nexthop for this entry, which may an IP +address or interface name. + +@param opts [Hash] Additional options for the route entry. + +@option opts router\_ip [String] If nexthop is an egress interface, +router\_ip specifies the router to which traffic will be forwarded. + +@option opts distance [String] The administrative distance (metric). + +@option opts tag [String] The route tag. + +@option opts name [String] A route name. + +@return [Boolean] Returns True on success, otherwise False. cmd = "ip +route {destination} {nexthop}" cmd << " {opts[:router\_ip]}" if +opts[:router\_ip] cmd << " {opts[:distance]}" if opts[:distance] cmd << +" tag {opts[:tag]}" if opts[:tag] cmd << " name {opts[:name]}" if +opts[:name] + +Removes a given route from EOS. May remove multiple routes if nexthop is +not specified. + +commands no ip route [nexthop] + +@param destination [String] The destination and prefix matching the +route(s). Ex '192.168.0.2/24'. + +@param nexthop [String] The nexthop for this entry, which may an IP +address or interface name. + +@return [Boolean] Returns True on success, otherwise False. cmd = "no ip +route {destination}" cmd << " {nexthop}" if nexthop + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Stp class provides a base class instance for working with the EOS +spanning-tree configuration. + +get returns the current stp configuration parsed from the nodes current +running configuration. + +@example { mode: instances: { : { priority: } } interfaces: { : { +portfast: , portfast\_type: , bpduguard: } } } + +@return [Hash] returns a Hash of attributes derived from eAPI. + +parse\_mode scans the nodes running configuration and extracts the value +of the spanning-tree mode. The spanning tree mode is expected to be +always be available in the running config. The return value is intended +to be merged into the stp resource hash. + +@api private + +@return [Hash] Resource hash attribute. + +instances returns a memoized instance of StpInstances for configuring +individual stp instances. + +@return [StpInstances] an instance of StpInstances class. + +interfaces returns a memoized instance of StpInterfaces for configuring +individual stp interfaces. + +@return [StpInterfaces] an instance of StpInterfaces class. + +set\_mode configures the stp mode in the global nodes running +configuration. If the enable option is false, then the stp mode is +configured with the no keyword argument. If the default option is +specified then the mode is configured with the default keyword argument. +The default keyword argument takes precedence over the enable option if +both are provided. + +@since eos\_version 4.13.7M + +commands spanning-tree mode no spanning-tree mode default spanning-tree +mode + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the stp mode to in +the nodes current running configuration. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the stp mode value using the +default keyword. + +@return [Boolean] returns true if the command completed successfully. + +The StpInstances class provides a class instance for working with +spanning-tree instances in EOS + +get returns the specified stp instance config parsed from the nodes +current running configuration. + +@example { priority: } + +@param inst [String] The named stp instance to return. + +@return [nil, Hash] Returns all configured stp instances +found in the nodes running configuration. + +parse\_instances will scan the nodes current configuration and extract +the list of configured mst instances. If no instances are configured +then this method will return an empty array. + +@api private + +@return [Array] Returns an Array of configured stp instances. + +parse\_priority will scan the nodes current configuration and extract +the stp priority value for the given stp instance. If the stp instance +priority is not configured, the priority value will be set using +DEFAULT\_STP\_PRIORITY. The returned hash is intended to be merged into +the resource hash. + +@api private + +@return [Hash] Resource hash attribute. priority\_re = +/(?<=^spanning-tree:raw-latex:`\smst`:raw-latex:`\s{inst}`:raw-latex:`\spriority`:raw-latex:`\s`)(.+$)/x + +Deletes a configured MST instance. + +@param inst [String] The MST instance to delete. + +@return [Boolean] True if the commands succeed otherwise False. +configure ['spanning-tree mst configuration', "no instance {inst}", + +Configures the spanning-tree MST priority. + +@param inst [String] The MST instance to configure. + +@param opts [Hash] The configuration parameters for the priority. + +@option opts value [string] The value to set the priority to. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. + +@return [Boolean] True if the commands succeed otherwise False. cmd = +"default spanning-tree mst {inst} priority" cmd = "spanning-tree mst +{inst} priority {value}" cmd = "no spanning-tree mst {inst} priority" + +The StpInterfaces class provides a class instance for working with +spanning-tree interfaces in EOS. + +get returns the configured stp interfaces from the nodes running +configuration as a resource hash. If the specified interface is not +configured as a switchport then this method will return nil. + +@example { portfast: , portfast\_type: , bpduguard: } + +@param name [String] The interface name to return a resource for from +the nodes configuration. + +@return [nil, Hash] Returns the stp interface as a +resource hash. config = get\_block("interface {name}") + +getall returns all of the configured stp interfaces parsed from the +nodes current running configuration. The returned hash is keyed by the +interface name. + +@example { : { portfast: , portfast\_type: , bpduguard: }, : { portfast: +, portfast\_type: , bpduguard: }, ... } + +@return [Hash] Returns the stp interfaces config as a +resource hash from the nodes running configuration. + +parse\_portfast scans the supplied interface configuration block and +parses the value stp portfast. The value of portfast is either enabled +(true) or disabled (false). + +@api private + +@return [Hash] Resource hash attribute. + +parse\_portfast\_type scans the supplied interface configuration block +and parses the value stp portfast type. The value of portfast type is +either not set which implies normal (default), edge, or network. + +@api private + +@return [Hash] Resource hash attribute. + +parse\_bpduguard scans the supplied interface configuration block and +parses the value of stp bpduguard. The value of bpduguard is either +disabled (false) or enabled (true). + +@api private + +@return [Hash] Resource hash attribute. + +Configures the interface portfast value. + +@param name [String] The name of the interface to configure. + +@param opts [Hash] The configuration parameters for portfast. + +@option opts value [Boolean] The value to set portfast. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. + +@return [Boolean] True if the commands succeed otherwise False. + +Configures the interface portfast type value + +@param name [String] The name of the interface to configure. + +@param opts [Hash] The configuration parameters for portfast type. + +@option opts value [String] The value to set portfast type to. The value +must be set for calls to this method. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. + +@return [Boolean] True if the commands succeed otherwise False. cmds = +"default spanning-tree portfast {value}" cmds = "spanning-tree portfast +{value}" cmds = "no spanning-tree portfast {value}" + +Configures the interface bpdu guard value + +@param name [String] The name of the interface to configure. + +@param opts [Hash] The configuration parameters for bpduguard. + +@option opts value [Boolean] The value to set bpduguard. + +@option opts enable [Boolean] If false then the bpduguard is disabled. +If true then the bpduguard is enabled. Default is true. + +@option opts default [Boolean] The value should be set to default. + +@return [Boolean] True if the commands succeed otherwise False. + +Copyright (c) 2014,2015 Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Switchport class provides a base class instance for working with +logical layer-2 interfaces. + +Retrieves the properties for a logical switchport from the +running-config using eAPI. + +Example { "name": , "mode": [access, trunk], "trunk\_allowed\_vlans": +array "trunk\_native\_vlan": , "access\_vlan": , "trunk\_groups": array +} + +@param name [String] The full name of the interface to get. The +interface name must be the full interface (ie Ethernet, not Et). + +@return [Hash] Returns a hash that includes the switchport properties. +config = get\_block("interface {name}") + +parse\_mode parses switchport mode from the provided config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_access\_vlan parses access vlan from the provided config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_trunk\_native\_vlan parses trunk native vlan from the provided +config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_trunk\_allowed\_vlans parses trunk allowed vlan from the provided +config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] Returns the resource hash attribute. + +parse\_trunk\_groups parses trunk group values from the provided config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] Returns the resource hash attribute. + +Retrieves all switchport interfaces from the running-config. + +@example { : { mode: , access\_vlan: , trunk\_native\_vlan: , +trunk\_allowed\_vlans: , trunk\_groups: }, : { mode: , access\_vlan: , +trunk\_native\_vlan: , trunk\_allowed\_vlans: , trunk\_groups: }, ... } + +@return [Array] Returns an array of switchport hashes. + +Creates a new logical switchport interface in EOS. + +@param name [String] The name of the logical interface. + +@return [Boolean] Returns True if it succeeds otherwise False. configure +["interface {name}", 'no ip address', 'switchport'] + +Deletes a logical switchport interface from the running-config. + +@param name [String] The name of the logical interface. + +@return [Boolean] Returns True if it succeeds otherwise False. configure +["interface {name}", 'no switchport'] + +Defaults a logical switchport interface in the running-config. + +@param name [String] The name of the logical interface. + +@return [Boolean] Returns True if it succeeds otherwise False. configure +["interface {name}", 'default switchport'] + +Configures the switchport mode for the specified interface. + +@param name [String] The name of the interface to configure. + +@param opts [Hash] The configuration parameters for the interface. + +@option opts value [string] The value to set the mode to. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. + +@return [Boolean] Returns True if the commands succeed otherwise False. + +set\_trunk\_allowed\_vlans configures the list of vlan ids that are +allowed on the specified trunk port. If the enable option is set to +false, then the allowed trunks is configured using the no keyword. If +the default keyword is provided then the allowed trunks is configured +using the default keyword. The default option takes precedence over the +enable option if both are specified. + +@since eos\_version 4.13.7M + +commands switchport trunk allowed vlan add no switchport trunk allowed +vlan default switchport trunk allowed vlan + +@param name [String] The name of the interface to configure. + +@param opts [Hash] The configuration parameters for the interface. + +@option ots value [Array] The list of vlan ids to configure on the +switchport to be allowed. This value must be an array of valid vlan ids. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option default [Boolean] Configures the switchport trunk allowed vlans +command using the default keyword. Default takes precedence over enable. + +@return [Boolean] Returns true if the commands complete successfully. +"switchport trunk allowed vlan {value}"] + +Configures the trunk port native vlan for the specified interface. This +value is only valid if the switchport mode is configure as trunk. + +@param name [String] The name of the interface to configure. + +@param opts [Hash] The configuration parameters for the interface. + +@option opts value [string] The value of the trunk native vlan. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. +Default takes precedence over enable. + +@return [Boolean] Returns True if the commands succeed otherwise False. + +Configures the access port vlan for the specified interface. This value +is only valid if the switchport mode is configure in access mode. + +@param name [String] The name of the interface to configure. + +@param opts [Hash] The configuration parameters for the interface. + +@option opts value [string] The value of the access vlan. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default +Default takes precedence over enable. + +@return [Boolean] Returns True if the commands succeed otherwise False. + +Configures the trunk group vlans for the specified interface. Trunk +groups not currently set are added and trunk groups currently configured +but not in the passed in value array are removed. + +@param name [String] The name of the interface to configure. + +@param opts [Hash] The configuration parameters for the interface. + +@option opts value [string] Set of values to configure the trunk group. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default +Default takes precedence over enable. + +@return [Boolean] Returns True if the commands succeed otherwise False. +Add trunk groups that are not currently in the list. cmds << "switchport +trunk group {group}" Remove trunk groups that are not in the new list. +cmds << "no switchport trunk group {group}" + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace + +Api is module namespace for working with the EOS command API. + +The System class configures the node system services such as hostname +and domain name. + +Returns the system settings for hostname, iprouting, and banners. + +@example { hostname: , iprouting: , banner\_motd: , banner\_login: } + +@return [Hash] A Ruby hash object that provides the system settings as +key/value pairs. + +parse\_hostname parses hostname values from the provided config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] The resource hash attribute. + +parse\_iprouting parses ip routing from the provided config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] The resource hash attribute. + +Parses the global config and returns the value for both motd and login +banners. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] The resource hash attribute. If the +banner is not set it will return a value of None for that key. + +Configures the system hostname value in the running-config. + +@param opts [Hash] The configuration parameters. + +@option opts value [string] The value to set the hostname to. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] If true configure the command using the +default keyword. Default is false. + +@return [Boolean] Returns true if the command completed successfully. + +Configures the state of global ip routing. + +@param opts [Hash] The configuration parameters. + +@option opts enable [Boolean] True if ip routing should be enabled or +False if ip routing should be disabled. Default is true. + +@option opts default [Boolean] If true configure the command using the +default keyword. Default is false. + +@return [Boolean] Returns true if the command completed successfully. + +Configures system banners. + +@param banner\_type [String] Banner to be changed (likely either login +or motd). + +@param opts [Hash] The configuration parameters. + +@option opts value [string] The value to set for the banner. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] If true configure the command using the +default keyword. Default is false. + +@return [Boolean] Returns true if the command completed successfully. +cmd\_string = "banner {banner\_type}" + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +Tacacs provides instance methods to retrieve and set tacacs +configuration values. Regular expression to extract a tacacs server's +attributes from the running-configuration text. The explicit [ ] spaces +enable line wrapping and indentation with the /x flag. Default Tacacs +TCP port + +getall Returns an Array with a single resource Hash describing the +current state of the global tacacs configuration on the target device. +This method is intended to be used by a provider's instances class +method. + +@example { name: , enable: , key: , key\_format: , timeout: } + +@return [Array] Single element Array of resource hashes. + +parse\_global\_key takes a running configuration as a string and parses +out the radius global key and global key format if it exists in the +configuration. An empty Hash is returned if there is no global key +configured. The intent of the Hash is to be merged into a property hash. + +@api private + +@return [Hash] Returns the resource hash attributes. + +parse\_global\_timeout takes a running configuration as a string and +parses out the tacacs global timeout if it exists in the configuration. +An empty Hash is returned if there is no global timeout value +configured. The intent of the Hash is to be merged into a property hash. + +@api private + +@return [Hash] Returns the resource hash attributes. + +servers returns an Array of tacacs server resource hashes. Each hash +describes the current state of the tacacs server and is suitable for use +in initializing a tacacs\_server provider. + +The resource hash returned contains the following information: + +- hostname: hostname or ip address, part of the identifier. +- port: (Fixnum) TCP port of the server, part of the identifier. +- key: (String) the key either in plain text or hashed format. +- key\_format: (Fixnum) e.g. 0 or 7. +- timeout: (Fixnum) seconds before the timeout period ends. +- multiplex: (Boolean) true when configured to make requests through a + single connection. + +@api public + +@return [Array>] Array of resource hashes. + +set\_global\_key configures the tacacs default key. This method maps to +the ``tacacs-server key`` EOS configuration command, e.g. +``tacacs-server key 7 070E234F1F5B4A``. + +@option opts key [String] ('070E234F1F5B4A') The key value. + +@option opts key\_format [Fixnum] (7) The key format, 0 for plain text +and 7 for a hashed value. 7 will be assumed if this option is not +provided. + +@api public + +@return [Boolean] Returns true if no errors. result = +api.config("tacacs-server key {format} {key}") + +set\_timeout configures the tacacs default timeout. This method maps to +the ``tacacs-server timeout`` setting. + +@param opts [Hash] The configuration parameters. + +@option opts value [string] The value to set the timeout to. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. + +@api public + +@return [Boolean] Returns true if no errors. + +update\_server configures a tacacs server resource on the target device. +This API method maps to the ``tacacs server host`` command, e.g. +``tacacs-server host 1.2.3.4 single-connection port 4949 timeout 6 key 7 06070D221D1C5A``. + +@api public + +@param opts [Hash] The configuration parameters. + +@option opts key\_format [Integer] The format for the key. + +@option opts hostname [String] The host value. + +@option opts multiplex [String] Defines single-connection. + +@option opts port [String] The port value. + +@option opts timeout [String] The timeout value. + +@option opts key [String] The key value. + +@return [Boolean] Returns true if there are no errors. cmd = +"tacacs-server host {opts[:hostname]}" cmd << " port {opts[:port]}" if +opts[:port] cmd << " timeout {opts[:timeout]}" if opts[:timeout] cmd << +" key {key\_format} {opts[:key]}" if opts[:key] + +remove\_server removes the tacacs server identified by the hostname, and +port attributes. + +@api public + +@param opts [Hash] The configuration parameters. + +@option hostname [String] The host value. + +@option port [String] The port value. + +@return [Boolean] Returns true if there are no errors. cmd = "no +tacacs-server host {opts[:hostname]}" cmd << " port {opts[:port]}" if +opts[:port] + +Copyright (c) 2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Users class provides configuration of local user resources for an +EOS node. The regex used here parses the running configuration to find +all username entries. There is extra logic in the regular expression to +store the username as 'user' and then creates a back reference to find a +following configuration line that might contain the users sshkey. + +get returns the local user configuration. + +@example { name: , privilege: , role: , nopassword: , encryption: +<'cleartext', 'md5', 'sha512'> secret: , sshkey: } + +@param name [String] The user name to return a resource for from the +nodes configuration + +@return [nil, Hash] Returns the user resource as a Hash. +If the specified user name is not found in the nodes current +configuration a nil object is returned. The regex used here parses the +running configuration to find one username entry. user\_re = +Regexp.new(/^username:raw-latex:`\s`+(?{name}):raw-latex:`\s`+ +(username:raw-latex:`\s`+{name}:raw-latex:`\s`+ + +getall returns a collection of user resource hashes from the nodes +running configuration. The user resource collection hash is keyed by the +unique user name. + +@example [ : { name: , privilege: , role: +, nopassword: , encryption: <'cleartext', 'md5', +'sha512'> secret: , sshkey: }, : { name: +, privilege: , role: , nopassword: , +encryption: <'cleartext', 'md5', 'sha512'> secret: , sshkey: + }, ... ] + +@return [Hash] Returns a hash that represents the entire +user collection from the nodes running configuration. If there are no +user names configured, this method will return an empty hash. + +parse\_user\_entry maps the tokens find to the hash entries. + +@api private + +@param user [Array] An array of values returned from the regular +expression scan of the nodes configuration. + +@return [Hash] Returns the resource hash attribute. Map +the encryption value if set, if there is no mapping then just return the +value. + +create will create a new user name resource in the nodes current +configuration with the specified user name. Creating users require +either a secret (password) or the nopassword keyword to be specified. +Optional parameters can be passed in to initialize user name specific +settings. + +@since eos\_version 4.13.7M + +commands username nopassword privilege role username secret [0,5,sha512] +... + +@param name [String] The name of the user to create. + +@param opts [hash] Optional keyword arguments. + +@option opts nopassword [Boolean] Configures the user to be able to +authenticate without a password challenge. + +@option opts secret [String] The secret (password) to assign to this +user. + +@option opts encryption [String] Specifies how the secret is encoded. +Valid values are "cleartext", "md5", "sha512". The default is +"cleartext". + +@option opts privilege [String] The privilege value to assign to the +user. + +@option opts role [String] The role value to assign to the user. + +@option opts sshkey [String] The sshkey value to assign to the user. + +@return [Boolean] Returns true if the command completed successfully. +cmd = "username {name}" cmd << " privilege {opts[:privilege]}" if +opts[:privilege] cmd << " role {opts[:role]}" if opts[:role] Map the +encryption value if set, if there is no mapping then just return the +value. fail ArgumentError, "invalid encryption value: {enc}" cmd << " +secret {enc} {opts[:secret]}" cmds << "username {name} sshkey +{opts[:sshkey]}" if opts[:sshkey] + +delete will delete an existing user name from the nodes current running +configuration. If the delete method is called and the user name does not +exist, this method will succeed. + +@since eos\_version 4.13.7M + +commands no username + +@param name [String] The user name to delete from the node. + +@return [Boolean] Returns true if the command completed successfully. +configure("no username {name}") + +default will configure the user name using the default keyword. This +command has the same effect as deleting the user name from the nodes +running configuration. + +@since eos\_version 4.13.7M + +commands default username + +@param name [String] The user name to default in the nodes +configuration. + +@return [Boolean] Returns true if the command complete successfully. +configure("default username {name}") + +set\_privilege configures the user privilege value for the specified +user name in the nodes running configuration. If enable is false in the +opts keyword Hash then the name value is negated using the no keyword. +If the default keyword is set to true, then the privilege value is +defaulted using the default keyword. The default keyword takes +precedence over the enable keyword + +@since eos\_version 4.13.7M + +commands username privilege no username privilege default username +privilege + +@param name [String] The user name to default in the nodes +configuration. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The privilege value to assign to the user. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the user privilege value using +the default keyword. + +@return [Boolean] Returns true if the command completed successfully. +configure(command\_builder("username {name} privilege", opts)) + +set\_role configures the user role value for the specified user name in +the nodes running configuration. If enable is false in the opts keyword +Hash then the name value is negated using the no keyword. If the default +keyword is set to true, then the role value is defaulted using the +default keyword. The default keyword takes precedence over the enable +keyword + +@since eos\_version 4.13.7M + +commands username role no username role default username role + +@param name [String] The user name to default in the nodes +configuration. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The role value to assign to the user. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the user role value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. +configure(command\_builder("username {name} role", opts)) + +set\_sshkey configures the user sshkey value for the specified user name +in the nodes running configuration. If enable is false in the opts +keyword Hash then the name value is negated using the no keyword. If the +default keyword is set to true, then the sshkey value is defaulted using +the default keyword. The default keyword takes precedence over the +enable keyword. + +@since eos\_version 4.13.7M + +commands username sshkey no username sshkey default username sshkey + +@param name [String] The user name to default in the nodes +configuration. + +@param opts [Hash] Optional keyword arguments + +@option opts value [String] The sshkey value to assign to the user + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the user sshkey value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. +configure(command\_builder("username {name} sshkey", opts)) + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Varp class provides an instance for working with the global VARP +configuration of the node. + +Returns the global VARP configuration from the node. + +@example { mac\_address: , interfaces: { : { addresses: }, : { +addresses: }, ... } } + +@return [Hash] A Ruby hash object that provides the Varp settings as key +/ value pairs. + +parse\_mac\_address parses mac-address values from the provided config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] Returns the resource hash attribute. ip +virtual-router mac-address value will always be stored in +aa:bb:cc:dd:ee:ff format. + +Configure the VARP virtual-router mac-address value. + +@param opts [Hash] The configuration parameters. + +@option opts value [string] The value to set the mac-address to. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. + +@return [Boolean] Returns true if the command completed successfully. + +The VarpInterfaces class provides an instance for working with the +global VARP interface configuration of the node. + +Returns a single VARP interface configuration. + +@example { "addresses": array } + +@param name [String] The interface name to return the configuration +values for. This must be the full interface identifier. + +@return [nil, Hash] A Ruby hash that represents the VARP +interface configuration. A nil object is returned if the specified +interface is not configured config = get\_block("^interface {name}") + +Returns the collection of MLAG interfaces as a hash index by the +interface name. + +@example { : { addresses: }, : { addresses: }, ... } + +@return [nil, Hash] A Ruby hash that represents the MLAG +interface configuration. A nil object is returned if no interfaces are +configured. + +parse\_addresses parses ip virtual-router address from the provided +config. + +@api private + +@param config [String] The configuration block returned from the node's +running configuration. + +@return [Hash] Returns the resource hash attribute. + +The set\_addresses method assigns one or more virtual IPv4 address to +the specified VLAN interface. All existing addresses are removed before +the ones in value are added. + +@param name [String] The name of the interface. The name argument must +be the full interface name. Valid interfaces are restricted to VLAN +interfaces. + +@param opts [Hash] The configuration parameters. + +@option opts value [Array] Array of IPv4 addresses to add to the virtual +router. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] The value should be set to default. + +@return [Boolean] True if the commands succeeds otherwise False. cmds = +["interface {name}"] cmds << "ip virtual-router address {addr}" + +The add\_address method assigns one virtual IPv4 address. + +@param name [String] The name of the interface. The name argument must +be the full interface name. Valid interfaces are restricted to VLAN +interfaces. + +@param value [string] The virtual router address to add. + +@return [Boolean] True if the commands succeeds otherwise False. +configure(["interface {name}", "ip virtual-router address {value}"]) + +The remove\_address method removes one virtual IPv4 address. + +@param name [String] The name of the interface. The name argument must +be the full interface name. Valid interfaces are restricted to VLAN +interfaces. + +@param value [string] The virtual router address to remove. + +@return [Boolean] True if the commands succeeds otherwise False. +configure(["interface {name}", "no ip virtual-router address {value}"]) + +Copyright (c) 2014,2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Rbeapi toplevel namespace. + +Api is module namespace for working with the EOS command API. + +The Vlan class provides a class implementation for working with the +collection of Vlans on the node. This class presents an abstraction of +the nodes configured vlan id's from the running configuration. + +@since eos\_version 4.13.7M + +get returns the specified vlan resource Hash that represents the nodes +current vlan configuration. + +@example { name: , state: , trunk\_groups: array[] Returns the vlan resource as a Hash. +If the specified vlan id is not found in the nodes current configuration +a nil object is returned. config = get\_block("vlan {id}") + +getall returns the collection of vlan resources from the nodes running +configuration as a hash. The vlan resource collection hash is keyed by +the unique vlan id. + +@example { : { name: , state: , trunk\_groups: array[] Returns a hash that represents the entire +vlan collection from the nodes running configuration. If there are no +vlans configured, this method will return an empty hash. + +parse\_name scans the provided configuration block and parses the vlan +name value. The vlan name should always return a value from the running +configuration. The return value is intended to be merged into the +resource hash. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_state scans the provided configuration block and parses the vlan +state value. The vlan state should always return a value from the nodes +running configuration. The return hash is intended to be merged into the +resource hash. + +@api private + +@return [Hash] Returns the resource hash attribute. + +parse\_trunk\_groups scans the provided configuration block and parses +the trunk groups. If no trunk groups are found in the nodes running +configuration then an empty array is returned as the value. The return +hash is intended to be merged into the resource hash. + +@api private + +@return [Hash] Returns the resource hash attribute. + +create will create a new vlan resource in the nodes current +configuration with the specified vlan id. If the create method is called +and the vlan id already exists, this method will still return true. + +@since eos\_version 4.13.7M + +commands vlan + +@param id [String, Integer] The vlan id to create on the node. The vlan +id must be in the valid range of 1 to 4094. + +@return [Boolean] Returns true if the command completed successfully. +configure("vlan {id}") + +delete will delete an existing vlan resource from the nodes current +running configuration. If the delete method is called and the vlan id +does not exist, this method will succeed. + +@since eos\_version 4.13.7M + +commands no vlan + +@param id [String, Integer] The vlan id to delete from the node. The id +value should be in the valid range of 1 to 4094. + +@return [Boolean] Returns true if the command completed successfully. +configure("no vlan {id}") + +default will configure the vlan using the default keyword. This command +has the same effect as deleting the vlan from the nodes running +configuration. + +@since eos\_version 4.13.7M + +commands default vlan + +@param id [String, Integer] The vlan id to default in the nodes +configuration. Ths vid value should be in the valid range of 1 to 4094. + +@return [Boolean] Returns true if the command complete successfully. +configure("default vlan {id}") + +set\_name configures the name value for the specified vlan id in the +nodes running configuration. If enable is false in the opts keyword Hash +then the name value is negated using the no keyword. If the default +keyword is set to true, then the name value is defaulted using the +default keyword. The default keyword takes precedence over the enable +keyword. + +@since eos\_version 4.13.7M + +commands vlan name no name default name + +@param id [String, Integer] The vlan id to apply the configuration to. +The id value should be in the valid range of 1 to 4094. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the vlan name to in +the node configuration. The name parameter accepts a-z, 0-9 and \_. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the vlan name value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. +cmds = ["vlan {id}", cmd] + +set\_state configures the state value for the specified vlan id in the +nodes running configuration. If enable is set to false in the opts +keyword Hash then the state value is negated using the no keyword. If +the default keyword is set to true, then the state value is defaulted +using the default keyword. The default keyword takes precedence over the +enable keyword + +@since eos\_version 4.13.7M + +commands vlan state [active, suspend] no state default state + +@param id [String, Integer] The vlan id to apply the configuration to. +The id value should be in the valid range of 1 to 4094. + +@param opts [Hash] Optional keyword arguments. + +@option opts value [String] The value to configure the vlan state to in +the node's configuration. Accepted values are 'active' or 'suspend'. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the vlan state value using the +default keyword. + +@return [Boolean] Returns true if the command completed successfully. + +@raise [ArgumentError] if the value is not in the accept list of values. +cmds = ["vlan {id}", cmd] + +add\_trunk\_group adds a new trunk group value to the specified vlan id +in the nodes running configuration. The trunk group name value accepts +a-z 0-9 and \_. + +@since version 4.13.7M + +commands vlan trunk group + +@param id [String, Integer] The vlan id to apply the configuration to. +the id value should be in the range of 1 to 4094 + +@param value [String] The value to add to the vlan id configuration on +the node. + +@return [Boolean] Returns true if the command completed successfully. +configure(["vlan {id}", "trunk group {value}"]) + +remove\_trunk\_group removes the specified trunk group value from the +specified vlan id in the node's configuration. If the trunk group name +does not exist, this method will return success + +@since eos\_version 4.13.7M + +commands vlan no trunk group + +@param id [String, Integer] The vlan id to apply the configuration to. +the id value should be in the range of 1 to 4094. + +@param value [String] The value to remove from the list of trunk group +names configured for the specified vlan. + +configure(["vlan {id}", "no trunk group {value}"]) + +Copyright (c) 2015, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +Eos is the toplevel namespace for working with Arista EOS nodes. + +Api is module namespace for working with the EOS command API. + +The Vrrp class manages the set of virtual routers. rubocop:disable +Metrics/ClassLength + +get returns the all the virtual router IPs for the given layer 3 +interface name from the nodes current configuration. + +rubocop:disable Metrics/MethodLength + +@example { 1: { enable: primary\_ip: priority: description: +secondary\_ip: [ , ] ip\_version: timers\_advertise: +mac\_addr\_adv\_interval: preempt: preempt\_delay\_min: +preempt\_delay\_reload: delay\_reload: track: [ { name: 'Ethernet3', +action: 'decrement', amount: 33 }, { name: 'Ethernet2', action: +'decrement', amount: 22 }, { name: 'Ethernet2', action: 'shutdown' } ] } +} + +@param name [String] The layer 3 interface name. + +@return [nil, Hash] Returns the VRRP resource as a Hash +with the virtual router ID as the key. If the interface name does not +exist then a nil object is returned. config = get\_block("^interface +{name}") Parse the vrrp configuration for the vrid(s) in the list + +getall returns the collection of virtual router IPs for all the layer 3 +interfaces from the nodes running configuration as a hash. The resource +collection hash is keyed by the ACL name. + +@example { 'Vlan100': { 1: { data }, 250: { data }, }, 'Vlan200': { 2: { +data }, 250: { data }, } } + +@return [nil, Hash] Returns a hash that represents the +entire virtual router IPs collection for all the layer 3 interfaces from +the nodes running configuration. If there are no virtual routers +configured, this method will return an empty hash. + +parse\_primary\_ip scans the nodes configurations for the given virtual +router id and extracts the primary IP. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'primary\_ip', String>] Where string is the IPv4 address +or nil if the value is not set. match = +config.scan(/^:raw-latex:`\s`+vrrp {vrid} ip +(:raw-latex:`\d`+.:raw-latex:`\d`+.:raw-latex:`\d`+.:raw-latex:`\d`+)$/) + +parse\_priority scans the nodes configurations for the given virtual +router id and extracts the priority value. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'priority', Integer>] The priority is between <1-255> or +nil if the value is not set. match = config.scan(/^:raw-latex:`\s`+vrrp +{vrid} priority (:raw-latex:`\d`+)$/) + +parse\_timers\_advertise scans the nodes configurations for the given +virtual router id and extracts the timers advertise value. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [nil, Hash<'timers\_advertise', Integer>] The timers\_advertise +is between <1-255> or nil if the value is not set. match = +config.scan(/^:raw-latex:`\s`+vrrp {vrid} timers advertise +(:raw-latex:`\d`+)$/) + +parse\_preempt scans the nodes configurations for the given virtual +router id and extracts the preempt value. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [nil, Hash<'preempt', Integer>] The preempt is between <1-255> +or nil if the value is not set. match = +config.scan(/^:raw-latex:`\s`+vrrp {vrid} preempt$/) + +parse\_enable scans the nodes configurations for the given virtual +router id and extracts the enable value. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'enable', Boolean>] match = +config.scan(/^:raw-latex:`\s`+vrrp {vrid} shutdown$/) + +parse\_secondary\_ip scans the nodes configurations for the given +virtual router id and extracts the secondary\_ip value. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [nil, Hash<'secondary\_ip', Array>] Returns an empty +array if the value is not set. regex = "vrrp {vrid} ip" matches = +config.scan(/^:raw-latex:`\s`+{regex} +(:raw-latex:`\d`+.:raw-latex:`\d`+.:raw-latex:`\d`+.:raw-latex:`\d`+) +secondary$/) + +parse\_description scans the nodes configurations for the given virtual +router id and extracts the description. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [nil, Hash<'secondary\_ip', String>] Returns nil if the value is +not set. match = config.scan(/^:raw-latex:`\s`+vrrp {vrid} +description:raw-latex:`\s`+(.\*):raw-latex:`\s*`$/) + +parse\_track scans the nodes configurations for the given virtual router +id and extracts the track entries. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'track', Array] Returns an empty array if the +value is not set. An example array of hashes follows: { name: +'Ethernet3', action: 'decrement', amount: 33 }, { name: 'Ethernet2', +action: 'decrement', amount: 22 }, { name: 'Ethernet2', action: +'shutdown' } pre = "vrrp {vrid} track " +config.scan(/^:raw-latex:`\s`+{pre}(:raw-latex:`\S`+) +(decrement\|shutdown):raw-latex:`\s*`(?:(:raw-latex:`\d`+\ :math:`|`))/) + +parse\_ip\_version scans the nodes configurations for the given virtual +router id and extracts the IP version. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'ip\_version', Integer>] Returns nil if the value is not +set. match = config.scan(/^:raw-latex:`\s`+vrrp {vrid} ip version +(:raw-latex:`\d`+)$/) + +parse\_mac\_addr\_adv\_interval scans the nodes configurations for the +given virtual router id and extracts the mac address advertisement +interval. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'mac\_addr\_adv\_interval', Integer>] Returns nil if the +value is not set. regex = "vrrp {vrid} mac-address +advertisement-interval" match = config.scan(/^:raw-latex:`\s`+{regex} +(:raw-latex:`\d`+)$/) + +parse\_preempt\_delay\_min scans the nodes configurations for the given +virtual router id and extracts the preempt delay minimum value. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'preempt\_delay\_min', Integer>] Returns nil if the value +is not set. match = config.scan(/^:raw-latex:`\s`+vrrp {vrid} preempt +delay minimum (:raw-latex:`\d`+)$/) + +parse\_preempt\_delay\_reload scans the nodes configurations for the +given virtual router id and extracts the preempt delay reload value. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'preempt\_delay\_reload', Integer>] Returns nil if the +value is not set. match = config.scan(/^:raw-latex:`\s`+vrrp {vrid} +preempt delay reload (:raw-latex:`\d`+)$/) + +parse\_delay\_reload scans the nodes configurations for the given +virtual router id and extracts the delay reload value. + +@api private + +@param config [String] The interface config. + +@param vrid [String] The virtual router id. + +@return [Hash<'delay\_reload', Integer>] Returns empty hash if the value +is not set. match = config.scan(/^:raw-latex:`\s`+vrrp {vrid} delay +reload (:raw-latex:`\d`+)$/) + +create will create a new virtual router ID resource for the interface in +the nodes current. If the create method is called and the virtual router +ID already exists for the interface, this method will still return true. +Create takes optional parameters, but at least one parameter needs to be +set or the command will fail. + +@since eos\_version 4.13.7M + +commands interface vrrp ... + +@param name [String] The layer 3 interface name. + +@param vrid [String] The virtual router id. + +@param opts [hash] Optional keyword arguments. + +@option opts enable [Boolean] Enable the virtual router. + +@option opts primary\_ip [String] The primary IPv4 address. + +@option opts priority [Integer] The priority setting for a virtual +router. + +@option opts description [String] Associates a text string to a virtual +router. + +@option opts secondary\_ip [Array] The secondary IPv4 address to the +specified virtual router. + +@option opts ip\_version [Integer] Configures the VRRP version for the +VRRP router. + +@option opts timers\_advertise [Integer] The interval between successive +advertisement messages that the switch sends to routers in the specified +virtual router ID. + +@option opts mac\_addr\_adv\_interval [Integer] Specifies interval in +seconds between advertisement packets sent to VRRP group members. + +@option opts preempt [Boolean] A virtual router preempt mode setting. +When preempt mode is enabled, if the switch has a higher priority it +will preempt the current master virtual router. When preempt mode is +disabled, the switch can become the master virtual router only when a +master virtual router is not present on the subnet, regardless of +priority settings. + +@option opts preempt\_delay\_min [Integer] Interval in seconds between +VRRP preempt event and takeover. Minimum delays takeover when VRRP is +fully implemented. + +@option opts preempt\_delay\_reload [Integer] Interval in seconds +between VRRP preempt event and takeover. Reload delays takeover after +initialization following a switch reload. + +@option opts delay\_reload [Integer] Delay between system reboot and +VRRP initialization. + +@option opts track [Array] The track hash contains the name of an +interface to track, the action to take on state-change of the tracked +interface, and the amount to decrement the priority. + +@return [Boolean] Returns true if the command completed successfully. +cmds << "no vrrp {vrid} shutdown" cmds << "vrrp {vrid} shutdown" cmds << +"vrrp {vrid} ip {opts[:primary\_ip]}" if opts.key?(:primary\_ip) cmds << +"vrrp {vrid} priority {opts[:priority]}" cmds << "vrrp {vrid} +description {opts[:description]}" cmds << "vrrp {vrid} ip version +{opts[:ip\_version]}" cmds << "vrrp {vrid} timers advertise +{opts[:timers\_advertise]}" cmds << "vrrp {vrid} mac-address +advertisement-interval {val}" cmds << "vrrp {vrid} preempt" cmds << "no +vrrp {vrid} preempt" cmds << "vrrp {vrid} preempt delay minimum {val}" +cmds << "vrrp {vrid} preempt delay reload {val}" cmds << "vrrp {vrid} +delay reload {opts[:delay\_reload]}" + +delete will delete the virtual router ID on the interface from the nodes +current running configuration. If the delete method is called and the +virtual router id does not exist on the interface, this method will +succeed. + +@since eos\_version 4.13.7M + +commands interface no vrrp + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@return [Boolean] Returns true if the command completed successfully. +configure\_interface(name, "no vrrp {vrid}") + +default will default the virtual router ID on the interface from the +nodes current running configuration. This command has the same effect as +deleting the virtual router id from the interface in the nodes running +configuration. If the default method is called and the virtual router id +does not exist on the interface, this method will succeed. + +@since eos\_version 4.13.7M + +commands interface default vrrp + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@return [Boolean] Returns true if the command complete successfully. +configure\_interface(name, "default vrrp {vrid}") + +set\_shutdown enables and disables the virtual router. + +commands interface {no \| default} vrrp shutdown + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts enable [Boolean] If enable is true then the virtual router +is administratively enabled for the interface and if enable is false +then the virtual router is administratively disabled for the interface. +Default is true. + +@option opts default [Boolean] Configure shutdown using the default +keyword. + +@return [Boolean] Returns true if the command complete successfully. +Shutdown semantics are opposite of enable semantics so invert enable. +cmd = "vrrp {vrid} shutdown" + +set\_primary\_ip sets the primary IP address for the virtual router. + +commands interface {no \| default} vrrp ip + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The primary IPv4 address. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the primary IP address using +the default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} ip" + +set\_priority sets the priority for a virtual router. + +commands interface {no \| default} vrrp priority + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The priority value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the priority using the default +keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} priority" + +set\_description sets the description for a virtual router. + +commands interface {no \| default} vrrp description + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The description value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the description using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} description" + +build\_secondary\_ip\_cmd builds the array of commands required to +update the secondary IP addresses. This method allows the create methods +to leverage the code in the setter. + +@api private + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param ip\_addrs [Array] Array of secondary IPv4 address. An empty array +will remove all secondary IPv4 addresses set for the virtual router on +the specified layer 3 interface. + +@return [Array] Returns the array of commands. The array could +be empty. Get the current secondary IP address set for the virtual +router A return of nil means that nothing has been configured for the +virtual router. Add commands to delete any secondary IP addresses that +are currently set for the virtual router but not in ip\_addrs. cmds << +"no vrrp {vrid} ip {addr} secondary" Add commands to add any secondary +IP addresses that are not currently set for the virtual router but are +in ip\_addrs. cmds << "vrrp {vrid} ip {addr} secondary" +set\_secondary\_ips configures the set of secondary IP addresses +associated with the virtual router. The ip\_addrs value passed should be +an array of IP Addresses. This method will remove secondary IP addresses +that are currently set for the virtual router but not included in the +ip\_addrs array value passed in. The method will then add secondary IP +addresses that are not currently set for the virtual router but are +included in the ip\_addrs array value passed in. + +commands interface {no} vrrp ip secondary + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param ip\_addrs [Array] Array of secondary IPv4 address. An empty array +will remove all secondary IPv4 addresses set for the virtual router on +the specified layer 3 interface. + +@return [Boolean] Returns true if the command complete successfully. + +set\_ip\_version sets the VRRP version for a virtual router. + +commands interface {no \| default} vrrp ip version + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The VRRP version. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the VRRP version using the +default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} ip version" + +set\_timers\_advertise sets the interval between successive +advertisement messages that the switch sends to routers in the specified +virtual router ID. + +commands interface {no \| default} vrrp timers advertise + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The timer value in seconds. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the timer advertise value using +the default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} timers advertise" + +set\_mac\_addr\_adv\_interval sets the interval in seconds between +advertisement packets sent to VRRP group members for the specified +virtual router ID. + +commands interface {no \| default} vrrp mac-address +advertisement-interval + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments + +@option opts value [String] The mac address advertisement interval value +in seconds. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the timer advertise value using +the default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} mac-address advertisement-interval" + +set\_preempt sets the virtual router's preempt mode setting. When +preempt mode is enabled, if the switch has a higher priority it will +preempt the current master virtual router. When preempt mode is +disabled, the switch can become the master virtual router only when a +master virtual router is not present on the subnet, regardless of +priority settings. + +commands interface {no \| default} vrrp preempt + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts enable [Boolean] If enable is true then the virtual router +preempt mode is administratively enabled for the interface and if enable +is false then the virtual router preempt mode is administratively +disabled for the interface. Default is true. + +@option opts default [Boolean] Configure the timer advertise value using +the default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} preempt" + +set\_preempt\_delay\_min sets the minimum time in seconds for the +virtual router to wait before taking over the active role. + +commands interface {no \| default} vrrp preempt delay minimum + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The preempt delay minimum value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the preempt delay minimum value +using the default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} preempt delay minimum" + +set\_preempt\_delay\_reload sets the preemption delay after a reload +only. This delay period applies only to the first interface-up event +after the virtual router has reloaded. + +commands interface {no \| default} vrrp preempt delay reload + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments. + +@option opts value [String] The preempt delay reload value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] :default Configure the preempt delay +reload value using the default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} preempt delay reload" + +set\_delay\_reload sets the delay between system reboot and VRRP +initialization for the virtual router. + +commands interface {no \| default} vrrp delay reload + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param opts [hash] Optional keyword arguments + +@option opts value [String] The delay reload value. + +@option opts enable [Boolean] If false then the command is negated. +Default is true. + +@option opts default [Boolean] Configure the delay reload value using +the default keyword. + +@return [Boolean] Returns true if the command complete successfully. cmd += "vrrp {vrid} delay reload" + +build\_tracks\_cmd builds the array of commands required to update the +tracks. This method allows the create methods to leverage the code in +the setter. + +@api private + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param tracks [Array] Array of a hash of track information. Hash format: +{ name: 'Eth2', action: 'decrement', amount: 33 }, The name and action +key are required. The amount key should only be specified if the action +is shutdown. The valid actions are 'decrement' and 'shutdown'. An empty +array will remove all tracks set for the virtual router on the specified +layer 3 interface. + +@return [Array] Returns the array of commands. The array could +be empty. Validate the track hash rubocop:disable Style/Next fail +ArgumentError, 'Key: {key} invalid in track hash' Get the current tracks +set for the virtual router. A return of nil means that nothing has been +configured for the virtual router. Add commands to delete any tracks +that are currently set for the virtual router but not in tracks. cmds << +"no vrrp {vrid} track {tk[:name]} {tk[:action]}" Add commands to add any +tracks that are not currently set for the virtual router but are in +tracks. cmd = "vrrp {vrid} track {tk[:name]} {tk[:action]}" cmd << " +{tk[:amount]}" if tk.key?(:amount) set\_tracks configures the set of +track settings associated with the virtual router. The tracks value +passed should be an array of hashes, each hash containing a track entry. +This method will remove tracks that are currently set for the virtual +router but not included in the tracks array value passed in. The method +will then add tracks that are not currently set for the virtual router +but are included in the tracks array value passed in. + +commands interface {no} vrrp track [] + +@param name [String] The layer 3 interface name. + +@param vrid [Integer] The virtual router ID. + +@param tracks [Array] Array of a hash of track information. Hash format: +{ name: 'Eth2', action: 'decrement', amount: 33 }, An empty array will +remove all tracks set for the virtual router on the specified layer 3 +interface. + +@return [Boolean] Returns true if the command complete successfully. diff --git a/guide/contributing.rst b/guide/contributing.rst new file mode 100644 index 0000000..b13d670 --- /dev/null +++ b/guide/contributing.rst @@ -0,0 +1,6 @@ +Contributing +============ + +.. contents:: :local: + +Contributing pull requests are gladly welcomed for this repository. Please note that all contributions that modify the library behavior require corresponding test cases otherwise the pull request will be rejected. \ No newline at end of file diff --git a/guide/cookbook.rst b/guide/cookbook.rst deleted file mode 100644 index c5535bd..0000000 --- a/guide/cookbook.rst +++ /dev/null @@ -1,4 +0,0 @@ -Cookbook -============ - -.. contents:: :local: \ No newline at end of file diff --git a/guide/developing.rst b/guide/developing.rst deleted file mode 100644 index 5e7e5e4..0000000 --- a/guide/developing.rst +++ /dev/null @@ -1,4 +0,0 @@ -Developing -========== - -.. contents:: :local: \ No newline at end of file diff --git a/guide/faq.rst b/guide/faq.rst deleted file mode 100644 index eb5392d..0000000 --- a/guide/faq.rst +++ /dev/null @@ -1,4 +0,0 @@ -FAQ -=== - -.. contents:: :local: \ No newline at end of file diff --git a/guide/getting-started.rst b/guide/getting-started.rst new file mode 100644 index 0000000..8420889 --- /dev/null +++ b/guide/getting-started.rst @@ -0,0 +1,134 @@ +Getting Started +=============== + +.. contents:: :local: + +In order to use rbeapi, the EOS command API must be enabled using management api http-commands configuration mode. This library supports eAPI calls over both HTTP and UNIX Domain Sockets. Once the command API is enabled on the destination node, create a configuration file with the node properities. + +Note: The default search path for the conf file is ~/.eapi.conf followed by /mnt/flash/eapi.conf. This can be overridden by setting EAPI_CONF= in your environment. + +Example eapi.conf File +---------------------- + +Below is an example of an eAPI conf file. The conf file can contain more than one node. Each node section must be prefaced by connection: where is the name of the connection. + +The following configuration options are available for defining node entries: + + host - The IP address or FQDN of the remote device. If the host parameter is omitted then the connection name is used + username - The eAPI username to use for authentication (only required for http or https connections) + password - The eAPI password to use for authentication (only required for http or https connections) + enablepwd - The enable mode password if required by the destination node + transport - Configures the type of transport connection to use. The default value is https. Valid values are: + socket (available in EOS 4.14.5 or later) + http_local (available in EOS 4.14.5 or later) + http + https + port - Configures the port to use for the eAPI connection. A default port is used if this parameter is absent, based on the transport setting using the following values: + transport: http, default port: 80 + transport: https, deafult port: 443 + transport: https_local, default port: 8080 + transport: socket, default port: n/a + open_timeout - The default number of seconds to wait for the eAPI connection to open. Any number may be used, including Floats for fractional seconds. Default value is 10 seconds. + read_timeout - The default number of seconds to wait for one block of eAPI results to be read (via one read(2) call). Any number may be used, including Floats for fractional seconds. Default value is 10 seconds. + +Note: See the EOS User Manual found at arista.com for more details on configuring eAPI values. + +All configuration values are optional. + +[connection:veos01] +username: eapi +password: password +transport: http + +[connection:veos02] +transport: http + +[connection:veos03] +transport: socket + +[connection:veos04] +host: 172.16.10.1 +username: eapi +password: password +enablepwd: itsasecret +port: 1234 +transport: https + +[connection:localhost] +transport: http_local + +The above example shows different ways to define EOS node connections. All configuration options will attempt to use default values if not explicitly defined. If the host parameter is not set for a given entry, then the connection name will be used as the host address. + +Configuring [connection:localhost] +---------------------------------- + +The rbeapi library automatically installs a single default configuration entry for connecting to localhost host using a transport of sockets. If using the rbeapi library locally on an EOS node, simply enable the command API to use sockets and no further configuration is needed for rbeapi to function. If you specify an entry in a conf file with the name [connection:localhost], the values in the conf file will overwrite the default. + +Using rbeapi +------------ + +The Ruby Client for eAPI was designed to be easy to use and implement for writing tools and applications that interface with the Arista EOS management plane. + +Creating a connection and sending commands +------------------------------------------ + +Once EOS is configured properly and the config file created, getting started with a connection to EOS is simple. Below demonstrates a basic connection using rbeapi. For more examples, please see the examples folder. + +# start by importing the library +require 'rbeapi/client' + +# create a node object by specifying the node to work with +node = Rbeapi::Client.connect_to('veos01') + +# send one or more commands to the node +node.enable('show hostname') +node.enable('show hostname') +=> [{:command=>"show hostname", :result=>{"fqdn"=>"veos01.arista.com", "hostname"=>"veos01"}, :encoding=>"json"}] + +# use the config method to send configuration commands +node.config('hostname veos01') +=> [{}] + +# multiple commands can be sent by using a list (works for both enable or config) + +node.config(['interface Ethernet1', 'description foo']) +=> [{}, {}] + +# return the running or startup configuration from the node (output omitted for brevity) + +node.running_config + +node.startup_config + +Using the API +------------- + +The rbeapi library provides both a client for send and receiving commands over eAPI as well as an API for working directly with EOS resources. The API is designed to be easy and straightforward to use yet also extensible. Below is an example of working with the vlans API + +# create a connection to the node +require 'rbeapi/client' +node = Rbeapi::Client.connect_to('veos01') + +# get the instance of the API (in this case vlans) +vlans = node.api('vlans') + +# return all vlans from the node +vlans.getall +=> {"1"=>{:name=>"tester", :state=>"active", :trunk_groups=>[]}, + "4"=>{:name=>"VLAN0004", :state=>"active", :trunk_groups=>[]}, + "100"=>{:name=>"TEST_VLAN_100", :state=>"active", :trunk_groups=>[]}, + "300"=>{:name=>"VLAN0300", :state=>"active", :trunk_groups=>[]}} + +# return a specific vlan from the node +vlans.get(1) +=> {:name=>"tester", :state=>"active", :trunk_groups=>[]} + +# add a new vlan to the node +vlans.create(400) +=> true + +# set the new vlan name +vlans.set_name(100, value: 'foo') +=> true + +All API implementations developed by Arista EOS+ CS are found in the rbeapi/api folder. See the examples folder for additional examples. \ No newline at end of file diff --git a/guide/index.rst b/guide/index.rst index fb21811..29e4770 100644 --- a/guide/index.rst +++ b/guide/index.rst @@ -12,12 +12,10 @@ Contents: :maxdepth: 2 overview - quickstart + getting-started installation - cookbook - troubleshooting - developing + upgrading testing - faq + contributing release-notes license \ No newline at end of file diff --git a/guide/installation.rst b/guide/installation.rst index 3c4aa04..792a678 100644 --- a/guide/installation.rst +++ b/guide/installation.rst @@ -1,4 +1,59 @@ Installation ============ -.. contents:: :local: \ No newline at end of file +.. contents:: :local: + +The source code for rbeapi is provided on Github at http://github.com/arista-eosplus/rbeapi. All current development is done in the develop branch. Stable released versions are tagged in the master branch and uploaded to RubyGems. + + To install the latest stable version of rbeapi, simply run gem install rbeapi + + To install the latest development version from Github, simply clone the develop branch and run + + $ rake build + $ rake install + + To create an RPM, run rake rpm + + To generate a SWIX file for EOS with necessary dependencies, run rake all_rpms then follow the swix create instructions, provided by the build. NOTE: PuppetLabs provides a puppet agent SWIX which includes Ruby 1.9.3 in /opt/puppet/bin/ which is different from where you might otherwise install Ruby. If you have installed the puppet-enterprise 3.x SWIX, then you should build and use the rbeapi-puppet3 swix, below. If you have installed the puppet-enterprise 2015.x SWIX, then you should build and use the rbeapi-puppet-aio swix, below. Otherwise, if you have installed at least Ruby 1.9.3 in the standard system location, then the rbeapi SWIX may be used. + + $ bundle install --path .bundle/gems/ + $ bundle exec rake all_rpms + ... + RPMs are available in rpms/noarch/ + Copy the RPMs to an EOS device then run the 'swix create' command. + Examples: + Puppet Open Source: + cd /mnt/flash; \ + swix create rbeapi-0.4.0-1.swix \ + rubygem-rbeapi-0.4.0-1.eos4.noarch.rpm \ + rubygem-inifile-3.0.0-3.eos4.noarch.rpm \ + rubygem-netaddr-1.5.0-2.eos4.noarch.rpm \ + rubygem-net_http_unix-0.2.1-3.eos4.noarch.rpm + Puppet-enterprise agent (3.x): + cd/mnt/flash; \ + swix create rbeapi-puppet3-0.4.0-1.swix \ + rubygem-rbeapi-puppet3-0.4.0-1.eos4.noarch.rpm \ + rubygem-inifile-puppet3-3.0.0-3.eos4.noarch.rpm \ + rubygem-netaddr-puppet3-1.5.0-2.eos4.noarch.rpm + Puppet-All-in-one agent (2015.x/4.x): + cd/mnt/flash; \ + swix create rbeapi-puppet-aio-0.4.0-1.swix \ + rubygem-rbeapi-puppet-aio-0.4.0-1.eos4.noarch.rpm \ + rubygem-inifile-puppet-aio-3.0.0-3.eos4.noarch.rpm \ + rubygem-netaddr-puppet-aio-1.5.0-2.eos4.noarch.rpm \ + rubygem-net_http_unix-puppet-aio-0.2.1-3.eos4.noarch.rpm + + On EOS: + + Arista# copy flash: + Arista# bash + -bash-4.1# cd /mnt/flash/ + -bash-4.1# swix create rbeapi-puppet3-0.4.0-1.swix \ + rubygem-rbeapi-puppet3-0.4.0-1.eos4.noarch.rpm \ + rubygem-inifile-puppet3-3.0.0-1.eos4.noarch.rpm \ + rubygem-netaddr-puppet3-1.5.0-1.eos4.noarch.rpm + -bash-4.1# exit + Arista# copy flash:rbeapi-puppet3-0.4.0-1.swix extension: + Arista# extension rbeapi-puppet3-0.4.0-1.swix + Arista# copy installed-extensions boot-extensions + diff --git a/guide/license.rst b/guide/license.rst index df32f7b..d1719a2 100644 --- a/guide/license.rst +++ b/guide/license.rst @@ -1,5 +1,16 @@ License ======= -.. include:: ../LICENSE - :literal: \ No newline at end of file +.. contents:: :local: + +Copyright (c) 2015, 2016, Arista Networks, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +Neither the name of Arista Networks nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/guide/overview.rst b/guide/overview.rst index d97ec29..088133a 100644 --- a/guide/overview.rst +++ b/guide/overview.rst @@ -3,17 +3,14 @@ Overview .. contents:: :local: -Introduction ------------- - The Ruby Client for eAPI provides a native Ruby implementation for programming Arista EOS network devices using Ruby. The Ruby client provides the ability to build native applications in Ruby that can communicate with EOS either locally via Unix domain sockets (on-box) or remotely over a HTTP/S transport (off-box). It uses a standard INI-style configuration file to specifiy one or more connection profiles. The rbeapi implemenation also provides an API layer for building native Ruby objects that allow for configuration and state extraction of EOS nodes. The API layer provides a consistent implementation for working with EOS configuration resources. The implementation of the API layer is highly extensible and can be used as a foundation for building custom data models. The libray is freely provided to the open source community for building robust applications using Arista EOS eAPI. Support is provided as best effort through Github iusses. -Prerequisites -------------- +Requirements +------------ * Arista EOS 4.12 or later * Arista eAPI enabled for at least one transport (see official EOS Config Guide at arista.com for details) diff --git a/guide/quickstart.rst b/guide/quickstart.rst deleted file mode 100644 index 41feb59..0000000 --- a/guide/quickstart.rst +++ /dev/null @@ -1,4 +0,0 @@ -Quick Start -=========== - -.. contents:: :local: \ No newline at end of file diff --git a/guide/testing.rst b/guide/testing.rst index 79ab0db..d28b5c4 100644 --- a/guide/testing.rst +++ b/guide/testing.rst @@ -1,4 +1,8 @@ Testing Modules =============== -.. contents:: :local: \ No newline at end of file +.. contents:: :local: + +The rbeapi library provides spec tests. To run the spec tests, you will need to update the dut.conf file found in spec/fixtures. The switch used for testing should have at least interfaces Ethernet1-7. + + To run the spec tests, run bundle exec rspec spec from the root of the rbeapi source folder. diff --git a/guide/troubleshooting.rst b/guide/troubleshooting.rst deleted file mode 100644 index 3fa493d..0000000 --- a/guide/troubleshooting.rst +++ /dev/null @@ -1 +0,0 @@ -.. _troubleshooting: \ No newline at end of file diff --git a/guide/upgrading.rst b/guide/upgrading.rst new file mode 100644 index 0000000..1467255 --- /dev/null +++ b/guide/upgrading.rst @@ -0,0 +1,10 @@ +Upgrading +========= + +.. contents:: :local: + +On EOS: + + Arista# no extension pe-rbeapi-0.3.0-1.swix + Arista# extension rbeapi-puppet3-0.4.0-1.swix + Arista# copy installed-extensions boot-extensions diff --git a/lib/rbeapi/api/aaa.rb b/lib/rbeapi/api/aaa.rb index 956d325..aa5dfb4 100644 --- a/lib/rbeapi/api/aaa.rb +++ b/lib/rbeapi/api/aaa.rb @@ -263,7 +263,7 @@ def find_type(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # aaa group server # # @param name [String] The name of the aaa group server to create in the @@ -286,7 +286,7 @@ def create(name, type) # # @since eos_version 4.13.7M # - # commands + # ===Commands # no aaa group server [radius | tacacs+] # # @param name [String] The name of the aaa group server to create in the @@ -420,7 +420,7 @@ def add_tacacs_server(name, server, opts = {}) # # eos_version 4.13.7M # - # commands + # ===Commands # aaa group server [radius | tacacs+] # no server # diff --git a/lib/rbeapi/api/acl.rb b/lib/rbeapi/api/acl.rb index 6124523..6735e69 100644 --- a/lib/rbeapi/api/acl.rb +++ b/lib/rbeapi/api/acl.rb @@ -194,7 +194,7 @@ def parse_entries(config) # # @since eos_version 4.13.7M # - # commands + # ===Commands # ip access-list standard # # @param name [String] The ACL name to create on the node. Must @@ -213,7 +213,7 @@ def create(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # no ip access-list standard # # @param name [String] The ACL name to delete on the node. @@ -230,7 +230,7 @@ def delete(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # default no ip access-list standard # # @param name [String] The ACL name to set to the default value diff --git a/lib/rbeapi/api/bgp.rb b/lib/rbeapi/api/bgp.rb index 25d11b9..efdba9d 100644 --- a/lib/rbeapi/api/bgp.rb +++ b/lib/rbeapi/api/bgp.rb @@ -195,7 +195,7 @@ def parse_networks(config) # Optional parameters can be passed in to initialize BGP specific # settings. # - # commands + # ===Commands # router bgp # # @param bgp_as [String] The BGP autonomous system number to be @@ -247,7 +247,7 @@ def create(bgp_as, opts = {}) ## # delete will delete the BGP routing instance from the node. # - # commands + # ===Commands # no router bgp # # @return [Boolean] Returns true if the command completed successfully. @@ -262,7 +262,7 @@ def delete # keyword. This command has the same effect as deleting the BGP # routine instance from the nodes running configuration. # - # commands + # ===Commands # default router bgp # # @return [Boolean] returns true if the command complete successfully @@ -294,7 +294,7 @@ def configure_bgp(cmd) ## # set_router_id sets the router_id for the BGP routing instance. # - # commands + # ===Commands # router bgp # {no | default} router-id # @@ -325,7 +325,7 @@ def set_router_id(opts = {}) # set_shutdown configures the administrative state for the global # BGP routing process. The value option is not used by this method. # - # commands + # ===Commands # router bgp # {no | default} shutdown # @@ -352,7 +352,7 @@ def set_shutdown(opts = {}) # set_maximum_paths sets the maximum number of equal cost paths and # the maximum number of installed ECMP routes. # - # commands + # ===Commands # router bgp # {no | default} # maximum-paths [ecmp ] @@ -391,7 +391,7 @@ def set_maximum_paths(maximum_paths, maximum_ecmp_paths, opts = {}) ## # add_network creates a new instance of a BGP network on the node. # - # commands + # ===Commands # router bgp # network / # route-map @@ -415,7 +415,7 @@ def add_network(prefix, masklen, route_map = nil) ## # remove_network removes the instance of a BGP network on the node. # - # commands + # ===Commands # router bgp # {no} shutdown # @@ -720,7 +720,7 @@ def create(name) ## # delete will delete the BGP neighbor from the node. # - # commands + # ===Commands # no neighbor # or # no neighbor peer-group @@ -765,7 +765,7 @@ def neigh_command_builder(name, cmd, opts) ## # set_peer_group creates a BGP static peer group name. # - # commands + # ===Commands # router bgp # {no | default} neighbor peer-group # @@ -790,7 +790,7 @@ def set_peer_group(name, opts = {}) # set_remote_as configures the expected AS number for a neighbor # (peer). # - # commands + # ===Commands # router bgp # {no | default} neighbor remote-as # @@ -815,7 +815,7 @@ def set_remote_as(name, opts = {}) # set_shutdown disables the specified neighbor. The value option is # not used by this method. # - # commands + # ===Commands # router bgp # {no | default} neighbor shutdown # @@ -843,7 +843,7 @@ def set_shutdown(name, opts = {}) # attributes to the specified BGP neighbor. The value option is # not used by this method. # - # commands + # ===Commands # router bgp # {no | default} neighbor send-community # @@ -869,7 +869,7 @@ def set_send_community(name, opts = {}) # BGP-speaking neighbor or neighbors in the specified peer group. # The value option is not used by this method. # - # commands + # ===Commands # router bgp # {no | default} neighbor next-hop-self # @@ -893,7 +893,7 @@ def set_next_hop_self(name, opts = {}) # set_route_map_in command applies a route map to inbound BGP # routes. # - # commands + # ===Commands # router bgp # {no | default} neighbor route-map in # @@ -919,7 +919,7 @@ def set_route_map_in(name, opts = {}) # set_route_map_out command applies a route map to outbound BGP # routes. # - # commands + # ===Commands # router bgp # {no | default} neighbor route-map out # @@ -945,7 +945,7 @@ def set_route_map_out(name, opts = {}) # set_description associates descriptive text with the specified # peer or peer group. # - # commands + # ===Commands # router bgp # {no | default} neighbor description # diff --git a/lib/rbeapi/api/dns.rb b/lib/rbeapi/api/dns.rb index 2072ccf..f2046d0 100644 --- a/lib/rbeapi/api/dns.rb +++ b/lib/rbeapi/api/dns.rb @@ -126,7 +126,7 @@ def set_domain_name(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # ip name-server # no ip name-server # default ip name-server @@ -193,7 +193,7 @@ def remove_name_server(server) # # @since eos_version 4.13.7M # - # commands + # ===Commands # ip domain-list # no ip domain-list # default ip domain-list diff --git a/lib/rbeapi/api/ipinterfaces.rb b/lib/rbeapi/api/ipinterfaces.rb index 7b270a4..c3a47e2 100644 --- a/lib/rbeapi/api/ipinterfaces.rb +++ b/lib/rbeapi/api/ipinterfaces.rb @@ -170,7 +170,7 @@ def parse_helper_addresses(config) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # no switchport # @@ -191,7 +191,7 @@ def create(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # no ip address # switchport @@ -215,7 +215,7 @@ def delete(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # ip address # no ip address @@ -252,7 +252,7 @@ def set_address(name, opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # mtu # no mtu @@ -289,7 +289,7 @@ def set_mtu(name, opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # ip helper-address # no ip helper-address diff --git a/lib/rbeapi/api/logging.rb b/lib/rbeapi/api/logging.rb index 1c09a9a..ee5da73 100644 --- a/lib/rbeapi/api/logging.rb +++ b/lib/rbeapi/api/logging.rb @@ -100,7 +100,7 @@ def parse_hosts # # @since eos_version 4.13.7M # - # commands + # ===Commands # logging on # no logging on # default logging on @@ -126,7 +126,7 @@ def set_enable(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # logging host # # @param name [String] The host name or ip address of the destination @@ -144,7 +144,7 @@ def add_host(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # no logging host # # @param name [String] The host name or ip address of the destination diff --git a/lib/rbeapi/api/mlag.rb b/lib/rbeapi/api/mlag.rb index b57ccd0..eb5d57b 100644 --- a/lib/rbeapi/api/mlag.rb +++ b/lib/rbeapi/api/mlag.rb @@ -211,7 +211,7 @@ def parse_interfaces # # @since eos_version 4.13.7M # - # commands + # ===Commands # mlag configuration # domain-id # no domain-id @@ -245,7 +245,7 @@ def set_domain_id(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # mlag configuration # local-interface # no local-interface @@ -280,7 +280,7 @@ def set_local_interface(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # mlag configuration # peer-link # no peer-link @@ -315,7 +315,7 @@ def set_peer_link(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # mlag configuration # peer-address # no peer-address @@ -350,7 +350,7 @@ def set_peer_address(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # mlag configuration # shutdown # no shutdown @@ -386,7 +386,7 @@ def set_shutdown(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # mlag # no mlag diff --git a/lib/rbeapi/api/ntp.rb b/lib/rbeapi/api/ntp.rb index 4ae0058..27f91de 100644 --- a/lib/rbeapi/api/ntp.rb +++ b/lib/rbeapi/api/ntp.rb @@ -107,7 +107,7 @@ def parse_servers # # @since eos_version 4.13.7M # - # commands + # ===Commands # ntp source # no ntp source # default ntp source @@ -168,7 +168,7 @@ def remove_server(server) # # @since eos_version 4.13.7M # - # commands + # ===Commands # ntp server prefer # no ntp server prefer # diff --git a/lib/rbeapi/api/radius.rb b/lib/rbeapi/api/radius.rb index c2e73f7..e918658 100644 --- a/lib/rbeapi/api/radius.rb +++ b/lib/rbeapi/api/radius.rb @@ -172,7 +172,7 @@ def parse_servers # # @since eos_version 4.13.7M # - # commands + # ===Commands # radius-server key # no radius-server key # default radius-server key @@ -219,7 +219,7 @@ def set_global_key(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # radius-server timeout # no radius-server timeout # default radius-server timeout @@ -250,7 +250,7 @@ def set_global_timeout(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # radius-server retransmit # no radius-server retransmit # default radius-server retransmit diff --git a/lib/rbeapi/api/routemaps.rb b/lib/rbeapi/api/routemaps.rb index 9f75b43..a05cfe4 100644 --- a/lib/rbeapi/api/routemaps.rb +++ b/lib/rbeapi/api/routemaps.rb @@ -271,7 +271,7 @@ def name_commands(name, action, seqno, opts = {}) # # rubocop:disable Metrics/MethodLength # - # commands + # ===Commands # route-map action seqno description # match set continue # @@ -386,7 +386,7 @@ def remove_set_statements(name, action, seqno, cmds) # running configuration. If the delete method is called and the # routemap name does not exist, this method will succeed. # - # commands + # ===Commands # no route-map # # @param name [String] The routemap name to delete from the node. @@ -408,7 +408,7 @@ def delete(name, action, seqno) # exist then this method will not perform any changes but still # return True. # - # commands + # ===Commands # no route-map # # @param name [String] The routemap name to set to default. @@ -426,7 +426,7 @@ def default(name, action, seqno) # set_match_statements will set the match values for a specified routemap. # If the specified routemap does not exist, it will be created. # - # commands + # ===Commands # route-map action seqno match # # @param name [String] The name of the routemap to create. @@ -451,7 +451,7 @@ def set_match_statements(name, action, seqno, value) # set_set_statements will set the set values for a specified routemap. # If the specified routemap does not exist, it will be created. # - # commands + # ===Commands # route-map action seqno set # # @param name [String] The name of the routemap to create. @@ -476,7 +476,7 @@ def set_set_statements(name, action, seqno, value) # set_continue will set the continue value for a specified routemap. # If the specified routemap does not exist, it will be created. # - # commands + # ===Commands # route-map action seqno continue # # @param name [String] The name of the routemap to create. @@ -499,7 +499,7 @@ def set_continue(name, action, seqno, value) # set_description will set the description for a specified routemap. # If the specified routemap does not exist, it will be created. # - # commands + # ===Commands # route-map action seqno description # # @param name [String] The name of the routemap to create. diff --git a/lib/rbeapi/api/snmp.rb b/lib/rbeapi/api/snmp.rb index f4d38fe..db1bc56 100644 --- a/lib/rbeapi/api/snmp.rb +++ b/lib/rbeapi/api/snmp.rb @@ -187,7 +187,7 @@ def parse_notifications # # @since eos_version 4.13.7M # - # commands + # ===Commands # snmp-server enable traps # no snmp-server enable traps # default snmp-server enable traps @@ -217,7 +217,7 @@ def set_notification(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # snmp-server location # no snmp-server location # default snmp-server location @@ -248,7 +248,7 @@ def set_location(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # snmp-server contact # no snmp-server contact # default snmp-server contact @@ -279,7 +279,7 @@ def set_contact(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # snmp-server chassis-id # no snmp-server chassis-id # default snmp-server chassis-id @@ -310,7 +310,7 @@ def set_chassis_id(opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # snmp-server source-interface # no snmp-server source-interface # default snmp-server source-interface @@ -356,7 +356,7 @@ def add_community(name, access = 'ro') # # @since eos_version 4.13.7M # - # commands + # ===Commands # no snmp-server community # # @param name [String] The name of the snmp community to add to the @@ -374,7 +374,7 @@ def remove_community(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # no snmp-server [ro|rw] # snmp-server [ro|rw] # diff --git a/lib/rbeapi/api/staticroutes.rb b/lib/rbeapi/api/staticroutes.rb index 313b0a7..8d74967 100644 --- a/lib/rbeapi/api/staticroutes.rb +++ b/lib/rbeapi/api/staticroutes.rb @@ -88,7 +88,7 @@ def getall ## # Creates a static route in EOS. May add or overwrite an existing route. # - # commands + # ===Commands # ip route [router_ip] [distance] [tag ] # [name ] # @@ -123,7 +123,7 @@ def create(destination, nexthop, opts = {}) # Removes a given route from EOS. May remove multiple routes if nexthop # is not specified. # - # commands + # ===Commands # no ip route [nexthop] # # @param destination [String] The destination and prefix matching the diff --git a/lib/rbeapi/api/stp.rb b/lib/rbeapi/api/stp.rb index 20e5b9c..34bfef3 100644 --- a/lib/rbeapi/api/stp.rb +++ b/lib/rbeapi/api/stp.rb @@ -117,7 +117,7 @@ def interfaces # # @since eos_version 4.13.7M # - # commands + # ===Commands # spanning-tree mode # no spanning-tree mode # default spanning-tree mode diff --git a/lib/rbeapi/api/switchports.rb b/lib/rbeapi/api/switchports.rb index 45c9b15..16a3e62 100644 --- a/lib/rbeapi/api/switchports.rb +++ b/lib/rbeapi/api/switchports.rb @@ -255,7 +255,7 @@ def set_mode(name, opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # switchport trunk allowed vlan add # no switchport trunk allowed vlan # default switchport trunk allowed vlan diff --git a/lib/rbeapi/api/users.rb b/lib/rbeapi/api/users.rb index ca0f8d1..73c5ebd 100644 --- a/lib/rbeapi/api/users.rb +++ b/lib/rbeapi/api/users.rb @@ -180,7 +180,7 @@ def parse_user_entry(user) # # @since eos_version 4.13.7M # - # commands + # ===Commands # username nopassword privilege role # username secret [0,5,sha512] ... # @@ -239,7 +239,7 @@ def create(name, opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # no username # # @param name [String] The user name to delete from the node. @@ -256,7 +256,7 @@ def delete(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # default username # # @param name [String] The user name to default in the nodes @@ -277,7 +277,7 @@ def default(name) # # @since eos_version 4.13.7M # - # commands + # ===Commands # username privilege # no username privilege # default username privilege @@ -310,7 +310,7 @@ def set_privilege(name, opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # username role # no username role # default username role @@ -343,7 +343,7 @@ def set_role(name, opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # username sshkey # no username sshkey # default username sshkey diff --git a/lib/rbeapi/api/vlans.rb b/lib/rbeapi/api/vlans.rb index ef02a23..e173403 100644 --- a/lib/rbeapi/api/vlans.rb +++ b/lib/rbeapi/api/vlans.rb @@ -159,7 +159,7 @@ def parse_trunk_groups(config) # # @since eos_version 4.13.7M # - # commands + # ===Commands # vlan # # @param id [String, Integer] The vlan id to create on the node. The @@ -177,7 +177,7 @@ def create(id) # # @since eos_version 4.13.7M # - # commands + # ===Commands # no vlan # # @param id [String, Integer] The vlan id to delete from the node. The @@ -195,7 +195,7 @@ def delete(id) # # @since eos_version 4.13.7M # - # commands + # ===Commands # default vlan # # @param id [String, Integer] The vlan id to default in the nodes @@ -217,7 +217,7 @@ def default(id) # # @since eos_version 4.13.7M # - # commands + # ===Commands # vlan # name # no name @@ -255,7 +255,7 @@ def set_name(id, opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # vlan # state [active, suspend] # no state @@ -298,7 +298,7 @@ def set_state(id, opts = {}) # # @since version 4.13.7M # - # commands + # ===Commands # vlan # trunk group # @@ -320,7 +320,7 @@ def add_trunk_group(id, value) # # @since eos_version 4.13.7M # - # commands + # ===Commands # vlan # no trunk group # diff --git a/lib/rbeapi/api/vrrp.rb b/lib/rbeapi/api/vrrp.rb index 90d3fa0..2a42ea7 100644 --- a/lib/rbeapi/api/vrrp.rb +++ b/lib/rbeapi/api/vrrp.rb @@ -454,7 +454,7 @@ def parse_delay_reload(config, vrid) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # vrrp ... # @@ -570,7 +570,7 @@ def create(name, vrid, opts = {}) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # no vrrp # @@ -593,7 +593,7 @@ def delete(name, vrid) # # @since eos_version 4.13.7M # - # commands + # ===Commands # interface # default vrrp # @@ -609,7 +609,7 @@ def default(name, vrid) ## # set_shutdown enables and disables the virtual router. # - # commands + # ===Commands # interface # {no | default} vrrp shutdown # @@ -640,7 +640,7 @@ def set_shutdown(name, vrid, opts = {}) ## # set_primary_ip sets the primary IP address for the virtual router. # - # commands + # ===Commands # interface # {no | default} vrrp ip # @@ -667,7 +667,7 @@ def set_primary_ip(name, vrid, opts = {}) ## # set_priority sets the priority for a virtual router. # - # commands + # ===Commands # interface # {no | default} vrrp priority # @@ -694,7 +694,7 @@ def set_priority(name, vrid, opts = {}) ## # set_description sets the description for a virtual router. # - # commands + # ===Commands # interface # {no | default} vrrp description # @@ -775,7 +775,7 @@ def build_secondary_ip_cmd(name, vrid, ip_addrs) # currently set for the virtual router but are included in the # ip_addrs array value passed in. # - # commands + # ===Commands # interface # {no} vrrp ip secondary # @@ -797,7 +797,7 @@ def set_secondary_ip(name, vrid, ip_addrs) ## # set_ip_version sets the VRRP version for a virtual router. # - # commands + # ===Commands # interface # {no | default} vrrp ip version # @@ -826,7 +826,7 @@ def set_ip_version(name, vrid, opts = {}) # advertisement messages that the switch sends to routers in the # specified virtual router ID. # - # commands + # ===Commands # interface # {no | default} vrrp timers advertise # @@ -855,7 +855,7 @@ def set_timers_advertise(name, vrid, opts = {}) # advertisement packets sent to VRRP group members for the # specified virtual router ID. # - # commands + # ===Commands # interface # {no | default} vrrp mac-address advertisement-interval # @@ -888,7 +888,7 @@ def set_mac_addr_adv_interval(name, vrid, opts = {}) # when a master virtual router is not present on the subnet, # regardless of priority settings. # - # commands + # ===Commands # interface # {no | default} vrrp preempt # @@ -917,7 +917,7 @@ def set_preempt(name, vrid, opts = {}) # set_preempt_delay_min sets the minimum time in seconds for the # virtual router to wait before taking over the active role. # - # commands + # ===Commands # interface # {no | default} vrrp preempt delay minimum # @@ -946,7 +946,7 @@ def set_preempt_delay_min(name, vrid, opts = {}) # only. This delay period applies only to the first interface-up # event after the virtual router has reloaded. # - # commands + # ===Commands # interface # {no | default} vrrp preempt delay reload # @@ -974,7 +974,7 @@ def set_preempt_delay_reload(name, vrid, opts = {}) # set_delay_reload sets the delay between system reboot and VRRP # initialization for the virtual router. # - # commands + # ===Commands # interface # {no | default} vrrp delay reload # @@ -1085,7 +1085,7 @@ def build_tracks_cmd(name, vrid, tracks) # tracks that are not currently set for the virtual router but are # included in the tracks array value passed in. # - # commands + # ===Commands # interface # {no} vrrp track [] # From 032d19ce48ef48d0ab6715aaf97dace1282fe4dc Mon Sep 17 00:00:00 2001 From: John Corbin Date: Mon, 25 Jan 2016 17:31:48 -0800 Subject: [PATCH 105/110] Add support for DEFAULT section to eapi config file. Fixes issue #71 --- lib/rbeapi/client.rb | 11 +++++++---- spec/fixtures/test.conf | 6 +++--- spec/unit/rbeapi/client_spec.rb | 1 + 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/rbeapi/client.rb b/lib/rbeapi/client.rb index fe5ebb8..e5d04d8 100644 --- a/lib/rbeapi/client.rb +++ b/lib/rbeapi/client.rb @@ -226,11 +226,14 @@ def read(filename) # For each section, if the host parameter is omitted then the # connection name is used. + has_default = self.has_section?('DEFAULT') sections.each do |name| - if name.start_with?('connection:') - conn = self["#{name}"] - conn['host'] = name.split(':')[1] unless conn['host'] - end + next unless name.start_with?('connection:') + conn = self["#{name}"] + conn['host'] = name.split(':')[1] unless conn['host'] + + # Merge in the default values into the connections + conn.merge!(self['DEFAULT']) { |_key, v1, _v2| v1 } if has_default end return if get_connection 'localhost' diff --git a/spec/fixtures/test.conf b/spec/fixtures/test.conf index 595eda7..555c767 100644 --- a/spec/fixtures/test.conf +++ b/spec/fixtures/test.conf @@ -1,6 +1,8 @@ -[connection:veos01] +[DEFAULT] username: eapi password: password + +[connection:veos01] transport: http host: veos01 @@ -14,8 +16,6 @@ host: veos03 [connection:veos04] host: 172.16.10.1 -username: eapi -password: password enablepwd: itsasecret port: 1234 transport: https diff --git a/spec/unit/rbeapi/client_spec.rb b/spec/unit/rbeapi/client_spec.rb index 4af7038..7e4fbd9 100644 --- a/spec/unit/rbeapi/client_spec.rb +++ b/spec/unit/rbeapi/client_spec.rb @@ -121,6 +121,7 @@ def wildcard_conf it 'returns the configuration options for the connection' do expect(subject.load_config(test_conf)).to eq(nil) expect(subject.config_for('veos01')).to eq(veos01) + expect(subject.config_for('veos05')).to eq(veos05) end end From e611d2e4b578e688cc7b534f5e72bcc269bec84b Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Mon, 8 Feb 2016 13:28:25 -0500 Subject: [PATCH 106/110] Update CHANGELOG for v0.5.1 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24b152b..b4ea109 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ Ruby Client for eAPI ==================== +## v0.5.1, February, 2016 + +- Fix issue where vlans API was not returning all configured vlan trunk_groups. + ## v0.5.0, January, 2016 - Add optional ‘mode’ parameter to set_members() method in port-channel From 5e80e64e52cea844abeaafe7858d9bf8cca7be64 Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Mon, 8 Feb 2016 13:30:55 -0500 Subject: [PATCH 107/110] Update version string --- Gemfile | 2 +- README.md | 22 +++++++++++----------- lib/rbeapi/version.rb | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Gemfile b/Gemfile index 548e7a7..db3a9d1 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,7 @@ group :development, :test do gem 'pry', require: false gem 'pry-doc', require: false gem 'pry-stack_explorer', require: false - gem 'rbeapi', '0.5.0', path: '.' + gem 'rbeapi', '0.5.1', path: '.' gem 'ci_reporter_rspec', require: false gem 'simplecov-json', require: false gem 'simplecov-rcov', require: false diff --git a/README.md b/README.md index 390903b..3173708 100644 --- a/README.md +++ b/README.md @@ -235,21 +235,21 @@ Copy the RPMs to an EOS device then run the 'swix create' command. Examples: Puppet Open Source: cd /mnt/flash; \ - swix create rbeapi-0.5.0-1.swix \ - rubygem-rbeapi-0.5.0-1.eos4.noarch.rpm \ + swix create rbeapi-0.5.1-1.swix \ + rubygem-rbeapi-0.5.1-1.eos4.noarch.rpm \ rubygem-inifile-3.0.0-3.eos4.noarch.rpm \ rubygem-netaddr-1.5.0-2.eos4.noarch.rpm \ rubygem-net_http_unix-0.2.1-3.eos4.noarch.rpm Puppet-enterprise agent (3.x): cd/mnt/flash; \ - swix create rbeapi-puppet3-0.5.0-1.swix \ - rubygem-rbeapi-puppet3-0.5.0-1.eos4.noarch.rpm \ + swix create rbeapi-puppet3-0.5.1-1.swix \ + rubygem-rbeapi-puppet3-0.5.1-1.eos4.noarch.rpm \ rubygem-inifile-puppet3-3.0.0-3.eos4.noarch.rpm \ rubygem-netaddr-puppet3-1.5.0-2.eos4.noarch.rpm Puppet-All-in-one agent (2015.x/4.x): cd/mnt/flash; \ - swix create rbeapi-puppet-aio-0.5.0-1.swix \ - rubygem-rbeapi-puppet-aio-0.5.0-1.eos4.noarch.rpm \ + swix create rbeapi-puppet-aio-0.5.1-1.swix \ + rubygem-rbeapi-puppet-aio-0.5.1-1.eos4.noarch.rpm \ rubygem-inifile-puppet-aio-3.0.0-3.eos4.noarch.rpm \ rubygem-netaddr-puppet-aio-1.5.0-2.eos4.noarch.rpm \ rubygem-net_http_unix-puppet-aio-0.2.1-3.eos4.noarch.rpm @@ -260,13 +260,13 @@ Copy the RPMs to an EOS device then run the 'swix create' command. Arista# copy flash: Arista# bash -bash-4.1# cd /mnt/flash/ - -bash-4.1# swix create rbeapi-puppet3-0.5.0-1.swix \ - rubygem-rbeapi-puppet3-0.5.0-1.eos4.noarch.rpm \ + -bash-4.1# swix create rbeapi-puppet3-0.5.1-1.swix \ + rubygem-rbeapi-puppet3-0.5.1-1.eos4.noarch.rpm \ rubygem-inifile-puppet3-3.0.0-1.eos4.noarch.rpm \ rubygem-netaddr-puppet3-1.5.0-1.eos4.noarch.rpm -bash-4.1# exit - Arista# copy flash:rbeapi-puppet3-0.5.0-1.swix extension: - Arista# extension rbeapi-puppet3-0.5.0-1.swix + Arista# copy flash:rbeapi-puppet3-0.5.1-1.swix extension: + Arista# extension rbeapi-puppet3-0.5.1-1.swix Arista# copy installed-extensions boot-extensions ``` @@ -275,7 +275,7 @@ Copy the RPMs to an EOS device then run the 'swix create' command. On EOS: ``` Arista# no extension pe-rbeapi-0.3.0-1.swix - Arista# extension rbeapi-puppet3-0.5.0-1.swix + Arista# extension rbeapi-puppet3-0.5.1-1.swix Arista# copy installed-extensions boot-extensions ``` diff --git a/lib/rbeapi/version.rb b/lib/rbeapi/version.rb index 9c4cb0b..da3475c 100644 --- a/lib/rbeapi/version.rb +++ b/lib/rbeapi/version.rb @@ -33,5 +33,5 @@ # # # Rbeapi toplevel namespace. module Rbeapi - VERSION = '0.5.0' + VERSION = '0.5.1' end From 848671088e78079b4ca685c70ae4997ad56423d4 Mon Sep 17 00:00:00 2001 From: John Corbin Date: Sun, 31 Jan 2016 06:48:08 -0800 Subject: [PATCH 108/110] Only first trunk group was being returned. Fixes issue #113 --- lib/rbeapi/api/vlans.rb | 2 +- spec/system/rbeapi/api/vlans_spec.rb | 7 +++++-- spec/unit/rbeapi/api/vlans/default_spec.rb | 2 +- spec/unit/rbeapi/api/vlans/fixture_vlans.text | 2 ++ 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/rbeapi/api/vlans.rb b/lib/rbeapi/api/vlans.rb index e173403..561bcea 100644 --- a/lib/rbeapi/api/vlans.rb +++ b/lib/rbeapi/api/vlans.rb @@ -145,7 +145,7 @@ def parse_state(config) # # @return [Hash] Returns the resource hash attribute. def parse_trunk_groups(config) - values = config.scan(/trunk group (.+)$/).first + values = config.scan(/trunk group (.+)$/).flatten values = [] unless values { trunk_groups: values } end diff --git a/spec/system/rbeapi/api/vlans_spec.rb b/spec/system/rbeapi/api/vlans_spec.rb index 546873e..fe0692f 100644 --- a/spec/system/rbeapi/api/vlans_spec.rb +++ b/spec/system/rbeapi/api/vlans_spec.rb @@ -14,10 +14,13 @@ context '#get' do describe 'with defaults' do let(:entity) do - { name: 'default', state: 'active', trunk_groups: [] } + { name: 'default', state: 'active', trunk_groups: %w(mlag test) } end - before { node.config(['no vlan 1-4094', 'vlan 1']) } + before do + node.config(['no vlan 1-4094', 'vlan 1', 'trunk group mlag', + 'trunk group test']) + end it 'returns the vlan resource' do expect(subject.get('1')).to eq(entity) diff --git a/spec/unit/rbeapi/api/vlans/default_spec.rb b/spec/unit/rbeapi/api/vlans/default_spec.rb index 6c5c0f2..09f48c5 100644 --- a/spec/unit/rbeapi/api/vlans/default_spec.rb +++ b/spec/unit/rbeapi/api/vlans/default_spec.rb @@ -21,7 +21,7 @@ def vlans describe '#get' do let(:entity) do - { name: 'default', state: 'active', trunk_groups: [] } + { name: 'default', state: 'active', trunk_groups: %w(mlag_ctl test) } end it 'returns the vlan resource' do diff --git a/spec/unit/rbeapi/api/vlans/fixture_vlans.text b/spec/unit/rbeapi/api/vlans/fixture_vlans.text index 3f1489f..8330a80 100644 --- a/spec/unit/rbeapi/api/vlans/fixture_vlans.text +++ b/spec/unit/rbeapi/api/vlans/fixture_vlans.text @@ -2,4 +2,6 @@ vlan 1 name default state active no private-vlan + trunk group mlag_ctl + trunk group test ! From 93fd50aa8b863ecf5f953589e10e5c59ba68acf6 Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Tue, 12 Jan 2016 06:19:14 -0500 Subject: [PATCH 109/110] Bump version strings --- Gemfile | 4 ++++ README.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index db3a9d1..611e5f7 100644 --- a/Gemfile +++ b/Gemfile @@ -24,7 +24,11 @@ group :development, :test do gem 'pry', require: false gem 'pry-doc', require: false gem 'pry-stack_explorer', require: false +<<<<<<< HEAD gem 'rbeapi', '0.5.1', path: '.' +======= + gem 'rbeapi', '0.5.0', path: '.' +>>>>>>> Bump version strings gem 'ci_reporter_rspec', require: false gem 'simplecov-json', require: false gem 'simplecov-rcov', require: false diff --git a/README.md b/README.md index 3173708..be522c3 100644 --- a/README.md +++ b/README.md @@ -296,7 +296,7 @@ corresponding test cases otherwise the pull request will be rejected. # License -Copyright (c) 2015, Arista Networks, Inc. All rights reserved. +Copyright (c) 2016, Arista Networks, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: From 762eeae194a55f18f455cfae19bd1d6cdabb747a Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Mon, 8 Feb 2016 14:28:15 -0500 Subject: [PATCH 110/110] Fixup version --- Gemfile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Gemfile b/Gemfile index 611e5f7..db3a9d1 100644 --- a/Gemfile +++ b/Gemfile @@ -24,11 +24,7 @@ group :development, :test do gem 'pry', require: false gem 'pry-doc', require: false gem 'pry-stack_explorer', require: false -<<<<<<< HEAD gem 'rbeapi', '0.5.1', path: '.' -======= - gem 'rbeapi', '0.5.0', path: '.' ->>>>>>> Bump version strings gem 'ci_reporter_rspec', require: false gem 'simplecov-json', require: false gem 'simplecov-rcov', require: false