cvprac 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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