From 274ecb90d45a77bfd49843a13d058d77acc8cf1a Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Mon, 26 Feb 2024 12:41:52 +0900 Subject: [PATCH] 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 --- manifests/bootstrap.pp | 59 ++++++++------ manifests/resource/service_identity.pp | 44 +++++------ ...or-internal-endpoint-97a26387552c4060.yaml | 10 +++ spec/classes/keystone_bootstrap_spec.rb | 76 ++++++++++++++++++- spec/type_aliases/endpointurl_spec.rb | 31 ++++++++ spec/type_aliases/keystoneendpointurl_spec.rb | 31 ++++++++ spec/type_aliases/publicendpointurl_spec.rb | 31 ++++++++ types/endpointurl.pp | 4 + types/keystoneendpointurl.pp | 4 + types/keystonepublicendpointurl.pp | 1 + types/omittedendpointurl.pp | 1 + types/publicendpointurl.pp | 5 ++ 12 files changed, 248 insertions(+), 49 deletions(-) create mode 100644 releasenotes/notes/omit-admin-or-internal-endpoint-97a26387552c4060.yaml create mode 100644 spec/type_aliases/endpointurl_spec.rb create mode 100644 spec/type_aliases/keystoneendpointurl_spec.rb create mode 100644 spec/type_aliases/publicendpointurl_spec.rb create mode 100644 types/endpointurl.pp create mode 100644 types/keystoneendpointurl.pp create mode 100644 types/keystonepublicendpointurl.pp create mode 100644 types/omittedendpointurl.pp create mode 100644 types/publicendpointurl.pp diff --git a/manifests/bootstrap.pp b/manifests/bootstrap.pp index 5c4af3960..d614e297d 100644 --- a/manifests/bootstrap.pp +++ b/manifests/bootstrap.pp @@ -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', diff --git a/manifests/resource/service_identity.pp b/manifests/resource/service_identity.pp index 61ff1c237..eb37b7ecb 100644 --- a/manifests/resource/service_identity.pp +++ b/manifests/resource/service_identity.pp @@ -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 diff --git a/releasenotes/notes/omit-admin-or-internal-endpoint-97a26387552c4060.yaml b/releasenotes/notes/omit-admin-or-internal-endpoint-97a26387552c4060.yaml new file mode 100644 index 000000000..a7db7575c --- /dev/null +++ b/releasenotes/notes/omit-admin-or-internal-endpoint-97a26387552c4060.yaml @@ -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). diff --git a/spec/classes/keystone_bootstrap_spec.rb b/spec/classes/keystone_bootstrap_spec.rb index f19c4882e..24590a9b0 100644 --- a/spec/classes/keystone_bootstrap_spec.rb +++ b/spec/classes/keystone_bootstrap_spec.rb @@ -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({ diff --git a/spec/type_aliases/endpointurl_spec.rb b/spec/type_aliases/endpointurl_spec.rb new file mode 100644 index 000000000..051867372 --- /dev/null +++ b/spec/type_aliases/endpointurl_spec.rb @@ -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 diff --git a/spec/type_aliases/keystoneendpointurl_spec.rb b/spec/type_aliases/keystoneendpointurl_spec.rb new file mode 100644 index 000000000..7e70035b9 --- /dev/null +++ b/spec/type_aliases/keystoneendpointurl_spec.rb @@ -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 diff --git a/spec/type_aliases/publicendpointurl_spec.rb b/spec/type_aliases/publicendpointurl_spec.rb new file mode 100644 index 000000000..040e496e1 --- /dev/null +++ b/spec/type_aliases/publicendpointurl_spec.rb @@ -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 diff --git a/types/endpointurl.pp b/types/endpointurl.pp new file mode 100644 index 000000000..b89e53d29 --- /dev/null +++ b/types/endpointurl.pp @@ -0,0 +1,4 @@ +type Keystone::EndpointUrl = Variant[ + Keystone::PublicEndpointUrl, + Keystone::OmittedEndpointUrl +] diff --git a/types/keystoneendpointurl.pp b/types/keystoneendpointurl.pp new file mode 100644 index 000000000..4a0ea68e1 --- /dev/null +++ b/types/keystoneendpointurl.pp @@ -0,0 +1,4 @@ +type Keystone::KeystoneEndpointUrl = Variant[ + Keystone::KeystonePublicEndpointUrl, + Keystone::OmittedEndpointUrl +] diff --git a/types/keystonepublicendpointurl.pp b/types/keystonepublicendpointurl.pp new file mode 100644 index 000000000..b6e928c0d --- /dev/null +++ b/types/keystonepublicendpointurl.pp @@ -0,0 +1 @@ +type Keystone::KeystonePublicEndpointUrl = Stdlib::HTTPUrl diff --git a/types/omittedendpointurl.pp b/types/omittedendpointurl.pp new file mode 100644 index 000000000..cb93478aa --- /dev/null +++ b/types/omittedendpointurl.pp @@ -0,0 +1 @@ +type Keystone::OmittedEndpointUrl = String[0, 0] diff --git a/types/publicendpointurl.pp b/types/publicendpointurl.pp new file mode 100644 index 000000000..999f0bdaf --- /dev/null +++ b/types/publicendpointurl.pp @@ -0,0 +1,5 @@ +type Keystone::PublicEndpointUrl = Variant[ + Stdlib::HTTPUrl, + # NOTE(tkajinam): This is required by Zaqar + Pattern[/(?i:\Awss?:\/\/.*\z)/], +]