From 0bd89832123afa196fe1c5fbd5a6e560616fe128 Mon Sep 17 00:00:00 2001 From: Ken Thomas Date: Wed, 21 Jan 2015 17:32:19 +0000 Subject: [PATCH] Allow different URLs for internal/public endpoints Provide new endpoint routines for admin_endpoint, internal_endpoint, and public_endpoint. These will allow folks to specify different URLs for those endpoints if they wish. This is the first part of the fix. After the routines have been merged, I'll start working on using the routines in the various component recipies. Change-Id: I5b3b90324ee0f9bf6b2c5278ad60724856d43321 Partial-Bug: 1412919 --- CHANGELOG.md | 1 + README.md | 3 + attributes/default.rb | 13 ++++ libraries/endpoints.rb | 30 ++++++++++ spec/endpoints_spec.rb | 132 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 179 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27976aaa..ee30c657 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ This file is used to list changes made in each version of cookbook-openstack-com * Add a new custom matcher render_config_file to test ini file content * Add global rabbit ha flag * Removed all ceph logic +* Allow different URLs for internal, public, admin endpoints (bug 1412919) ## 10.1.0 * Adding identity admin bind host endpoint to allow flexibility and consistency diff --git a/README.md b/README.md index fa14b43f..49211681 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,9 @@ This cookbook exposes a set of default library routines: * `cli` -- Used to call openstack CLIs * `endpoint` -- Used to return a `::URI` object representing the named OpenStack endpoint +* `admin_endpoint` -- Used to return a `::URI` object representing the named OpenStack admin endpoint if one was specified. Otherwise, it will return the same value as `endpoint`. +* `internal_endpoint` -- Used to return a `::URI` object representing the named OpenStack internal endpoint if one was specified. Otherwise, it will return the same value as `endpoint`. +* `public_endpoint` -- Used to return a `::URI` object representing the named OpenStack public endpoint if one was specified. Otherwise, it will return the same value as `endpoint`. * `endpoints` -- Useful for operating on all OpenStack endpoints * `db` -- Returns a Hash of information about a named OpenStack database * `db_uri` -- Returns the SQLAlchemy RFC-1738 DB URI (see: http://rfc.net/rfc1738.html) for a named OpenStack database diff --git a/attributes/default.rb b/attributes/default.rb index b7f1b2e4..f6b8645f 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -157,6 +157,19 @@ default['openstack']['yum']['repo-key'] = 'https://raw.githubusercontent.com/red # IP) in a network to a particular OpenStack service endpoint. If the # bind_interface is set, it will set the host IP in the # set_endpoints_by_interface recipe. +# +# If you wish to use different values for the admin, public, and internal +# URIs for a service, you can easily do so by putting that service's +# information within the node['openstack']['endpoints'][type][service] hash +# (where type is one of 'admin', 'public', or 'internal'). +# For example, to use a special public URI for compute-api, it could be +# specified within... +# node['openstack']['endpoints']['public']['compute-api'] = ... +# +# If you have no need for separate URIs for any of the admin, public, or +# internal endpoints for compute-api, then you could just set the general +# service endpoint within... +# node['openstack']['endpoints']['compute-api'] = ... # ******************** OpenStack Identity Endpoints *************************** default['openstack']['endpoints']['host'] = '127.0.0.1' diff --git a/libraries/endpoints.rb b/libraries/endpoints.rb index 4b968f63..a7a088b4 100644 --- a/libraries/endpoints.rb +++ b/libraries/endpoints.rb @@ -104,6 +104,27 @@ module ::Openstack # rubocop:disable Documentation end end + # Get the admin endpoint for the specified service. + # If there's no specific endpoint, then get the general service endpoint. + def admin_endpoint(name) + ep = specific_endpoint('admin', name) + uri_from_hash(ep) if ep + end + + # Get the public endpoint for the specified service. + # If there's no specific endpoint, then get the general service endpoint. + def public_endpoint(name) + ep = specific_endpoint('public', name) + uri_from_hash(ep) if ep + end + + # Get the internal endpoint for the specified service. + # If there's no specific endpoint, then get the general service endpoint. + def internal_endpoint(name) + ep = specific_endpoint('internal', name) + uri_from_hash(ep) if ep + end + private # Instead of specifying the verbose node['openstack']['endpoints'][name], @@ -113,4 +134,13 @@ module ::Openstack # rubocop:disable Documentation rescue nil end + + # Attempt to find the specific endpoint ('internal', 'admin', or + # 'public') for the given name. If it's not found, then return the + # general endpoint. + def specific_endpoint(type, name) + node['openstack']['endpoints'][type][name] + rescue + endpoint_for(name) + end end diff --git a/spec/endpoints_spec.rb b/spec/endpoints_spec.rb index 1d7a36de..bb0020c1 100644 --- a/spec/endpoints_spec.rb +++ b/spec/endpoints_spec.rb @@ -120,6 +120,138 @@ describe 'openstack-common::set_endpoints_by_interface' do end end + describe '#admin_endpoint' do + it 'returns nil admin_endpoint when not exists' do + allow(subject).to receive(:node).and_return({}) + expect( + subject.admin_endpoint('nonexisting') + ).to be_nil + end + + it 'returns general endpoint no admin endpoint exists' do + uri_hash = { + 'openstack' => { + 'endpoints' => { + 'compute-api' => { + 'uri' => 'http://localhost:8080/path' + } + } + } + } + allow(subject).to receive(:node).and_return(uri_hash) + expect(subject.admin_endpoint('compute-api').to_s).to eq('http://localhost:8080/path') + end + + it 'returns admin endpoint when it exists' do + uri_hash = { + 'openstack' => { + 'endpoints' => { + 'compute-api' => { + 'uri' => 'http://localhost:8080/path' + }, + 'admin' => { + 'compute-api' => { + 'uri' => 'https://localhost:1234/path' + } + } + } + } + } + allow(subject).to receive(:node).and_return(uri_hash) + expect(subject.admin_endpoint('compute-api').to_s).to eq('https://localhost:1234/path') + # Make sure that the general endpoint didn't break + expect(subject.endpoint('compute-api').to_s).to eq('http://localhost:8080/path') + end + end + + describe '#public_endpoint' do + it 'returns nil public_endpoint when not exists' do + allow(subject).to receive(:node).and_return({}) + expect( + subject.public_endpoint('nonexisting') + ).to be_nil + end + + it 'returns general endpoint no public endpoint exists' do + uri_hash = { + 'openstack' => { + 'endpoints' => { + 'compute-api' => { + 'uri' => 'http://localhost:8080/path' + } + } + } + } + allow(subject).to receive(:node).and_return(uri_hash) + expect(subject.public_endpoint('compute-api').to_s).to eq('http://localhost:8080/path') + end + + it 'returns public endpoint when it exists' do + uri_hash = { + 'openstack' => { + 'endpoints' => { + 'compute-api' => { + 'uri' => 'http://localhost:8080/path' + }, + 'public' => { + 'compute-api' => { + 'uri' => 'https://localhost:1234/path' + } + } + } + } + } + allow(subject).to receive(:node).and_return(uri_hash) + expect(subject.public_endpoint('compute-api').to_s).to eq('https://localhost:1234/path') + # Make sure that the general endpoint didn't break + expect(subject.endpoint('compute-api').to_s).to eq('http://localhost:8080/path') + end + end + + describe '#internal_endpoint' do + it 'returns nil internal_endpoint when not exists' do + allow(subject).to receive(:node).and_return({}) + expect( + subject.internal_endpoint('nonexisting') + ).to be_nil + end + + it 'returns general endpoint no internal endpoint exists' do + uri_hash = { + 'openstack' => { + 'endpoints' => { + 'compute-api' => { + 'uri' => 'http://localhost:8080/path' + } + } + } + } + allow(subject).to receive(:node).and_return(uri_hash) + expect(subject.internal_endpoint('compute-api').to_s).to eq('http://localhost:8080/path') + end + + it 'returns internal endpoint when it exists' do + uri_hash = { + 'openstack' => { + 'endpoints' => { + 'compute-api' => { + 'uri' => 'http://localhost:8080/path' + }, + 'internal' => { + 'compute-api' => { + 'uri' => 'https://localhost:1234/path' + } + } + } + } + } + allow(subject).to receive(:node).and_return(uri_hash) + expect(subject.internal_endpoint('compute-api').to_s).to eq('https://localhost:1234/path') + # Make sure that the general endpoint didn't break + expect(subject.endpoint('compute-api').to_s).to eq('http://localhost:8080/path') + end + end + describe '#endpoints' do it 'does nothing when no endpoints' do allow(subject).to receive(:node).and_return({})