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)/], +]