Class: ACIrb::RestClient
- Inherits:
-
Object
- Object
- ACIrb::RestClient
- Defined in:
- lib/restclient.rb
Overview
REST client end point implementation
Defined Under Namespace
Classes: ApicAuthenticationError, ApicErrorResponse
Instance Attribute Summary collapse
-
#auth_cookie ⇒ Object
readonly
Returns the value of attribute auth_cookie.
-
#baseurl ⇒ Object
Returns the value of attribute baseurl.
-
#debug ⇒ Object
Returns the value of attribute debug.
-
#format ⇒ Object
Returns the value of attribute format.
-
#password ⇒ Object
Returns the value of attribute password.
-
#refresh_time ⇒ Object
readonly
Returns the value of attribute refresh_time.
-
#user ⇒ Object
Returns the value of attribute user.
-
#verify ⇒ Object
Returns the value of attribute verify.
Instance Method Summary collapse
-
#authenticate ⇒ Object
Public: Authenticates the REST session with APIC Sends a aaaLogin message to APIC and updates the following instance variables: @auth_cookie - session cookie @refresh_time - session refresh timeout in seconds.
-
#get(options) ⇒ Object
Internal: Queries the APIC REST API for data.
-
#initialize(options = {}) ⇒ RestClient
constructor
Public: Initializes and establishes an authenticated session with APIC REST endpoint.
-
#lookupByClass(cls, options = {}) ⇒ Object
Public: Helper function that performs a simple lookup on a Class.
-
#lookupByDn(dn, options = {}) ⇒ Object
Public: Helper function that performs a simple lookup on a Dn.
-
#parse_error(doc) ⇒ Object
Internal: Parses for error responses in APIC response payload.
-
#parse_response(response) ⇒ Object
Internal: Parses APIC response payload into ACIrb::MO objects.
-
#post(options) ⇒ Object
Internal: Posts data to the APIC REST interface.
-
#query(query_obj) ⇒ Object
Public: Sends a query to APIC and returns the matching MO objects.
-
#refresh_session ⇒ Object
Public: Refreshes an existing RestClient object session Sends a aaaRefresh message to APIC and updates the following instance variables: @auth_cookie - session cookie @refresh_time - session refresh timeout in seconds.
-
#refresh_subscription(subscription_id) ⇒ Object
Public: Refreshes an existing subscription query.
-
#subscribe(query_obj) ⇒ Object
Public: Sends an event subscription query to APIC.
Constructor Details
#initialize(options = {}) ⇒ RestClient
Public: Initializes and establishes an authenticated session with APIC
REST endpoint
options - Hash options used to specify connectivity
attributes (default: {}):
:url - string URL of APIC, e.g., https://apic (required)
:user - string containing User ID for authentication (required)
:password - string containing Password for
authentication (required)
:debug - boolean true or false for including verbose REST output
(default: false)
:format - string 'xml' or 'json' specifying the format to use
for messaging to APIC. (default: xml)
:verify - boolean true or false for verifying the SSL
certificate. (default: false)
Examples:
rest = ACIrb::RestClient.new(url: 'https://apic', user: 'admin',
password: 'password', format: 'json',
debug: false)
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/restclient.rb', line 42 def initialize( = {}) uri = URI.parse([:url]) @baseurl = '%s://%s:%s' % [uri.scheme, uri.host, uri.port] @format = [:format] ? [:format] : 'xml' @user = [:user] @password = [:password] @verify = [:verify] @client = HTTPClient.new @client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE \ unless [:verify] && uri.scheme == 'https' @debug = [:debug] @auth_cookie = '' authenticate if @user && @password end |
Instance Attribute Details
#auth_cookie ⇒ Object (readonly)
Returns the value of attribute auth_cookie.
13 14 15 |
# File 'lib/restclient.rb', line 13 def @auth_cookie end |
#baseurl ⇒ Object
Returns the value of attribute baseurl.
12 13 14 |
# File 'lib/restclient.rb', line 12 def baseurl @baseurl end |
#debug ⇒ Object
Returns the value of attribute debug.
12 13 14 |
# File 'lib/restclient.rb', line 12 def debug @debug end |
#format ⇒ Object
Returns the value of attribute format.
12 13 14 |
# File 'lib/restclient.rb', line 12 def format @format end |
#password ⇒ Object
Returns the value of attribute password.
12 13 14 |
# File 'lib/restclient.rb', line 12 def password @password end |
#refresh_time ⇒ Object (readonly)
Returns the value of attribute refresh_time.
13 14 15 |
# File 'lib/restclient.rb', line 13 def refresh_time @refresh_time end |
#user ⇒ Object
Returns the value of attribute user.
12 13 14 |
# File 'lib/restclient.rb', line 12 def user @user end |
#verify ⇒ Object
Returns the value of attribute verify.
12 13 14 |
# File 'lib/restclient.rb', line 12 def verify @verify end |
Instance Method Details
#authenticate ⇒ Object
Public: Authenticates the REST session with APIC Sends a aaaLogin message to APIC and updates the following instance variables:
@auth_cookie - session cookie
@refresh_time - session refresh timeout in seconds
Returns nothing.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/restclient.rb', line 71 def authenticate builder = Nokogiri::XML::Builder.new do |xml| xml.aaaUser(name: @user, pwd: @password) end post_url = URI.encode(@baseurl.to_s + '/api/mo/aaaLogin.xml') puts 'POST REQUEST', post_url if @debug puts 'POST BODY', builder.to_xml if @debug response = @client.post(post_url, body: builder.to_xml) puts 'POST RESPONSE: ', response.body if @debug doc = Nokogiri::XML(response.body) fail ApicAuthenticationError, 'Authentication error(%s): %s' % [doc.at_css('error')['code'], doc.at_css('error')['text']] \ if doc.at_css('error') fail ApicErrorResponse, 'Unexpected HTTP Error response code(%s): %s' % [response.code, response.body] if response.code != 200 @auth_cookie = doc.at_css('aaaLogin')['token'] @refresh_time = doc.at_css('aaaLogin')['refreshTimeoutSeconds'] end |
#get(options) ⇒ Object
Internal: Queries the APIC REST API for data
options - Hash options for defining get parameters (default: {})
:url - relative URL for request (required)
Returns results of parse_response, which will be the parsed results of the XML or JSON payload represented as ACIrb::MO objects
140 141 142 143 144 145 146 147 148 |
# File 'lib/restclient.rb', line 140 def get() get_url = URI.encode(@baseurl.to_s + [:url].to_s) puts 'GET REQUEST', get_url if @debug response = @client.get(get_url) puts 'GET RESPONSE: ', response.body if @debug parse_response(response) end |
#lookupByClass(cls, options = {}) ⇒ Object
Public: Helper function that performs a simple lookup on a Class
cls - string containing the class name to query (required) options - Hash options for defining query options (default: {})
:subtree - specifies the subtree query options, which can be
children, full or self
Examples
# return all L1 physical interfaces on the fabric with complete subtree
mo = rest.lookupByClass('l1PhysIf', subtree: 'full')
Returns an array of ACIrb::MO objects for the query
317 318 319 320 321 322 |
# File 'lib/restclient.rb', line 317 def lookupByClass(cls, = {}) subtree = [:subtree] cls_query = ACIrb::ClassQuery.new(cls) cls_query.subtree = subtree query(cls_query) end |
#lookupByDn(dn, options = {}) ⇒ Object
Public: Helper function that performs a simple lookup on a Dn
dn - string containing distinguished name for the object to query
(required)
options - Hash options for defining query options (default: {})
:subtree - specifies the subtree query options, which can be
children, full or self
Examples
mo = rest.lookupByDn('uni/tn-common', subtree: 'full')
Returns a single ACIrb::MO object or nil if no response for the query is received
293 294 295 296 297 298 299 300 301 302 303 304 |
# File 'lib/restclient.rb', line 293 def lookupByDn(dn, = {}) subtree = [:subtree] dn_query = ACIrb::DnQuery.new(dn) dn_query.subtree = subtree mos = query(dn_query) if mos.length == 1 return mos[0] else return nil end end |
#parse_error(doc) ⇒ Object
Internal: Parses for error responses in APIC response payload
doc - Nokigiri XML document or Hash array containing well formed
APIC response payload (required)
154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/restclient.rb', line 154 def parse_error(doc) if format == 'xml' fail ApicErrorResponse, 'Error response from APIC (%s): "%s"' % \ [doc.at_css('error')['code'], doc.at_css('error')['text']] \ if doc.at_css('error') elsif format == 'json' fail ApicErrorResponse, 'Error response from APIC (%s): "%s"' % \ [doc['imdata'][0]['error']['attributes']['code'].to_s, \ doc['imdata'][0]['error']['attributes']['text'].to_s] \ if doc['imdata'].length > 0 && doc['imdata'][0].include?('error') end end |
#parse_response(response) ⇒ Object
Internal: Parses APIC response payload into ACIrb::MO objects
response - string containing the XML or JSON payload that will be
parsed according to the format defined at instance creation
(required)
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/restclient.rb', line 172 def parse_response(response) if format == 'xml' xml_data = response.body doc = Nokogiri::XML(xml_data) parse_error(doc) mos = [] doc.root.elements.each do |xml_obj| mo = ACIrb::Loader.load_xml(xml_obj) mos.push(mo) end return mos elsif format == 'json' json_data = response.body doc = JSON.parse(json_data) parse_error(doc) mos = [] doc['imdata'].each do |json_obj| mo = ACIrb::Loader.load_json(json_obj) mos.push(mo) end return mos end end |
#post(options) ⇒ Object
Internal: Posts data to the APIC REST interface
options - Hash options for defining post parameters (default: {})
:url - relative URL for request (required)
:data - post payload to be included in the request (required)
Returns results of parse_response, which will be the parsed results of the XML or JSON payload represented as ACIrb::MO objects
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/restclient.rb', line 115 def post() post_url = URI.encode(@baseurl.to_s + [:url].to_s) data = [:data] if @format == 'xml' data = data.to_xml elsif @format == 'json' data = data.to_json end puts 'POST REQUEST', post_url if @debug puts 'POST BODY', data if @debug response = @client.post(post_url, body: data) puts 'POST RESPONSE: ', response.body if @debug parse_response(response) end |
#query(query_obj) ⇒ Object
Public: Sends a query to APIC and returns the matching MO objects
query_obj - ACIrb::Query object, typically either ACIrb::DnQuery or
ACIrb::ClassQuery which contains the query that will be issued
(required)
Examples
dn_query = ACIrb::DnQuery.new('uni/tn-common')
dn_query.subtree = 'full'
mos = rest.query(dn_query)
Returns array of ACIrb::MO objects for the query
215 216 217 218 |
# File 'lib/restclient.rb', line 215 def query(query_obj) query_uri = query_obj.uri(@format) get(url: query_uri) end |
#refresh_session ⇒ Object
Public: Refreshes an existing RestClient object session Sends a aaaRefresh message to APIC and updates the following instance variables:
@auth_cookie - session cookie
@refresh_time - session refresh timeout in seconds
Returns nothing.
95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/restclient.rb', line 95 def refresh_session get_url = URI.encode(@baseurl.to_s + '/api/mo/aaaRefresh.xml') puts 'GET REQUEST', get_url if @debug response = @client.get(get_url) puts 'GET RESPONSE: ', response.body if @debug doc = Nokogiri::XML(response.body) fail ApicAuthenticationError, 'Authentication error(%s): %s' % [doc.at_css('error')['code'], doc.at_css('error')['text']] \ if doc.at_css('error') @auth_cookie = doc.at_css('aaaLogin')['token'] @refresh_time = doc.at_css('aaaLogin')['refreshTimeoutSeconds'] end |
#refresh_subscription(subscription_id) ⇒ Object
Public: Refreshes an existing subscription query
subscription_id - string containing the subscription ID for a previously
subscribed to query
Examples
class_query = ACIrb::ClassQuery.new('fvCEp')
class_query.page_size = '1'
class_query.page = '0'
subscription_id = rest.subscribe(class_query)
sleep(50)
rest.refresh_subscription(subcription_id)
Returns nothing.
276 277 278 279 |
# File 'lib/restclient.rb', line 276 def refresh_subscription(subscription_id) query_uri = '/api/subscriptionRefresh.%s?id=%s' % [@format, subscription_id] get(url: query_uri) end |
#subscribe(query_obj) ⇒ Object
Public: Sends an event subscription query to APIC
query_obj - ACIrb::Query object, typically either ACIrb::DnQuery or
ACIrb::ClassQuery which contains the query that will be
issued. This query will have the .subscribe property set
to "yes" as part of the subscription process (required)
Examples
# subscribe to all changes on fvCEp end points on fabric
# but restrict the results of the query to only include 1
# as to reduce the initial subscription time
class_query = ACIrb::ClassQuery.new('fvCEp')
class_query.page_size = '1'
class_query.page = '0'
subscription_id = rest.subscribe(class_query)
Returns the subscription ID for the newly registered subscription
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/restclient.rb', line 237 def subscribe(query_obj) query_obj.subscribe = 'yes' query_uri = query_obj.uri(@format) get_url = URI.encode(@baseurl.to_s + query_uri.to_s) puts 'GET REQUEST', get_url if @debug response = @client.get(get_url) puts 'GET RESPONSE: ', response.body if @debug if format == 'xml' xml_data = response.body doc = Nokogiri::XML(xml_data) parse_error(doc) subscriptionId = doc.at_css('imdata')['subscriptionId'] elsif format == 'json' json_data = response.body doc = JSON.parse(json_data) parse_error(doc) subscriptionId = doc['subscriptionId'] end subscriptionId end |