ruby_nsx_cli 0.1.0

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