Skip to content

Commit

Permalink
Merge pull request #4 from jeffmccune/ar21_snmp_community
Browse files Browse the repository at this point in the history
(ARISTA-21) Use snmp_community flush for management
  • Loading branch information
Jeff McCune committed Nov 3, 2014
2 parents 7197566 + de9b045 commit 365d1c7
Show file tree
Hide file tree
Showing 9 changed files with 532 additions and 12 deletions.
64 changes: 64 additions & 0 deletions lib/puppet/provider/snmp_community/eos.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# encoding: utf-8

require 'puppet/type'
require 'puppet_x/net_dev/eos_api'
Puppet::Type.type(:snmp_community).provide(:eos) do

# Create methods that set the @property_hash for the #flush method
mk_resource_methods

# Mix in the api as instance methods
include PuppetX::NetDev::EosProviderMethods
# Mix in the api as class methods
extend PuppetX::NetDev::EosProviderMethods
# Mix in common provider class methods (e.g. self.prefetch)
extend PuppetX::NetDev::EosProviderClassMethods

def self.instances
communities = api.snmp_communities
communities.each { |hsh| hsh[:ensure] = :present }
communities.map { |resource_hash| new(resource_hash) }
end

def initialize(resource = {})
super(resource)
@property_flush = {}
end

def exists?
@property_hash[:ensure] == :present
end

def create
@property_flush = resource.to_hash.select do |key, _|
[:name, :group, :acl].include? key
end
@property_flush[:ensure] = :present
end

def destroy
@property_flush = { name: name, ensure: :absent }
end

def group=(value)
@property_flush[:group] = value
end

def acl=(value)
@property_flush[:acl] = value
end

def flush
new_property_hash = @property_hash.merge(@property_flush)
new_property_hash[:name] = name

case new_property_hash[:ensure]
when :absent, 'absent'
api.snmp_community_destroy(name: name)
else
api.snmp_community_set(new_property_hash)
end

@property_hash = new_property_hash
end
end
117 changes: 117 additions & 0 deletions lib/puppet_x/net_dev/eos_api/snmp_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

module PuppetX
module NetDev
##
class EosApi
##
# SnmpMethods encapsulate the SNMP specific EOS API methods. This
Expand Down Expand Up @@ -135,6 +136,122 @@ def snmp_location=(location)
cmd << "snmp-server location #{location}"
eapi_action(cmd, 'set snmp location') && true || false
end

##
# snmp_communities retrieves all of the SNMP community strings defined
# on the target device and returns an Array of Hash objects suitable
# for use as a resource hash to the provider's initializer method.
#
# @param [String] buf Describe the string parameter here
#
# @api public
#
# @return [Array<Hash<Symbol,Object>>] Array of resource hashes.
def snmp_communities
cmd = 'show snmp community'
result = eapi_action(cmd, 'get snmp communities', format: 'text')
text = result.first['output']
parse_snmp_communities(text)
end

##
# parse_snmp_communities takes the text output from the `show snmp
# community` EAPI command and parses the text into structured data
# suitable for use as a resource hash to the provider initializer
# method. An example of the output looks like:
#
# ```
# Community name: jeff
# Community access: read-write
# Access list: stest1
#
# Community name: jeff2
# Community access: read-write
# Access list: stest2 (non-existent)
#
# Community name: private
# Community access: read-write
#
# Community name: public
# Community access: read-only
# ```
#
# @param [String] text The text to parse
#
# @api private
#
# @return [Array<Hash<Symbol,Object>>] Array of resource hashes.
def parse_snmp_communities(text)
blocks = text.split("\n\n")
# (?:\s*\(.*?\)|\n|$) deals with trailing data after the value. e.g.
# an ACL might come back as `Access list: stest2 (non-existent)`
regexp = / (\w+): (\w.*?)(?:\s*\(.*?\)|\n|$)/
communities = blocks.map { |l| l.scan(regexp) }
communities.map do |pairs|
pairs.each_with_object({}) do |(key, val), resource_hash|
resource_hash.merge!(map_snmp_keys(key, val))
end
end
end

##
# map_snmp_keys maps the keys and values parsed from the show snmp
# community raw text output into resource attributes and values.
#
# @api private
def map_snmp_keys(key, val)
case key
when 'name' then { name: val }
when 'list' then { acl: val }
when 'access'
group = case val
when 'read-write'; then 'rw'
when 'read-only'; then 'ro'
end
{ group: group }
end
end
private :map_snmp_keys

##
# snmp_community_set creates or updates an snmp community on the target
# device given a hash of attributes from the resource model.
#
# @option opts [String] :name ('public') The community name
#
# @option opts [Symbol] :group (:ro) :ro or :rw for read-only or
# read-write access control for the community name.
#
# @option opts [String] :acl ('stest1') The standard ACL name defined on
# the switch. This ACL is defined using the `ip access-list standard
# stest1` command.
#
# @api public
#
# @return [Boolean] true if the resource was successfully created
def snmp_community_set(opts)
prefix = %w(enable configure)
cmd = "snmp-server community #{opts[:name]}"
cmd << " #{opts[:group]}" if opts[:group]
cmd << " #{opts[:acl]}" if opts[:acl]
eapi_action([*prefix, cmd], 'define snmp community') && true || false
end

##
# snmp_community_destroy deletes an SNMP community from the target
# device. given a hash of attributes from the resource model.
#
# @option opts [String] :name ('public') The community name
#
# @api public
#
# @return [Boolean] true if the resource was successfully created
def snmp_community_destroy(opts)
prefix = %w(enable configure)
cmd = "no snmp-server community #{opts[:name]}"
result = eapi_action([*prefix, cmd], 'destroy snmp community')
result && true || false
end
end
end
end
Expand Down
8 changes: 8 additions & 0 deletions spec/fixtures/fixture_api_snmp_communities.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
- !ruby/sym name: jeff
!ruby/sym group: rw
!ruby/sym acl: stest1
- !ruby/sym name: private
!ruby/sym group: rw
- !ruby/sym name: public
!ruby/sym group: ro
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
- output: "\nCommunity name: jeff\nCommunity access: read-write\nAccess list: stest1\n\nCommunity name: jeff2\nCommunity access: read-only\nAccess list: stest1\n\nCommunity name: jeff3\nCommunity access: read-only\nAccess list: stest1\n\nCommunity name: jeff4\nCommunity access: read-only\nAccess list: stest2 (non-existent)\n\nCommunity name: private\nCommunity access: read-write\n\nCommunity name: public\nCommunity access: read-only\n"
2 changes: 2 additions & 0 deletions spec/fixtures/fixture_show_snmp_community.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
- output: "\nCommunity name: jeff\nCommunity access: read-write\nAccess list: stest1\n\nCommunity name: private\nCommunity access: read-write\n\nCommunity name: public\nCommunity access: read-only\n"
11 changes: 4 additions & 7 deletions spec/support/fixtures.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,9 @@ def fixture(key, opts = {})
yaml = Pathname.new(File.join(dir, "fixture_#{key}.yaml"))
json = Pathname.new(File.join(dir, "fixture_#{key}.json"))

if yaml.exist?
Fixtures[key] = YAML.load(File.read(yaml))
elsif json.exist?
Fixtures[key] = JSON.load(File.read(json))
else
fail "could not load YAML or JSON fixture #{key}"
end
Fixtures[key] = if yaml.exist?; then YAML.load(File.read(yaml))
elsif json.exist?; then JSON.load(File.read(json))
else fail "could not load YAML or JSON fixture #{key}"
end
end
end
10 changes: 5 additions & 5 deletions spec/unit/puppet/provider/network_snmp/eos_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@
subject { described_class.instances.find { |p| p.name == 'settings' } }

include_examples 'provider resource methods',
name: 'settings',
enable: :true,
contact: 'Jane Doe',
location: 'Planet Earth',
exists?: true
name: 'settings',
enable: :true,
contact: 'Jane Doe',
location: 'Planet Earth',
exists?: true
end
end

Expand Down
Loading

0 comments on commit 365d1c7

Please sign in to comment.