From ed58789665342aebd1550197179ccc4baa34a3df Mon Sep 17 00:00:00 2001 From: Colleen Murphy Date: Thu, 5 Mar 2015 11:16:50 -0800 Subject: [PATCH] Move openstackclient parent provider to openstacklib This patch abandons the use of the Aviator library for interacting with the openstack APIs in favor of the universal openstack client[1]. This work has already been implemented in the keystone module. This patch moves that work into openstacklib in order to make it available for the other modules. [1] https://wiki.openstack.org/wiki/OpenStackClient Change-Id: I68705c28955a54e26d98f1de718016691c64e4b1 --- .fixtures.yml | 1 - .gitignore | 1 - Gemfile | 2 - lib/puppet/provider/aviator.rb | 297 ---------------- lib/puppet/provider/openstack.rb | 183 ++++++++++ lib/puppet/util/{aviator.rb => openstack.rb} | 21 +- manifests/openstackclient.pp | 18 + metadata.json | 1 - .../vcr/aviator/request/with_session.yml | 67 ---- .../vcr/aviator/request/without_session.yml | 36 -- .../vcr/aviator/session/with_password.yml | 67 ---- .../vcr/aviator/session/with_token.yml | 36 -- spec/spec_helper.rb | 7 - spec/unit/provider/aviator_spec.rb | 320 ------------------ spec/unit/provider/openstack_spec.rb | 228 +++++++++++++ 15 files changed, 440 insertions(+), 845 deletions(-) delete mode 100644 lib/puppet/provider/aviator.rb create mode 100644 lib/puppet/provider/openstack.rb rename lib/puppet/util/{aviator.rb => openstack.rb} (59%) create mode 100644 manifests/openstackclient.pp delete mode 100644 spec/fixtures/vcr/aviator/request/with_session.yml delete mode 100644 spec/fixtures/vcr/aviator/request/without_session.yml delete mode 100644 spec/fixtures/vcr/aviator/session/with_password.yml delete mode 100644 spec/fixtures/vcr/aviator/session/with_token.yml delete mode 100644 spec/unit/provider/aviator_spec.rb create mode 100644 spec/unit/provider/openstack_spec.rb diff --git a/.fixtures.yml b/.fixtures.yml index d5ce9483..a07981ce 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -1,7 +1,6 @@ fixtures: repositories: apache: git://github.com/puppetlabs/puppetlabs-apache.git - aviator: git://github.com/aimonb/puppet_aviator.git concat: git://github.com/puppetlabs/puppetlabs-concat.git mysql: git://github.com/puppetlabs/puppetlabs-mysql.git postgresql: git://github.com/puppetlabs/puppetlabs-postgresql.git diff --git a/.gitignore b/.gitignore index 8a0be9a4..3808b62f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ *.swp spec/fixtures/* -!spec/fixtures/vcr/ pkg Gemfile.lock diff --git a/Gemfile b/Gemfile index adf7ed23..3fa70788 100644 --- a/Gemfile +++ b/Gemfile @@ -8,8 +8,6 @@ group :development, :test do gem 'rspec' gem 'mocha' gem 'json' - gem 'faraday', '0.8.8', :require => false - gem 'vcr', :require => false end if puppetversion = ENV['PUPPET_GEM_VERSION'] diff --git a/lib/puppet/provider/aviator.rb b/lib/puppet/provider/aviator.rb deleted file mode 100644 index 8de1bf20..00000000 --- a/lib/puppet/provider/aviator.rb +++ /dev/null @@ -1,297 +0,0 @@ -require 'puppet' -require 'puppet/feature/aviator' -require 'puppet/util/inifile' - -class Puppet::Provider::Aviator < Puppet::Provider - - def session - @session ||= authenticate(resource[:auth], resource[:log_file]) - end - - def self.session - @session ||= authenticate(nil, nil) - end - - def request(service, request, &block) - self.class.make_request(service, request, session_data, &block) - end - - def self.request(service, request, &block) - self.make_request(service, request, session_data, &block) - end - - # needed for tests - def session_data - @session_data - end - - def self.session_data - @session_data - end - - def session_data=(data) - @session_data=data - end - - def self.session_data=(data) - @session_data=data - end - - private - - # Attempt to find credentials in this order: - # 1. username,password,tenant,host set in type parameters - # 2. openrc file path set in type parameters - # 3. service token and host set in type parameters - # 4. username,password,tenant,host set in environment variables - # 5. service token and host set in keystone.conf (backwards compatible version) - def authenticate(auth_params, log_file) - auth_params ||= {} - if password_credentials_set?(auth_params) - @session = get_authenticated_session(auth_params, log_file) - - elsif openrc_set?(auth_params) - credentials = get_credentials_from_openrc(auth_params['openrc']) - @session = get_authenticated_session(credentials, log_file) - - elsif service_credentials_set?(auth_params) - session_hash = get_unauthenticated_session(auth_params, log_file) - @session_data = session_hash[:data] - @session = session_hash[:session] - - elsif env_vars_set? - credentials = get_credentials_from_env - @session = get_authenticated_session(credentials, log_file) - - else # Last effort: try to get the token from keystone.conf - session_hash = self.class.try_auth_with_token(keystone_file, log_file) - @session_data = session_hash[:data] - @session = session_hash[:session] - end - end - - def self.authenticate(auth_params, log_file) - auth_params = {} unless auth_params - if env_vars_set? - credentials = get_credentials_from_env - @session = get_authenticated_session(credentials, log_file) - - else # Last effort: try to get the token from keystone.conf - session_hash = try_auth_with_token(keystone_file, log_file) - @session_data = session_hash[:data] - @session = session_hash[:session] - end - end - - - def self.try_auth_with_token(conf_file, log_file) - service_token = get_admin_token_from_keystone_file(conf_file) - auth_url = get_auth_url_from_keystone_file(conf_file) - session_hash = {} - if service_token - credentials = { - 'service_token' => service_token, - 'host_uri' => auth_url, - } - session_hash = get_unauthenticated_session(credentials, log_file) - else # All authentication efforts failed - raise(Puppet::Error, 'No credentials provided.') - end - end - - - def self.make_request(service, request, session_data, &block) - response = nil - if service && service.default_session_data - response = service.request(request, :endpoint_type => 'admin') do |params| - yield(params) if block - end - elsif session_data - response = service.request(request, :endpoint_type => 'admin', - :session_data => session_data) do |params| - yield(params) if block - end - else - raise(Puppet::Error, 'Cannot make a request with no session data.') - end - if response.body.hash['error'] - raise(Puppet::Error, "Error making request: #{response.body.hash['error']['code']} #{response.body.hash['error']['title']}") - end - response - end - - - def password_credentials_set?(auth_params) - auth_params['username'] && auth_params['password'] && auth_params['tenant_name'] && auth_params['host_uri'] - end - - - def openrc_set?(auth_params) - auth_params['openrc'] - end - - - def service_credentials_set?(auth_params) - auth_params['service_token'] && auth_params['host_uri'] - end - - - def self.env_vars_set? - ENV['OS_USERNAME'] && ENV['OS_PASSWORD'] && ENV['OS_TENANT_NAME'] && ENV['OS_AUTH_URL'] - end - - - def env_vars_set? - self.class.env_vars_set? - end - - - def get_credentials_from_openrc(file) - creds = {} - begin - File.open(file).readlines.delete_if{|l| l=~ /^#/}.each do |line| - key, value = line.split('=') - key = key.split(' ').last - value = value.chomp.gsub(/'/, '') - creds[key] = value - end - return creds - rescue Exception => error - return {} - end - end - - - def self.get_credentials_from_env - ENV.to_hash.dup.delete_if { |key, _| ! (key =~ /^OS/) } # Ruby 1.8.7 - end - - def get_credentials_from_env - self.class.get_credentials_from_env - end - - - def self.keystone_file - keystone_file = Puppet::Util::IniConfig::File.new - keystone_file.read('/etc/keystone/keystone.conf') - keystone_file - end - - def keystone_file - return @keystone_file if @keystone_file - @keystone_file = Puppet::Util::IniConfig::File.new - @keystone_file.read('/etc/keystone/keystone.conf') - @keystone_file - end - - - def self.get_admin_token_from_keystone_file(conf_file) - if conf_file and conf_file['DEFAULT'] and conf_file['DEFAULT']['admin_token'] - return "#{conf_file['DEFAULT']['admin_token'].strip}" - else - return nil - end - end - - def get_admin_token_from_keystone_file - conf_file = keystone_file - self.class.get_admin_token_from_keystone_file(conf_file) - end - - - def self.get_auth_url_from_keystone_file(conf_file) - if conf_file - if conf_file['DEFAULT'] - if conf_file['DEFAULT']['admin_endpoint'] - auth_url = conf_file['DEFAULT']['admin_endpoint'].strip - return versioned_endpoint(auth_url) - end - - if conf_file['DEFAULT']['admin_port'] - admin_port = conf_file['DEFAULT']['admin_port'].strip - else - admin_port = '35357' - end - - if conf_file['DEFAULT']['admin_bind_host'] - host = conf_file['DEFAULT']['admin_bind_host'].strip - if host == "0.0.0.0" - host = "127.0.0.1" - end - else - host = "127.0.0.1" - end - end - - if conf_file['ssl'] && conf_file['ssl']['enable'] && conf_file['ssl']['enable'].strip.downcase == 'true' - protocol = 'https' - else - protocol = 'http' - end - end - - "#{protocol}://#{host}:#{admin_port}/v2.0/" - end - - def get_auth_url_from_keystone_file - self.class.get_auth_url_from_keystone_file(keystone_file) - end - - - def self.make_configuration(credentials) - host_uri = versioned_endpoint(credentials['host_uri'] || credentials['OS_AUTH_URL'], credentials['api_version']) - { - :provider => 'openstack', - :auth_service => { - :name => 'identity', - :host_uri => host_uri, - :request => 'create_token', - :validator => 'list_tenants', - }, - :auth_credentials => { - :username => credentials['username'] || credentials['OS_USERNAME'], - :password => credentials['password'] || credentials['OS_PASSWORD'], - :tenant_name => credentials['tenant_name'] || credentials['OS_TENANT_NAME'] - } - } - end - - - def self.get_authenticated_session(credentials, log_file) - configuration = make_configuration(credentials) - session = ::Aviator::Session.new(:config => configuration, :log_file => log_file) - session.authenticate - session - end - - def get_authenticated_session(credentials, log_file) - self.class.get_authenticated_session(credentials, log_file) - end - - - def self.get_unauthenticated_session(credentials, log_file) - configuration = { - :provider => 'openstack', - } - session_data = { - :base_url => credentials['host_uri'], - :service_token => credentials['service_token'] - } - session = ::Aviator::Session.new(:config => configuration, :log_file => log_file) - { :session => session, :data => session_data } - end - - def get_unauthenticated_session(credentials, log_file) - self.class.get_unauthenticated_session(credentials, log_file) - end - - - def self.versioned_endpoint(endpoint, version = 'v2.0') - version = 'v2.0' if version.nil? - if endpoint =~ /\/#{version}\/?$/ || endpoint =~ /\/v2.0\/?$/ || endpoint =~ /\/v3\/?$/ - endpoint - else - "#{endpoint.chomp('/')}/#{version}" - end - end -end diff --git a/lib/puppet/provider/openstack.rb b/lib/puppet/provider/openstack.rb new file mode 100644 index 00000000..c47df095 --- /dev/null +++ b/lib/puppet/provider/openstack.rb @@ -0,0 +1,183 @@ +require 'csv' +require 'puppet' + +class Puppet::Error::OpenstackAuthInputError < Puppet::Error +end + +class Puppet::Error::OpenstackUnauthorizedError < Puppet::Error +end + +class Puppet::Provider::Openstack < Puppet::Provider + + initvars # so commands will work + commands :openstack => 'openstack' + + def request(service, action, object, credentials, *properties) + if password_credentials_set?(credentials) + auth_args = password_auth_args(credentials) + elsif openrc_set?(credentials) + credentials = get_credentials_from_openrc(credentials['openrc']) + auth_args = password_auth_args(credentials) + elsif service_credentials_set?(credentials) + auth_args = token_auth_args(credentials) + elsif env_vars_set? + # noop; auth needs no extra arguments + auth_args = nil + else # All authentication efforts failed + raise(Puppet::Error::OpenstackAuthInputError, 'No credentials provided.') + end + args = [object, properties, auth_args].flatten.compact + authenticate_request(service, action, args) + end + + def self.request(service, action, object, *properties) + if env_vars_set? + # noop; auth needs no extra arguments + auth_args = nil + else # All authentication efforts failed + raise(Puppet::Error::OpenstackAuthInputError, 'No credentials provided.') + end + args = [object, properties, auth_args].flatten.compact + authenticate_request(service, action, args) + end + + # Returns an array of hashes, where the keys are the downcased CSV headers + # with underscores instead of spaces + def self.authenticate_request(service, action, *args) + rv = nil + timeout = 10 + end_time = Time.now.to_i + timeout + loop do + begin + if(action == 'list') + response = openstack(service, action, '--quiet', '--format', 'csv', args) + # Ignore warnings - assume legitimate output starts with a double quote + # Errors will be caught and raised prior to this + response = response.split("\n").select { |line| line =~ /^\".*\",\".*\"/ }.join("\n") + response = CSV.parse(response.to_s) + keys = response.delete_at(0) # ID,Name,Description,Enabled + rv = response.collect do |line| + hash = {} + keys.each_index do |index| + key = keys[index].downcase.gsub(/ /, '_').to_sym + hash[key] = line[index] + end + hash + end + elsif(action == 'show' || action == 'create') + rv = {} + # shell output is name="value"\nid="value2"\ndescription="value3" etc. + openstack(service, action, '--format', 'shell', args).split("\n").each do |line| + # key is everything before the first "=" + key, val = line.split("=", 2) + next unless val # Ignore warnings + # value is everything after the first "=", with leading and trailing double quotes stripped + val = val.gsub(/\A"|"\Z/, '') + rv[key.downcase.to_sym] = val + end + else + rv = openstack(service, action, args) + end + break + rescue Puppet::ExecutionFailure => e + if e.message =~ /HTTP 401/ + raise(Puppet::Error::OpenstackUnauthorizedError, 'Could not authenticate.') + elsif e.message =~ /Unable to establish connection/ + current_time = Time.now.to_i + if current_time > end_time + break + else + wait = end_time - current_time + Puppet::debug("Non-fatal error: \"#{e.message}\"; retrying for #{wait} more seconds.") + if wait > timeout - 2 # Only notice the first time + notice("#{service} service is unavailable. Will retry for up to #{wait} seconds.") + end + end + sleep(2) + else + raise e + end + end + end + return rv + end + + def authenticate_request(service, action, *args) + self.class.authenticate_request(service, action, *args) + end + + private + + def password_credentials_set?(auth_params) + auth_params && auth_params['username'] && auth_params['password'] && auth_params['tenant_name'] && auth_params['auth_url'] + end + + + def openrc_set?(auth_params) + auth_params && auth_params['openrc'] + end + + + def service_credentials_set?(auth_params) + auth_params && auth_params['token'] && auth_params['auth_url'] + end + + + def self.env_vars_set? + ENV['OS_USERNAME'] && ENV['OS_PASSWORD'] && ENV['OS_TENANT_NAME'] && ENV['OS_AUTH_URL'] + end + + + def env_vars_set? + self.class.env_vars_set? + end + + + + def self.password_auth_args(credentials) + ['--os-username', credentials['username'], + '--os-password', credentials['password'], + '--os-tenant-name', credentials['tenant_name'], + '--os-auth-url', credentials['auth_url']] + end + + def password_auth_args(credentials) + self.class.password_auth_args(credentials) + end + + + def self.token_auth_args(credentials) + ['--os-token', credentials['token'], + '--os-url', credentials['auth_url']] + end + + def token_auth_args(credentials) + self.class.token_auth_args(credentials) + end + + def get_credentials_from_openrc(file) + creds = {} + File.open(file).readlines.delete_if{|l| l=~ /^#/}.each do |line| + key, value = line.split('=') + key = key.split(' ').last.downcase.sub(/^os_/, '') + value = value.chomp.gsub(/'/, '') + creds[key] = value + end + return creds + end + + + def self.get_credentials_from_env + env = ENV.to_hash.dup.delete_if { |key, _| ! (key =~ /^OS_/) } + credentials = {} + env.each do |name, value| + credentials[name.downcase.sub(/^os_/, '')] = value + end + credentials + end + + def get_credentials_from_env + self.class.get_credentials_from_env + end + +end diff --git a/lib/puppet/util/aviator.rb b/lib/puppet/util/openstack.rb similarity index 59% rename from lib/puppet/util/aviator.rb rename to lib/puppet/util/openstack.rb index bc24b025..867964af 100644 --- a/lib/puppet/util/aviator.rb +++ b/lib/puppet/util/openstack.rb @@ -1,6 +1,6 @@ # Add the auth parameter to whatever type is given -module Puppet::Util::Aviator - def self.add_aviator_params(type) +module Puppet::Util::Openstack + def self.add_openstack_type_methods(type, comment) type.newparam(:auth) do @@ -12,7 +12,7 @@ auth => { 'username' => 'test', 'password' => 'passw0rd', 'tenant_name' => 'test', - 'host_uri' => 'http://localhost:35357/v2.0', + 'auth_url' => 'http://localhost:35357/v2.0', } or a path to an openrc file containing these credentials, e.g.: @@ -25,12 +25,13 @@ or a service token and host, e.g.: auth => { 'service_token' => 'ADMIN', - 'host_uri' => 'http://localhost:35357/v2.0', + 'auth_url' => 'http://localhost:35357/v2.0', } -If not present, the provider will first look for environment variables -for password credentials and then to /etc/keystone/keystone.conf for a -service token. +If not present, the provider will look for environment variables for +password credentials. + +#{comment} EOT validate do |value| @@ -38,9 +39,9 @@ EOT end end - type.newparam(:log_file) do - desc 'Log file. Defaults to no logging.' - defaultto('/dev/null') + type.autorequire(:package) do + 'python-openstackclient' end + end end diff --git a/manifests/openstackclient.pp b/manifests/openstackclient.pp new file mode 100644 index 00000000..13335261 --- /dev/null +++ b/manifests/openstackclient.pp @@ -0,0 +1,18 @@ +# == Class: openstacklib::openstackclient +# +# Installs the openstackclient +# +# == Parameters +# +# [package_ensure] +# Ensure state of the openstackclient package. +# Optional. Defaults to 'present'. +# +class openstacklib::openstackclient( + $package_ensure = 'present', +){ + package { 'python-openstackclient': + ensure => $package_ensure, + tag => 'openstack', + } +} diff --git a/metadata.json b/metadata.json index 14afa4c5..566133a9 100644 --- a/metadata.json +++ b/metadata.json @@ -31,7 +31,6 @@ ], "description": "Puppet module library to expose common functionality between OpenStack modules.", "dependencies": [ - { "name": "aimonb/aviator", "version_requirement": ">=0.4.2 <1.0.0" }, { "name": "puppetlabs/apache", "version_requirement": ">=1.0.0 <2.0.0" }, { "name": "puppetlabs/mysql", "version_requirement": ">=3.0.0 <4.0.0" }, { "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" }, diff --git a/spec/fixtures/vcr/aviator/request/with_session.yml b/spec/fixtures/vcr/aviator/request/with_session.yml deleted file mode 100644 index 2d052df2..00000000 --- a/spec/fixtures/vcr/aviator/request/with_session.yml +++ /dev/null @@ -1,67 +0,0 @@ ---- - http_interactions: - - request: - method: post - uri: "http://192.168.11.4:35357/v2.0/tokens" - body: - encoding: UTF-8 - string: "{\x22auth\x22:{\x22passwordCredentials\x22:{\x22username\x22:\x22admin\x22,\x22password\x22:\x22fyby-tet\x22},\x22tenantName\x22:\x22admin\x22}}" - headers: - Content-Type: - - application/json - User-Agent: - - "Faraday v0.8.8" - response: - status: - code: 200 - message: - headers: - vary: - - X-Auth-Token - content-type: - - application/json - content-length: - - "9780" - date: - - "Tue, 30 Sep 2014 06:59:48 GMT" - connection: - - close - body: - encoding: UTF-8 - string: "{\x22access\x22: {\x22token\x22: {\x22issued_at\x22: \x222014-09-30T06:59:48.338940\x22, \x22expires\x22: \x222014-09-30T07:59:48Z\x22, \x22id\x22: \x22MIIRIAYJKoZIhvcNAQcCoIIRETCCEQ0CAQExCTAHBgUrDgMCGjCCD3YGCSqGSIb3DQEHAaCCD2cEgg9jeyJhY2Nlc3MiOiB7InRva2VuIjogeyJpc3N1ZWRfYXQiOiAiMjAxNC0wOS0zMFQwNjo1OTo0OC4zMzg5NDAiLCAiZXhwaXJlcyI6ICIyMDE0LTA5LTMwVDA3OjU5OjQ4WiIsICJpZCI6ICJwbGFjZWhvbGRlciIsICJ0ZW5hbnQiOiB7ImRlc2NyaXB0aW9uIjogImFkbWluIHRlbmFudCIsICJlbmFibGVkIjogdHJ1ZSwgImlkIjogImM1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgIm5hbWUiOiAiYWRtaW4ifX0sICJzZXJ2aWNlQ2F0YWxvZyI6IFt7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc0L3YyL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzQvdjIvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiMWJiNzU4NWIzMzgxNGI4Mjk4NzJlYjQ0MjAyMTg5OGEiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3NC92Mi9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJjb21wdXRlIiwgIm5hbWUiOiAibm92YSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5Njk2LyIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5Njk2LyIsICJpZCI6ICJhYTdkNDU2NTNhYjI0ZGY2YmE5ZDE4NGE1ZWRkNGYxMyIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE5Mi4xNjguMTEuNDo5Njk2LyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJuZXR3b3JrIiwgIm5hbWUiOiAibmV1dHJvbiJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc2L3YyL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzYvdjIvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiMmJmNGQ5YzZiYTgwNDM1M2JjZGNlZGZjNTAxMDNiYjYiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3Ni92Mi9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJ2b2x1bWV2MiIsICJuYW1lIjogImNpbmRlcnYyIn0sIHsiZW5kcG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzQvdjMiLCAicmVnaW9uIjogIm9wZW5zdGFjayIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODc3NC92MyIsICJpZCI6ICIzZmQ4NDBjYmFkZDM0NmFiOTE2YjA2YWYxZjRlNWJmMCIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE5Mi4xNjguMTEuNDo4Nzc0L3YzIn1dLCAiZW5kcG9pbnRzX2xpbmtzIjogW10sICJ0eXBlIjogImNvbXB1dGV2MyIsICJuYW1lIjogIm5vdmF2MyJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5MjkyIiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40OjkyOTIiLCAiaWQiOiAiMTJjOTM1NzkwYmM5NGE3ODljNzJmOWJiYjIxZjM5YmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6OTI5MiJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJpbWFnZSIsICJuYW1lIjogImdsYW5jZSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc3IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzciLCAiaWQiOiAiMWNlNDkwMWQ4OTE1NDIzZTk2ZGFiM2ZlMWZiMzY2M2MiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3NyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJtZXRlcmluZyIsICJuYW1lIjogImNlaWxvbWV0ZXIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwMC92MS8iLCAicmVnaW9uIjogIm9wZW5zdGFjayIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwMC92MS8iLCAiaWQiOiAiNWU4ZjExYzk3ZTgwNDNiNWJkZTA1YmVhMmRlNDYxNmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODAwMC92MS8ifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiY2xvdWRmb3JtYXRpb24iLCAibmFtZSI6ICJoZWF0LWNmbiJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc2L3YxL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzYvdjEvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiNTRiOWVjMjhiYzYwNDI1MmIwMGNmZTZlMGU0NGFhOTQiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3Ni92MS9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJ2b2x1bWUiLCAibmFtZSI6ICJjaW5kZXIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODc3My9zZXJ2aWNlcy9BZG1pbiIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4NzczL3NlcnZpY2VzL0Nsb3VkIiwgImlkIjogIjA3NWVjNzliMGJlMzQxYmFhYmUyZTliMTIwNTkxZjQ4IiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTkyLjE2OC4xMS40Ojg3NzMvc2VydmljZXMvQ2xvdWQifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiZWMyIiwgIm5hbWUiOiAibm92YV9lYzIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwNC92MS9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4MDA0L3YxL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgImlkIjogIjI2MmM0YjM3MzY3ODQ2OGE5ODU1YTNlYmM2MDE1OTYwIiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTkyLjE2OC4xMS40OjgwMDQvdjEvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAib3JjaGVzdHJhdGlvbiIsICJuYW1lIjogImhlYXQifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6MzUzNTcvdjIuMCIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo1MDAwL3YyLjAiLCAiaWQiOiAiMDg5ZmRiMjIyNDk1NDZiOTlhMWU1N2FlYzBiMWU3NmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6NTAwMC92Mi4wIn1dLCAiZW5kcG9pbnRzX2xpbmtzIjogW10sICJ0eXBlIjogImlkZW50aXR5IiwgIm5hbWUiOiAia2V5c3RvbmUifV0sICJ1c2VyIjogeyJ1c2VybmFtZSI6ICJhZG1pbiIsICJyb2xlc19saW5rcyI6IFtdLCAiaWQiOiAiM2Y3NmI5NDY2NzQzNGNmM2JkYzMyM2NmMDIxYzUwZjgiLCAicm9sZXMiOiBbeyJuYW1lIjogImFkbWluIn1dLCAibmFtZSI6ICJhZG1pbiJ9LCAibWV0YWRhdGEiOiB7ImlzX2FkbWluIjogMCwgInJvbGVzIjogWyIxZThiYzVkMWYzYTQ0OGU5YTJhMWNkYTU4ZDk3ZjkyYiJdfX19MYIBgTCCAX0CAQEwXDBXMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVW5zZXQxDjAMBgNVBAcMBVVuc2V0MQ4wDAYDVQQKDAVVbnNldDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tAgEBMAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIIBAHGQ0NFb0OcE74KIU9DmmvgVyYCrNwwWrwG1CObr9111AHfEr+bn6YfX1ePRUhB2KpcuBPLeIfM-RlLHNwpLzYtvKIwdj0TxIecbF9PuTkWMEZ9Kxl+KE8F4dJOnv0XnAiWZ8QzrMZOo4d+owLJmNNLE1TKfGqv8ughdcrjHtUicHT2E0AOfO3ylEhJPsazUl8XIIWQ4sMWTrs0ROMiZnWPWbomYb49LIaREHD6nDfZX+EDZbHSfPVLTYVL-+qkiIH52-lXqz-OKPCn+Lt3RzXYDzapZd8cpzVgJpTuq2YKMZ+H06yvHFCTZNN49j6kZHz0Qkn2MjbwU8sH10wA7W6k=\x22, \x22tenant\x22: {\x22description\x22: \x22admin tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c518b36fa220499b85ba9a71014ce2a5\x22, \x22name\x22: \x22admin\x22}}, \x22serviceCatalog\x22: [{\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8774/v2/c518b36fa220499b85ba9a71014ce2a5\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8774/v2/c518b36fa220499b85ba9a71014ce2a5\x22, \x22id\x22: \x221bb7585b33814b829872eb442021898a\x22, \x22publicURL\x22: \x22http://192.168.11.4:8774/v2/c518b36fa220499b85ba9a71014ce2a5\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22compute\x22, \x22name\x22: \x22nova\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:9696/\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:9696/\x22, \x22id\x22: \x22aa7d45653ab24df6ba9d184a5edd4f13\x22, \x22publicURL\x22: \x22http://192.168.11.4:9696/\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22network\x22, \x22name\x22: \x22neutron\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8776/v2/c518b36fa220499b85ba9a71014ce2a5\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8776/v2/c518b36fa220499b85ba9a71014ce2a5\x22, \x22id\x22: \x222bf4d9c6ba804353bcdcedfc50103bb6\x22, \x22publicURL\x22: \x22http://192.168.11.4:8776/v2/c518b36fa220499b85ba9a71014ce2a5\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22volumev2\x22, \x22name\x22: \x22cinderv2\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8774/v3\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8774/v3\x22, \x22id\x22: \x223fd840cbadd346ab916b06af1f4e5bf0\x22, \x22publicURL\x22: \x22http://192.168.11.4:8774/v3\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22computev3\x22, \x22name\x22: \x22novav3\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:9292\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:9292\x22, \x22id\x22: \x2212c935790bc94a789c72f9bbb21f39bc\x22, \x22publicURL\x22: \x22http://192.168.11.4:9292\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22image\x22, \x22name\x22: \x22glance\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8777\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8777\x22, \x22id\x22: \x221ce4901d8915423e96dab3fe1fb3663c\x22, \x22publicURL\x22: \x22http://192.168.11.4:8777\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22metering\x22, \x22name\x22: \x22ceilometer\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8000/v1/\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8000/v1/\x22, \x22id\x22: \x225e8f11c97e8043b5bde05bea2de4616c\x22, \x22publicURL\x22: \x22http://192.168.11.4:8000/v1/\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22cloudformation\x22, \x22name\x22: \x22heat-cfn\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8776/v1/c518b36fa220499b85ba9a71014ce2a5\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8776/v1/c518b36fa220499b85ba9a71014ce2a5\x22, \x22id\x22: \x2254b9ec28bc604252b00cfe6e0e44aa94\x22, \x22publicURL\x22: \x22http://192.168.11.4:8776/v1/c518b36fa220499b85ba9a71014ce2a5\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22volume\x22, \x22name\x22: \x22cinder\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8773/services/Admin\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8773/services/Cloud\x22, \x22id\x22: \x22075ec79b0be341baabe2e9b120591f48\x22, \x22publicURL\x22: \x22http://192.168.11.4:8773/services/Cloud\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22ec2\x22, \x22name\x22: \x22nova_ec2\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8004/v1/c518b36fa220499b85ba9a71014ce2a5\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8004/v1/c518b36fa220499b85ba9a71014ce2a5\x22, \x22id\x22: \x22262c4b373678468a9855a3ebc6015960\x22, \x22publicURL\x22: \x22http://192.168.11.4:8004/v1/c518b36fa220499b85ba9a71014ce2a5\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22orchestration\x22, \x22name\x22: \x22heat\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:35357/v2.0\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:5000/v2.0\x22, \x22id\x22: \x22089fdb22249546b99a1e57aec0b1e76c\x22, \x22publicURL\x22: \x22http://192.168.11.4:5000/v2.0\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22identity\x22, \x22name\x22: \x22keystone\x22}], \x22user\x22: {\x22username\x22: \x22admin\x22, \x22roles_links\x22: [], \x22id\x22: \x223f76b94667434cf3bdc323cf021c50f8\x22, \x22roles\x22: [{\x22name\x22: \x22admin\x22}], \x22name\x22: \x22admin\x22}, \x22metadata\x22: {\x22is_admin\x22: 0, \x22roles\x22: [\x221e8bc5d1f3a448e9a2a1cda58d97f92b\x22]}}}" - http_version: - recorded_at: "Tue, 30 Sep 2014 06:59:48 GMT" - - request: - method: get - uri: "http://172.16.33.4:35357/v2.0/tenants" - body: - encoding: US-ASCII - string: "" - headers: - Content-Type: - - application/json - User-Agent: - - "Faraday v0.8.8" - X-Auth-Token: - - "MIIRIAYJKoZIhvcNAQcCoIIRETCCEQ0CAQExCTAHBgUrDgMCGjCCD3YGCSqGSIb3DQEHAaCCD2cEgg9jeyJhY2Nlc3MiOiB7InRva2VuIjogeyJpc3N1ZWRfYXQiOiAiMjAxNC0wOS0zMFQwNjo1OTo0OC4zMzg5NDAiLCAiZXhwaXJlcyI6ICIyMDE0LTA5LTMwVDA3OjU5OjQ4WiIsICJpZCI6ICJwbGFjZWhvbGRlciIsICJ0ZW5hbnQiOiB7ImRlc2NyaXB0aW9uIjogImFkbWluIHRlbmFudCIsICJlbmFibGVkIjogdHJ1ZSwgImlkIjogImM1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgIm5hbWUiOiAiYWRtaW4ifX0sICJzZXJ2aWNlQ2F0YWxvZyI6IFt7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc0L3YyL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzQvdjIvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiMWJiNzU4NWIzMzgxNGI4Mjk4NzJlYjQ0MjAyMTg5OGEiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3NC92Mi9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJjb21wdXRlIiwgIm5hbWUiOiAibm92YSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5Njk2LyIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5Njk2LyIsICJpZCI6ICJhYTdkNDU2NTNhYjI0ZGY2YmE5ZDE4NGE1ZWRkNGYxMyIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE5Mi4xNjguMTEuNDo5Njk2LyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJuZXR3b3JrIiwgIm5hbWUiOiAibmV1dHJvbiJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc2L3YyL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzYvdjIvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiMmJmNGQ5YzZiYTgwNDM1M2JjZGNlZGZjNTAxMDNiYjYiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3Ni92Mi9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJ2b2x1bWV2MiIsICJuYW1lIjogImNpbmRlcnYyIn0sIHsiZW5kcG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzQvdjMiLCAicmVnaW9uIjogIm9wZW5zdGFjayIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODc3NC92MyIsICJpZCI6ICIzZmQ4NDBjYmFkZDM0NmFiOTE2YjA2YWYxZjRlNWJmMCIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE5Mi4xNjguMTEuNDo4Nzc0L3YzIn1dLCAiZW5kcG9pbnRzX2xpbmtzIjogW10sICJ0eXBlIjogImNvbXB1dGV2MyIsICJuYW1lIjogIm5vdmF2MyJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5MjkyIiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40OjkyOTIiLCAiaWQiOiAiMTJjOTM1NzkwYmM5NGE3ODljNzJmOWJiYjIxZjM5YmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6OTI5MiJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJpbWFnZSIsICJuYW1lIjogImdsYW5jZSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc3IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzciLCAiaWQiOiAiMWNlNDkwMWQ4OTE1NDIzZTk2ZGFiM2ZlMWZiMzY2M2MiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3NyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJtZXRlcmluZyIsICJuYW1lIjogImNlaWxvbWV0ZXIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwMC92MS8iLCAicmVnaW9uIjogIm9wZW5zdGFjayIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwMC92MS8iLCAiaWQiOiAiNWU4ZjExYzk3ZTgwNDNiNWJkZTA1YmVhMmRlNDYxNmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODAwMC92MS8ifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiY2xvdWRmb3JtYXRpb24iLCAibmFtZSI6ICJoZWF0LWNmbiJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc2L3YxL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzYvdjEvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiNTRiOWVjMjhiYzYwNDI1MmIwMGNmZTZlMGU0NGFhOTQiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3Ni92MS9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJ2b2x1bWUiLCAibmFtZSI6ICJjaW5kZXIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODc3My9zZXJ2aWNlcy9BZG1pbiIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4NzczL3NlcnZpY2VzL0Nsb3VkIiwgImlkIjogIjA3NWVjNzliMGJlMzQxYmFhYmUyZTliMTIwNTkxZjQ4IiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTkyLjE2OC4xMS40Ojg3NzMvc2VydmljZXMvQ2xvdWQifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiZWMyIiwgIm5hbWUiOiAibm92YV9lYzIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwNC92MS9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4MDA0L3YxL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgImlkIjogIjI2MmM0YjM3MzY3ODQ2OGE5ODU1YTNlYmM2MDE1OTYwIiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTkyLjE2OC4xMS40OjgwMDQvdjEvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAib3JjaGVzdHJhdGlvbiIsICJuYW1lIjogImhlYXQifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6MzUzNTcvdjIuMCIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo1MDAwL3YyLjAiLCAiaWQiOiAiMDg5ZmRiMjIyNDk1NDZiOTlhMWU1N2FlYzBiMWU3NmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6NTAwMC92Mi4wIn1dLCAiZW5kcG9pbnRzX2xpbmtzIjogW10sICJ0eXBlIjogImlkZW50aXR5IiwgIm5hbWUiOiAia2V5c3RvbmUifV0sICJ1c2VyIjogeyJ1c2VybmFtZSI6ICJhZG1pbiIsICJyb2xlc19saW5rcyI6IFtdLCAiaWQiOiAiM2Y3NmI5NDY2NzQzNGNmM2JkYzMyM2NmMDIxYzUwZjgiLCAicm9sZXMiOiBbeyJuYW1lIjogImFkbWluIn1dLCAibmFtZSI6ICJhZG1pbiJ9LCAibWV0YWRhdGEiOiB7ImlzX2FkbWluIjogMCwgInJvbGVzIjogWyIxZThiYzVkMWYzYTQ0OGU5YTJhMWNkYTU4ZDk3ZjkyYiJdfX19MYIBgTCCAX0CAQEwXDBXMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVW5zZXQxDjAMBgNVBAcMBVVuc2V0MQ4wDAYDVQQKDAVVbnNldDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tAgEBMAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIIBAHGQ0NFb0OcE74KIU9DmmvgVyYCrNwwWrwG1CObr9111AHfEr+bn6YfX1ePRUhB2KpcuBPLeIfM-RlLHNwpLzYtvKIwdj0TxIecbF9PuTkWMEZ9Kxl+KE8F4dJOnv0XnAiWZ8QzrMZOo4d+owLJmNNLE1TKfGqv8ughdcrjHtUicHT2E0AOfO3ylEhJPsazUl8XIIWQ4sMWTrs0ROMiZnWPWbomYb49LIaREHD6nDfZX+EDZbHSfPVLTYVL-+qkiIH52-lXqz-OKPCn+Lt3RzXYDzapZd8cpzVgJpTuq2YKMZ+H06yvHFCTZNN49j6kZHz0Qkn2MjbwU8sH10wA7W6k=" - response: - status: - code: 200 - message: - headers: - vary: - - X-Auth-Token - content-type: - - application/json - content-length: - - "491" - date: - - "Tue, 30 Sep 2014 06:59:48 GMT" - connection: - - close - body: - encoding: UTF-8 - string: "{\x22tenants_links\x22: [], \x22tenants\x22: [{\x22description\x22: \x22Test tenant\x22, \x22enabled\x22: true, \x22id\x22: \x2234e463e2bab24f78990ca864e4a28ba2\x22, \x22name\x22: \x22test2\x22}, {\x22description\x22: \x22Tenant for the openstack services\x22, \x22enabled\x22: true, \x22id\x22: \x2268c8fcf77aff4b409cc158c0f6cbff7b\x22, \x22name\x22: \x22services\x22}, {\x22description\x22: \x22Test tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c330f1bc663648df9c1e7835a1e7a955\x22, \x22name\x22: \x22test\x22}, {\x22description\x22: \x22admin tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c518b36fa220499b85ba9a71014ce2a5\x22, \x22name\x22: \x22admin\x22}]}" - http_version: - recorded_at: "Tue, 30 Sep 2014 06:59:48 GMT" - recorded_with: "VCR 2.9.3" \ No newline at end of file diff --git a/spec/fixtures/vcr/aviator/request/without_session.yml b/spec/fixtures/vcr/aviator/request/without_session.yml deleted file mode 100644 index 784fb2fe..00000000 --- a/spec/fixtures/vcr/aviator/request/without_session.yml +++ /dev/null @@ -1,36 +0,0 @@ ---- - http_interactions: - - request: - method: get - uri: "http://192.168.11.4:35357/v2.0/tenants" - body: - encoding: US-ASCII - string: "" - headers: - Content-Type: - - application/json - User-Agent: - - "Faraday v0.8.8" - X-Auth-Token: - - sosp-kyl - response: - status: - code: 200 - message: - headers: - vary: - - X-Auth-Token - content-type: - - application/json - content-length: - - "491" - date: - - "Tue, 30 Sep 2014 06:59:48 GMT" - connection: - - close - body: - encoding: UTF-8 - string: "{\x22tenants_links\x22: [], \x22tenants\x22: [{\x22description\x22: \x22Test tenant\x22, \x22enabled\x22: true, \x22id\x22: \x2234e463e2bab24f78990ca864e4a28ba2\x22, \x22name\x22: \x22test2\x22}, {\x22description\x22: \x22Tenant for the openstack services\x22, \x22enabled\x22: true, \x22id\x22: \x2268c8fcf77aff4b409cc158c0f6cbff7b\x22, \x22name\x22: \x22services\x22}, {\x22description\x22: \x22Test tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c330f1bc663648df9c1e7835a1e7a955\x22, \x22name\x22: \x22test\x22}, {\x22description\x22: \x22admin tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c518b36fa220499b85ba9a71014ce2a5\x22, \x22name\x22: \x22admin\x22}]}" - http_version: - recorded_at: "Tue, 30 Sep 2014 06:59:48 GMT" - recorded_with: "VCR 2.9.3" \ No newline at end of file diff --git a/spec/fixtures/vcr/aviator/session/with_password.yml b/spec/fixtures/vcr/aviator/session/with_password.yml deleted file mode 100644 index 3faa4743..00000000 --- a/spec/fixtures/vcr/aviator/session/with_password.yml +++ /dev/null @@ -1,67 +0,0 @@ ---- - http_interactions: - - request: - method: post - uri: "http://192.168.11.4:35357/v2.0/tokens" - body: - encoding: UTF-8 - string: "{\x22auth\x22:{\x22passwordCredentials\x22:{\x22username\x22:\x22admin\x22,\x22password\x22:\x22fyby-tet\x22},\x22tenantName\x22:\x22admin\x22}}" - headers: - Content-Type: - - application/json - User-Agent: - - "Faraday v0.8.8" - response: - status: - code: 200 - message: - headers: - vary: - - X-Auth-Token - content-type: - - application/json - content-length: - - "9780" - date: - - "Tue, 30 Sep 2014 07:16:15 GMT" - connection: - - close - body: - encoding: UTF-8 - string: "{\x22access\x22: {\x22token\x22: {\x22issued_at\x22: \x222014-09-30T07:16:15.042778\x22, \x22expires\x22: \x222014-09-30T08:16:15Z\x22, \x22id\x22: \x22MIIRIAYJKoZIhvcNAQcCoIIRETCCEQ0CAQExCTAHBgUrDgMCGjCCD3YGCSqGSIb3DQEHAaCCD2cEgg9jeyJhY2Nlc3MiOiB7InRva2VuIjogeyJpc3N1ZWRfYXQiOiAiMjAxNC0wOS0zMFQwNzoxNjoxNS4wNDI3NzgiLCAiZXhwaXJlcyI6ICIyMDE0LTA5LTMwVDA4OjE2OjE1WiIsICJpZCI6ICJwbGFjZWhvbGRlciIsICJ0ZW5hbnQiOiB7ImRlc2NyaXB0aW9uIjogImFkbWluIHRlbmFudCIsICJlbmFibGVkIjogdHJ1ZSwgImlkIjogImM1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgIm5hbWUiOiAiYWRtaW4ifX0sICJzZXJ2aWNlQ2F0YWxvZyI6IFt7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc0L3YyL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzQvdjIvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiMWJiNzU4NWIzMzgxNGI4Mjk4NzJlYjQ0MjAyMTg5OGEiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3NC92Mi9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJjb21wdXRlIiwgIm5hbWUiOiAibm92YSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5Njk2LyIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5Njk2LyIsICJpZCI6ICJhYTdkNDU2NTNhYjI0ZGY2YmE5ZDE4NGE1ZWRkNGYxMyIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE5Mi4xNjguMTEuNDo5Njk2LyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJuZXR3b3JrIiwgIm5hbWUiOiAibmV1dHJvbiJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc2L3YyL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzYvdjIvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiMmJmNGQ5YzZiYTgwNDM1M2JjZGNlZGZjNTAxMDNiYjYiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3Ni92Mi9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJ2b2x1bWV2MiIsICJuYW1lIjogImNpbmRlcnYyIn0sIHsiZW5kcG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzQvdjMiLCAicmVnaW9uIjogIm9wZW5zdGFjayIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODc3NC92MyIsICJpZCI6ICIzZmQ4NDBjYmFkZDM0NmFiOTE2YjA2YWYxZjRlNWJmMCIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE5Mi4xNjguMTEuNDo4Nzc0L3YzIn1dLCAiZW5kcG9pbnRzX2xpbmtzIjogW10sICJ0eXBlIjogImNvbXB1dGV2MyIsICJuYW1lIjogIm5vdmF2MyJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5MjkyIiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40OjkyOTIiLCAiaWQiOiAiMTJjOTM1NzkwYmM5NGE3ODljNzJmOWJiYjIxZjM5YmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6OTI5MiJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJpbWFnZSIsICJuYW1lIjogImdsYW5jZSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc3IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzciLCAiaWQiOiAiMWNlNDkwMWQ4OTE1NDIzZTk2ZGFiM2ZlMWZiMzY2M2MiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3NyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJtZXRlcmluZyIsICJuYW1lIjogImNlaWxvbWV0ZXIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwMC92MS8iLCAicmVnaW9uIjogIm9wZW5zdGFjayIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwMC92MS8iLCAiaWQiOiAiNWU4ZjExYzk3ZTgwNDNiNWJkZTA1YmVhMmRlNDYxNmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODAwMC92MS8ifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiY2xvdWRmb3JtYXRpb24iLCAibmFtZSI6ICJoZWF0LWNmbiJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc2L3YxL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzYvdjEvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiNTRiOWVjMjhiYzYwNDI1MmIwMGNmZTZlMGU0NGFhOTQiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3Ni92MS9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJ2b2x1bWUiLCAibmFtZSI6ICJjaW5kZXIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODc3My9zZXJ2aWNlcy9BZG1pbiIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4NzczL3NlcnZpY2VzL0Nsb3VkIiwgImlkIjogIjA3NWVjNzliMGJlMzQxYmFhYmUyZTliMTIwNTkxZjQ4IiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTkyLjE2OC4xMS40Ojg3NzMvc2VydmljZXMvQ2xvdWQifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiZWMyIiwgIm5hbWUiOiAibm92YV9lYzIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwNC92MS9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4MDA0L3YxL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgImlkIjogIjI2MmM0YjM3MzY3ODQ2OGE5ODU1YTNlYmM2MDE1OTYwIiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTkyLjE2OC4xMS40OjgwMDQvdjEvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAib3JjaGVzdHJhdGlvbiIsICJuYW1lIjogImhlYXQifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6MzUzNTcvdjIuMCIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo1MDAwL3YyLjAiLCAiaWQiOiAiMDg5ZmRiMjIyNDk1NDZiOTlhMWU1N2FlYzBiMWU3NmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6NTAwMC92Mi4wIn1dLCAiZW5kcG9pbnRzX2xpbmtzIjogW10sICJ0eXBlIjogImlkZW50aXR5IiwgIm5hbWUiOiAia2V5c3RvbmUifV0sICJ1c2VyIjogeyJ1c2VybmFtZSI6ICJhZG1pbiIsICJyb2xlc19saW5rcyI6IFtdLCAiaWQiOiAiM2Y3NmI5NDY2NzQzNGNmM2JkYzMyM2NmMDIxYzUwZjgiLCAicm9sZXMiOiBbeyJuYW1lIjogImFkbWluIn1dLCAibmFtZSI6ICJhZG1pbiJ9LCAibWV0YWRhdGEiOiB7ImlzX2FkbWluIjogMCwgInJvbGVzIjogWyIxZThiYzVkMWYzYTQ0OGU5YTJhMWNkYTU4ZDk3ZjkyYiJdfX19MYIBgTCCAX0CAQEwXDBXMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVW5zZXQxDjAMBgNVBAcMBVVuc2V0MQ4wDAYDVQQKDAVVbnNldDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tAgEBMAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIIBAEOAl3MRmSUB+J+kRi+qRhwOrNRmj-wDqT5nJTlbafOjofSXsHG683LaipA7oPoH-ARUPDxXIZfevRue7bQQB3I4cWIUSItIPyW4xDpF+iHy3QOm+I-3v3ctze2Z3Rp0TRaYFsItTZZETsSXI28yBt9+3Dsk3a7Vv10HAZetbV1i6qu6avLcJsmN-1J3KLwCDSEvpMgDAcpzAnhba1fi+X8GrCCTz4c1uIcPfsHxX4g8gNkB4-VT0lkRmfSxdrGeRz0uN12oDqgCL64IV1mJ6Bi9Unh15QFcLwU0F8ote+joG9G29fw3WDzneXHIeEIZSBXmOAX2kQBOnZa2sZg8gls=\x22, \x22tenant\x22: {\x22description\x22: \x22admin tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c518b36fa220499b85ba9a71014ce2a5\x22, \x22name\x22: \x22admin\x22}}, \x22serviceCatalog\x22: [{\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8774/v2/c518b36fa220499b85ba9a71014ce2a5\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8774/v2/c518b36fa220499b85ba9a71014ce2a5\x22, \x22id\x22: \x221bb7585b33814b829872eb442021898a\x22, \x22publicURL\x22: \x22http://192.168.11.4:8774/v2/c518b36fa220499b85ba9a71014ce2a5\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22compute\x22, \x22name\x22: \x22nova\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:9696/\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:9696/\x22, \x22id\x22: \x22aa7d45653ab24df6ba9d184a5edd4f13\x22, \x22publicURL\x22: \x22http://192.168.11.4:9696/\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22network\x22, \x22name\x22: \x22neutron\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8776/v2/c518b36fa220499b85ba9a71014ce2a5\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8776/v2/c518b36fa220499b85ba9a71014ce2a5\x22, \x22id\x22: \x222bf4d9c6ba804353bcdcedfc50103bb6\x22, \x22publicURL\x22: \x22http://192.168.11.4:8776/v2/c518b36fa220499b85ba9a71014ce2a5\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22volumev2\x22, \x22name\x22: \x22cinderv2\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8774/v3\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8774/v3\x22, \x22id\x22: \x223fd840cbadd346ab916b06af1f4e5bf0\x22, \x22publicURL\x22: \x22http://192.168.11.4:8774/v3\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22computev3\x22, \x22name\x22: \x22novav3\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:9292\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:9292\x22, \x22id\x22: \x2212c935790bc94a789c72f9bbb21f39bc\x22, \x22publicURL\x22: \x22http://192.168.11.4:9292\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22image\x22, \x22name\x22: \x22glance\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8777\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8777\x22, \x22id\x22: \x221ce4901d8915423e96dab3fe1fb3663c\x22, \x22publicURL\x22: \x22http://192.168.11.4:8777\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22metering\x22, \x22name\x22: \x22ceilometer\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8000/v1/\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8000/v1/\x22, \x22id\x22: \x225e8f11c97e8043b5bde05bea2de4616c\x22, \x22publicURL\x22: \x22http://192.168.11.4:8000/v1/\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22cloudformation\x22, \x22name\x22: \x22heat-cfn\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8776/v1/c518b36fa220499b85ba9a71014ce2a5\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8776/v1/c518b36fa220499b85ba9a71014ce2a5\x22, \x22id\x22: \x2254b9ec28bc604252b00cfe6e0e44aa94\x22, \x22publicURL\x22: \x22http://192.168.11.4:8776/v1/c518b36fa220499b85ba9a71014ce2a5\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22volume\x22, \x22name\x22: \x22cinder\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8773/services/Admin\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8773/services/Cloud\x22, \x22id\x22: \x22075ec79b0be341baabe2e9b120591f48\x22, \x22publicURL\x22: \x22http://192.168.11.4:8773/services/Cloud\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22ec2\x22, \x22name\x22: \x22nova_ec2\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8004/v1/c518b36fa220499b85ba9a71014ce2a5\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8004/v1/c518b36fa220499b85ba9a71014ce2a5\x22, \x22id\x22: \x22262c4b373678468a9855a3ebc6015960\x22, \x22publicURL\x22: \x22http://192.168.11.4:8004/v1/c518b36fa220499b85ba9a71014ce2a5\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22orchestration\x22, \x22name\x22: \x22heat\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:35357/v2.0\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:5000/v2.0\x22, \x22id\x22: \x22089fdb22249546b99a1e57aec0b1e76c\x22, \x22publicURL\x22: \x22http://192.168.11.4:5000/v2.0\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22identity\x22, \x22name\x22: \x22keystone\x22}], \x22user\x22: {\x22username\x22: \x22admin\x22, \x22roles_links\x22: [], \x22id\x22: \x223f76b94667434cf3bdc323cf021c50f8\x22, \x22roles\x22: [{\x22name\x22: \x22admin\x22}], \x22name\x22: \x22admin\x22}, \x22metadata\x22: {\x22is_admin\x22: 0, \x22roles\x22: [\x221e8bc5d1f3a448e9a2a1cda58d97f92b\x22]}}}" - http_version: - recorded_at: "Tue, 30 Sep 2014 07:16:15 GMT" - - request: - method: get - uri: "http://192.168.11.4:5000/v2.0/tenants" - body: - encoding: US-ASCII - string: "" - headers: - Content-Type: - - application/json - User-Agent: - - "Faraday v0.8.8" - X-Auth-Token: - - "MIIRIAYJKoZIhvcNAQcCoIIRETCCEQ0CAQExCTAHBgUrDgMCGjCCD3YGCSqGSIb3DQEHAaCCD2cEgg9jeyJhY2Nlc3MiOiB7InRva2VuIjogeyJpc3N1ZWRfYXQiOiAiMjAxNC0wOS0zMFQwNzoxNjoxNS4wNDI3NzgiLCAiZXhwaXJlcyI6ICIyMDE0LTA5LTMwVDA4OjE2OjE1WiIsICJpZCI6ICJwbGFjZWhvbGRlciIsICJ0ZW5hbnQiOiB7ImRlc2NyaXB0aW9uIjogImFkbWluIHRlbmFudCIsICJlbmFibGVkIjogdHJ1ZSwgImlkIjogImM1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgIm5hbWUiOiAiYWRtaW4ifX0sICJzZXJ2aWNlQ2F0YWxvZyI6IFt7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc0L3YyL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzQvdjIvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiMWJiNzU4NWIzMzgxNGI4Mjk4NzJlYjQ0MjAyMTg5OGEiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3NC92Mi9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJjb21wdXRlIiwgIm5hbWUiOiAibm92YSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5Njk2LyIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5Njk2LyIsICJpZCI6ICJhYTdkNDU2NTNhYjI0ZGY2YmE5ZDE4NGE1ZWRkNGYxMyIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE5Mi4xNjguMTEuNDo5Njk2LyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJuZXR3b3JrIiwgIm5hbWUiOiAibmV1dHJvbiJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc2L3YyL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzYvdjIvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiMmJmNGQ5YzZiYTgwNDM1M2JjZGNlZGZjNTAxMDNiYjYiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3Ni92Mi9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJ2b2x1bWV2MiIsICJuYW1lIjogImNpbmRlcnYyIn0sIHsiZW5kcG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzQvdjMiLCAicmVnaW9uIjogIm9wZW5zdGFjayIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODc3NC92MyIsICJpZCI6ICIzZmQ4NDBjYmFkZDM0NmFiOTE2YjA2YWYxZjRlNWJmMCIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE5Mi4xNjguMTEuNDo4Nzc0L3YzIn1dLCAiZW5kcG9pbnRzX2xpbmtzIjogW10sICJ0eXBlIjogImNvbXB1dGV2MyIsICJuYW1lIjogIm5vdmF2MyJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5MjkyIiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40OjkyOTIiLCAiaWQiOiAiMTJjOTM1NzkwYmM5NGE3ODljNzJmOWJiYjIxZjM5YmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6OTI5MiJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJpbWFnZSIsICJuYW1lIjogImdsYW5jZSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc3IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzciLCAiaWQiOiAiMWNlNDkwMWQ4OTE1NDIzZTk2ZGFiM2ZlMWZiMzY2M2MiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3NyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJtZXRlcmluZyIsICJuYW1lIjogImNlaWxvbWV0ZXIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwMC92MS8iLCAicmVnaW9uIjogIm9wZW5zdGFjayIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwMC92MS8iLCAiaWQiOiAiNWU4ZjExYzk3ZTgwNDNiNWJkZTA1YmVhMmRlNDYxNmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODAwMC92MS8ifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiY2xvdWRmb3JtYXRpb24iLCAibmFtZSI6ICJoZWF0LWNmbiJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc2L3YxL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzYvdjEvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiNTRiOWVjMjhiYzYwNDI1MmIwMGNmZTZlMGU0NGFhOTQiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3Ni92MS9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJ2b2x1bWUiLCAibmFtZSI6ICJjaW5kZXIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODc3My9zZXJ2aWNlcy9BZG1pbiIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4NzczL3NlcnZpY2VzL0Nsb3VkIiwgImlkIjogIjA3NWVjNzliMGJlMzQxYmFhYmUyZTliMTIwNTkxZjQ4IiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTkyLjE2OC4xMS40Ojg3NzMvc2VydmljZXMvQ2xvdWQifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiZWMyIiwgIm5hbWUiOiAibm92YV9lYzIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwNC92MS9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4MDA0L3YxL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgImlkIjogIjI2MmM0YjM3MzY3ODQ2OGE5ODU1YTNlYmM2MDE1OTYwIiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTkyLjE2OC4xMS40OjgwMDQvdjEvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAib3JjaGVzdHJhdGlvbiIsICJuYW1lIjogImhlYXQifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6MzUzNTcvdjIuMCIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo1MDAwL3YyLjAiLCAiaWQiOiAiMDg5ZmRiMjIyNDk1NDZiOTlhMWU1N2FlYzBiMWU3NmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6NTAwMC92Mi4wIn1dLCAiZW5kcG9pbnRzX2xpbmtzIjogW10sICJ0eXBlIjogImlkZW50aXR5IiwgIm5hbWUiOiAia2V5c3RvbmUifV0sICJ1c2VyIjogeyJ1c2VybmFtZSI6ICJhZG1pbiIsICJyb2xlc19saW5rcyI6IFtdLCAiaWQiOiAiM2Y3NmI5NDY2NzQzNGNmM2JkYzMyM2NmMDIxYzUwZjgiLCAicm9sZXMiOiBbeyJuYW1lIjogImFkbWluIn1dLCAibmFtZSI6ICJhZG1pbiJ9LCAibWV0YWRhdGEiOiB7ImlzX2FkbWluIjogMCwgInJvbGVzIjogWyIxZThiYzVkMWYzYTQ0OGU5YTJhMWNkYTU4ZDk3ZjkyYiJdfX19MYIBgTCCAX0CAQEwXDBXMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVW5zZXQxDjAMBgNVBAcMBVVuc2V0MQ4wDAYDVQQKDAVVbnNldDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tAgEBMAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIIBAEOAl3MRmSUB+J+kRi+qRhwOrNRmj-wDqT5nJTlbafOjofSXsHG683LaipA7oPoH-ARUPDxXIZfevRue7bQQB3I4cWIUSItIPyW4xDpF+iHy3QOm+I-3v3ctze2Z3Rp0TRaYFsItTZZETsSXI28yBt9+3Dsk3a7Vv10HAZetbV1i6qu6avLcJsmN-1J3KLwCDSEvpMgDAcpzAnhba1fi+X8GrCCTz4c1uIcPfsHxX4g8gNkB4-VT0lkRmfSxdrGeRz0uN12oDqgCL64IV1mJ6Bi9Unh15QFcLwU0F8ote+joG9G29fw3WDzneXHIeEIZSBXmOAX2kQBOnZa2sZg8gls=" - response: - status: - code: 200 - message: - headers: - vary: - - X-Auth-Token - content-type: - - application/json - content-length: - - "143" - date: - - "Tue, 30 Sep 2014 07:16:15 GMT" - connection: - - close - body: - encoding: UTF-8 - string: "{\x22tenants_links\x22: [], \x22tenants\x22: [{\x22description\x22: \x22admin tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c518b36fa220499b85ba9a71014ce2a5\x22, \x22name\x22: \x22admin\x22}]}" - http_version: - recorded_at: "Tue, 30 Sep 2014 07:16:15 GMT" - recorded_with: "VCR 2.9.3" \ No newline at end of file diff --git a/spec/fixtures/vcr/aviator/session/with_token.yml b/spec/fixtures/vcr/aviator/session/with_token.yml deleted file mode 100644 index 784fb2fe..00000000 --- a/spec/fixtures/vcr/aviator/session/with_token.yml +++ /dev/null @@ -1,36 +0,0 @@ ---- - http_interactions: - - request: - method: get - uri: "http://192.168.11.4:35357/v2.0/tenants" - body: - encoding: US-ASCII - string: "" - headers: - Content-Type: - - application/json - User-Agent: - - "Faraday v0.8.8" - X-Auth-Token: - - sosp-kyl - response: - status: - code: 200 - message: - headers: - vary: - - X-Auth-Token - content-type: - - application/json - content-length: - - "491" - date: - - "Tue, 30 Sep 2014 06:59:48 GMT" - connection: - - close - body: - encoding: UTF-8 - string: "{\x22tenants_links\x22: [], \x22tenants\x22: [{\x22description\x22: \x22Test tenant\x22, \x22enabled\x22: true, \x22id\x22: \x2234e463e2bab24f78990ca864e4a28ba2\x22, \x22name\x22: \x22test2\x22}, {\x22description\x22: \x22Tenant for the openstack services\x22, \x22enabled\x22: true, \x22id\x22: \x2268c8fcf77aff4b409cc158c0f6cbff7b\x22, \x22name\x22: \x22services\x22}, {\x22description\x22: \x22Test tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c330f1bc663648df9c1e7835a1e7a955\x22, \x22name\x22: \x22test\x22}, {\x22description\x22: \x22admin tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c518b36fa220499b85ba9a71014ce2a5\x22, \x22name\x22: \x22admin\x22}]}" - http_version: - recorded_at: "Tue, 30 Sep 2014 06:59:48 GMT" - recorded_with: "VCR 2.9.3" \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 4f919c0f..53d4dd02 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,14 +1,7 @@ require 'puppetlabs_spec_helper/module_spec_helper' require 'shared_examples' -require 'vcr' - RSpec.configure do |c| c.alias_it_should_behave_like_to :it_configures, 'configures' c.alias_it_should_behave_like_to :it_raises, 'raises' end - -VCR.configure do |c| - c.cassette_library_dir = 'spec/fixtures/vcr' - c.hook_into :faraday -end diff --git a/spec/unit/provider/aviator_spec.rb b/spec/unit/provider/aviator_spec.rb deleted file mode 100644 index 35564e64..00000000 --- a/spec/unit/provider/aviator_spec.rb +++ /dev/null @@ -1,320 +0,0 @@ -# Load libraries from aviator here to simulate how they live together in a real puppet run -$LOAD_PATH.push(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'modules', 'aviator', 'lib')) -require 'puppet' -require 'vcr' -require 'spec_helper' -require 'puppet/provider/aviator' - - -describe Puppet::Provider::Aviator do - - before(:each) do - ENV['OS_USERNAME'] = nil - ENV['OS_PASSWORD'] = nil - ENV['OS_TENANT_NAME'] = nil - ENV['OS_AUTH_URL'] = nil - end - - let(:log_file) { '/tmp/aviator_spec.log' } - - let(:type) do - Puppet::Type.newtype(:test_resource) do - newparam(:name, :namevar => true) - newparam(:auth) - newparam(:log_file) - end - end - - - shared_examples 'creating a session using environment variables' do - it 'creates an authenticated session' do - ENV['OS_USERNAME'] = 'admin' - ENV['OS_PASSWORD'] = 'fyby-tet' - ENV['OS_TENANT_NAME'] = 'admin' - ENV['OS_AUTH_URL'] = 'http://192.168.11.4:35357/v2.0' - response = nil - VCR.use_cassette('aviator/session/with_password') do - session = provider.session - response = session.identity_service.request(:list_tenants, :session_data => provider.session_data) - end - expect(response.status).to eq(200) - end - end - - shared_examples 'creating a session using a service token from keystone.conf' do - it 'creates an unauthenticated session' do - data = "[DEFAULT]\nadmin_token=sosp-kyl\nadmin_endpoint=http://192.168.11.4:35357/v2.0" - response = nil - VCR.use_cassette('aviator/session/with_token') do - # Stubbing File.read produces inconsistent results because of how IniConfig - # overrides the File class in some versions of Puppet. - # Stubbing FileType.filetype(:flat) simplifies working with IniConfig - Puppet::Util::FileType.filetype(:flat).any_instance.expects(:read).returns(StringIO.new(data).read) - session = provider.session - Puppet::Util::FileType.filetype(:flat).any_instance.unstub(:read) - response = session.identity_service.request(:list_tenants, :session_data => provider.session_data) - end - - expect(response.status).to eq(200) - end - end - - shared_examples 'it has no credentials' do - it 'fails to authenticate' do - expect{ provider.session }.to raise_error(Puppet::Error, /No credentials provided/) - end - end - - shared_examples 'making request with an existing session' do - it 'makes a successful request' do - VCR.use_cassette('aviator/request/with_session') do - session = provider.session - response = provider.request(session.identity_service, :list_tenants) - expect(response.status).to eq(200) - end - end - end - - shared_examples 'making request with injected session data' do - it 'makes a successful request' do - VCR.use_cassette('aviator/request/without_session') do - session = provider.session - response = provider.request(session.identity_service, :list_tenants) - expect(response.status).to eq(200) - end - end - end - - shared_examples 'making request with no session or session data' do - it 'fails to make a request' do - expect{ provider.request(nil, :list_tenants) }.to raise_error(Puppet::Error, /Cannot make a request/) - end - end - - describe '#session' do - - context 'with valid password credentials in parameters' do - let(:resource_attrs) do - { - :name => 'stubresource', - :auth => { - 'username' => 'admin', - 'password' => 'fyby-tet', - 'tenant_name' => 'admin', - 'host_uri' => 'http://192.168.11.4:35357/v2.0', - } - } - end - - it 'creates a session' do - provider = Puppet::Provider::Aviator.new(type.new(resource_attrs)) - response = nil - VCR.use_cassette('aviator/session/with_password') do - session = provider.session - response = session.identity_service.request(:list_tenants) - end - expect(response.status).to eq(200) - end - end - - context 'with valid openrc file in parameters' do - data = "export OS_USERNAME='admin'\nexport OS_PASSWORD='fyby-tet'\nexport OS_TENANT_NAME='admin'\nexport OS_AUTH_URL='http://192.168.11.4:35357/v2.0'" - let(:resource_attrs) do - { - :name => 'stubresource', - :auth => { - 'openrc' => '/root/openrc' - } - } - end - - it 'creates a session' do - provider = Puppet::Provider::Aviator.new(type.new(resource_attrs)) - response = nil - VCR.use_cassette('aviator/session/with_password') do - File.expects(:open).with('/root/openrc').returns(StringIO.new(data)) - session = provider.session - File.unstub(:open) # Ignore File.open calls to cassette file - response = session.identity_service.request(:list_tenants) - end - expect(response.status).to eq(200) - end - end - - context 'with valid service token in parameters' do - let(:resource_attrs) do - { - :name => 'stubresource', - :auth => { - 'service_token' => 'sosp-kyl', - 'host_uri' => 'http://192.168.11.4:35357/v2.0' - } - } - end - - subject(:session) do - provider = Puppet::Provider::Aviator.new(type.new(resource_attrs)) - VCR.use_cassette('aviator/session/with_token') do - session = provider.session - response = session.identity_service.request(:list_tenants, :session_data => provider.session_data) - end - end - - it 'creates a session' do - expect(session.status).to eq(200) - end - - end - - context 'with valid password credentials in environment variables' do - it_behaves_like 'creating a session using environment variables' do - let(:resource_attrs) do - { - :name => 'stubresource', - } - end - let(:provider) do - Puppet::Provider::Aviator.new(type.new(resource_attrs)) - end - end - end - - context 'with valid service token in keystone.conf' do - it_behaves_like 'creating a session using a service token from keystone.conf' do - let(:resource_attrs) do - { - :name => 'stubresource', - } - end - let(:provider) do - Puppet::Provider::Aviator.new(type.new(resource_attrs)) - end - end - - end - - context 'with no valid credentials' do - it_behaves_like 'it has no credentials' do - let(:resource_attrs) do - { - :name => 'stubresource', - } - end - let(:provider) { Puppet::Provider::Aviator.new(type.new(resource_attrs)) } - end - end - - end - - - describe '::session' do - - context 'with valid password credentials in environment variables' do - it_behaves_like 'creating a session using environment variables' do - let(:provider) { Puppet::Provider::Aviator.dup } - end - end - - context 'with valid service token in keystone.conf' do - it_behaves_like 'creating a session using a service token from keystone.conf' do - let(:provider) { Puppet::Provider::Aviator.dup } - end - end - - context 'with no valid credentials' do - it_behaves_like 'it has no credentials' do - let(:provider) { Puppet::Provider::Aviator.dup } - end - end - end - - describe '#request' do - context 'when a session exists' do - it_behaves_like 'making request with an existing session' do - let(:resource_attrs) do - { - :name => 'stubresource', - :auth => { - 'username' => 'admin', - 'password' => 'fyby-tet', - 'tenant_name' => 'admin', - 'host_uri' => 'http://192.168.11.4:35357/v2.0', - } - } - end - let (:provider) { Puppet::Provider::Aviator.new(type.new(resource_attrs)) } - end - end - - context 'when injecting session data' do - let(:resource_attrs) do - { - :name => 'stubresource', - :auth => { - 'service_token' => 'sosp-kyl', - 'host_uri' => 'http://192.168.11.4:35357/v2.0' - } - } - end - let(:provider) { Puppet::Provider::Aviator.new(type.new(resource_attrs)) } - it 'makes a successful request' do - provider = Puppet::Provider::Aviator.new(type.new(resource_attrs)) - VCR.use_cassette('aviator/request/without_session') do - session = provider.session - response = provider.request(session.identity_service, :list_tenants) - expect(response.status).to eq(200) - end - end - end - - context 'when there is no session or session data' do - it_behaves_like 'making request with no session or session data' do - let(:resource_attrs) do - { - :name => 'stubresource', - } - end - let(:provider) {Puppet::Provider::Aviator.new(type.new(resource_attrs)) } - end - end - end - - describe '::request' do - context 'when a session exists' do - - it_behaves_like 'making request with an existing session' do - let(:provider) { provider = Puppet::Provider::Aviator.dup } - before(:each) do - ENV['OS_USERNAME'] = 'admin' - ENV['OS_PASSWORD'] = 'fyby-tet' - ENV['OS_TENANT_NAME'] = 'admin' - ENV['OS_AUTH_URL'] = 'http://192.168.11.4:35357/v2.0' - end - end - end - - context 'when injecting session data' do - let(:session_data) do - { - :base_url => 'http://192.168.11.4:35357/v2.0', - :service_token => 'sosp-kyl' - } - end - it 'makes a successful request' do - provider = Puppet::Provider::Aviator.dup - VCR.use_cassette('aviator/request/without_session') do - session = ::Aviator::Session.new(:config => { :provider => 'openstack' }, :log_file => log_file) - provider.session_data = session_data - response = provider.request(session.identity_service, :list_tenants) - expect(response.status).to eq(200) - end - end - end - - context 'when there is no session or session data' do - it_behaves_like 'making request with no session or session data' do - let(:provider) { Puppet::Provider::Aviator.dup } - end - end - end -end diff --git a/spec/unit/provider/openstack_spec.rb b/spec/unit/provider/openstack_spec.rb new file mode 100644 index 00000000..447f3f6c --- /dev/null +++ b/spec/unit/provider/openstack_spec.rb @@ -0,0 +1,228 @@ +# Load libraries from aviator here to simulate how they live together in a real puppet run +$LOAD_PATH.push(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'modules', 'aviator', 'lib')) +require 'puppet' +require 'spec_helper' +require 'puppet/provider/openstack' + + +describe Puppet::Provider::Openstack do + + before(:each) do + ENV['OS_USERNAME'] = nil + ENV['OS_PASSWORD'] = nil + ENV['OS_TENANT_NAME'] = nil + ENV['OS_AUTH_URL'] = nil + end + + let(:type) do + Puppet::Type.newtype(:test_resource) do + newparam(:name, :namevar => true) + newparam(:auth) + newparam(:log_file) + end + end + + shared_examples 'authenticating with environment variables' do + it 'makes a successful request' do + ENV['OS_USERNAME'] = 'test' + ENV['OS_PASSWORD'] = 'abc123' + ENV['OS_TENANT_NAME'] = 'test' + ENV['OS_AUTH_URL'] = 'http://127.0.0.1:35357/v2.0' + if provider.class == Class + provider.stubs(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', [[ '--long' ]]) + .returns('"ID","Name","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True +') + else + provider.class.stubs(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', [[ '--long' ]]) + .returns('"ID","Name","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True +') + end + response = provider.request('project', 'list', nil, nil, '--long' ) + expect(response.first[:description]).to match /Test tenant/ + end + end + + shared_examples 'it has no credentials' do + it 'fails to authenticate' do + expect{ provider.request('project', 'list', nil, nil, '--long') }.to raise_error(Puppet::Error::OpenstackAuthInputError, /No credentials provided/) + end + end + + describe '#request' do + + context 'with valid password credentials in parameters' do + let(:resource_attrs) do + { + :name => 'stubresource', + :auth => { + 'username' => 'test', + 'password' => 'abc123', + 'tenant_name' => 'test', + 'auth_url' => 'http://127.0.0.1:5000/v2.0', + } + } + end + let(:provider) do + Puppet::Provider::Openstack.new(type.new(resource_attrs)) + end + + it 'makes a successful request' do + provider.class.stubs(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .returns('"ID","Name","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True +') + response = provider.request('project', 'list', nil, resource_attrs[:auth], '--long') + expect(response.first[:description]).to match /Test tenant/ + end + end + + context 'with valid openrc file in parameters' do + mock = "export OS_USERNAME='test'\nexport OS_PASSWORD='abc123'\nexport OS_TENANT_NAME='test'\nexport OS_AUTH_URL='http://127.0.0.1:5000/v2.0'" + let(:resource_attrs) do + { + :name => 'stubresource', + :auth => { + 'openrc' => '/root/openrc' + } + } + end + let(:provider) do + Puppet::Provider::Openstack.new(type.new(resource_attrs)) + end + + it 'makes a successful request' do + File.expects(:open).with('/root/openrc').returns(StringIO.new(mock)) + provider.class.stubs(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .returns('"ID","Name","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True +') + response = provider.request('project', 'list', nil, resource_attrs[:auth], '--long') + expect(response.first[:description]).to match /Test tenant/ + end + end + + context 'with valid service token in parameters' do + let(:resource_attrs) do + { + :name => 'stubresource', + :auth => { + 'token' => 'secrettoken', + 'auth_url' => 'http://127.0.0.1:5000/v2.0' + } + } + end + let(:provider) do + Puppet::Provider::Openstack.new(type.new(resource_attrs)) + end + + it 'makes a successful request' do + provider.class.stubs(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-token', 'secrettoken', '--os-url', 'http://127.0.0.1:5000/v2.0']]) + .returns('"ID","Name","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True +') + response = provider.request('project', 'list', nil, resource_attrs[:auth], '--long') + expect(response.first[:description]).to match /Test tenant/ + end + + it 'makes a successful show request' do + provider.class.stubs(:openstack) + .with('project', 'show', '--format', 'shell', [['test', '--os-token', 'secrettoken', '--os-url', 'http://127.0.0.1:5000/v2.0']]) + .returns('ID="1cb05cfed7c24279be884ba4f6520262" +Name="test" +Description="Test Tenant" +Enabled="True" +') + response = provider.request('project', 'show', 'test', resource_attrs[:auth]) + expect(response[:description]).to match /Test Tenant/ + expect(response[:id]).to match /1cb05cfed7c24279be884ba4f6520262/ + expect(response[:name]).to match /test/ + expect(response[:enabled]).to match /True/ + end + + end + + context 'with valid password credentials in environment variables' do + it_behaves_like 'authenticating with environment variables' do + let(:resource_attrs) do + { + :name => 'stubresource', + } + end + let(:provider) do + Puppet::Provider::Openstack.new(type.new(resource_attrs)) + end + end + end + + context 'with no valid credentials' do + it_behaves_like 'it has no credentials' do + let(:resource_attrs) do + { + :name => 'stubresource', + } + end + let(:provider) do + Puppet::Provider::Openstack.new(type.new(resource_attrs)) + end + end + end + + context 'it retries on connection errors' do + let(:resource_attrs) do + { + :name => 'stubresource', + :auth => { + 'username' => 'test', + 'password' => 'abc123', + 'tenant_name' => 'test', + 'auth_url' => 'http://127.0.0.1:5000/v2.0', + } + } + end + let(:provider) do + Puppet::Provider::Openstack.new(type.new(resource_attrs)) + end + it 'retries' do + provider.class.stubs(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .raises(Puppet::ExecutionFailure, 'Unable to establish connection') + .then + .returns('') + provider.class.expects(:sleep).with(2).returns(nil) + provider.request('project', 'list', nil, resource_attrs[:auth], '--long') + end + end + end + + + describe '::request' do + + context 'with valid password credentials in environment variables' do + it_behaves_like 'authenticating with environment variables' do + let(:resource_attrs) do + { + :name => 'stubresource', + } + end + let(:provider) do + Puppet::Provider::Openstack.dup + end + end + end + + context 'with no valid credentials' do + it_behaves_like 'it has no credentials' do + let(:provider) { Puppet::Provider::Openstack.dup } + end + end + + end + +end