cvprac 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2016, Arista Networks EOS+
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ * Neither the name Arista nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,152 @@
1
+ # Cvprac - CloudVision Portal RESTful API Client
2
+
3
+ #### Table of Contents
4
+
5
+ 1. [Overview](#overview)
6
+ 2. [Installation](#installation)
7
+ 3. [Usage](#usage)
8
+ 4. [Development](#development)
9
+ 5. [Contributing](#contributing)
10
+ 6. [Support](#support)
11
+
12
+ [![Gem Version](https://badge.fury.io/rb/cvprac)](https://badge.fury.io/rb/cvprac)
13
+ [![Unittest Status](https://revproxy.arista.com/eosplus/ci/buildStatus/icon?job=Pipeline_jerearista_test/cvprac-rb/develop&style=plastic)](https://revproxy.arista.com/eosplus/ci/job/Pipeline_jerearista_test/cvprac-rb/develop)
14
+
15
+ ## Overview
16
+
17
+ The cvprac rubygem is a Ruby RESTful API Client for Arista CloudVision®
18
+ Portal (CVP) which can be used for building applications that work with Arista
19
+ CVP. If you are looking for a Python version, see [cvprac on
20
+ PyPI](https://pypi.python.org/pypi/cvprac) or
21
+ [GitHub](https://pypi.python.org/pypi/cvprac).
22
+
23
+ When the class is instantiated the logging is configured. Either syslog,
24
+ file logging, both, or none can be enabled. If neither syslog nor
25
+ filename is specified then no logging will be performed.
26
+
27
+ This class supports creating a connection to a CVP node and then issuing
28
+ subsequent GET and POST requests to CVP. A GET or POST request will be
29
+ automatically retried on the same node if the request times out. A GET or POST
30
+ request will be automatically retried on the same node if the request receives
31
+ a CvpSessionLogOutError. For this case a login will be performed before the
32
+ request is retried. For either case, the maximum number of times a request will
33
+ be retried on the same node is specified by the class attribute
34
+ NUM\_RETRY\_REQUESTS.
35
+
36
+ If more than one CVP node is specified when creating a connection, and a GET or
37
+ POST request receives a ConnectionError, HTTPError, or TooManyRedirects it will
38
+ be retried on the next CVP node in the list. If a GET or POST request receives
39
+ a Timeout or CvpSessionLogOutError and the retries on the same node exceed
40
+ NUM\_RETRY\_REQUESTS, then the request will be retried on the next node on the
41
+ list.
42
+
43
+ If any of the errors persists across all nodes then the GET or POST
44
+ request will fail and the last error that occurred will be raised.
45
+
46
+ The class provides connect, get, and post methods that allow the user to
47
+ make RESTful API calls to CVP. See the example below using the get
48
+ method.
49
+
50
+ The class provides a wrapper function around the CVP RESTful API
51
+ operations. Each API method takes the RESTful API parameters as method
52
+ parameters to the operation method. The API class was added to the
53
+ client class because the API functions are required when using the CVP
54
+ RESTful API and placing them in this library avoids duplicating the
55
+ calls in every application that uses this class. See the examples below
56
+ using the API methods.
57
+
58
+ ## Requirements
59
+
60
+ - Ruby 1.9.3 or later
61
+
62
+ ## Installation
63
+
64
+ Add this line to your application's Gemfile:
65
+
66
+ ```ruby
67
+ gem 'cvprac'
68
+ ```
69
+
70
+ And then execute:
71
+
72
+ $ bundle
73
+
74
+ Or install it yourself as:
75
+
76
+ $ gem install cvprac
77
+
78
+ ## Usage
79
+
80
+ Basic usage:
81
+
82
+ ```
83
+ require ‘cvprac’
84
+ cvp = CvpClient.new
85
+ cvp.connect(['192.0.2.101', '192.0.2.102, '192.0.2.103'],
86
+ 'cvpadmin', 'arista123')
87
+ result = cvp.get('/cvpInfo/getCvpInfo.do')
88
+ print result
89
+ {“appVersion”=>”Phase_2_Sprint_34_HF09”, “version”=>”2017.1.0.1”}
90
+
91
+ result = cvp.get('/user/getUsers.do',
92
+ data: { queryparam: nil, startIndex: 0, endIndex: 0 })
93
+
94
+ cvp.post('/some/endpoint.do', body: '{"some":"data"}')
95
+ ```
96
+
97
+ Modifying logging settings:
98
+
99
+ ```
100
+ require ‘cvprac’
101
+
102
+ # Log to Syslog
103
+ cvp = CvpClient.new(syslog: true)
104
+
105
+ # Log to a file or ‘STDOUT’ and increase the logging level
106
+ cvp = CvpClient.new(filename: 'STDOUT', file_log_level: Logger::DEBUG)
107
+
108
+ ```
109
+
110
+ API Class example:
111
+
112
+ ```
113
+ require ‘cvprac’
114
+ cvp = CvpClient.new
115
+ cvp.connect(['192.0.2.101', '192.0.2.102, '192.0.2.103'],
116
+ 'cvpadmin', 'arista123')
117
+
118
+ result = cvp.api.get_cvp_info
119
+ print result
120
+ => {“appVersion”=>”Phase_2_Sprint_34_HF09”, “version”=>”2017.1.0.1”}
121
+ ```
122
+
123
+ ### Notes for API Class Usage
124
+
125
+ #### Containers
126
+
127
+ With the API the containers are added for all cases. If you add the container
128
+ to the original root container ‘Tenant’ then you have to do a refresh from the
129
+ GUI to see the container after it is added or deleted. If the root container
130
+ has been renamed or the parent container is not the root container then an add
131
+ or delete will update the GUI without requiring a manual refresh.
132
+
133
+ ## Development
134
+
135
+ See [CONTRIBUTING](CONTRUBUTING.md)
136
+
137
+ ## Contributing
138
+
139
+ Bug reports and pull requests are welcome on
140
+ [GitHub](https://github.com/arista-aristanetworks/cvprac-rb). Pull-requests
141
+ must include relevant unittests and updated docstrings to be accepted.
142
+
143
+ This project is intended to be a safe, welcoming space for collaboration, and
144
+ contributors are expected to adhere to the [Contributor
145
+ Covenant](http://contributor-covenant.org) code of conduct.
146
+
147
+ ## Support
148
+
149
+ For support, please open an
150
+ [issue](https://github.com/arista-aristanetworks/cvprac-rb) on GitHub or
151
+ contact eosplus@arista.com. Commercial support agreements are available
152
+ through your Arista account team.
@@ -0,0 +1,55 @@
1
+ # Rakefile
2
+ require 'bump/tasks'
3
+ require 'bundler/gem_tasks'
4
+ require 'ci/reporter/rake/rspec'
5
+ require 'github_changelog_generator/task'
6
+ require 'rspec/core/rake_task'
7
+ require 'rubocop/rake_task'
8
+ require 'yard'
9
+
10
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
11
+ require 'cvprac/version'
12
+
13
+ GitHubChangelogGenerator::RakeTask.new :changelog do |config|
14
+ config.future_release = Cvprac::VERSION
15
+ end
16
+
17
+ RuboCop::RakeTask.new
18
+ RSpec::Core::RakeTask.new(:spec) do |task|
19
+ task.rspec_opts = ['--color', '--format', 'documentation']
20
+ end
21
+
22
+ namespace :spec do
23
+ RSpec::Core::RakeTask.new(:unit) do |task|
24
+ task.pattern = 'spec/unit/**/*_spec.rb'
25
+ task.rspec_opts = ['--color', '--format', 'documentation']
26
+ end
27
+
28
+ RSpec::Core::RakeTask.new(:system) do |task|
29
+ task.pattern = 'spec/system/**/*_spec.rb'
30
+ task.rspec_opts = ['--color', '--format', 'documentation']
31
+ end
32
+ end
33
+
34
+ YARD::Rake::YardocTask.new do |t|
35
+ t.files = ['lib/**/*.rb']
36
+ end
37
+
38
+ desc 'Prep CI RSpec tests'
39
+ task :ci_prep do
40
+ require 'rubygems'
41
+ begin
42
+ gem 'ci_reporter'
43
+ require 'ci/reporter/rake/rspec'
44
+ ENV['CI_REPORTS'] = 'results'
45
+ rescue LoadError
46
+ puts 'Missing ci_reporter gem. You must have the ci_reporter gem ' \
47
+ 'installed to run the CI spec tests'
48
+ end
49
+ end
50
+
51
+ desc 'Run the CI RSpec tests'
52
+ task ci_spec: [:ci_prep, 'ci:setup:rspec', 'spec:unit']
53
+
54
+ task checks: %I[rubocop spec:unit yard]
55
+ task default: %I[rubocop spec:unit yard]
@@ -0,0 +1,57 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'cvprac/version'
6
+
7
+ # rubocop:disable Style/UnneededPercentQ
8
+ Gem::Specification.new do |spec|
9
+ spec.name = 'cvprac'
10
+ spec.version = Cvprac::VERSION
11
+ spec.authors = ['Arista Networks']
12
+ spec.email = ['eosplus-dev@arista.com']
13
+ spec.summary = %q(Arista REST API Client for CloudVision Portal)
14
+ spec.description = %q(Arista REST API Client for CloudVision Portal)
15
+ spec.homepage = 'https://github.com/arista-aristanetworks/cvprac-rb'
16
+ spec.license = 'BSD-3-Clause'
17
+
18
+ # NOTE: This may cause issues on Jenkins in detached head
19
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
20
+ f.match(%r{^(bin|test|spec|features)/})
21
+ end
22
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
+ spec.require_paths = ['lib']
24
+
25
+ spec.metadata['yard.run'] = 'yri' # use "yard" to build full HTML docs.
26
+
27
+ # spec.add_runtime_dependency 'inifile', '~> 0'
28
+ spec.add_runtime_dependency 'http-cookie'
29
+ spec.add_runtime_dependency 'require_all'
30
+
31
+ spec.add_development_dependency 'bump'
32
+ spec.add_development_dependency 'bundler'
33
+ spec.add_development_dependency 'ci_reporter'
34
+ spec.add_development_dependency 'ci_reporter_rspec'
35
+ spec.add_development_dependency 'fuubar'
36
+ spec.add_development_dependency 'github_changelog_generator'
37
+ spec.add_development_dependency 'guard'
38
+ spec.add_development_dependency 'guard-rspec'
39
+ spec.add_development_dependency 'json'
40
+ spec.add_development_dependency 'pry'
41
+ spec.add_development_dependency 'pry-remote'
42
+ spec.add_development_dependency 'pry-nav'
43
+ spec.add_development_dependency 'rake'
44
+ spec.add_development_dependency 'rb-readline'
45
+ spec.add_development_dependency 'rspec'
46
+ spec.add_development_dependency 'rspec-core'
47
+ spec.add_development_dependency 'rspec-expectations'
48
+ spec.add_development_dependency 'rspec-mocks'
49
+ spec.add_development_dependency 'rspec-nc'
50
+ spec.add_development_dependency 'rubocop'
51
+ spec.add_development_dependency 'simplecov'
52
+ spec.add_development_dependency 'simplecov-rcov'
53
+ spec.add_development_dependency 'webmock'
54
+ spec.add_development_dependency 'yard'
55
+
56
+ spec.required_ruby_version = '>= 1.9.3'
57
+ end
@@ -0,0 +1,41 @@
1
+ # BSD 3-Clause License
2
+ #
3
+ # Copyright (c) 2016, Arista Networks EOS+
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice, this
10
+ # list of conditions and the following disclaimer.
11
+ #
12
+ # * Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ #
16
+ # * Neither the name Arista nor the names of its
17
+ # contributors may be used to endorse or promote products derived from
18
+ # this software without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ require 'cvprac/version'
32
+ require 'cvprac/client_errors'
33
+ require 'cvprac/client'
34
+ require 'cvprac/api'
35
+
36
+ # Top level definition of Cvprac
37
+ #
38
+ module Cvprac
39
+ # Your code goes here...
40
+ true
41
+ end
@@ -0,0 +1,79 @@
1
+ # encoding: utf-8
2
+
3
+ # BSD 3-Clause License
4
+ #
5
+ # Copyright (c) 2017, Arista Networks EOS+
6
+ # All rights reserved.
7
+ #
8
+ # Redistribution and use in source and binary forms, with or without
9
+ # modification, are permitted provided that the following conditions are met:
10
+ #
11
+ # * Redistributions of source code must retain the above copyright notice, this
12
+ # list of conditions and the following disclaimer.
13
+ #
14
+ # * Redistributions in binary form must reproduce the above copyright notice,
15
+ # this list of conditions and the following disclaimer in the documentation
16
+ # and/or other materials provided with the distribution.
17
+ #
18
+ # * Neither the name Arista nor the names of its
19
+ # contributors may be used to endorse or promote products derived from
20
+ # this software without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+ #
33
+
34
+ require 'json'
35
+ require 'pp'
36
+ require 'require_all'
37
+ require_rel 'api/*.rb'
38
+
39
+ # Abstract methods for interacting with Arista CloudVision
40
+ #
41
+ # CvpApi provides high-level, convenience methods which utilize CvpClient for
42
+ # handling communications with CVP.
43
+ #
44
+ # @example Basic usage
45
+ # require 'cvprac'
46
+ # cvp = CvpClient.new
47
+ # cvp.connect(['cvp1', 'cvp2', 'cvp3'], 'cvpadmin', 'arista123')
48
+ # api = CvpApi.new(cvp)
49
+ # result = api.get_cvp_info
50
+ # print result
51
+ # {"version"=>"2016.1.1"}
52
+ #
53
+ # @author Arista EOS+ Consulting Services <eosplus-dev@arista.com>
54
+ class CvpApi
55
+ # Methods are split into modules by subject. Pull mothods back into the
56
+ # main class here. New modules in lib/cvprac/api/ must be added.
57
+ include Cvprac::Api::Info
58
+ include Cvprac::Api::Configlet
59
+ include Cvprac::Api::Provisioning
60
+ include Cvprac::Api::Inventory
61
+ include Cvprac::Api::Task
62
+
63
+ # Initialize a new CvpClient object
64
+ #
65
+ # @param [CvpClient] clnt CvpClient object
66
+ # @param opts [Hash] optional parameters
67
+ # @option opts [Fixnum] :request_timeout (30) Max seconds for a request
68
+ def initialize(clnt, **opts)
69
+ opts = { request_timeout: 30 }.merge(opts)
70
+ @clnt = clnt
71
+ @request_timeout = opts[:request_timeout]
72
+ end
73
+
74
+ # @see #CvpClient.log
75
+ def log(severity = Logger::INFO, msg = nil)
76
+ msg = yield if block_given?
77
+ @clnt.log(severity, msg)
78
+ end
79
+ end
@@ -0,0 +1,309 @@
1
+ # encoding: utf-8
2
+
3
+ # BSD 3-Clause License
4
+ #
5
+ # Copyright (c) 2017, Arista Networks EOS+
6
+ # All rights reserved.
7
+ #
8
+ # Redistribution and use in source and binary forms, with or without
9
+ # modification, are permitted provided that the following conditions are met:
10
+ #
11
+ # * Redistributions of source code must retain the above copyright notice, this
12
+ # list of conditions and the following disclaimer.
13
+ #
14
+ # * Redistributions in binary form must reproduce the above copyright notice,
15
+ # this list of conditions and the following disclaimer in the documentation
16
+ # and/or other materials provided with the distribution.
17
+ #
18
+ # * Neither the name Arista nor the names of its
19
+ # contributors may be used to endorse or promote products derived from
20
+ # this software without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+ #
33
+
34
+ # @author Arista EOS+ Consulting Services <eosplus-dev@arista.com>
35
+ module Cvprac
36
+ # Cvprac::Api namespace
37
+ module Api
38
+ # CVP Configlet api methods
39
+ # rubocop:disable Metrics/ModuleLength
40
+ module Configlet
41
+ # @!group Configlet Method Summary
42
+
43
+ # Add configlet
44
+ #
45
+ # @param [String] name The name of the desired configlet
46
+ # @param [String] config Multiline string of EOS configuration
47
+ #
48
+ # @return [String, nil] The key for the new configlet. nil on failure
49
+ #
50
+ # @raise CvpApiError on failure. Common: errorCode: 132518: Data already
51
+ # exists in Database.
52
+ #
53
+ # @example
54
+ # result = api.add_configlet('api_test_3',
55
+ # "interface Ethernet1\n shutdown")
56
+ def add_configlet(name, config)
57
+ log(Logger::DEBUG) do
58
+ "add_configlet: #{name} Config: #{config.inspect}"
59
+ end
60
+ resp = @clnt.post('/configlet/addConfiglet.do',
61
+ body: { name: name, config: config.to_s }.to_json)
62
+ log(Logger::DEBUG) do
63
+ "add_configlet: #{name} Response: #{resp.inspect}"
64
+ end
65
+ resp['data']
66
+ end
67
+
68
+ # Update configlet
69
+ #
70
+ # @param [String] name The name of the desired configlet
71
+ # @param [String] key The configlet key
72
+ # @param [Hash] config The configlet definition
73
+ #
74
+ # @return [String] The key for the new configlet
75
+ #
76
+ # @example
77
+ # result = api.update_configlet('api_test_3', configlet_new['key'],
78
+ # "interface Ethernet1\n shutdown")
79
+ def update_configlet(name, key, config)
80
+ log(Logger::DEBUG) do
81
+ "update_configlet: #{name} Key: #{key} Config: #{config.inspect}"
82
+ end
83
+ data = @clnt.post('/configlet/updateConfiglet.do',
84
+ body: { name: name, key: key,
85
+ config: config }.to_json)
86
+ data['data']
87
+ end
88
+
89
+ # Delete configlet
90
+ #
91
+ # @param [String] name The name of the desired configlet
92
+ # @param [String] key The configlet key
93
+ #
94
+ # @return [String] The request result
95
+ #
96
+ # @raise CvpApiError on failure. Common when name or key is invalid:
97
+ # errorCode: 132718: Invalid input parameters.
98
+ def delete_configlet(name, key)
99
+ log(Logger::DEBUG) { "delete_configlet: #{name} Key: #{key}" }
100
+ resp = @clnt.post('/configlet/deleteConfiglet.do',
101
+ body: [{ name: name, key: key }].to_json)
102
+ resp['data']
103
+ end
104
+
105
+ # Get all configlet definitions
106
+ #
107
+ # @param [Fixnum] start_i (0) Start index of pagination
108
+ # @param [Fixnum] end_i (0) End index for pagination. 0 will get all
109
+ # @param [String] type ('Configlet') Possible types are All, Configlet,
110
+ # Builder, Draft, Builderwithoutdraft, Generated, IgnoreDraft
111
+ #
112
+ # @return [Hash] configlet definitions with keys: total and data (a list
113
+ # of definitions)
114
+ #
115
+ # @example
116
+ # configlet = api.get_configlets()
117
+ def get_configlets(start_i = 0, end_i = 0, type = 'Configlet')
118
+ log(Logger::DEBUG) do
119
+ "get_configlets: start=#{start_i}, end=#{end_i}, type=#{type}"
120
+ end
121
+ @clnt.get('/configlet/getConfiglets.do', data: { startIndex: start_i,
122
+ endIndex: end_i,
123
+ type: type })
124
+ end
125
+
126
+ # Get configlet definition by configlet name
127
+ #
128
+ # @param [String] name The name of the desired configlet
129
+ #
130
+ # @return [Hash] configlet definition
131
+ #
132
+ # @example
133
+ # configlet = api.get_configlet_by_name('api_test_3')
134
+ def get_configlet_by_name(name)
135
+ log(Logger::DEBUG) { "get_configlet_by_name: #{name}" }
136
+ @clnt.get('/configlet/getConfigletByName.do', data: { name: name })
137
+ end
138
+
139
+ # Get devices associated with a configlet name
140
+ #
141
+ # @param [String] name The name of the desired configlet
142
+ # @param opts [Hash] Optional arguments
143
+ # @option opts [String] :queryparam Search string
144
+ # @option opts [Fixnum] :start_index (0) Start index for pagination
145
+ # @option opts [Fixnum] :end_index (0) End index for pagination
146
+ #
147
+ # @return [Hash] configlet definition
148
+ #
149
+ # @example
150
+ # configlet = api.get_configlet_by_name('api_test_3')
151
+ #
152
+ def get_devices_by_configlet_name(name, **opts)
153
+ opts = { queryparam: nil,
154
+ start_index: 0,
155
+ end_index: 0 }.merge(opts)
156
+ log(Logger::DEBUG) { "get_configlet_by_name: #{name}" }
157
+ @clnt.get('/configlet/getAppliedDevices.do',
158
+ data: { configletName: name,
159
+ queryparam: opts[:queryparam],
160
+ startIndex: opts[:start_index],
161
+ endIndex: opts[:end_index] })
162
+ end
163
+
164
+ # Apply configlets to a device
165
+ #
166
+ # @param [String] app_name The name to use in the info field
167
+ # @param [Hash] device Device definition from #get_device_by_id()
168
+ # @param [Hash] new_configlets List of configlet name & key pairs
169
+ #
170
+ # @return [Hash] Hash including status and a list of task IDs created,
171
+ # if any
172
+ #
173
+ # @example
174
+ # result = api.apply_configlets_to_device('test',
175
+ # {...},
176
+ # [{'name' => 'new_configlet',
177
+ # 'key' => '...'}])
178
+ # => {"data"=>{"taskIds"=>["8"], "status"=>"success"}}
179
+ #
180
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
181
+ def apply_configlets_to_device(app_name, device, new_configlets)
182
+ log(Logger::DEBUG) { "apply_configlets_to_device: #{app_name}" }
183
+
184
+ # get the list of existing configlets
185
+ configlets = get_configlets_by_device_id(device['systemMacAddress'])
186
+
187
+ # Get a list of the configlet names and keys
188
+ cnames = []
189
+ ckeys = []
190
+ configlets.each do |configlet|
191
+ cnames << configlet['name']
192
+ ckeys << configlet['key']
193
+ end
194
+
195
+ new_configlets.each do |configlet|
196
+ cnames << configlet['name']
197
+ ckeys << configlet['key']
198
+ end
199
+
200
+ info = "#{app_name}: Configlet Assign: to Device #{device['fqdn']}"
201
+ info_preview = "<b>Configlet Assign:</b> to Device #{device['fqdn']}"
202
+ data = { data: [{ id: 1,
203
+ info: info,
204
+ infoPreview: info_preview,
205
+ note: '',
206
+ action: 'associate',
207
+ nodeType: 'configlet',
208
+ nodeId: '',
209
+ configletList: ckeys,
210
+ configletNamesList: cnames,
211
+ ignoreConfigletNamesList: [],
212
+ ignoreConfigletList: [],
213
+ configletBuilderList: [],
214
+ configletBuilderNamesList: [],
215
+ ignoreConfigletBuilderList: [],
216
+ ignoreConfigletBuilderNamesList: [],
217
+ toId: device['systemMacAddress'],
218
+ toIdType: 'netelement',
219
+ fromId: '',
220
+ nodeName: '',
221
+ fromName: '',
222
+ toName: device['fqdn'],
223
+ nodeIpAddress: device['ipAddress'],
224
+ nodeTargetIpAddress: device['ipAddress'],
225
+ childTasks: [],
226
+ parentTask: '' }] }
227
+ log(Logger::DEBUG) do
228
+ "#{__method__}: saveTopology data #{data['data']}"
229
+ end
230
+ add_temp_action(data)
231
+ save_topology_v2([])
232
+ end
233
+
234
+ # Remove configlets from a device
235
+ #
236
+ # @param [String] app_name The name to use in the info field
237
+ # @param [Hash] device Device definition from #get_device_by_id()
238
+ # @param [Hash] configlets List of configlet name & key pairs to remove
239
+ #
240
+ # @return [Hash] Hash including status and a list of task IDs created,
241
+ # if any
242
+ #
243
+ # @example
244
+ # result = api.remove_configlets_from_device('test',
245
+ # {...},
246
+ # [{'name' => 'configlet',
247
+ # 'key' => '...'}])
248
+ # => {"data"=>{"taskIds"=>["8"], "status"=>"success"}}
249
+ #
250
+ def remove_configlets_from_device(app_name, device, configlets)
251
+ log(Logger::DEBUG) { "#{__method__}: #{app_name}" }
252
+
253
+ # get the list of existing configlets
254
+ curr_cfglts = get_configlets_by_device_id(device['systemMacAddress'])
255
+
256
+ # Get a list of the configlet names and keys
257
+ keep_cnames = []
258
+ keep_ckeys = []
259
+ curr_cfglts.each do |configlet|
260
+ next if configlets.include?('name' => configlet['name'],
261
+ 'key' => configlet['key'])
262
+ keep_cnames << configlet['name']
263
+ keep_ckeys << configlet['key']
264
+ end
265
+
266
+ del_cnames = []
267
+ del_ckeys = []
268
+ configlets.each do |configlet|
269
+ del_cnames << configlet['name']
270
+ del_ckeys << configlet['key']
271
+ end
272
+
273
+ info = "#{app_name}: Configlet Remove from Device #{device['fqdn']}"
274
+ info_preview = "<b>Configlet Remove:</b> from Device #{device['fqdn']}"
275
+ data = { data: [{ id: 1,
276
+ info: info,
277
+ infoPreview: info_preview,
278
+ note: '',
279
+ action: 'associate',
280
+ nodeType: 'configlet',
281
+ nodeId: '',
282
+ configletList: keep_ckeys,
283
+ configletNamesList: keep_cnames,
284
+ ignoreConfigletNamesList: del_cnames,
285
+ ignoreConfigletList: del_ckeys,
286
+ configletBuilderList: [],
287
+ configletBuilderNamesList: [],
288
+ ignoreConfigletBuilderList: [],
289
+ ignoreConfigletBuilderNamesList: [],
290
+ toId: device['systemMacAddress'],
291
+ toIdType: 'netelement',
292
+ fromId: '',
293
+ nodeName: '',
294
+ fromName: '',
295
+ toName: device['fqdn'],
296
+ nodeIpAddress: device['ipAddress'],
297
+ nodeTargetIpAddress: device['ipAddress'],
298
+ childTasks: [],
299
+ parentTask: '' }] }
300
+ log(Logger::DEBUG) do
301
+ "#{__method__}: saveTopology data #{data['data']}"
302
+ end
303
+ add_temp_action(data)
304
+ save_topology_v2([])
305
+ end
306
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
307
+ end
308
+ end
309
+ end