ruby_nsx_cli 0.1.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.
@@ -0,0 +1,189 @@
1
+ require 'rest-client'
2
+ require 'nokogiri'
3
+ require 'erb'
4
+ require 'yaml'
5
+ require 'logger'
6
+
7
+ module RubyNsxCli
8
+ class NSXObject
9
+
10
+ XML_HEADER = {'Content-Type': 'application/xml'}
11
+
12
+ def initialize(**args)
13
+ @logger = Logger.new(STDOUT)
14
+ @logger.level = Logger::DEBUG
15
+
16
+ @nsx_manager_url = args[:nsx_manager_url] || ENV['NSX_MANAGER_URL'] || (raise 'NSX Manager URL not specified!')
17
+ @nsx_username = args[:nsx_username] || ENV['NSX_USERNAME'] || (raise 'NSX Username not specified!')
18
+ @nsx_password = args[:nsx_password] || ENV['NSX_PASSWORD'] || (raise 'NSX Password not specified!')
19
+ @ssl_check = args[:verify_ssl] ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
20
+ end
21
+
22
+ # Deletes an NSX object using the NSX API.
23
+ #
24
+ # @param api_endpoint [String] NSX endpoint to send the request
25
+ # @return [RestClient::Response] Response from the NSX API.
26
+ def delete(api_endpoint:)
27
+
28
+ @logger.info("Deleting NSX object: #{self.class}...")
29
+ @logger.debug("Sending request to: #{@nsx_manager_url}...")
30
+ @logger.debug("API endpoint is: #{api_endpoint}")
31
+
32
+ begin
33
+ resp = create_new_request(api_endpoint, nil).delete
34
+
35
+ if resp.code >= 200 && resp.code < 300
36
+ @logger.info("Successfully deleted NSX object: #{self.class}")
37
+ return resp
38
+ else
39
+ raise "Unexpected return code during NSX object creation: #{self.class} returned #{resp.code}"
40
+ end
41
+
42
+ rescue RestClient::ExceptionWithResponse => err
43
+ puts "Failed to create NSX object: #{self.class}"
44
+ puts "Response code: #{err.http_code}"
45
+ puts "Response: #{err.message}"
46
+ return resp
47
+ end
48
+
49
+ end
50
+
51
+ # Sends a post request to the NSX API. Usually to update an object.
52
+ #
53
+ # @param api_endpoint [String] the NSX endpoint to send the request
54
+ # @param payload [String] the payload to send to the `api_endpoint`
55
+ # @return [RestClient::Response] the response from the NSX API.
56
+ def post(api_endpoint:, payload:)
57
+ @logger.info("Updating NSX object: #{self.class}...")
58
+ @logger.debug("Payload is: \n#{payload}")
59
+ @logger.debug("API endpoint is: #{api_endpoint}")
60
+ @logger.debug("Sending request to: #{@nsx_manager_url}...")
61
+
62
+ begin
63
+
64
+ resp = create_new_request(api_endpoint, XML_HEADER).post(payload)
65
+
66
+ if resp.code >= 200 && resp.code < 300
67
+ @logger.info("Successfully updated NSX object: #{self.class}")
68
+ return resp
69
+ else
70
+ raise "Unexpected return code during NSX object update: #{self.class} returned #{resp.code}"
71
+ end
72
+
73
+ rescue RestClient::ExceptionWithResponse => err
74
+ @logger.info("Failed to update NSX object: #{self.class}")
75
+ @logger.info("Response code: #{err.http_code}")
76
+ @logger.info("Response: #{err.message}")
77
+ return resp
78
+ end
79
+
80
+ end
81
+
82
+ # Sends a post request to the NSX API. Usually to update an object.
83
+ #
84
+ # @param api_endpoint [String] the NSX endpoint to send the request
85
+ # @param payload [String] the payload to send to the `api_endpoint`
86
+ # @return [RestClient::Response] the response from the NSX API.
87
+ def put(api_endpoint:, payload:)
88
+ @logger.info("Updating NSX object (HTTP put): #{self.class}")
89
+ @logger.debug("Payload is: \n#{payload}")
90
+ @logger.debug("API endpoint is: #{api_endpoint}")
91
+ @logger.debug("Sending request to: #{@nsx_manager_url}...")
92
+
93
+
94
+ begin
95
+ resp = create_new_request(api_endpoint, XML_HEADER).put(payload)
96
+
97
+ if resp.code >= 200 && resp.code < 300
98
+ @logger.info("Successfully put NSX object: #{self.class}")
99
+ return resp
100
+ else
101
+ raise "Unexpected return code during NSX object put: #{self.class} returned #{resp.code}"
102
+ end
103
+
104
+ rescue RestClient::ExceptionWithResponse => err
105
+ @logger.error("Failed to put NSX object: #{self.class}")
106
+ @logger.error("Response code: #{err.http_code}")
107
+ @logger.error("Response: #{err.message}")
108
+ return resp
109
+ end
110
+
111
+ end
112
+
113
+ # Sends a get request to the NSX API.
114
+ #
115
+ # @param api_endpoint [String] NSX endpoint to send the request
116
+ # @return [RestClient::Response] Response from the NSX API.
117
+ def get(api_endpoint)
118
+ resp = create_new_request(api_endpoint, nil).get
119
+ return resp
120
+ end
121
+
122
+ # Helper method that creates the initial RestClient::Request object.
123
+ #
124
+ # @param api_endpoint the NSX endpoint to send the request
125
+ # @param headers the headers to include in the request
126
+ # @return [RestClient::Request] the initial request object to be used to call REST methods.
127
+ def create_new_request(api_endpoint, headers)
128
+ return RestClient::Resource.new(
129
+ "https://#{@nsx_manager_url}/#{api_endpoint}",
130
+ :verify_ssl => @ssl_check,
131
+ :user => @nsx_username,
132
+ :password => @nsx_password,
133
+ :headers => headers
134
+ )
135
+ end
136
+
137
+ # Inserts an XML block into the provided XML at the parent node
138
+ # If the parent node does not exist, then the parent node will be created
139
+ # with the node injected into the grandparent node
140
+ # Returns the updated xml with the node injected
141
+ #
142
+ # @param xml [String] the NSX endpoint to send the request
143
+ # @param grandparent [String] the grandparent attribute of the node to insert;
144
+ # only required if the parent node is not included in the provided xml string
145
+ # @param parent [String] the parent attribute of the node to insert
146
+ # @param node [String] the payload to send to `:api_endpoint`
147
+ # @return [String] the original XML string including the inserted node.
148
+ def inject_xml(xml, grandparent, parent, node)
149
+ doc = Nokogiri::XML(xml)
150
+ parent_xml = doc.at_css(parent)
151
+ if parent_xml.nil?
152
+ grandparent_xml = doc.at_css(grandparent)
153
+ raise "No valid parent to insert XML block into with nodes provided: #{parent_xml}, #{grandparent_xml}" if grandparent_xml.nil?
154
+ parent_xml = Nokogiri::XML::Node.new(parent, doc)
155
+ grandparent_xml << parent_xml
156
+ end
157
+ parent_xml << node
158
+ return doc
159
+ end
160
+
161
+ # Removes the <?xml version="1.0" encoding="UTF-8"?> processing instruction from the start of an XML string
162
+ # The new line character left in place is also removed to prevent issues when sending a payload to the NSX API
163
+ # which includes this string
164
+ #
165
+ # @param xml [String] an XML string that includes the processing instruction '<?xml version="1.0" encoding="UTF-8"?>'
166
+ # @return [String] the XML string without the processing instruction
167
+ def strip_xml_root_pi(xml)
168
+ frag = Nokogiri::XML::DocumentFragment.parse(xml)
169
+ frag.xpath('processing-instruction()').remove
170
+ return frag.to_s.sub("\n", '') # remove new line generated from removing root pi
171
+ end
172
+
173
+ def get_attr_text_from_xml(xml, attr)
174
+ doc = Nokogiri::XML(xml)
175
+ return doc.at(attr).text
176
+ end
177
+
178
+ # Renders the specified erb file using the provided object
179
+ #
180
+ # @param template [String] the relative path to the template
181
+ # @param object [Object] the OpenStruct object that contains the key + values for rendering the template
182
+ # @return [Object] the rendered template
183
+ def render_template(template, object)
184
+ renderer = ERB.new(File.read(File.dirname(__FILE__) + template))
185
+ return renderer.result(object.instance_eval {binding})
186
+ end
187
+
188
+ end
189
+ end
@@ -0,0 +1,4 @@
1
+ <relayAgent>
2
+ <vnicIndex><%= vnic_index %></vnicIndex>
3
+ <giAddress><%= gi_address %></giAddress>
4
+ </relayAgent>
@@ -0,0 +1,9 @@
1
+ <ipPool>
2
+ <ipRange><%= ip_range %></ipRange>
3
+ <defaultGateway><%= default_gateway %></defaultGateway>
4
+ <domainName><%= domain_name %></domainName>
5
+ <primaryNameServer><%= primary_name_server %></primaryNameServer>
6
+ <secondaryNameServer><%= secondary_name_server %></secondaryNameServer>
7
+ <leaseTime><%= lease_time %></leaseTime>
8
+ <autoConfigureDNS>false</autoConfigureDNS>
9
+ </ipPool>
@@ -0,0 +1,15 @@
1
+ <interfaces>
2
+ <interface>
3
+ <name><%= name %></name>
4
+ <addressGroups>
5
+ <addressGroup>
6
+ <primaryAddress><%= primary_address %></primaryAddress>
7
+ <subnetMask><%= subnet_mask %></subnetMask>
8
+ </addressGroup>
9
+ </addressGroups>
10
+ <mtu><%= mtu %></mtu>
11
+ <type><%= type %></type>
12
+ <isConnected>true</isConnected>
13
+ <connectedToId><%= connected_to_id %></connectedToId>
14
+ </interface>
15
+ </interfaces>
@@ -0,0 +1,6 @@
1
+ <virtualWireCreateSpec>
2
+ <name><%= name %></name>
3
+ <description><%= description %></description>
4
+ <tenantId><%= tenant_id %></tenantId>
5
+ <controlPlaneMode><%= control_plane_mode %></controlPlaneMode>
6
+ </virtualWireCreateSpec>
@@ -0,0 +1,3 @@
1
+ module RubyNsxCli
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,6 @@
1
+ require "ruby_nsx_cli/version"
2
+
3
+ module RubyNsxCli
4
+ require 'ruby_nsx_cli/nsx_objects/nsx_edge'
5
+ require 'ruby_nsx_cli/nsx_objects/nsx_virtualwire'
6
+ end
@@ -0,0 +1,28 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "ruby_nsx_cli/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ruby_nsx_cli"
8
+ spec.version = RubyNsxCli::VERSION
9
+ spec.authors = ["Daniel Cole"]
10
+ spec.email = ["dannycole12@gmail.com"]
11
+
12
+ spec.summary = %q{Simple Ruby VMWare NSX API Client to create}
13
+ spec.homepage = "https://github.com/daniel-cole"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.16"
24
+ spec.add_development_dependency "rake", "~> 12.0.0"
25
+ spec.add_development_dependency 'rest-client', '2.0.2'
26
+ spec.add_development_dependency 'nokogiri', '1.8.1'
27
+ spec.add_development_dependency 'minitest', '5.10.1'
28
+ end
metadata ADDED
@@ -0,0 +1,141 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby_nsx_cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Cole
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-12-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 12.0.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 12.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rest-client
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 2.0.2
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 2.0.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: nokogiri
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 1.8.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 1.8.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 5.10.1
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 5.10.1
83
+ description:
84
+ email:
85
+ - dannycole12@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".idea/.rakeTasks"
92
+ - ".idea/dictionaries/dancole.xml"
93
+ - ".idea/inspectionProfiles/Project_Default.xml"
94
+ - ".idea/misc.xml"
95
+ - ".idea/modules.xml"
96
+ - ".idea/ruby_nsx_cli.iml"
97
+ - ".idea/vcs.xml"
98
+ - ".idea/workspace.xml"
99
+ - CODE_OF_CONDUCT.md
100
+ - Gemfile
101
+ - Gemfile.lock
102
+ - LICENSE.txt
103
+ - README.md
104
+ - Rakefile
105
+ - bin/console
106
+ - bin/setup
107
+ - lib/ruby_nsx_cli.rb
108
+ - lib/ruby_nsx_cli/nsx_objects/nsx_edge.rb
109
+ - lib/ruby_nsx_cli/nsx_objects/nsx_virtualwire.rb
110
+ - lib/ruby_nsx_cli/nsx_objects/nsxobject.rb
111
+ - lib/ruby_nsx_cli/nsx_objects/templates/dhcp/relayagent.xml.erb
112
+ - lib/ruby_nsx_cli/nsx_objects/templates/dhcp/simple-dhcp-pool.xml.erb
113
+ - lib/ruby_nsx_cli/nsx_objects/templates/interface/interfaces.xml.erb
114
+ - lib/ruby_nsx_cli/nsx_objects/templates/virtualwire/virtualwire.xml.erb
115
+ - lib/ruby_nsx_cli/version.rb
116
+ - ruby_nsx_cli.gemspec
117
+ homepage: https://github.com/daniel-cole
118
+ licenses:
119
+ - MIT
120
+ metadata: {}
121
+ post_install_message:
122
+ rdoc_options: []
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ requirements: []
136
+ rubyforge_project:
137
+ rubygems_version: 2.6.14
138
+ signing_key:
139
+ specification_version: 4
140
+ summary: Simple Ruby VMWare NSX API Client to create
141
+ test_files: []