Fix broken Puppet::Provider::Glance

This patch fixes Puppet::Provider::Glance, broken because it still
depends on glance_store/os_region_name, which was removed in [1].

This patch also updates outdated provider implementation, and introduce
the implementetion consisntent with other modules like puppet-nova or
puppet-neutron.

[1] 9e82f598ad

Closes-Bug: #1872656
Closes-Bug: #1872691
Change-Id: I1dfcb311c10c633788c24484c21277255b60e4e5
This commit is contained in:
Takashi Kajinami 2020-04-14 17:20:19 +09:00
parent dbdabfca18
commit 066f45758d
2 changed files with 101 additions and 64 deletions

View File

@ -1,4 +1,4 @@
# Since there's only one glance type for now, # Since there's only one Glance type for now,
# this probably could have all gone in the provider file. # this probably could have all gone in the provider file.
# But maybe this is good long-term. # But maybe this is good long-term.
require 'puppet/util/inifile' require 'puppet/util/inifile'
@ -18,79 +18,85 @@ class Puppet::Provider::Glance < Puppet::Provider::Openstack
end end
def self.glance_request(service, action, error, properties=nil) def self.glance_request(service, action, error, properties=nil)
properties ||= []
@credentials.username = glance_credentials['username'] @credentials.username = glance_credentials['username']
@credentials.password = glance_credentials['password'] @credentials.password = glance_credentials['password']
@credentials.project_name = glance_credentials['project_name'] @credentials.project_name = glance_credentials['project_name']
@credentials.auth_url = auth_endpoint @credentials.auth_url = auth_endpoint
@credentials.user_domain_name = glance_credentials['user_domain_name']
@credentials.project_domain_name = glance_credentials['project_domain_name']
if glance_credentials['region_name']
@credentials.region_name = glance_credentials['region_name']
end
raise error unless @credentials.set? raise error unless @credentials.set?
Puppet::Provider::Openstack.request(service, action, properties, @credentials) Puppet::Provider::Openstack.request(service, action, properties, @credentials)
end end
def self.conf_filename
'/etc/glance/glance-api.conf'
end
def self.glance_conf
return @glance_conf if @glance_conf
@glance_conf = Puppet::Util::IniConfig::File.new
@glance_conf.read(conf_filename)
@glance_conf
end
def self.glance_credentials def self.glance_credentials
@glance_credentials ||= get_glance_credentials @glance_credentials ||= get_glance_credentials
end end
def self.get_glance_credentials def self.get_glance_credentials
if glance_file and glance_file['keystone_authtoken'] and #needed keys for authentication
glance_file['keystone_authtoken']['auth_host'] and auth_keys = ['auth_url', 'project_name', 'username', 'password']
glance_file['keystone_authtoken']['auth_port'] and conf = glance_conf
glance_file['keystone_authtoken']['auth_protocol'] and if conf and conf['keystone_authtoken'] and
glance_file['keystone_authtoken']['project_name'] and auth_keys.all?{|k| !conf['keystone_authtoken'][k].nil?}
glance_file['keystone_authtoken']['username'] and creds = Hash[ auth_keys.map \
glance_file['keystone_authtoken']['password'] and { |k| [k, conf['keystone_authtoken'][k].strip] } ]
glance_file['glance_store']['os_region_name']
g = {} if !conf['keystone_authtoken']['region_name'].nil?
g['auth_host'] = glance_file['keystone_authtoken']['auth_host'].strip creds['region_name'] = conf['keystone_authtoken']['region_name'].strip
g['auth_port'] = glance_file['keystone_authtoken']['auth_port'].strip end
g['auth_protocol'] = glance_file['keystone_authtoken']['auth_protocol'].strip
g['project_name'] = glance_file['keystone_authtoken']['project_name'].strip
g['username'] = glance_file['keystone_authtoken']['username'].strip
g['password'] = glance_file['keystone_authtoken']['password'].strip
g['os_region_name'] = glance_file['glance_store']['os_region_name'].strip
# auth_admin_prefix not required to be set. if !conf['keystone_authtoken']['project_domain_name'].nil?
g['auth_admin_prefix'] = (glance_file['keystone_authtoken']['auth_admin_prefix'] || '').strip creds['project_domain_name'] = conf['keystone_authtoken']['project_domain_name'].strip
else
creds['project_domain_name'] = 'Default'
end
return g if !conf['keystone_authtoken']['user_domain_name'].nil?
elsif glance_file and glance_file['keystone_authtoken'] and creds['user_domain_name'] = conf['keystone_authtoken']['user_domain_name'].strip
glance_file['keystone_authtoken']['auth_url'] and else
glance_file['keystone_authtoken']['project_name'] and creds['user_domain_name'] = 'Default'
glance_file['keystone_authtoken']['username'] and end
glance_file['keystone_authtoken']['password'] and
glance_file['glance_store']['os_region_name']
g = {} return creds
g['auth_url'] = glance_file['keystone_authtoken']['auth_url'].strip
g['project_name'] = glance_file['keystone_authtoken']['project_name'].strip
g['username'] = glance_file['keystone_authtoken']['username'].strip
g['password'] = glance_file['keystone_authtoken']['password'].strip
g['os_region_name'] = glance_file['glance_store']['os_region_name'].strip
return g
else else
raise(Puppet::Error, 'File: /etc/glance/glance-api.conf does not contain all required sections.') raise(Puppet::Error, "File: #{conf_filename} does not contain all " +
"required sections. Glance types will not work if glance is not " +
"correctly configured.")
end end
end end
def self.get_auth_endpoint
g = glance_credentials
"#{g['auth_url']}"
end
def self.auth_endpoint def self.auth_endpoint
@auth_endpoint ||= get_auth_endpoint @auth_endpoint ||= get_auth_endpoint
end end
def self.get_auth_endpoint def self.reset
g = glance_credentials @glance_conf = nil
if g.key?('auth_url') @glance_credentials = nil
"#{g['auth_url']}/"
else
"#{g['auth_protocol']}://#{g['auth_host']}:#{g['auth_port']}#{g['auth_admin_prefix']}/v3/"
end
end end
# To keep backward compatibility
def self.glance_file def self.glance_file
return @glance_file if @glance_file self.class.glance_conf
@glance_file = Puppet::Util::IniConfig::File.new
@glance_file.read('/etc/glance/glance-api.conf')
@glance_file
end end
def self.glance_hash def self.glance_hash

View File

@ -3,33 +3,64 @@ require 'spec_helper'
require 'puppet/provider/glance' require 'puppet/provider/glance'
require 'tempfile' require 'tempfile'
klass = Puppet::Provider::Glance
class Puppet::Provider::Glance
def self.reset
@admin_endpoint = nil
@tenant_hash = nil
@admin_token = nil
@keystone_file = nil
end
end
describe Puppet::Provider::Glance do describe Puppet::Provider::Glance do
def klass
described_class
end
let :credential_hash do
{
'auth_url' => 'https://192.168.56.210:5000/v3/',
'project_name' => 'admin_tenant',
'username' => 'admin',
'password' => 'password',
'region_name' => 'Region1',
}
end
let :auth_endpoint do
'https://192.168.56.210:5000/v3/'
end
let :credential_error do
/Glance types will not work/
end
after :each do after :each do
klass.reset klass.reset
end end
describe 'when retrieving the auth credentials' do describe 'when determining credentials' do
it 'should fail if no auth params are passed and the glance config file does not have the expected contents' do it 'should fail if config is empty' do
mock = {} conf = {}
Puppet::Util::IniConfig::File.expects(:new).returns(mock) klass.expects(:glance_conf).returns(conf)
mock.expects(:read).with('/etc/glance/glance-api.conf')
expect do expect do
klass.glance_credentials klass.glance_credentials
end.to raise_error(Puppet::Error, /does not contain all required sections/) end.to raise_error(Puppet::Error, credential_error)
end
it 'should fail if config does not have keystone_authtoken section.' do
conf = {'foo' => 'bar'}
klass.expects(:glance_conf).returns(conf)
expect do
klass.glance_credentials
end.to raise_error(Puppet::Error, credential_error)
end
it 'should fail if config does not contain all auth params' do
conf = {'keystone_authtoken' => {'invalid_value' => 'foo'}}
klass.expects(:glance_conf).returns(conf)
expect do
klass.glance_credentials
end.to raise_error(Puppet::Error, credential_error)
end
it 'should use specified uri in the auth endpoint' do
conf = {'keystone_authtoken' => credential_hash}
klass.expects(:glance_conf).returns(conf)
expect(klass.get_auth_endpoint).to eq(auth_endpoint)
end end
end end