Allow omitting admin/internal endpoint

Keystone v3 API does not require that all the three endpoint types are
given and allows using only specific endpoint types(eg. only public, or
public and internal). This allows users to omit specific endpoint types
by setting endpoint url options to ''.

Change-Id: Ifef2070ad25cadf961466ca9f384965d03c08f81
This commit is contained in:
Takashi Kajinami 2024-02-26 12:41:52 +09:00
parent 50b5260cc6
commit 274ecb90d4
12 changed files with 248 additions and 49 deletions

View File

@ -60,18 +60,18 @@
#
class keystone::bootstrap (
String[1] $password,
String[1] $username = 'admin',
String[1] $email = 'admin@localhost',
String[1] $project_name = 'admin',
String[1] $service_project_name = 'services',
String[1] $role_name = 'admin',
String[1] $service_name = 'keystone',
Stdlib::HTTPUrl $admin_url = 'http://127.0.0.1:5000',
Stdlib::HTTPUrl $public_url = 'http://127.0.0.1:5000',
Optional[Stdlib::HTTPUrl] $internal_url = undef,
String[1] $region = 'RegionOne',
String[1] $interface = 'public',
Boolean $bootstrap = true,
String[1] $username = 'admin',
String[1] $email = 'admin@localhost',
String[1] $project_name = 'admin',
String[1] $service_project_name = 'services',
String[1] $role_name = 'admin',
String[1] $service_name = 'keystone',
Keystone::KeystoneEndpointUrl $admin_url = 'http://127.0.0.1:5000',
Keystone::KeystonePublicEndpointUrl $public_url = 'http://127.0.0.1:5000',
Optional[Keystone::KeystoneEndpointUrl] $internal_url = undef,
String[1] $region = 'RegionOne',
String[1] $interface = 'public',
Boolean $bootstrap = true,
) inherits keystone::params {
include keystone::deps
@ -88,22 +88,32 @@ class keystone::bootstrap (
}
if $bootstrap {
$bootstrap_adminurl_env = $admin_url ? {
'' => undef,
default => "OS_BOOTSTRAP_ADMIN_URL=${admin_url}",
}
$bootstrap_internalurl_env = $internal_url_real ? {
'' => undef,
default => "OS_BOOTSTRAP_INTERNAL_URL=${internal_url_real}",
}
$bootstrap_env = delete_undef_values([
"OS_BOOTSTRAP_USERNAME=${username}",
"OS_BOOTSTRAP_PASSWORD=${password}",
"OS_BOOTSTRAP_PROJECT_NAME=${project_name}",
"OS_BOOTSTRAP_ROLE_NAME=${role_name}",
"OS_BOOTSTRAP_SERVICE_NAME=${service_name}",
"OS_BOOTSTRAP_PUBLIC_URL=${public_url}",
"OS_BOOTSTRAP_REGION_ID=${region}",
$bootstrap_adminurl_env,
$bootstrap_internalurl_env,
])
# The initial bootstrap that creates all resources required but
# only subscribes to notifies from the keystone::dbsync::end anchor
# which means this is not guaranteed to execute on each run.
exec { 'keystone bootstrap':
command => 'keystone-manage bootstrap',
environment => [
"OS_BOOTSTRAP_USERNAME=${username}",
"OS_BOOTSTRAP_PASSWORD=${password}",
"OS_BOOTSTRAP_PROJECT_NAME=${project_name}",
"OS_BOOTSTRAP_ROLE_NAME=${role_name}",
"OS_BOOTSTRAP_SERVICE_NAME=${service_name}",
"OS_BOOTSTRAP_ADMIN_URL=${admin_url}",
"OS_BOOTSTRAP_PUBLIC_URL=${public_url}",
"OS_BOOTSTRAP_INTERNAL_URL=${internal_url_real}",
"OS_BOOTSTRAP_REGION_ID=${region}",
],
environment => $bootstrap_env,
user => $keystone_user,
path => '/usr/bin',
refreshonly => true,
@ -174,6 +184,9 @@ class keystone::bootstrap (
'internal' => $internal_url_real,
default => $public_url
}
if $auth_url_real == '' {
fail("The ${interface} endpoint should not be empty to be used by the interface parameter.")
}
ensure_resource('file', '/etc/openstack', {
'ensure' => 'directory',

View File

@ -110,28 +110,28 @@
# Defaults to undef (use the keystone server default domain)
#
define keystone::resource::service_identity(
Enum['present', 'absent'] $ensure = 'present',
Optional[String[1]] $admin_url = undef,
Optional[String[1]] $internal_url = undef,
Optional[String[1]] $password = undef,
Optional[String[1]] $public_url = undef,
String[1] $auth_name = $name,
Optional[String[1]] $service_name = $auth_name,
Optional[String[1]] $service_type = undef,
Boolean $configure_endpoint = true,
Boolean $configure_user = true,
Boolean $configure_user_role = true,
Boolean $configure_service = true,
String $email = "${name}@localhost",
String[1] $region = 'RegionOne',
String $service_description = "${name} service",
String[1] $tenant = 'services',
Array[String[1]] $roles = ['admin'],
String[1] $system_scope = 'all',
Array[String[1]] $system_roles = [],
Optional[String[1]] $default_domain = undef,
Optional[String[1]] $user_domain = $default_domain,
Optional[String[1]] $project_domain = $default_domain,
Enum['present', 'absent'] $ensure = 'present',
Optional[Keystone::EndpointUrl] $admin_url = undef,
Optional[Keystone::EndpointUrl] $internal_url = undef,
Optional[String[1]] $password = undef,
Optional[Keystone::PublicEndpointUrl] $public_url = undef,
String[1] $auth_name = $name,
Optional[String[1]] $service_name = $auth_name,
Optional[String[1]] $service_type = undef,
Boolean $configure_endpoint = true,
Boolean $configure_user = true,
Boolean $configure_user_role = true,
Boolean $configure_service = true,
String $email = "${name}@localhost",
String[1] $region = 'RegionOne',
String $service_description = "${name} service",
String[1] $tenant = 'services',
Array[String[1]] $roles = ['admin'],
String[1] $system_scope = 'all',
Array[String[1]] $system_roles = [],
Optional[String[1]] $default_domain = undef,
Optional[String[1]] $user_domain = $default_domain,
Optional[String[1]] $project_domain = $default_domain,
) {
include keystone::deps

View File

@ -0,0 +1,10 @@
---
features:
- |
The ``keystone::boostrap`` class now supports omitting internal endpoint
and/or admin endpoint. Set the url parameter(s) to ``''`` (empty string).
- |
The ``keystone::resource::service_identity`` defined type now allows
omitting internal endpiint and/or admin endpoint. Set the url parameter(s)
to ``''`` (empty string).

View File

@ -19,10 +19,10 @@ describe 'keystone::bootstrap' do
"OS_BOOTSTRAP_PROJECT_NAME=admin",
"OS_BOOTSTRAP_ROLE_NAME=admin",
"OS_BOOTSTRAP_SERVICE_NAME=keystone",
"OS_BOOTSTRAP_ADMIN_URL=http://127.0.0.1:5000",
"OS_BOOTSTRAP_PUBLIC_URL=http://127.0.0.1:5000",
"OS_BOOTSTRAP_INTERNAL_URL=http://127.0.0.1:5000",
"OS_BOOTSTRAP_REGION_ID=RegionOne",
"OS_BOOTSTRAP_ADMIN_URL=http://127.0.0.1:5000",
"OS_BOOTSTRAP_INTERNAL_URL=http://127.0.0.1:5000",
],
:user => platform_params[:user],
:path => '/usr/bin',
@ -131,10 +131,10 @@ describe 'keystone::bootstrap' do
"OS_BOOTSTRAP_PROJECT_NAME=adminproj",
"OS_BOOTSTRAP_ROLE_NAME=adminrole",
"OS_BOOTSTRAP_SERVICE_NAME=servicename",
"OS_BOOTSTRAP_ADMIN_URL=http://admin:1234",
"OS_BOOTSTRAP_PUBLIC_URL=http://public:4321",
"OS_BOOTSTRAP_INTERNAL_URL=http://internal:1342",
"OS_BOOTSTRAP_REGION_ID=RegionTwo",
"OS_BOOTSTRAP_ADMIN_URL=http://admin:1234",
"OS_BOOTSTRAP_INTERNAL_URL=http://internal:1342",
],
:user => platform_params[:user],
:path => '/usr/bin',
@ -290,6 +290,74 @@ describe 'keystone::bootstrap' do
:interface => 'internal',
)}
end
context 'when admin endpoint is omitted' do
let :params do
{
:password => 'secret',
:admin_url => '',
}
end
it { is_expected.to contain_exec('keystone bootstrap').with(
:command => 'keystone-manage bootstrap',
:environment => [
"OS_BOOTSTRAP_USERNAME=admin",
"OS_BOOTSTRAP_PASSWORD=secret",
"OS_BOOTSTRAP_PROJECT_NAME=admin",
"OS_BOOTSTRAP_ROLE_NAME=admin",
"OS_BOOTSTRAP_SERVICE_NAME=keystone",
"OS_BOOTSTRAP_PUBLIC_URL=http://127.0.0.1:5000",
"OS_BOOTSTRAP_REGION_ID=RegionOne",
"OS_BOOTSTRAP_INTERNAL_URL=http://127.0.0.1:5000",
],
:user => platform_params[:user],
:path => '/usr/bin',
:refreshonly => true,
:subscribe => 'Anchor[keystone::dbsync::end]',
:notify => 'Anchor[keystone::service::begin]',
:tag => 'keystone-bootstrap',
)}
it { is_expected.to contain_keystone_endpoint('RegionOne/keystone::identity').with(
:ensure => 'present',
:public_url => 'http://127.0.0.1:5000',
:internal_url => 'http://127.0.0.1:5000',
)}
end
context 'when internal endpoint is omitted' do
let :params do
{
:password => 'secret',
:internal_url => '',
}
end
it { is_expected.to contain_exec('keystone bootstrap').with(
:command => 'keystone-manage bootstrap',
:environment => [
"OS_BOOTSTRAP_USERNAME=admin",
"OS_BOOTSTRAP_PASSWORD=secret",
"OS_BOOTSTRAP_PROJECT_NAME=admin",
"OS_BOOTSTRAP_ROLE_NAME=admin",
"OS_BOOTSTRAP_SERVICE_NAME=keystone",
"OS_BOOTSTRAP_PUBLIC_URL=http://127.0.0.1:5000",
"OS_BOOTSTRAP_REGION_ID=RegionOne",
"OS_BOOTSTRAP_ADMIN_URL=http://127.0.0.1:5000",
],
:user => platform_params[:user],
:path => '/usr/bin',
:refreshonly => true,
:subscribe => 'Anchor[keystone::dbsync::end]',
:notify => 'Anchor[keystone::service::begin]',
:tag => 'keystone-bootstrap',
)}
it { is_expected.to contain_keystone_endpoint('RegionOne/keystone::identity').with(
:ensure => 'present',
:public_url => 'http://127.0.0.1:5000',
:admin_url => 'http://127.0.0.1:5000',
)}
end
end
on_supported_os({

View File

@ -0,0 +1,31 @@
require 'spec_helper'
describe 'Keystone::EndpointUrl' do
describe 'valid types' do
context 'with valid types' do
[
'http://127.0.0.1:5000',
'https://[::1]:5000',
'ws://127.0.0.1:5000',
'wss://[::1]:5000',
''
].each do |value|
describe value.inspect do
it { is_expected.to allow_value(value) }
end
end
end
end
describe 'invalid types' do
context 'with garbage inputs' do
[
'ftp://127.0.0.1:5000',
].each do |value|
describe value.inspect do
it { is_expected.not_to allow_value(value) }
end
end
end
end
end

View File

@ -0,0 +1,31 @@
require 'spec_helper'
describe 'Keystone::KeystoneEndpointUrl' do
describe 'valid types' do
context 'with valid types' do
[
'http://127.0.0.1:5000',
'https://[::1]:5000',
''
].each do |value|
describe value.inspect do
it { is_expected.to allow_value(value) }
end
end
end
end
describe 'invalid types' do
context 'with garbage inputs' do
[
'ws://127.0.0.1:5000',
'wss://[::1]:5000',
'ftp://127.0.0.1:5000',
].each do |value|
describe value.inspect do
it { is_expected.not_to allow_value(value) }
end
end
end
end
end

View File

@ -0,0 +1,31 @@
require 'spec_helper'
describe 'Keystone::PublicEndpointUrl' do
describe 'valid types' do
context 'with valid types' do
[
'http://127.0.0.1:5000',
'https://[::1]:5000',
'ws://127.0.0.1:5000',
'wss://[::1]:5000',
].each do |value|
describe value.inspect do
it { is_expected.to allow_value(value) }
end
end
end
end
describe 'invalid types' do
context 'with garbage inputs' do
[
'ftp://127.0.0.1:5000',
''
].each do |value|
describe value.inspect do
it { is_expected.not_to allow_value(value) }
end
end
end
end
end

4
types/endpointurl.pp Normal file
View File

@ -0,0 +1,4 @@
type Keystone::EndpointUrl = Variant[
Keystone::PublicEndpointUrl,
Keystone::OmittedEndpointUrl
]

View File

@ -0,0 +1,4 @@
type Keystone::KeystoneEndpointUrl = Variant[
Keystone::KeystonePublicEndpointUrl,
Keystone::OmittedEndpointUrl
]

View File

@ -0,0 +1 @@
type Keystone::KeystonePublicEndpointUrl = Stdlib::HTTPUrl

View File

@ -0,0 +1 @@
type Keystone::OmittedEndpointUrl = String[0, 0]

View File

@ -0,0 +1,5 @@
type Keystone::PublicEndpointUrl = Variant[
Stdlib::HTTPUrl,
# NOTE(tkajinam): This is required by Zaqar
Pattern[/(?i:\Awss?:\/\/.*\z)/],
]