From 1287ab19bb046251c49a16a2202ba73153b31769 Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Mon, 25 Oct 2021 22:37:05 +0900 Subject: [PATCH] WIP: Load keystone credentials from clouds.yaml Change-Id: Ie8246aa18d90ba506fe708be13c9a5afa3e5d2fd --- lib/puppet/provider/openstack/credentials.rb | 8 +- manifests/clouds.pp | 73 +++++++++++++++++++ metadata.json | 4 + spec/defines/openstacklib_clouds_spec.rb | 41 +++++++++++ .../provider/openstack/credentials_spec.rb | 26 +++++++ templates/clouds.yaml.erb | 40 ++++++++++ 6 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 manifests/clouds.pp create mode 100644 spec/defines/openstacklib_clouds_spec.rb create mode 100644 templates/clouds.yaml.erb diff --git a/lib/puppet/provider/openstack/credentials.rb b/lib/puppet/provider/openstack/credentials.rb index 5f65512b..7ce313cb 100644 --- a/lib/puppet/provider/openstack/credentials.rb +++ b/lib/puppet/provider/openstack/credentials.rb @@ -88,7 +88,9 @@ class Puppet::Provider::Openstack::CredentialsV3 < Puppet::Provider::Openstack:: :trust_id, :user_domain_id, :user_domain_name, - :user_id + :user_id, + :cloud, + :client_config_file, ] KEYS.each { |var| attr_accessor var } @@ -113,12 +115,14 @@ class Puppet::Provider::Openstack::CredentialsV3 < Puppet::Provider::Openstack:: elsif @system_scope return 'system' else + # When OS_CLOUDS is used, parameters are not directly passed to puppet + # so the scope can't be detected. return nil end end def user_password_set? - return true if user_set? && @password && scope_set? && @auth_url + return true if (user_set? && @password && scope_set? && @auth_url) || @cloud end def initialize diff --git a/manifests/clouds.pp b/manifests/clouds.pp new file mode 100644 index 00000000..6f0937c8 --- /dev/null +++ b/manifests/clouds.pp @@ -0,0 +1,73 @@ +# == Class: openstacklib::clouds +# +# Generates clouds.yaml for openstack CLI +# +# == Parameters +# +# [*username*] +# (Required) The name of the keystone user. +# +# [*password*] +# (Required) Password of the keystone user. +# +# [*auth_url*] +# (Required) The URL to use for authentication. +# +# [*path*] +# (Optional) Path to the clouds.yaml file. +# Defaults to $name +# +# [*user_domain_name*] +# (Optional) Name of domain for $username. +# Defaults to 'Default' +# +# [*project_name*] +# (Optional) The name of the keystone project. +# Defaults to undef +# +# [*project_domain_name*] +# (Optional) Name of domain for $project_name. +# Defaults to 'Default' +# +# [*system_scope*] +# (Optional) Scope for system operations. +# Defaults to undef +# +# [*identity_api_version*] +# (Optional) Version of identity API. +# Defaults to '3' +# +# [*interface*] +# (Optional) Determine the endpoint to be used. +# Defaults to undef +# +# [*region_name*] +# (Optional) The region in which the service can be found. +# Defaults to undef +# +define openstacklib::clouds( + $username, + $password, + $auth_url, + $path = $name, + $user_domain_name = 'Default', + $project_name = undef, + $project_domain_name = 'Default', + $system_scope = undef, + $identity_api_version = '3', + $interface = undef, + $region_name = undef, +) { + + if !$project_name and !$system_scope { + fail('One of project_name and system_scope should be set') + } + + file { $path: + ensure => 'present', + mode => '0600', + owner => 'root', + group => 'root', + content => template('openstacklib/clouds.yaml.erb'), + } +} diff --git a/metadata.json b/metadata.json index 508e2848..31a0efa0 100644 --- a/metadata.json +++ b/metadata.json @@ -5,6 +5,10 @@ "name": "puppetlabs/apache", "version_requirement": ">=5.0.0" }, + { + "name": "puppetlabs/concat", + "version_requirement": ">=1.0.0 <8.0.0" + }, { "name": "puppetlabs/inifile", "version_requirement": ">=2.0.0 <3.0.0" diff --git a/spec/defines/openstacklib_clouds_spec.rb b/spec/defines/openstacklib_clouds_spec.rb new file mode 100644 index 00000000..2e4da62e --- /dev/null +++ b/spec/defines/openstacklib_clouds_spec.rb @@ -0,0 +1,41 @@ +require 'spec_helper' + +describe 'openstacklib::clouds' do + shared_examples 'openstacklib::clouds' do + let :title do + '/etc/openstack/clouds.yaml' + end + + context 'with the required parameters' do + let :params do + { + :username => 'admin', + :password => 'secrete', + :auth_url => 'http://127.0.0.1:5000/', + :project_name => 'demo', + } + end + + it 'creates a clouds.yaml file' do + should contain_file('/etc/openstack/clouds.yaml').with( + :mode => '0600', + :owner => 'root', + :group => 'root', + ) + end + end + end + + on_supported_os({ + :supported_os => OSDefaults.get_supported_os + }).each do |os,facts| + context "on #{os}" do + let (:facts) do + facts.merge!(OSDefaults.get_facts()) + end + + it_behaves_like 'openstacklib::clouds' + end + end + +end diff --git a/spec/unit/provider/openstack/credentials_spec.rb b/spec/unit/provider/openstack/credentials_spec.rb index 9f06d41c..e83c0c3e 100644 --- a/spec/unit/provider/openstack/credentials_spec.rb +++ b/spec/unit/provider/openstack/credentials_spec.rb @@ -74,6 +74,12 @@ describe Puppet::Provider::Openstack::Credentials do expect(creds.service_token_set?).to be_falsey end + it 'is successful with cloud' do + creds.cloud = 'openstack' + expect(creds.user_password_set?).to be_truthy + expect(creds.service_token_set?).to be_falsey + end + it 'fails' do creds.auth_url = 'auth_url' creds.password = 'password' @@ -111,6 +117,8 @@ describe Puppet::Provider::Openstack::Credentials do creds.endpoint = 'endpoint' creds.region_name = 'region_name' creds.identity_api_version = 'identity_api_version' + creds.cloud = 'openstack' + creds.client_config_file = '/etc/openstack/clouds.yaml' creds.unset expect(creds.auth_url).to eq('') expect(creds.password).to eq('') @@ -122,6 +130,8 @@ describe Puppet::Provider::Openstack::Credentials do expect(creds.endpoint).to eq('') expect(creds.region_name).to eq('') expect(creds.identity_api_version).to eq('identity_api_version') + expect(creds.cloud).to eq('') + expect(creds.client_config_file).to eq('') newcreds = Puppet::Provider::Openstack::CredentialsV3.new expect(newcreds.identity_api_version).to eq('3') end @@ -141,6 +151,8 @@ describe Puppet::Provider::Openstack::Credentials do creds.endpoint = 'endpoint' creds.region_name = 'Region1' creds.identity_api_version = 'identity_api_version' + creds.cloud = 'openstack' + creds.client_config_file = '/etc/openstack/clouds.yaml' expect(creds.to_env).to eq({ 'OS_USERNAME' => 'username', 'OS_PASSWORD' => 'password', @@ -152,6 +164,8 @@ describe Puppet::Provider::Openstack::Credentials do 'OS_ENDPOINT' => 'endpoint', 'OS_REGION_NAME' => 'Region1', 'OS_IDENTITY_API_VERSION' => 'identity_api_version', + 'OS_CLOUD' => 'openstack', + 'OS_CLIENT_CONFIG_FILE' => '/etc/openstack/clouds.yaml', }) end end @@ -173,6 +187,7 @@ describe Puppet::Provider::Openstack::Credentials do creds.project_name = 'project_name' creds.username = 'username' expect(creds.user_password_set?).to be_truthy + expect(creds.scope).to eq('project') end end describe '#password_set? with username and domain_name' do @@ -182,6 +197,7 @@ describe Puppet::Provider::Openstack::Credentials do creds.domain_name = 'domain_name' creds.username = 'username' expect(creds.user_password_set?).to be_truthy + expect(creds.scope).to eq('domain') end end describe '#password_set? with username and system_scope' do @@ -191,6 +207,14 @@ describe Puppet::Provider::Openstack::Credentials do creds.system_scope = 'all' creds.username = 'username' expect(creds.user_password_set?).to be_truthy + expect(creds.scope).to eq('system') + end + end + describe '#password_set? with cloud' do + it 'is successful' do + creds.cloud = 'openstack' + expect(creds.user_password_set?).to be_truthy + expect(creds.scope).to eq(nil) end end describe '#password_set? with user_id and project_id' do @@ -200,6 +224,7 @@ describe Puppet::Provider::Openstack::Credentials do creds.project_id = 'projid' creds.user_id = 'userid' expect(creds.user_password_set?).to be_truthy + expect(creds.scope).to eq('project') end end describe '#password_set? with user_id and domain_id' do @@ -209,6 +234,7 @@ describe Puppet::Provider::Openstack::Credentials do creds.domain_id = 'domid' creds.user_id = 'userid' expect(creds.user_password_set?).to be_truthy + expect(creds.scope).to eq('domain') end end end diff --git a/templates/clouds.yaml.erb b/templates/clouds.yaml.erb new file mode 100644 index 00000000..1cd41c7f --- /dev/null +++ b/templates/clouds.yaml.erb @@ -0,0 +1,40 @@ +clouds: +<% if @project_name -%> + project: + auth: + auth_url: <%= @auth_url %> + password: <%= @password %> + username: <%= @username %> + user_domain_name: <%= @user_domain_name %> + project_name: <%= @project_name %> + project_domain_name: <%= @project_domain_name %> + identity_api_version: <%= $identity_api_version %> +<% if @interface -%> + interface: <%= @interface %> +<% end -%> +<% if @region_name -%> + region_name: <%= @region_name %> +<% end -%> +<% if @cacert -%> + cacert: <%= @cacert %> +<% end -%> +<% end -%> +<% if @system_scope -%> + system: + auth: + auth_url: <%= @auth_url %> + password: <%= @password %> + username: <%= @username %> + user_domain_name: <%= @user_domain_name %> + system_scope: <%= @system_scope %> + identity_api_version: <%= $identity_api_version %> +<% if @interface -%> + interface: <%= @interface %> +<% end -%> +<% if @region_name -%> + region_name: <%= @region_name %> +<% end -%> +<% if @cacert -%> + cacert: <%= @cacert %> +<% end -%> +<% end -%>