Targeting Keystone V3 API support
The default domain (id 'default', name 'Default') is where the V2 tenants/users are defined. So V3, which is now the default API's version can and should be used. Beeing able to use V3 domains needs to be supported by specifying the domain name for a project/user. This patch : - Adds project and user domain names - Renames tenant (v2) as project (v3) - Renames os-auth-url to os-url, when using an authicated token against a service url, to distinct them from each other, as in OSC (opentackclient) - Updates newparam(:auth) accordingly to describe v2/v3 credential examples Note: Keystone API v2 is deprecated [1] [1] http://docs.openstack.org/developer/keystone/http-api.html#should-i-use-v2-0-or-v3 Change-Id: I72f79129a6875eb433eeb8a62f928e7210db134a
This commit is contained in:
parent
efa9181201
commit
d4073c2721
@ -106,46 +106,51 @@ class Puppet::Provider::Openstack < Puppet::Provider
|
|||||||
private
|
private
|
||||||
|
|
||||||
def password_credentials_set?(auth_params)
|
def password_credentials_set?(auth_params)
|
||||||
auth_params && auth_params['username'] && auth_params['password'] && auth_params['tenant_name'] && auth_params['auth_url']
|
auth_params && auth_params['username'] && auth_params['password'] && auth_params['project_name'] && auth_params['auth_url']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def openrc_set?(auth_params)
|
def openrc_set?(auth_params)
|
||||||
auth_params && auth_params['openrc']
|
auth_params && auth_params['openrc']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def service_credentials_set?(auth_params)
|
def service_credentials_set?(auth_params)
|
||||||
auth_params && auth_params['token'] && auth_params['auth_url']
|
auth_params && auth_params['token'] && auth_params['url']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def self.env_vars_set?
|
def self.env_vars_set?
|
||||||
ENV['OS_USERNAME'] && ENV['OS_PASSWORD'] && ENV['OS_TENANT_NAME'] && ENV['OS_AUTH_URL']
|
ENV['OS_USERNAME'] && ENV['OS_PASSWORD'] && ENV['OS_PROJECT_NAME'] && ENV['OS_AUTH_URL']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def env_vars_set?
|
def env_vars_set?
|
||||||
self.class.env_vars_set?
|
self.class.env_vars_set?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def self.password_auth_args(credentials)
|
def self.password_auth_args(credentials)
|
||||||
['--os-username', credentials['username'],
|
creds = [ '--os-username', credentials['username'],
|
||||||
'--os-password', credentials['password'],
|
'--os-password', credentials['password'],
|
||||||
'--os-tenant-name', credentials['tenant_name'],
|
'--os-project-name', credentials['project_name'],
|
||||||
'--os-auth-url', credentials['auth_url']]
|
'--os-auth-url', credentials['auth_url'] ]
|
||||||
|
|
||||||
|
if credentials.include?('project_domain_name')
|
||||||
|
creds << '--os-project-domain-name'
|
||||||
|
creds << credentials['project_domain_name']
|
||||||
|
end
|
||||||
|
|
||||||
|
if credentials.include?('user_domain_name')
|
||||||
|
creds << '--os-user-domain-name'
|
||||||
|
creds << credentials['user_domain_name']
|
||||||
|
end
|
||||||
|
|
||||||
|
creds
|
||||||
end
|
end
|
||||||
|
|
||||||
def password_auth_args(credentials)
|
def password_auth_args(credentials)
|
||||||
self.class.password_auth_args(credentials)
|
self.class.password_auth_args(credentials)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def self.token_auth_args(credentials)
|
def self.token_auth_args(credentials)
|
||||||
['--os-token', credentials['token'],
|
[ '--os-token', credentials['token'],
|
||||||
'--os-url', credentials['auth_url']]
|
'--os-url', credentials['url'] ]
|
||||||
end
|
end
|
||||||
|
|
||||||
def token_auth_args(credentials)
|
def token_auth_args(credentials)
|
||||||
@ -163,7 +168,6 @@ class Puppet::Provider::Openstack < Puppet::Provider
|
|||||||
return creds
|
return creds
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def self.get_credentials_from_env
|
def self.get_credentials_from_env
|
||||||
env = ENV.to_hash.dup.delete_if { |key, _| ! (key =~ /^OS_/) }
|
env = ENV.to_hash.dup.delete_if { |key, _| ! (key =~ /^OS_/) }
|
||||||
credentials = {}
|
credentials = {}
|
||||||
|
@ -5,27 +5,46 @@ module Puppet::Util::Openstack
|
|||||||
type.newparam(:auth) do
|
type.newparam(:auth) do
|
||||||
|
|
||||||
desc <<EOT
|
desc <<EOT
|
||||||
Hash of authentication credentials. Credentials can be specified as
|
Hash of authentication credentials. Credentials can be specified as either :
|
||||||
password credentials, e.g.:
|
|
||||||
|
|
||||||
|
1. Using a project/user with a password
|
||||||
|
|
||||||
|
For Keystone API V2:
|
||||||
auth => {
|
auth => {
|
||||||
'username' => 'test',
|
'username' => 'test',
|
||||||
'password' => 'passw0rd',
|
'password' => 'changeme',
|
||||||
'tenant_name' => 'test',
|
'project_name' => 'test',
|
||||||
'auth_url' => 'http://localhost:35357/v2.0',
|
'auth_url' => 'http://localhost:35357/v2.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
or a path to an openrc file containing these credentials, e.g.:
|
or altenatively for Keystone API V3:
|
||||||
|
|
||||||
auth => {
|
auth => {
|
||||||
'openrc' => '/root/openrc',
|
'username' => 'test',
|
||||||
|
'password' => 'changeme',
|
||||||
|
'project_name' => 'test',
|
||||||
|
'project_domain_name' => 'domain1',
|
||||||
|
'user_domain_name' => 'domain1',
|
||||||
|
'auth_url' => 'http://localhost:35357/v3'
|
||||||
}
|
}
|
||||||
|
|
||||||
or a service token and host, e.g.:
|
2. Using a path to an openrc file containing these credentials
|
||||||
|
|
||||||
auth => {
|
auth => {
|
||||||
'service_token' => 'ADMIN',
|
'openrc' => '/root/openrc'
|
||||||
'auth_url' => 'http://localhost:35357/v2.0',
|
}
|
||||||
|
|
||||||
|
3. Using a service token
|
||||||
|
|
||||||
|
For Keystone API V2:
|
||||||
|
auth => {
|
||||||
|
'token' => 'example',
|
||||||
|
'url' => 'http://localhost:35357/v2.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
Alternatively for Keystone API V3:
|
||||||
|
auth => {
|
||||||
|
'token' => 'example',
|
||||||
|
'url' => 'http://localhost:35357/v3.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
If not present, the provider will look for environment variables for
|
If not present, the provider will look for environment variables for
|
||||||
|
@ -10,7 +10,7 @@ describe Puppet::Provider::Openstack do
|
|||||||
before(:each) do
|
before(:each) do
|
||||||
ENV['OS_USERNAME'] = nil
|
ENV['OS_USERNAME'] = nil
|
||||||
ENV['OS_PASSWORD'] = nil
|
ENV['OS_PASSWORD'] = nil
|
||||||
ENV['OS_TENANT_NAME'] = nil
|
ENV['OS_PROJECT_NAME'] = nil
|
||||||
ENV['OS_AUTH_URL'] = nil
|
ENV['OS_AUTH_URL'] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -22,11 +22,11 @@ describe Puppet::Provider::Openstack do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
shared_examples 'authenticating with environment variables' do
|
shared_examples 'authenticating with environment variables using API v2' do
|
||||||
it 'makes a successful request' do
|
it 'makes a successful request' do
|
||||||
ENV['OS_USERNAME'] = 'test'
|
ENV['OS_USERNAME'] = 'test'
|
||||||
ENV['OS_PASSWORD'] = 'abc123'
|
ENV['OS_PASSWORD'] = 'abc123'
|
||||||
ENV['OS_TENANT_NAME'] = 'test'
|
ENV['OS_PROJECT_NAME'] = 'test'
|
||||||
ENV['OS_AUTH_URL'] = 'http://127.0.0.1:35357/v2.0'
|
ENV['OS_AUTH_URL'] = 'http://127.0.0.1:35357/v2.0'
|
||||||
if provider.class == Class
|
if provider.class == Class
|
||||||
provider.stubs(:openstack)
|
provider.stubs(:openstack)
|
||||||
@ -46,6 +46,30 @@ describe Puppet::Provider::Openstack do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
shared_examples 'authenticating with environment variables using API v3' do
|
||||||
|
it 'makes a successful request' do
|
||||||
|
ENV['OS_USERNAME'] = 'test'
|
||||||
|
ENV['OS_PASSWORD'] = 'abc123'
|
||||||
|
ENV['OS_PROJECT_NAME'] = 'test'
|
||||||
|
ENV['OS_AUTH_URL'] = 'http://127.0.0.1:35357/v3'
|
||||||
|
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
|
shared_examples 'it has no credentials' do
|
||||||
it 'fails to authenticate' do
|
it 'fails to authenticate' do
|
||||||
expect{ provider.request('project', 'list', nil, nil, '--long') }.to raise_error(Puppet::Error::OpenstackAuthInputError, /No credentials provided/)
|
expect{ provider.request('project', 'list', nil, nil, '--long') }.to raise_error(Puppet::Error::OpenstackAuthInputError, /No credentials provided/)
|
||||||
@ -61,7 +85,7 @@ describe Puppet::Provider::Openstack do
|
|||||||
:auth => {
|
:auth => {
|
||||||
'username' => 'test',
|
'username' => 'test',
|
||||||
'password' => 'abc123',
|
'password' => 'abc123',
|
||||||
'tenant_name' => 'test',
|
'project_name' => 'test',
|
||||||
'auth_url' => 'http://127.0.0.1:5000/v2.0',
|
'auth_url' => 'http://127.0.0.1:5000/v2.0',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,7 +96,7 @@ describe Puppet::Provider::Openstack do
|
|||||||
|
|
||||||
it 'makes a successful request' do
|
it 'makes a successful request' do
|
||||||
provider.class.stubs(:openstack)
|
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']])
|
.with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
|
||||||
.returns('"ID","Name","Description","Enabled"
|
.returns('"ID","Name","Description","Enabled"
|
||||||
"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
|
"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
|
||||||
')
|
')
|
||||||
@ -82,7 +106,7 @@ describe Puppet::Provider::Openstack do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'with valid openrc file in parameters' do
|
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'"
|
mock = "export OS_USERNAME='test'\nexport OS_PASSWORD='abc123'\nexport OS_PROJECT_NAME='test'\nexport OS_AUTH_URL='http://127.0.0.1:5000/v2.0'"
|
||||||
let(:resource_attrs) do
|
let(:resource_attrs) do
|
||||||
{
|
{
|
||||||
:name => 'stubresource',
|
:name => 'stubresource',
|
||||||
@ -98,7 +122,7 @@ describe Puppet::Provider::Openstack do
|
|||||||
it 'makes a successful request' do
|
it 'makes a successful request' do
|
||||||
File.expects(:open).with('/root/openrc').returns(StringIO.new(mock))
|
File.expects(:open).with('/root/openrc').returns(StringIO.new(mock))
|
||||||
provider.class.stubs(:openstack)
|
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']])
|
.with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
|
||||||
.returns('"ID","Name","Description","Enabled"
|
.returns('"ID","Name","Description","Enabled"
|
||||||
"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
|
"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
|
||||||
')
|
')
|
||||||
@ -113,7 +137,7 @@ describe Puppet::Provider::Openstack do
|
|||||||
:name => 'stubresource',
|
:name => 'stubresource',
|
||||||
:auth => {
|
:auth => {
|
||||||
'token' => 'secrettoken',
|
'token' => 'secrettoken',
|
||||||
'auth_url' => 'http://127.0.0.1:5000/v2.0'
|
'url' => 'http://127.0.0.1:5000/v2.0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
@ -149,7 +173,7 @@ Enabled="True"
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'with valid password credentials in environment variables' do
|
context 'with valid password credentials in environment variables' do
|
||||||
it_behaves_like 'authenticating with environment variables' do
|
it_behaves_like 'authenticating with environment variables using API v2' do
|
||||||
let(:resource_attrs) do
|
let(:resource_attrs) do
|
||||||
{
|
{
|
||||||
:name => 'stubresource',
|
:name => 'stubresource',
|
||||||
@ -181,7 +205,7 @@ Enabled="True"
|
|||||||
:auth => {
|
:auth => {
|
||||||
'username' => 'test',
|
'username' => 'test',
|
||||||
'password' => 'abc123',
|
'password' => 'abc123',
|
||||||
'tenant_name' => 'test',
|
'project_name' => 'test',
|
||||||
'auth_url' => 'http://127.0.0.1:5000/v2.0',
|
'auth_url' => 'http://127.0.0.1:5000/v2.0',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,7 +215,7 @@ Enabled="True"
|
|||||||
end
|
end
|
||||||
it 'retries' do
|
it 'retries' do
|
||||||
provider.class.stubs(:openstack)
|
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']])
|
.with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
|
||||||
.raises(Puppet::ExecutionFailure, 'Unable to establish connection')
|
.raises(Puppet::ExecutionFailure, 'Unable to establish connection')
|
||||||
.then
|
.then
|
||||||
.returns('')
|
.returns('')
|
||||||
@ -205,7 +229,7 @@ Enabled="True"
|
|||||||
describe '::request' do
|
describe '::request' do
|
||||||
|
|
||||||
context 'with valid password credentials in environment variables' do
|
context 'with valid password credentials in environment variables' do
|
||||||
it_behaves_like 'authenticating with environment variables' do
|
it_behaves_like 'authenticating with environment variables using API v2' do
|
||||||
let(:resource_attrs) do
|
let(:resource_attrs) do
|
||||||
{
|
{
|
||||||
:name => 'stubresource',
|
:name => 'stubresource',
|
||||||
|
Loading…
Reference in New Issue
Block a user