Fix endpoint update when one endpoint is missing.
Endpoint are created for admin, internal and public network by this provider. If only one of the endpoint is missing then all the endpoints are recreated as puppet fails to match the resource with the remaining endpoint. This fix enable one to update the resource where update means "recreate the missing endpoint". Change-Id: Ic605725d1923680c6518ebadda36cb5d596c08fe Closes-bug: 1559013
This commit is contained in:
parent
a02d2aeec7
commit
fe0edef97d
@ -9,6 +9,8 @@ Puppet::Type.type(:keystone_endpoint).provide(
|
||||
|
||||
include PuppetX::Keystone::CompositeNamevar::Helpers
|
||||
|
||||
attr_accessor :property_hash, :property_flush
|
||||
|
||||
@endpoints = nil
|
||||
@services = nil
|
||||
@credentials = Puppet::Provider::Openstack::CredentialsV3.new
|
||||
@ -31,30 +33,18 @@ Puppet::Type.type(:keystone_endpoint).provide(
|
||||
if self.class.do_not_manage
|
||||
fail("Not managing Keystone_endpoint[#{@resource[:name]}] due to earlier Keystone API failures.")
|
||||
end
|
||||
# Reset the cache.
|
||||
self.class.services = nil
|
||||
name = resource[:name]
|
||||
region = resource[:region]
|
||||
type = resource[:type]
|
||||
type = self.class.type_from_service(name) unless set?(:type)
|
||||
@property_hash[:type] = type
|
||||
services = self.class.services.find_all { |s| s[:name] == name }
|
||||
service = services.find { |s| s[:type] == type }
|
||||
|
||||
if service.nil? && services.count == 1
|
||||
# For backward comptatibility, match the service by name only.
|
||||
name = services[0][:id]
|
||||
else
|
||||
# Math the service by id.
|
||||
name = service[:id] if service
|
||||
end
|
||||
ids = []
|
||||
|
||||
s_id = service_id
|
||||
created = false
|
||||
[:admin_url, :internal_url, :public_url].each do |scope|
|
||||
if resource[scope]
|
||||
created = true
|
||||
ids << endpoint_create(name, region, scope.to_s.sub(/_url$/, ''),
|
||||
ids << endpoint_create(s_id, region, scope.to_s.sub(/_url$/, ''),
|
||||
resource[scope])[:id]
|
||||
end
|
||||
end
|
||||
@ -134,11 +124,11 @@ Puppet::Type.type(:keystone_endpoint).provide(
|
||||
new(
|
||||
:name => endpoint[:name],
|
||||
:ensure => :present,
|
||||
:id => "#{endpoint[:admin][:id]},#{endpoint[:internal][:id]},#{endpoint[:public][:id]}",
|
||||
:region => endpoint[:admin][:region],
|
||||
:admin_url => endpoint[:admin][:url],
|
||||
:internal_url => endpoint[:internal][:url],
|
||||
:public_url => endpoint[:public][:url]
|
||||
:id => make_id(endpoint),
|
||||
:region => get_region(endpoint),
|
||||
:admin_url => get_url(endpoint, :admin),
|
||||
:internal_url => get_url(endpoint, :internal),
|
||||
:public_url => get_url(endpoint, :public)
|
||||
)
|
||||
end
|
||||
end
|
||||
@ -153,19 +143,27 @@ Puppet::Type.type(:keystone_endpoint).provide(
|
||||
end
|
||||
|
||||
def flush
|
||||
if @property_flush && @property_hash[:id]
|
||||
ids = @property_hash[:id].split(',')
|
||||
if @property_flush[:admin_url]
|
||||
self.class.request('endpoint', 'set', [ids[0], "--url=#{resource[:admin_url]}"])
|
||||
end
|
||||
if @property_flush[:internal_url]
|
||||
self.class.request('endpoint', 'set', [ids[1], "--url=#{resource[:internal_url]}"])
|
||||
end
|
||||
if @property_flush[:public_url]
|
||||
self.class.request('endpoint', 'set', [ids[2], "--url=#{resource[:public_url]}"])
|
||||
if property_flush && property_hash[:id]
|
||||
scopes = [:admin_url, :internal_url, :public_url]
|
||||
ids = Hash[scopes.zip(property_hash[:id].split(','))]
|
||||
scopes.each do |scope|
|
||||
if property_flush[scope]
|
||||
if ids[scope].nil? || ids[scope].empty?
|
||||
ids[scope] = endpoint_create(service_id, resource[:region],
|
||||
scope.to_s.sub(/_url$/, ''),
|
||||
property_flush[scope])[:id]
|
||||
else
|
||||
self.class.request('endpoint',
|
||||
'set',
|
||||
[ids[scope],
|
||||
"--url=#{resource[scope]}"])
|
||||
end
|
||||
end
|
||||
end
|
||||
@property_hash = resource.to_hash
|
||||
@property_hash[:id] = scopes.map { |s| ids[s] }.join(',')
|
||||
@property_hash[:ensure] = :present
|
||||
end
|
||||
@property_hash = resource.to_hash
|
||||
end
|
||||
|
||||
private
|
||||
@ -252,4 +250,47 @@ Puppet::Type.type(:keystone_endpoint).provide(
|
||||
"#{region}/#{name}::#{type}"
|
||||
end
|
||||
end
|
||||
|
||||
def self.make_id(endpoint)
|
||||
id_str = ''
|
||||
id_sep = ''
|
||||
[:admin, :internal, :public].each do |type|
|
||||
id_str += "#{id_sep}#{endpoint[type][:id]}" if endpoint[type]
|
||||
id_sep = ','
|
||||
end
|
||||
id_str
|
||||
end
|
||||
|
||||
def self.get_region(endpoint)
|
||||
type = [:admin, :internal, :public].detect { |t| endpoint.key? t }
|
||||
type ? endpoint[type][:region] : ''
|
||||
end
|
||||
|
||||
def self.get_url(endpoint, type, default='')
|
||||
endpoint[type][:url] rescue default
|
||||
end
|
||||
|
||||
def service_id
|
||||
# Reset the cache.
|
||||
self.class.services = nil
|
||||
name = resource[:name]
|
||||
type = resource[:type]
|
||||
|
||||
services = self.class.services.find_all { |s| s[:name] == name }
|
||||
service = services.find { |s| s[:type] == type }
|
||||
service_id = ''
|
||||
if service.nil? && services.count == 1
|
||||
# For backward comptatibility, match the service by name only.
|
||||
service_id = services[0][:id]
|
||||
else
|
||||
# Math the service by id.
|
||||
service_id = service[:id] if service
|
||||
end
|
||||
if service_id.nil? || service_id.empty?
|
||||
title = self.class.transform_name(resource[:region], resource[:name], resource[:type])
|
||||
fail(Puppet::Error, "Cannot find service associated with #{title}")
|
||||
end
|
||||
|
||||
service_id
|
||||
end
|
||||
end
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
fixes:
|
||||
- Fixes `bug 1559013
|
||||
<https://bugs.launchpad.net/puppet-keystone/+bug/1559013>`__ so
|
||||
update of a keystone_endpoint does not recreate all endpoints when
|
||||
one or two network endpoint are missing.
|
@ -233,9 +233,9 @@ describe 'keystone server running with Apache/WSGI with resources' do
|
||||
ensure => present,
|
||||
region => 'RegionOne',
|
||||
type => 'type_1',
|
||||
public_url => 'http://public_url/',
|
||||
internal_url => 'http://public_url/',
|
||||
admin_url => 'http://public_url/'
|
||||
public_url => 'http://public_service1_type1/',
|
||||
internal_url => 'http://internal_service1_type1/',
|
||||
admin_url => 'http://admin_service1_type1/'
|
||||
}
|
||||
EOM
|
||||
end
|
||||
|
@ -326,5 +326,67 @@ region="region"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#flush' do
|
||||
let(:endpoint_attrs) do
|
||||
{
|
||||
:title => 'region/service_1',
|
||||
:ensure => 'present',
|
||||
:public_url => 'http://127.0.0.1:5000',
|
||||
:internal_url => 'http://127.0.0.1:5001',
|
||||
:admin_url => 'http://127.0.0.1:4999',
|
||||
:type => 'service_type1'
|
||||
}
|
||||
end
|
||||
context '#update a missing endpoint' do
|
||||
it 'creates an endpoint' do
|
||||
described_class.expects(:openstack)
|
||||
.with('endpoint', 'create', '--format', 'shell',
|
||||
['service_id_1', 'admin', 'http://127.0.0.1:4999',
|
||||
'--region', 'region'])
|
||||
.returns(<<-eoo
|
||||
enabled="True"
|
||||
id="endpoint1_id"
|
||||
interface="internal"
|
||||
region="None"
|
||||
region_id="None"
|
||||
service_id="service_id_1"
|
||||
service_name="service_1"
|
||||
service_type="service_type1"
|
||||
url="http://127.0.0.1:5001"
|
||||
eoo
|
||||
)
|
||||
|
||||
provider.expects(:property_flush)
|
||||
.times(5)
|
||||
.returns({:admin_url => 'http://127.0.0.1:4999'})
|
||||
provider.expects(:property_hash)
|
||||
.twice
|
||||
.returns({:id => ',endpoint2_id,endpoint3_id'})
|
||||
provider.expects(:service_id)
|
||||
.returns('service_id_1')
|
||||
provider.flush
|
||||
expect(provider.exists?).to be_truthy
|
||||
expect(provider.id).to eq('endpoint1_id,endpoint2_id,endpoint3_id')
|
||||
end
|
||||
end
|
||||
|
||||
context 'adjust a url' do
|
||||
it 'update the url' do
|
||||
described_class.expects(:openstack)
|
||||
.with('endpoint', 'set',
|
||||
['endpoint1_id', '--url=http://127.0.0.1:4999'])
|
||||
provider.expects(:property_flush)
|
||||
.times(4)
|
||||
.returns({:admin_url => 'http://127.0.0.1:4999'})
|
||||
provider.expects(:property_hash)
|
||||
.twice
|
||||
.returns({:id => 'endpoint1_id,endpoint2_id,endpoint3_id'})
|
||||
provider.flush
|
||||
expect(provider.exists?).to be_truthy
|
||||
expect(provider.id).to eq('endpoint1_id,endpoint2_id,endpoint3_id')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user