use_cookbook-openstackclient/identity_v3
- Removed v2 support - Workover Endpoint creation Identity Endpoints now will be bootstrapped - Removed bootstrap_token - Added domain_creation - Edited openrc to work with itendity_v3 - changed "tenant"-naming to project - Removed unused files and functions providers/register.rb spec/register_spec.rb resources/register.rb libraries/machters.rb - rewrote specs - updated readme - added apache_site disable keystone since ubuntu auto-enables it - bumbed ubuntu version to 16.04 Change-Id: I0f8955f05de9b33711c54b9a198f45018cceb8e1
This commit is contained in:
parent
0751804867
commit
4dcd956337
|
@ -4,3 +4,6 @@ metadata
|
|||
|
||||
cookbook "openstack-common",
|
||||
github: "openstack/cookbook-openstack-common"
|
||||
|
||||
cookbook "openstackclient",
|
||||
github: "cloudbau/cookbook-openstackclient"
|
140
README.md
140
README.md
|
@ -30,7 +30,8 @@ Cookbooks
|
|||
The following cookbooks are dependencies:
|
||||
|
||||
- 'apache2', '~> 3.1'
|
||||
- 'openstack-common', '>= 13.0.0'
|
||||
- 'openstack-common', '>= 14.0.0'
|
||||
- 'openstackclient', '>= 0.1.0'
|
||||
|
||||
Attributes
|
||||
==========
|
||||
|
@ -64,142 +65,6 @@ Recipes
|
|||
apache webserver. The recipe is documented in detail with inline comments
|
||||
inside the recipe.
|
||||
|
||||
Resources
|
||||
=========
|
||||
|
||||
## openstack_identity_register
|
||||
|
||||
### Actions
|
||||
|
||||
- create_ec2_credentials:
|
||||
- create_endpoint:
|
||||
- create_role:
|
||||
- create_service:
|
||||
- create_tenant:
|
||||
- create_user:
|
||||
- grant_role:
|
||||
|
||||
### Attribute Parameters
|
||||
|
||||
- auth_uri: The uri used to as authentication endpoint for requests
|
||||
- bootstrap_token: The admin bootstrap_token used for authentication
|
||||
- service_type: Type of service to create (e.g. 'identity' or 'volume')
|
||||
- service_name: The name of the service to create (only for action
|
||||
:create_service)
|
||||
- service_description: The description for the service to create (only for
|
||||
action :create_service)
|
||||
- endpoint_region: The region to create the endpoint in (only for action
|
||||
:create_endpoint) Defaults to <code>"RegionOne"</code>.
|
||||
- endpoint_adminurl: The public url to register for the endpoint (only for
|
||||
action :create_endpoint)
|
||||
- endpoint_internalurl: The internal url to register for the endpoint (only for
|
||||
action :create_endpoint)
|
||||
- endpoint_publicurl: The public url to register for the endpoint (only for
|
||||
action :create_endpoint)
|
||||
- tenant_name: The name of the tenant to create or create the user in (only for
|
||||
action :create_tenant and :create_user)
|
||||
- tenant_description: The description of the tenant to create (only for action
|
||||
:create_tenant)
|
||||
- tenant_enabled: Enable or disable tenant to create (only for action
|
||||
:create_tenant) Defaults to <code>true</code>.
|
||||
- user_name: The name of the user to create (only for action :create_user)
|
||||
- user_pass: The passwort of the user to create (only for action :create_user)
|
||||
- user_enabled: Enable or disable user to create (only for action :create_user)
|
||||
Defaults to <code>true</code>.
|
||||
- role_name: The name of the role to create or grant to the user (only for
|
||||
:create_role and :grant_role)
|
||||
- admin_tenant_name: The name of the admin tenant (only for
|
||||
:create_ec2_credentials)
|
||||
- admin_user: The name of the admin user (only for :create_ec2_credentials)
|
||||
- admin_pass: The password of the admin user (only for :create_ec2_credentials)
|
||||
- identity_endpoint: The identity endpoint to use for user and ec2 creation. If
|
||||
not specified, default endpoint will be used. (only for create_ec2_credentials
|
||||
and create_user)
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
# Create 'openstack' tenant
|
||||
openstack_identity_register "Register 'openstack' Tenant" do
|
||||
auth_host "192.168.1.10"
|
||||
auth_port "35357"
|
||||
auth_protocol "http"
|
||||
api_ver "/v2.0"
|
||||
auth_token "123456789876"
|
||||
tenant_name "openstack"
|
||||
tenant_description "Default Tenant"
|
||||
tenant_enabled "true" # Not required as this is the default
|
||||
action :create_tenant
|
||||
end
|
||||
|
||||
# Create 'admin' user
|
||||
openstack_identity_register "Register 'admin' User" do
|
||||
auth_host "192.168.1.10"
|
||||
auth_port "35357"
|
||||
auth_protocol "http"
|
||||
api_ver "/v2.0"
|
||||
auth_token "123456789876"
|
||||
tenant_name "openstack"
|
||||
user_name "admin"
|
||||
user_pass "secrete"
|
||||
user_enabled "true" # Not required as this is the default
|
||||
action :create_user
|
||||
end
|
||||
|
||||
# Create 'admin' role
|
||||
openstack_identity_register "Register 'admin' Role" do
|
||||
auth_host "192.168.1.10"
|
||||
auth_port "35357"
|
||||
auth_protocol "http"
|
||||
api_ver "/v2.0"
|
||||
auth_token "123456789876"
|
||||
role_name role_key
|
||||
action :create_role
|
||||
end
|
||||
|
||||
# Grant 'admin' role to 'admin' user in the 'openstack' tenant
|
||||
openstack_identity_register "Grant 'admin' Role to 'admin' User" do
|
||||
auth_host "192.168.1.10"
|
||||
auth_port "35357"
|
||||
auth_protocol "http"
|
||||
api_ver "/v2.0"
|
||||
auth_token "123456789876"
|
||||
tenant_name "openstack"
|
||||
user_name "admin"
|
||||
role_name "admin"
|
||||
action :grant_role
|
||||
end
|
||||
|
||||
# Create 'identity' service
|
||||
openstack_identity_register "Register Identity Service" do
|
||||
auth_host "192.168.1.10"
|
||||
auth_port "35357"
|
||||
auth_protocol "http"
|
||||
api_ver "/v2.0"
|
||||
auth_token "123456789876"
|
||||
service_name "keystone"
|
||||
service_type "identity"
|
||||
service_description "Keystone Identity Service"
|
||||
action :create_service
|
||||
end
|
||||
|
||||
# Create 'identity' endpoint
|
||||
openstack_identity_register "Register Identity Endpoint" do
|
||||
auth_host "192.168.1.10"
|
||||
auth_port "35357"
|
||||
auth_protocol "http"
|
||||
api_ver "/v2.0"
|
||||
auth_token "123456789876"
|
||||
service_type "identity"
|
||||
endpoint_region "RegionOne"
|
||||
endpoint_adminurl "http://192.168.1.10:35357/v2.0"
|
||||
endpoint_internalurl "http://192.168.1.10:5001/v2.0"
|
||||
endpoint_publicurl "http://1.2.3.4:5001/v2.0"
|
||||
action :create_endpoint
|
||||
end
|
||||
```
|
||||
|
||||
|
||||
License and Author
|
||||
==================
|
||||
|
||||
|
@ -218,6 +83,7 @@ Author:: Ionut Artarisi (<iartarisi@suse.cz>)
|
|||
Author:: Chen Zhiwei (zhiwchen@cn.ibm.com)
|
||||
Author:: Eric Zhou (zyouzhou@cn.ibm.com)
|
||||
Author:: Jan Klare (j.klare@cloudbau.de)
|
||||
Author:: Christoph Albers (<c.albers@x-ion.de>)
|
||||
|
||||
Copyright 2012, Rackspace US, Inc.
|
||||
Copyright 2012-2013, Opscode, Inc.
|
||||
|
|
|
@ -30,7 +30,7 @@ default['openstack']['identity']['custom_template_banner'] =
|
|||
# scheme for openstack admin/internal/public identity endpoint
|
||||
default['openstack']['endpoints'][ep_type]['identity']['scheme'] = 'http'
|
||||
# path for openstack admin/internal/public identity endpoint
|
||||
default['openstack']['endpoints'][ep_type]['identity']['path'] = '/v2.0'
|
||||
default['openstack']['endpoints'][ep_type]['identity']['path'] = '/v3'
|
||||
end
|
||||
|
||||
# port for openstack public identity endpoint
|
||||
|
@ -96,18 +96,14 @@ default['openstack']['identity']['syslog']['config_facility'] = 'local2'
|
|||
|
||||
# user to be created and used for identity service
|
||||
default['openstack']['identity']['admin_user'] = 'admin'
|
||||
# tenant to be created and used for identity service
|
||||
default['openstack']['identity']['admin_tenant_name'] = 'admin'
|
||||
|
||||
default['openstack']['identity']['users'] = {
|
||||
default['openstack']['identity']['admin_user'] => {
|
||||
'default_tenant' => default['openstack']['identity']['admin_tenant_name'],
|
||||
'roles' => {
|
||||
'admin' => ['admin'],
|
||||
'service' => ['admin']
|
||||
}
|
||||
}
|
||||
}
|
||||
# project to be created and used for identity service
|
||||
default['openstack']['identity']['admin_project'] = 'admin'
|
||||
# domain to be created and used for identity service project
|
||||
default['openstack']['identity']['admin_project_domain'] = 'default'
|
||||
# role to be created and used for identity service
|
||||
default['openstack']['identity']['admin_role'] = 'admin'
|
||||
# domain to be created and used for identity service user
|
||||
default['openstack']['identity']['admin_domain_name'] = 'default'
|
||||
|
||||
# specify whether to enable SSL for Keystone API endpoint
|
||||
default['openstack']['identity']['ssl']['enabled'] = false
|
||||
|
@ -144,6 +140,8 @@ default['openstack']['identity']['fernet']['keys'] = [0, 1]
|
|||
default['openstack']['identity']['auth']['external'] = 'keystone.auth.plugins.external.DefaultDomain'
|
||||
# Default auth methods. (List value)
|
||||
default['openstack']['identity']['auth']['methods'] = 'external, password, token, oauth1'
|
||||
# Default auth_version for now
|
||||
default['openstack']['identity']['auth']['version'] = 'v3'
|
||||
|
||||
# enable or disable the usage of the token flushing cronjob
|
||||
default['openstack']['identity']['token_flush_cron']['enabled'] = true
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
# encoding: UTF-8
|
||||
if defined?(ChefSpec)
|
||||
def create_service_openstack_identity_register(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(
|
||||
:openstack_identity_register,
|
||||
:create_service,
|
||||
resource_name)
|
||||
end
|
||||
|
||||
def create_endpoint_openstack_identity_register(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(
|
||||
:openstack_identity_register,
|
||||
:create_endpoint,
|
||||
resource_name)
|
||||
end
|
||||
|
||||
def create_tenant_openstack_identity_register(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(
|
||||
:openstack_identity_register,
|
||||
:create_tenant,
|
||||
resource_name)
|
||||
end
|
||||
|
||||
def create_user_openstack_identity_register(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(
|
||||
:openstack_identity_register,
|
||||
:create_user,
|
||||
resource_name)
|
||||
end
|
||||
|
||||
def create_role_openstack_identity_register(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(
|
||||
:openstack_identity_register,
|
||||
:create_role,
|
||||
resource_name)
|
||||
end
|
||||
|
||||
def grant_role_openstack_identity_register(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(
|
||||
:openstack_identity_register,
|
||||
:grant_role,
|
||||
resource_name)
|
||||
end
|
||||
|
||||
def create_ec2_credentials_openstack_identity_register(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(
|
||||
:openstack_identity_register,
|
||||
:create_ec2_credentials,
|
||||
resource_name)
|
||||
end
|
||||
end
|
|
@ -14,3 +14,4 @@ end
|
|||
|
||||
depends 'apache2', '~> 3.1'
|
||||
depends 'openstack-common', '>= 14.0.0'
|
||||
depends 'openstackclient'
|
||||
|
|
|
@ -1,347 +0,0 @@
|
|||
# encoding: UTF-8
|
||||
#
|
||||
# Cookbook Name:: openstack-identity
|
||||
# Provider:: register
|
||||
#
|
||||
# Copyright 2012, Rackspace US, Inc.
|
||||
# Copyright 2012-2013, AT&T Services, Inc.
|
||||
# Copyright 2013, Opscode, Inc.
|
||||
# Copyright 2013, Craig Tracey <craigtracey@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
require 'chef/mixin/shell_out'
|
||||
include Chef::Mixin::ShellOut
|
||||
include ::Openstack
|
||||
|
||||
use_inline_resources
|
||||
|
||||
# creates the defined service as new service for keystone
|
||||
action :create_service do
|
||||
new_resource.updated_by_last_action(false)
|
||||
if node['openstack']['identity']['catalog']['backend'] == 'templated'
|
||||
Chef::Log.info('Skipping service creation - templated catalog backend in use.')
|
||||
else
|
||||
begin
|
||||
service_uuid = identity_uuid new_resource, 'service', 'type', new_resource.service_type
|
||||
need_updated = false
|
||||
if service_uuid
|
||||
Chef::Log.info("Service Type '#{new_resource.service_type}' already exists..")
|
||||
Chef::Log.info("Service UUID: #{service_uuid}")
|
||||
need_updated = service_need_updated? new_resource
|
||||
if need_updated
|
||||
Chef::Log.info("Service Type '#{new_resource.service_type}' needs to be updated, delete it first.")
|
||||
identity_command(new_resource, 'service-delete',
|
||||
'' => service_uuid)
|
||||
end
|
||||
end
|
||||
unless service_uuid && !need_updated
|
||||
identity_command(new_resource, 'service-create',
|
||||
'type' => new_resource.service_type,
|
||||
'name' => new_resource.service_name,
|
||||
'description' => new_resource.service_description)
|
||||
Chef::Log.info("Created service '#{new_resource.service_name}'")
|
||||
new_resource.updated_by_last_action(true)
|
||||
end
|
||||
rescue StandardError => e
|
||||
raise "Unable to create service '#{new_resource.service_name}' Error:" + e.message
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# registers all endpoints for the defined service in keystone
|
||||
action :create_endpoint do
|
||||
new_resource.updated_by_last_action(false)
|
||||
if node['openstack']['identity']['catalog']['backend'] == 'templated'
|
||||
Chef::Log.info('Skipping endpoint creation - templated catalog backend in use.')
|
||||
else
|
||||
begin
|
||||
service_uuid = identity_uuid new_resource, 'service', 'type', new_resource.service_type
|
||||
raise "Unable to find service type '#{new_resource.service_type}'" unless service_uuid
|
||||
|
||||
endpoint_uuid = identity_uuid new_resource, 'endpoint', 'service_id', service_uuid
|
||||
need_updated = false
|
||||
if endpoint_uuid
|
||||
Chef::Log.info("Endpoint already exists for Service Type '#{new_resource.service_type}'.")
|
||||
need_updated = endpoint_need_updated? new_resource, 'service_id', service_uuid
|
||||
if need_updated
|
||||
Chef::Log.info("Endpoint for Service Type '#{new_resource.service_type}' needs to be updated, delete it first.")
|
||||
identity_command(new_resource, 'endpoint-delete',
|
||||
'' => endpoint_uuid)
|
||||
end
|
||||
end
|
||||
unless endpoint_uuid && !need_updated
|
||||
identity_command(new_resource, 'endpoint-create',
|
||||
'region' => new_resource.endpoint_region,
|
||||
'service_id' => service_uuid,
|
||||
'publicurl' => new_resource.endpoint_publicurl,
|
||||
'internalurl' => new_resource.endpoint_internalurl,
|
||||
'adminurl' => new_resource.endpoint_adminurl)
|
||||
Chef::Log.info("Created endpoint for service type '#{new_resource.service_type}'")
|
||||
new_resource.updated_by_last_action(true)
|
||||
end
|
||||
rescue StandardError => e
|
||||
raise "Unable to create endpoint for service type '#{new_resource.service_type}' Error: " + e.message
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# creates the defined tenant in keystone
|
||||
action :create_tenant do
|
||||
begin
|
||||
new_resource.updated_by_last_action(false)
|
||||
tenant_uuid = identity_uuid new_resource, 'tenant', 'name', new_resource.tenant_name
|
||||
|
||||
if tenant_uuid
|
||||
Chef::Log.info("Tenant '#{new_resource.tenant_name}' already exists.. Not creating.")
|
||||
Chef::Log.info("Tenant UUID: #{tenant_uuid}") if tenant_uuid
|
||||
else
|
||||
identity_command(new_resource, 'tenant-create',
|
||||
'name' => new_resource.tenant_name,
|
||||
'description' => new_resource.tenant_description,
|
||||
'enabled' => new_resource.tenant_enabled)
|
||||
Chef::Log.info("Created tenant '#{new_resource.tenant_name}'")
|
||||
new_resource.updated_by_last_action(true)
|
||||
end
|
||||
rescue StandardError => e
|
||||
raise "Unable to create tenant '#{new_resource.tenant_name}' Error: " + e.message
|
||||
end
|
||||
end
|
||||
|
||||
# creates the defined role in keystone
|
||||
action :create_role do
|
||||
begin
|
||||
new_resource.updated_by_last_action(false)
|
||||
role_uuid = identity_uuid new_resource, 'role', 'name', new_resource.role_name
|
||||
|
||||
if role_uuid
|
||||
Chef::Log.info("Role '#{new_resource.role_name}' already exists.. Not creating.")
|
||||
Chef::Log.info("Role UUID: #{role_uuid}")
|
||||
else
|
||||
identity_command(new_resource, 'role-create',
|
||||
'name' => new_resource.role_name)
|
||||
Chef::Log.info("Created Role '#{new_resource.role_name}'")
|
||||
new_resource.updated_by_last_action(true)
|
||||
end
|
||||
rescue StandardError => e
|
||||
raise "Unable to create role '#{new_resource.role_name}' Error: " + e.message
|
||||
end
|
||||
end
|
||||
|
||||
# creates the defined user in keystone
|
||||
action :create_user do
|
||||
begin
|
||||
new_resource.updated_by_last_action(false)
|
||||
|
||||
output = identity_command(new_resource, 'user-list')
|
||||
users = prettytable_to_array output
|
||||
user_found = false
|
||||
users.each do |user|
|
||||
user_found = true if user['name'] == new_resource.user_name
|
||||
end
|
||||
|
||||
if user_found
|
||||
Chef::Log.info("User '#{new_resource.user_name}' already exists")
|
||||
begin
|
||||
# Check if password is already updated by getting a token
|
||||
identity_command(new_resource, 'token-get', {}, 'user')
|
||||
rescue StandardError => e
|
||||
Chef::Log.debug('Get token error:' + e.message)
|
||||
Chef::Log.info("Sync password for user '#{new_resource.user_name}'")
|
||||
identity_command(new_resource, 'user-password-update',
|
||||
'pass' => new_resource.user_pass,
|
||||
'' => new_resource.user_name)
|
||||
new_resource.updated_by_last_action(true)
|
||||
end
|
||||
next
|
||||
end
|
||||
|
||||
identity_command(new_resource, 'user-create',
|
||||
'name' => new_resource.user_name,
|
||||
'tenant' => new_resource.tenant_name,
|
||||
'pass' => new_resource.user_pass,
|
||||
'enabled' => new_resource.user_enabled)
|
||||
Chef::Log.info("Created user '#{new_resource.user_name}' for tenant '#{new_resource.tenant_name}'")
|
||||
new_resource.updated_by_last_action(true)
|
||||
rescue StandardError => e
|
||||
raise "Unable to create user '#{new_resource.user_name}' for tenant '#{new_resource.tenant_name}' Error: " + e.message
|
||||
end
|
||||
end
|
||||
|
||||
# grants the defined role to a given user in a given tenant
|
||||
action :grant_role do
|
||||
begin
|
||||
new_resource.updated_by_last_action(false)
|
||||
|
||||
role_uuid = identity_uuid new_resource, 'role', 'name', new_resource.role_name
|
||||
raise "Unable to find role '#{new_resource.role_name}'" unless role_uuid
|
||||
|
||||
assigned_role_uuid = identity_uuid(new_resource, 'user-role', 'name',
|
||||
new_resource.role_name,
|
||||
'tenant' => new_resource.tenant_name,
|
||||
'user' => new_resource.user_name)
|
||||
if role_uuid == assigned_role_uuid
|
||||
Chef::Log.info("Role '#{new_resource.role_name}' already granted to User '#{new_resource.user_name}' in Tenant '#{new_resource.tenant_name}'")
|
||||
else
|
||||
identity_command(new_resource, 'user-role-add',
|
||||
'tenant' => new_resource.tenant_name,
|
||||
'role-id' => role_uuid,
|
||||
'user' => new_resource.user_name)
|
||||
Chef::Log.info("Granted Role '#{new_resource.role_name}' to User '#{new_resource.user_name}' in Tenant '#{new_resource.tenant_name}'")
|
||||
new_resource.updated_by_last_action(true)
|
||||
end
|
||||
rescue StandardError => e
|
||||
raise "Unable to grant role '#{new_resource.role_name}' to user '#{new_resource.user_name}' Error: " + e.message
|
||||
end
|
||||
end
|
||||
|
||||
# creates ec2_credentials for a given user in a given tenant
|
||||
action :create_ec2_credentials do
|
||||
begin
|
||||
new_resource.updated_by_last_action(false)
|
||||
tenant_uuid = identity_uuid new_resource, 'tenant', 'name', new_resource.tenant_name
|
||||
raise "Unable to find tenant '#{new_resource.tenant_name}'" unless tenant_uuid
|
||||
|
||||
user_uuid = identity_uuid(new_resource, 'user', 'name',
|
||||
new_resource.user_name,
|
||||
'tenant-id' => tenant_uuid)
|
||||
raise "Unable to find user '#{new_resource.user_name}' with tenant '#{new_resource.tenant_name}'" unless user_uuid
|
||||
|
||||
# this is not really a uuid, but this will work nonetheless
|
||||
access = identity_uuid new_resource, 'ec2-credentials', 'tenant', new_resource.tenant_name, { 'user-id' => user_uuid }, 'access'
|
||||
if access
|
||||
Chef::Log.info("EC2 credentials already exist for '#{new_resource.user_name}' in tenant '#{new_resource.tenant_name}'")
|
||||
else
|
||||
output = identity_command(new_resource, 'ec2-credentials-create',
|
||||
{ 'user-id' => user_uuid,
|
||||
'tenant-id' => tenant_uuid },
|
||||
'admin')
|
||||
Chef::Log.info("Created EC2 Credentials for User '#{new_resource.user_name}' in Tenant '#{new_resource.tenant_name}'")
|
||||
data = prettytable_to_array(output)
|
||||
|
||||
if data.length != 1
|
||||
raise "Got bad data when creating ec2 credentials for #{new_resource.user_name} Data: #{data}"
|
||||
else
|
||||
# Update node attributes
|
||||
node.set['credentials']['EC2'][new_resource.user_name]['access'] = data[0]['access']
|
||||
node.set['credentials']['EC2'][new_resource.user_name]['secret'] = data[0]['secret']
|
||||
node.save unless Chef::Config[:solo]
|
||||
new_resource.updated_by_last_action(true)
|
||||
end
|
||||
end
|
||||
rescue StandardError => e
|
||||
raise "Unable to create EC2 Credentials for User '#{new_resource.user_name}' in Tenant '#{new_resource.tenant_name}' Error: " + e.message
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_boot_creds(resource)
|
||||
{
|
||||
'OS_SERVICE_ENDPOINT' => resource.auth_uri,
|
||||
'OS_SERVICE_TOKEN' => resource.bootstrap_token
|
||||
}
|
||||
end
|
||||
|
||||
def generate_admin_creds(resource)
|
||||
identity_endpoint = resource.identity_endpoint
|
||||
identity_endpoint = admin_endpoint('identity').to_s unless identity_endpoint
|
||||
{
|
||||
'OS_USERNAME' => resource.admin_user,
|
||||
'OS_PASSWORD' => resource.admin_pass,
|
||||
'OS_TENANT_NAME' => resource.admin_tenant_name,
|
||||
'OS_AUTH_URL' => identity_endpoint
|
||||
}
|
||||
end
|
||||
|
||||
def generate_user_creds(resource)
|
||||
identity_endpoint = resource.identity_endpoint
|
||||
identity_endpoint = public_endpoint('identity').to_s unless identity_endpoint
|
||||
{
|
||||
'OS_USERNAME' => resource.user_name,
|
||||
'OS_PASSWORD' => resource.user_pass,
|
||||
'OS_TENANT_NAME' => resource.tenant_name,
|
||||
'OS_AUTH_URL' => identity_endpoint
|
||||
}
|
||||
end
|
||||
|
||||
def get_env(resource, env = 'boot')
|
||||
case env
|
||||
when 'boot'
|
||||
generate_boot_creds(resource)
|
||||
when 'user'
|
||||
generate_user_creds(resource)
|
||||
when 'admin'
|
||||
generate_admin_creds(resource)
|
||||
end
|
||||
end
|
||||
|
||||
def identity_command(resource, cmd, args = {}, env = 'boot')
|
||||
keystonecmd = build_keystone_cmd(cmd, args)
|
||||
cmd_env = get_env(resource, env)
|
||||
Chef::Log.debug("Running identity command: #{keystonecmd} env: " + cmd_env.to_s)
|
||||
rc = shell_out(keystonecmd, env: cmd_env)
|
||||
raise "#{rc.stderr} (#{rc.exitstatus})" if rc.exitstatus != 0
|
||||
rc.stdout
|
||||
end
|
||||
|
||||
def build_keystone_cmd(cmd, args)
|
||||
keystonecmd = ['keystone'] << '--insecure' << cmd
|
||||
args.each do |key, val|
|
||||
keystonecmd << "--#{key}" unless key.empty?
|
||||
keystonecmd << val.to_s
|
||||
end
|
||||
keystonecmd
|
||||
end
|
||||
|
||||
def identity_uuid(resource, type, key, value, args = {}, uuid_field = 'id')
|
||||
rc = nil
|
||||
begin
|
||||
output = identity_command resource, "#{type}-list", args
|
||||
output = prettytable_to_array(output)
|
||||
rc = (type == 'endpoint') ? search_uuid(output, uuid_field, key => value, 'region' => resource.endpoint_region) : search_uuid(output, uuid_field, key => value)
|
||||
rescue RuntimeError => e
|
||||
raise "Could not lookup uuid for #{type}:#{key}=>#{value}. Error was #{e.message}"
|
||||
end
|
||||
rc
|
||||
end
|
||||
|
||||
def search_uuid(output, uuid_field, required_hash = {})
|
||||
rc = nil
|
||||
output.each do |obj|
|
||||
rc = obj[uuid_field] if obj.key?(uuid_field) && required_hash.values - obj.values_at(*required_hash.keys) == []
|
||||
end
|
||||
rc
|
||||
end
|
||||
|
||||
def service_need_updated?(resource, args = {}, uuid_field = 'id')
|
||||
begin
|
||||
output = identity_command resource, 'service-list', args
|
||||
output = prettytable_to_array(output)
|
||||
return search_uuid(output, uuid_field, 'name' => resource.service_name).nil?
|
||||
rescue RuntimeError => e
|
||||
raise "Could not check service attributes for service: type => #{resource.service_type}, name => #{resource.service_name}. Error was #{e.message}"
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
def endpoint_need_updated?(resource, key, value, args = {}, uuid_field = 'id')
|
||||
begin
|
||||
output = identity_command resource, 'endpoint-list', args
|
||||
output = prettytable_to_array(output)
|
||||
return search_uuid(output, uuid_field, key => value, 'region' => resource.endpoint_region, 'publicurl' => resource.endpoint_publicurl, 'internalurl' => resource.endpoint_internalurl, 'adminurl' => resource.endpoint_adminurl).nil?
|
||||
rescue RuntimeError => e
|
||||
raise "Could not check endpoint attributes for endpoint:#{key}=>#{value}. Error was #{e.message}"
|
||||
end
|
||||
false
|
||||
end
|
|
@ -24,25 +24,15 @@ class ::Chef::Recipe
|
|||
include ::Openstack
|
||||
end
|
||||
|
||||
# check attributes before searching
|
||||
if node['openstack']['identity'] && node['openstack']['identity']['admin_tenant_name'] && node['openstack']['identity']['admin_user']
|
||||
ksadmin_tenant_name = node['openstack']['identity']['admin_tenant_name']
|
||||
ksadmin_user = node['openstack']['identity']['admin_user']
|
||||
else
|
||||
identity_service_role = node['openstack']['identity_service_chef_role']
|
||||
keystone = search_for(identity_service_role).first
|
||||
|
||||
if keystone.nil?
|
||||
Chef::Log.warn("openrc not created, identity role node not found: #{identity_service_role}")
|
||||
return
|
||||
end
|
||||
|
||||
ksadmin_tenant_name = keystone['openstack']['identity']['admin_tenant_name']
|
||||
ksadmin_user = keystone['openstack']['identity']['admin_user']
|
||||
end
|
||||
ksadmin_project = node['openstack']['identity']['admin_project']
|
||||
project_domain_name = node['openstack']['identity']['admin_project_domain']
|
||||
ksadmin_user = node['openstack']['identity']['admin_user']
|
||||
admin_domain_name = node['openstack']['identity']['admin_domain_name']
|
||||
|
||||
auth_api_version = node['openstack']['api']['auth']['version']
|
||||
ksadmin_pass = get_password 'user', ksadmin_user
|
||||
identity_public_endpoint = public_endpoint 'identity'
|
||||
auth_url = auth_uri_transform identity_public_endpoint.to_s, auth_api_version
|
||||
|
||||
directory node['openstack']['openrc']['path'] do
|
||||
owner node['openstack']['openrc']['user']
|
||||
|
@ -59,8 +49,11 @@ template "#{node['openstack']['openrc']['path']}/#{node['openstack']['openrc']['
|
|||
sensitive true
|
||||
variables(
|
||||
user: ksadmin_user,
|
||||
tenant: ksadmin_tenant_name,
|
||||
user_domain_name: admin_domain_name,
|
||||
project: ksadmin_project,
|
||||
project_domain_name: project_domain_name,
|
||||
api_version: '3',
|
||||
password: ksadmin_pass,
|
||||
identity_endpoint: identity_public_endpoint
|
||||
identity_endpoint: auth_url
|
||||
)
|
||||
end
|
||||
|
|
|
@ -24,92 +24,65 @@
|
|||
# comments inside the recipe.
|
||||
|
||||
require 'uri'
|
||||
require 'chef/mixin/shell_out'
|
||||
|
||||
class ::Chef::Recipe
|
||||
include ::Openstack
|
||||
end
|
||||
|
||||
# define the endpoints to register for the keystone identity service
|
||||
identity_admin_endpoint = admin_endpoint 'identity'
|
||||
identity_internal_endpoint = internal_endpoint 'identity'
|
||||
identity_public_endpoint = public_endpoint 'identity'
|
||||
auth_uri = ::URI.decode identity_admin_endpoint.to_s
|
||||
auth_url = ::URI.decode identity_admin_endpoint.to_s
|
||||
|
||||
# define the credentials to use for the initial admin user
|
||||
admin_tenant_name = node['openstack']['identity']['admin_tenant_name']
|
||||
admin_project = node['openstack']['identity']['admin_project']
|
||||
admin_user = node['openstack']['identity']['admin_user']
|
||||
admin_pass = get_password 'user', node['openstack']['identity']['admin_user']
|
||||
admin_role = node['openstack']['identity']['admin_role']
|
||||
admin_domain = node['openstack']['identity']['admin_domain_name']
|
||||
region = node['openstack']['identity']['region']
|
||||
|
||||
bootstrap_token = get_password 'token', 'openstack_identity_bootstrap_token'
|
||||
|
||||
# register all the tenants specified in the users hash
|
||||
identity_tenants = node['openstack']['identity']['users'].values.map do |user_info|
|
||||
user_info['roles'].values.push(user_info['default_tenant'])
|
||||
execute 'bootstrap_keystone' do
|
||||
command "keystone-manage bootstrap \\
|
||||
--bootstrap-password #{admin_pass} \\
|
||||
--bootstrap-username #{admin_user} \\
|
||||
--bootstrap-project-name #{admin_project} \\
|
||||
--bootstrap-role-name #{admin_role} \\
|
||||
--bootstrap-service-name keystone \\
|
||||
--bootstrap-region-id #{region} \\
|
||||
--bootstrap-admin-url #{identity_admin_endpoint} \\
|
||||
--bootstrap-public-url #{identity_public_endpoint} \\
|
||||
--bootstrap-internal-url #{identity_internal_endpoint}"
|
||||
end
|
||||
|
||||
identity_tenants.flatten.uniq.each do |tenant_name|
|
||||
openstack_identity_register "Register '#{tenant_name}' Tenant" do
|
||||
auth_uri auth_uri
|
||||
bootstrap_token bootstrap_token
|
||||
tenant_name tenant_name
|
||||
tenant_description "#{tenant_name} Tenant"
|
||||
connection_params = {
|
||||
openstack_auth_url: "#{auth_url}/auth/tokens",
|
||||
openstack_username: admin_user,
|
||||
openstack_api_key: admin_pass,
|
||||
openstack_project_name: admin_project,
|
||||
openstack_domain_name: admin_domain
|
||||
}
|
||||
|
||||
action :create_tenant
|
||||
end
|
||||
openstack_domain admin_domain do
|
||||
connection_params connection_params
|
||||
end
|
||||
|
||||
# register all the roles and users from the users hash
|
||||
identity_roles = node['openstack']['identity']['users'].values.map do |user_info|
|
||||
user_info['roles'].keys
|
||||
openstack_user admin_user do
|
||||
domain_name admin_domain
|
||||
role_name admin_role
|
||||
connection_params connection_params
|
||||
action :grant_domain
|
||||
end
|
||||
|
||||
identity_roles.flatten.uniq.each do |role_name|
|
||||
openstack_identity_register "Register '#{role_name}' Role" do
|
||||
auth_uri auth_uri
|
||||
bootstrap_token bootstrap_token
|
||||
role_name role_name
|
||||
|
||||
action :create_role
|
||||
end
|
||||
# create default service role
|
||||
openstack_role 'service' do
|
||||
connection_params connection_params
|
||||
end
|
||||
|
||||
node['openstack']['identity']['users'].each do |username, user_info|
|
||||
pwd = get_password 'user', username
|
||||
openstack_identity_register "Register '#{username}' User" do
|
||||
auth_uri auth_uri
|
||||
bootstrap_token bootstrap_token
|
||||
user_name username
|
||||
user_pass pwd
|
||||
tenant_name user_info['default_tenant']
|
||||
user_enabled true # Not required as this is the default
|
||||
|
||||
action :create_user
|
||||
end
|
||||
|
||||
user_info['roles'].each do |rolename, tenant_list|
|
||||
tenant_list.each do |tenantname|
|
||||
openstack_identity_register "Grant '#{rolename}' Role to '#{username}' User in '#{tenantname}' Tenant" do
|
||||
auth_uri auth_uri
|
||||
bootstrap_token bootstrap_token
|
||||
user_name username
|
||||
role_name rolename
|
||||
tenant_name tenantname
|
||||
|
||||
action :grant_role
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# register the identity service itself
|
||||
openstack_identity_register 'Register Identity Service' do
|
||||
auth_uri auth_uri
|
||||
bootstrap_token bootstrap_token
|
||||
service_name 'keystone'
|
||||
service_type 'identity'
|
||||
service_description 'Keystone Identity Service'
|
||||
|
||||
action :create_service
|
||||
not_if { node['openstack']['identity']['catalog']['backend'] == 'templated' }
|
||||
# create default role for horizon dashboard login
|
||||
openstack_role '_member_' do
|
||||
connection_params connection_params
|
||||
end
|
||||
|
||||
node.set['openstack']['identity']['adminURL'] = identity_admin_endpoint.to_s
|
||||
|
@ -119,32 +92,3 @@ node.set['openstack']['identity']['publicURL'] = identity_public_endpoint.to_s
|
|||
Chef::Log.info "Keystone AdminURL: #{identity_admin_endpoint}"
|
||||
Chef::Log.info "Keystone InternalURL: #{identity_internal_endpoint}"
|
||||
Chef::Log.info "Keystone PublicURL: #{identity_public_endpoint}"
|
||||
|
||||
# register the identity service endpoints
|
||||
openstack_identity_register 'Register Identity Endpoint' do
|
||||
auth_uri auth_uri
|
||||
bootstrap_token bootstrap_token
|
||||
service_type 'identity'
|
||||
endpoint_region node['openstack']['identity']['region']
|
||||
endpoint_adminurl node['openstack']['identity']['adminURL']
|
||||
endpoint_internalurl node['openstack']['identity']['internalURL']
|
||||
endpoint_publicurl node['openstack']['identity']['publicURL']
|
||||
|
||||
action :create_endpoint
|
||||
not_if { node['openstack']['identity']['catalog']['backend'] == 'templated' }
|
||||
end
|
||||
|
||||
# create ec2 creadentials for the users from the users hash
|
||||
node['openstack']['identity']['users'].each do |username, user_info|
|
||||
openstack_identity_register "Create EC2 credentials for '#{username}' user" do
|
||||
auth_uri auth_uri
|
||||
bootstrap_token bootstrap_token
|
||||
user_name username
|
||||
tenant_name user_info['default_tenant']
|
||||
admin_tenant_name admin_tenant_name
|
||||
admin_user admin_user
|
||||
admin_pass admin_pass
|
||||
|
||||
action :create_ec2_credentials
|
||||
end
|
||||
end
|
||||
|
|
|
@ -120,9 +120,6 @@ node.default['openstack']['identity']['conf_secrets']
|
|||
.[]('database')['connection'] =
|
||||
db_uri('identity', db_user, db_pass)
|
||||
|
||||
# define the admin keystone bootstrap token
|
||||
bootstrap_token = get_password 'token', 'openstack_identity_bootstrap_token'
|
||||
|
||||
# search for memcache servers using the method from cookbook-openstack-common
|
||||
memcache_servers = memcached_servers.join ','
|
||||
|
||||
|
@ -168,7 +165,6 @@ end
|
|||
|
||||
# set keystone config parameters for admin_token, endpoints and memcache
|
||||
node.default['openstack']['identity']['conf'].tap do |conf|
|
||||
conf['DEFAULT']['admin_token'] = bootstrap_token
|
||||
conf['DEFAULT']['public_endpoint'] = public_endpoint
|
||||
conf['DEFAULT']['admin_endpoint'] = admin_endpoint
|
||||
conf['memcache']['servers'] = memcache_servers if memcache_servers
|
||||
|
@ -334,6 +330,11 @@ wsgi_apps.each do |app, opt|
|
|||
end
|
||||
end
|
||||
|
||||
# disable keystone-site since ubuntu autoenables this
|
||||
apache_site 'keystone' do
|
||||
enable false
|
||||
end
|
||||
|
||||
# wait for apache2 to be fully reloaded and the keystone endpoint to become
|
||||
# available
|
||||
execute 'Keystone: sleep' do
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
# encoding: UTF-8
|
||||
#
|
||||
# Cookbook Name:: openstack-identity
|
||||
# Resource:: register
|
||||
#
|
||||
# Copyright 2012, Rackspace US, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# These resources provide an abstraction layer for interacting with the keystone
|
||||
# server's API, allowin for other nodes to register any required users, tenants,
|
||||
# roles, services, or endpoints.
|
||||
|
||||
actions :create_service, :create_endpoint, :create_tenant, :create_user, :create_role, :grant_role, :create_ec2_credentials
|
||||
|
||||
# In earlier versions of Chef the LWRP DSL doesn't support specifying
|
||||
# a default action, so you need to drop into Ruby.
|
||||
def initialize(*args)
|
||||
super
|
||||
@action = :create
|
||||
end
|
||||
|
||||
BOOLEAN = [TrueClass, FalseClass].freeze
|
||||
|
||||
# The uri used to as authentication endpoint for requests
|
||||
attribute :auth_uri, kind_of: String
|
||||
# The admin bootstrap_token used for authentication
|
||||
attribute :bootstrap_token, kind_of: String
|
||||
# The type of service to create (e.g. 'identity' or 'volume')
|
||||
attribute :service_type, kind_of: String
|
||||
# The name of the service to create (only for action :create_service)
|
||||
attribute :service_name, kind_of: String
|
||||
# The description for the service to create (only for action :create_service)
|
||||
attribute :service_description, kind_of: String
|
||||
# The region to create the endpoint in (only for action :create_endpoint)
|
||||
attribute :endpoint_region, kind_of: String, default: 'RegionOne'
|
||||
# The admin url to register for the endpoint (only for action :create_endpoint)
|
||||
attribute :endpoint_adminurl, kind_of: String
|
||||
# The internal url to register for the endpoint (only for action
|
||||
# :create_endpoint)
|
||||
attribute :endpoint_internalurl, kind_of: String
|
||||
# The public url to register for the endpoint (only for action :create_endpoint)
|
||||
attribute :endpoint_publicurl, kind_of: String
|
||||
# The name of the tenant to create or create the user in (only for action
|
||||
# :create_tenant and :create_user)
|
||||
attribute :tenant_name, kind_of: String
|
||||
# The description of the tenant to create (only for action :create_tenant)
|
||||
attribute :tenant_description, kind_of: String
|
||||
# Enable or disable tenant to create (only for action :create_tenant)
|
||||
attribute :tenant_enabled, kind_of: BOOLEAN, default: true
|
||||
# The name of the user to create (only for action :create_user)
|
||||
attribute :user_name, kind_of: String
|
||||
# The passwort of the user to create (only for action :create_user)
|
||||
attribute :user_pass, kind_of: String
|
||||
# Enable or disable user to create (only for action :create_user)
|
||||
attribute :user_enabled, kind_of: BOOLEAN, default: true
|
||||
# The name of the role to create or grant to the user (only for :create_role and
|
||||
# :grant_role)
|
||||
attribute :role_name, kind_of: String
|
||||
# The name of the admin tenant (only for :create_ec2_credentials)
|
||||
attribute :admin_tenant_name, kind_of: String
|
||||
# The name of the admin user (only for :create_ec2_credentials)
|
||||
attribute :admin_user, kind_of: String
|
||||
# The password of the admin user (only for :create_ec2_credentials)
|
||||
attribute :admin_pass, kind_of: String
|
||||
# The identity endpoint to use for user and ec2 creation. If not specified,
|
||||
# default endpoint will be used. (only for create_ec2_credentials and
|
||||
# create_user)
|
||||
attribute :identity_endpoint, kind_of: String
|
|
@ -33,9 +33,12 @@ describe 'openstack-identity::openrc' do
|
|||
it 'contains auth environment variables' do
|
||||
[
|
||||
/^export OS_USERNAME=admin$/,
|
||||
/^export OS_TENANT_NAME=admin$/,
|
||||
/^export OS_USER_DOMAIN_NAME=default$/,
|
||||
/^export OS_PASSWORD=admin$/,
|
||||
%r{^export OS_AUTH_URL=http://127.0.0.1:5000/v2.0$},
|
||||
/^export OS_PROJECT_NAME=admin$/,
|
||||
/^export OS_PROJECT_DOMAIN_NAME=default$/,
|
||||
/^export OS_IDENTITY_API_VERSION=3$/,
|
||||
%r{^export OS_AUTH_URL=http://127.0.0.1:5000/v3$},
|
||||
/^export OS_REGION_NAME=RegionOne$/
|
||||
].each do |line|
|
||||
expect(chef_run).to render_file(file.name).with_content(line)
|
||||
|
@ -51,11 +54,19 @@ describe 'openstack-identity::openrc' do
|
|||
end
|
||||
|
||||
it 'contains overridden auth environment variables' do
|
||||
node.set['openstack']['identity']['admin_tenant_name'] = 'admin-tenant-name-override'
|
||||
node.set['openstack']['identity']['admin_user'] = 'admin-user-override'
|
||||
node.set['openstack']['identity']['admin_project'] =
|
||||
'admin-project-name-override'
|
||||
node.set['openstack']['identity']['admin_user'] =
|
||||
'identity_admin'
|
||||
node.set['openstack']['identity']['admin_domain_id'] =
|
||||
'admin-domain-override'
|
||||
node.set['openstack']['endpoints']['public']['identity']['uri'] =
|
||||
'https://public.identity:1234/v3'
|
||||
[
|
||||
/^export OS_USERNAME=admin-user-override$/,
|
||||
/^export OS_TENANT_NAME=admin-tenant-name-override$/
|
||||
/^export OS_USERNAME=identity_admin$/,
|
||||
/^export OS_PROJECT_NAME=admin-project-name-override$/,
|
||||
/^export OS_PASSWORD=identity_admin_pass$/,
|
||||
%r{^export OS_AUTH_URL=https://public.identity:1234/v3$}
|
||||
].each do |line|
|
||||
expect(chef_run).to render_file(file.name).with_content(line)
|
||||
end
|
||||
|
|
|
@ -1,748 +0,0 @@
|
|||
# encoding: UTF-8
|
||||
|
||||
require_relative 'spec_helper'
|
||||
|
||||
describe 'openstack-identity::default' do
|
||||
describe 'ubuntu' do
|
||||
let(:runner) { ChefSpec::SoloRunner.new(UBUNTU_OPTS) }
|
||||
let(:node) { runner.node }
|
||||
let(:chef_run) { runner.converge(described_recipe) }
|
||||
let(:events) { Chef::EventDispatch::Dispatcher.new }
|
||||
let(:cookbook_collection) { Chef::CookbookCollection.new([]) }
|
||||
let(:run_context) { Chef::RunContext.new(node, cookbook_collection, events) }
|
||||
|
||||
# needed to create the provider class OpenstackIdentityRegister by chef magic
|
||||
before { chef_run }
|
||||
|
||||
describe 'tenant_create' do
|
||||
let(:resource) do
|
||||
r = Chef::Resource::OpenstackIdentityRegister.new('tenant1',
|
||||
run_context)
|
||||
r.tenant_name('tenant1')
|
||||
r.tenant_description('tenant1 Tenant')
|
||||
r
|
||||
end
|
||||
let(:provider) do
|
||||
Chef::Provider::OpenstackIdentityRegister.new(resource, run_context)
|
||||
end
|
||||
|
||||
context 'when tenant does not already exist' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'tenant', 'name', 'tenant1')
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'tenant-create',
|
||||
'name' => 'tenant1',
|
||||
'description' => 'tenant1 Tenant',
|
||||
'enabled' => true)
|
||||
.and_return(true)
|
||||
end
|
||||
|
||||
it 'should create a tenant' do
|
||||
provider.run_action(:create_tenant)
|
||||
|
||||
expect(resource).to be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context 'when tenant does already exist' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'tenant', 'name', 'tenant1')
|
||||
.and_return('1234567890ABCDEFGH')
|
||||
end
|
||||
|
||||
it 'should not create a tenant' do
|
||||
provider.run_action(:create_tenant)
|
||||
|
||||
expect(resource).to_not be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context 'when keystone tenant command fails' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'tenant', 'name', 'tenant1')
|
||||
.and_raise('Error!')
|
||||
end
|
||||
|
||||
it 'should raise error' do
|
||||
expect { provider.run_action(:create_tenant) }.to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'service_create' do
|
||||
let(:resource) do
|
||||
r = Chef::Resource::OpenstackIdentityRegister.new('service1',
|
||||
run_context)
|
||||
r.service_type('compute')
|
||||
r.service_name('service1')
|
||||
r.service_description('service1 Service')
|
||||
r
|
||||
end
|
||||
let(:provider) do
|
||||
Chef::Provider::OpenstackIdentityRegister.new(resource, run_context)
|
||||
end
|
||||
|
||||
context 'catalog.backend is sql' do
|
||||
before do
|
||||
node.set['openstack']['identity']['catalog']['backend'] = 'sql'
|
||||
end
|
||||
|
||||
context 'when service does not already exist' do
|
||||
it 'should create a service' do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'service', 'type', 'compute')
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'service-create',
|
||||
'type' => 'compute',
|
||||
'name' => 'service1',
|
||||
'description' => 'service1 Service')
|
||||
.and_return(true)
|
||||
provider.run_action(:create_service)
|
||||
|
||||
expect(resource).to be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context 'when service does already exist' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'service', 'type', 'compute')
|
||||
.and_return('1234567890ABCDEFGH')
|
||||
allow(provider).to receive(:service_need_updated?)
|
||||
.with(resource)
|
||||
.and_return(false)
|
||||
end
|
||||
|
||||
it 'should not create a service' do
|
||||
provider.run_action(:create_service)
|
||||
expect(resource).to_not be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context 'when service does already exist and needs to be updated' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'service', 'type', 'compute')
|
||||
.and_return('1234567890ABCDEFGH')
|
||||
allow(provider).to receive(:service_need_updated?)
|
||||
.with(resource)
|
||||
.and_return(true)
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'service-delete',
|
||||
'' => '1234567890ABCDEFGH')
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'service-create',
|
||||
'type' => 'compute',
|
||||
'name' => 'service1',
|
||||
'description' => 'service1 Service')
|
||||
end
|
||||
|
||||
it 'should update the service' do
|
||||
provider.run_action(:create_service)
|
||||
expect(resource).to be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context '#service_need_updated?, when service exists and does not need to be updated' do
|
||||
before do
|
||||
output = ' | 1234567890ABCDEFGH | service1 | compute | service1 Service '
|
||||
output_array = [{ 'id' => '1234567890ABCDEFGH', 'name' => 'service1', 'type' => 'compute', 'description' => 'service1 Service' }]
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'service-list', {})
|
||||
.and_return(output)
|
||||
allow(provider).to receive(:prettytable_to_array)
|
||||
.with(output)
|
||||
.and_return(output_array)
|
||||
end
|
||||
|
||||
it 'service should not be updated' do
|
||||
expect(
|
||||
provider.send(:service_need_updated?, resource)
|
||||
).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context '#service_need_updated?, when service exists and needs to be updated' do
|
||||
before do
|
||||
output = ' | 1234567890ABCDEFGH | service11 | compute | service11 Service '
|
||||
output_array = [{ 'id' => '1234567890ABCDEFGH', 'name' => 'service11', 'type' => 'compute', 'description' => 'service11 Service' }]
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'service-list', {})
|
||||
.and_return(output)
|
||||
allow(provider).to receive(:prettytable_to_array)
|
||||
.with(output)
|
||||
.and_return(output_array)
|
||||
end
|
||||
it 'service should be updated' do
|
||||
expect(
|
||||
provider.send(:service_need_updated?, resource)
|
||||
).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when keystone service command fails' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'service', 'name', 'compute')
|
||||
.and_raise('Error!')
|
||||
end
|
||||
|
||||
it 'should raise error' do
|
||||
expect { provider.run_action(:create_service) }.to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context 'catalog.backend is templated' do
|
||||
before do
|
||||
node.set['openstack']['identity']['catalog']['backend'] = 'templated'
|
||||
end
|
||||
|
||||
it 'should not create a service if using a templated backend' do
|
||||
provider.run_action(:create_service)
|
||||
expect(resource).to_not be_updated
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'endpoint_create' do
|
||||
let(:resource) do
|
||||
r = Chef::Resource::OpenstackIdentityRegister.new('endpoint1',
|
||||
run_context)
|
||||
r.endpoint_region('Region One')
|
||||
r.service_type('compute')
|
||||
r.endpoint_publicurl('http://public')
|
||||
r.endpoint_internalurl('http://internal')
|
||||
r.endpoint_adminurl('http://admin')
|
||||
r
|
||||
end
|
||||
let(:provider) do
|
||||
Chef::Provider::OpenstackIdentityRegister.new(resource, run_context)
|
||||
end
|
||||
|
||||
context 'catalog.backend is sql' do
|
||||
before do
|
||||
node.set['openstack']['identity']['catalog']['backend'] = 'sql'
|
||||
end
|
||||
|
||||
context 'when endpoint does not already exist' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'service', 'type', 'compute')
|
||||
.and_return('1234567890ABCDEFGH')
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'endpoint', 'service_id', '1234567890ABCDEFGH')
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'endpoint-create',
|
||||
'region' => 'Region One',
|
||||
'service_id' => '1234567890ABCDEFGH',
|
||||
'publicurl' => 'http://public',
|
||||
'internalurl' => 'http://internal',
|
||||
'adminurl' => 'http://admin')
|
||||
end
|
||||
|
||||
it 'should create an endpoint' do
|
||||
provider.run_action(:create_endpoint)
|
||||
expect(resource).to be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context 'when endpoint does already exist' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'service', 'type', 'compute')
|
||||
.and_return('1234567890ABCDEFGH')
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'endpoint', 'service_id', '1234567890ABCDEFGH')
|
||||
.and_return('0987654321HGFEDCBA')
|
||||
allow(provider).to receive(:endpoint_need_updated?)
|
||||
.with(resource, 'service_id', '1234567890ABCDEFGH')
|
||||
.and_return(false)
|
||||
end
|
||||
|
||||
it 'should not update an endpoint' do
|
||||
provider.run_action(:create_endpoint)
|
||||
expect(resource).not_to be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context 'when endpoint does already exist and need to be updated' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'service', 'type', 'compute')
|
||||
.and_return('1234567890ABCDEFGH')
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'endpoint', 'service_id', '1234567890ABCDEFGH')
|
||||
.and_return('0987654321HGFEDCBA')
|
||||
allow(provider).to receive(:endpoint_need_updated?)
|
||||
.with(resource, 'service_id', '1234567890ABCDEFGH')
|
||||
.and_return(true)
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'endpoint-delete',
|
||||
'' => '0987654321HGFEDCBA')
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'endpoint-create',
|
||||
'region' => 'Region One',
|
||||
'service_id' => '1234567890ABCDEFGH',
|
||||
'publicurl' => 'http://public',
|
||||
'internalurl' => 'http://internal',
|
||||
'adminurl' => 'http://admin')
|
||||
end
|
||||
|
||||
it 'should update an endpoint' do
|
||||
provider.run_action(:create_endpoint)
|
||||
expect(resource).to be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context '#identity_uuid, when service id for Region One already exist' do
|
||||
before do
|
||||
output = ' | 000d9c447d124754a197fc612f9d63d7 | Region One | http://public | http://internal | http://admin | f9511a66e0484f3dbd1584065e8bab1c '
|
||||
output_array = [{ 'id' => '000d9c447d124754a197fc612f9d63d7', 'region' => 'Region One', 'publicurl' => 'http://public', 'internalurl' => 'http://internal', 'adminurl' => 'http://admin', 'service_id' => 'f9511a66e0484f3dbd1584065e8bab1c' }]
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'endpoint-list', {})
|
||||
.and_return(output)
|
||||
allow(provider).to receive(:prettytable_to_array)
|
||||
.with(output)
|
||||
.and_return(output_array)
|
||||
end
|
||||
|
||||
it 'endpoint uuid should be returned' do
|
||||
expect(
|
||||
provider.send(:identity_uuid, resource, 'endpoint',
|
||||
'service_id', 'f9511a66e0484f3dbd1584065e8bab1c')
|
||||
).to eq('000d9c447d124754a197fc612f9d63d7')
|
||||
end
|
||||
end
|
||||
|
||||
context '#identity_uuid, when service id for Region Two does not exist' do
|
||||
before do
|
||||
output = ' | 000d9c447d124754a197fc612f9d63d7 | Region Two | http://public | http://internal | http://admin | f9511a66e0484f3dbd1584065e8bab1c '
|
||||
output_array = [{ 'id' => '000d9c447d124754a197fc612f9d63d7', 'region' => 'Region Two', 'publicurl' => 'http://public', 'internalurl' => 'http://internal', 'adminurl' => 'http://admin', 'service_id' => 'f9511a66e0484f3dbd1584065e8bab1c' }]
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'endpoint-list', {})
|
||||
.and_return(output)
|
||||
allow(provider).to receive(:prettytable_to_array)
|
||||
.with(output)
|
||||
.and_return(output_array)
|
||||
end
|
||||
|
||||
it 'no endpoint uuid should be returned' do
|
||||
expect(
|
||||
provider.send(:identity_uuid, resource, 'endpoint',
|
||||
'service_id', 'f9511a66e0484f3dbd1584065e8bab1c')
|
||||
).to eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
context '#search_uuid' do
|
||||
it 'required_hash only has key id' do
|
||||
output_array = [{ 'id' => '000d9c447d124754a197fc612f9d63d7', 'region' => 'Region Two', 'publicurl' => 'http://public' }]
|
||||
expect(
|
||||
provider.send(:search_uuid, output_array, 'id',
|
||||
'id' => '000d9c447d124754a197fc612f9d63d7')
|
||||
).to eq('000d9c447d124754a197fc612f9d63d7')
|
||||
expect(
|
||||
provider.send(:search_uuid, output_array, 'id', 'id' => 'abc')
|
||||
).to eq(nil)
|
||||
end
|
||||
|
||||
it 'required_hash has key id and region' do
|
||||
output_array = [{ 'id' => '000d9c447d124754a197fc612f9d63d7', 'region' => 'Region Two', 'publicurl' => 'http://public' }]
|
||||
expect(
|
||||
provider.send(:search_uuid, output_array, 'id',
|
||||
'id' => '000d9c447d124754a197fc612f9d63d7',
|
||||
'region' => 'Region Two')
|
||||
).to eq('000d9c447d124754a197fc612f9d63d7')
|
||||
expect(
|
||||
provider.send(:search_uuid, output_array, 'id',
|
||||
'id' => '000d9c447d124754a197fc612f9d63d7',
|
||||
'region' => 'Region One')
|
||||
).to eq(nil)
|
||||
expect(
|
||||
provider.send(:search_uuid, output_array, 'id',
|
||||
'id' => '000d9c447d124754a197fc612f9d63d7',
|
||||
'region' => 'Region Two', 'key' => 'value')
|
||||
).to eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
context '#endpoint_need_updated?, when endpoint exist and not need to be updated' do
|
||||
before do
|
||||
output = ' | 000d9c447d124754a197fc612f9d63d7 | Region One | http://public | http://internal | http://admin | f9511a66e0484f3dbd1584065e8bab1c '
|
||||
output_array = [{ 'id' => '000d9c447d124754a197fc612f9d63d7', 'region' => 'Region One', 'publicurl' => 'http://public', 'internalurl' => 'http://internal', 'adminurl' => 'http://admin', 'service_id' => 'f9511a66e0484f3dbd1584065e8bab1c' }]
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'endpoint-list', {})
|
||||
.and_return(output)
|
||||
allow(provider).to receive(:prettytable_to_array)
|
||||
.with(output)
|
||||
.and_return(output_array)
|
||||
end
|
||||
|
||||
it 'endpoint should not be updated' do
|
||||
expect(
|
||||
provider.send(:endpoint_need_updated?, resource,
|
||||
'service_id', 'f9511a66e0484f3dbd1584065e8bab1c')
|
||||
).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context '#endpoint_need_updated?, when endpoint exist and need to be updated' do
|
||||
before do
|
||||
output = ' | 000d9c447d124754a197fc612f9d63d7 | Region One | https://public | https://internal | https://admin | f9511a66e0484f3dbd1584065e8bab1c '
|
||||
output_array = [{ 'id' => '000d9c447d124754a197fc612f9d63d7', 'region' => 'Region One', 'publicurl' => 'https://public', 'internalurl' => 'https://internal', 'adminurl' => 'https://admin', 'service_id' => 'f9511a66e0484f3dbd1584065e8bab1c' }]
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'endpoint-list', {})
|
||||
.and_return(output)
|
||||
allow(provider).to receive(:prettytable_to_array)
|
||||
.with(output)
|
||||
.and_return(output_array)
|
||||
end
|
||||
|
||||
it 'endpoint should be updated' do
|
||||
expect(
|
||||
provider.send(:endpoint_need_updated?, resource,
|
||||
'service_id', 'f9511a66e0484f3dbd1584065e8bab1c')
|
||||
).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'catalog.backend is templated' do
|
||||
before do
|
||||
node.set['openstack']['identity']['catalog']['backend'] = 'templated'
|
||||
end
|
||||
|
||||
it 'should not create an endpoint' do
|
||||
provider.run_action(:create_endpoint)
|
||||
expect(resource).to_not be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context 'when keystone endpoint command fails' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'service', 'type', 'compute')
|
||||
.and_raise('Error!')
|
||||
end
|
||||
|
||||
it 'should raise error' do
|
||||
expect { provider.run_action(:create_endpoint) }.to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'role create' do
|
||||
let(:resource) do
|
||||
r = Chef::Resource::OpenstackIdentityRegister.new('role1', run_context)
|
||||
r.role_name('role1')
|
||||
r
|
||||
end
|
||||
let(:provider) do
|
||||
Chef::Provider::OpenstackIdentityRegister.new(resource, run_context)
|
||||
end
|
||||
|
||||
context 'when role does not already exist' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'role', 'name', 'role1')
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'role-create',
|
||||
'name' => 'role1')
|
||||
end
|
||||
|
||||
it 'should create a role' do
|
||||
provider.run_action(:create_role)
|
||||
expect(resource).to be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context 'when role already exist' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'role', 'name', 'role1')
|
||||
.and_return('1234567890ABCDEFGH')
|
||||
end
|
||||
|
||||
it 'should not create a role' do
|
||||
provider.run_action(:create_role)
|
||||
expect(resource).to_not be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context 'when keystone role command fails' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'role', 'name', 'role1')
|
||||
.and_raise('Error!')
|
||||
end
|
||||
|
||||
it 'should raise error' do
|
||||
expect { provider.run_action(:create_role) }.to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'user create' do
|
||||
let(:resource) do
|
||||
r = Chef::Resource::OpenstackIdentityRegister.new('user1', run_context)
|
||||
r.user_name('user1')
|
||||
r.tenant_name('tenant1')
|
||||
r.user_pass('password')
|
||||
r
|
||||
end
|
||||
let(:provider) do
|
||||
Chef::Provider::OpenstackIdentityRegister.new(resource, run_context)
|
||||
end
|
||||
|
||||
context 'when user does not already exist' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'user-list')
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'user-create',
|
||||
'name' => 'user1',
|
||||
'tenant' => 'tenant1',
|
||||
'pass' => 'password',
|
||||
'enabled' => true)
|
||||
allow(provider).to receive(:prettytable_to_array)
|
||||
.and_return([])
|
||||
end
|
||||
|
||||
it 'should create a user' do
|
||||
provider.run_action(:create_user)
|
||||
expect(resource).to be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user already exist with same password' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'tenant', 'name', 'tenant1')
|
||||
.and_return('1234567890ABCDEFGH')
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'user-list')
|
||||
allow(provider).to receive(:prettytable_to_array)
|
||||
.and_return([{ 'name' => 'user1' }])
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'user', 'name', 'user1')
|
||||
.and_return('HGFEDCBA0987654321')
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'token-get', {}, 'user')
|
||||
end
|
||||
|
||||
it 'should not create a user' do
|
||||
provider.run_action(:create_user)
|
||||
expect(resource).to_not be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user already exist and changed password' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'tenant', 'name', 'tenant1')
|
||||
.and_return('1234567890ABCDEFGH')
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'user-list')
|
||||
allow(provider).to receive(:prettytable_to_array)
|
||||
.and_return([{ 'name' => 'user1' }])
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'user', 'name', 'user1')
|
||||
.and_return('HGFEDCBA0987654321')
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'token-get', {}, 'user')
|
||||
.and_raise('Error!')
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'user-password-update',
|
||||
'pass' => 'password',
|
||||
'' => 'user1')
|
||||
end
|
||||
|
||||
it 'should update user password' do
|
||||
provider.run_action(:create_user)
|
||||
expect(resource).to be_updated
|
||||
end
|
||||
end
|
||||
|
||||
describe '#identity_command' do
|
||||
it 'should handle false values and long descriptions' do
|
||||
allow(provider).to receive(:shell_out)
|
||||
.with(['keystone', '--insecure', 'user-create', '--enabled',
|
||||
'false', '--description', 'more than one word'],
|
||||
env: {
|
||||
'OS_SERVICE_ENDPOINT' => nil,
|
||||
'OS_SERVICE_TOKEN' => nil })
|
||||
.and_return double('shell_out', exitstatus: 0, stdout: 'good')
|
||||
|
||||
expect(
|
||||
provider.send(:identity_command, resource, 'user-create',
|
||||
'enabled' => false,
|
||||
'description' => 'more than one word')
|
||||
).to eq('good')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when keystone user command fails' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'tenant', 'name', 'tenant1')
|
||||
.and_raise('Error!')
|
||||
end
|
||||
|
||||
it 'should raise error' do
|
||||
expect { provider.run_action(:create_user) }.to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'role grant' do
|
||||
let(:resource) do
|
||||
r = Chef::Resource::OpenstackIdentityRegister.new('grant1', run_context)
|
||||
r.user_name('user1')
|
||||
r.tenant_name('tenant1')
|
||||
r.role_name('role1')
|
||||
r
|
||||
end
|
||||
let(:provider) do
|
||||
Chef::Provider::OpenstackIdentityRegister.new(resource, run_context)
|
||||
end
|
||||
|
||||
context 'when role has not already been granted' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'role', 'name', 'role1')
|
||||
.and_return('ABC1234567890DEF')
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'user-role', 'name', 'role1',
|
||||
'tenant' => 'tenant1',
|
||||
'user' => 'user1')
|
||||
.and_return('ABCD1234567890EFGH')
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'user-role-add',
|
||||
'tenant' => 'tenant1',
|
||||
'role-id' => 'ABC1234567890DEF',
|
||||
'user' => 'user1')
|
||||
end
|
||||
|
||||
it 'should grant a role' do
|
||||
provider.run_action(:grant_role)
|
||||
expect(resource).to be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context 'when role has already been granted' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'role', 'name', 'role1')
|
||||
.and_return('ABC1234567890DEF')
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'user-role', 'name', 'role1',
|
||||
'tenant' => 'tenant1',
|
||||
'user' => 'user1')
|
||||
.and_return('ABC1234567890DEF')
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'user-role-add',
|
||||
'tenant' => 'tenant1',
|
||||
'role-id' => 'ABC1234567890DEF',
|
||||
'user' => 'user1')
|
||||
end
|
||||
|
||||
it 'should not grant a role' do
|
||||
provider.run_action(:grant_role)
|
||||
expect(resource).to_not be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context 'when keystone grant command fails' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'tenant', 'name', 'tenant1')
|
||||
.and_raise('Error!')
|
||||
end
|
||||
|
||||
it 'should raise error' do
|
||||
expect { provider.run_action(:grant_role) }.to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'ec2_credentials create' do
|
||||
let(:resource) do
|
||||
r = Chef::Resource::OpenstackIdentityRegister.new('ec2', run_context)
|
||||
r.user_name('user1')
|
||||
r.tenant_name('tenant1')
|
||||
r.admin_tenant_name('admintenant1')
|
||||
r.admin_user('adminuser1')
|
||||
r.admin_pass('password')
|
||||
r.identity_endpoint('http://admin')
|
||||
r
|
||||
end
|
||||
let(:provider) do
|
||||
Chef::Provider::OpenstackIdentityRegister.new(resource, run_context)
|
||||
end
|
||||
|
||||
context 'when ec2 creds have not already been created' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'tenant', 'name', 'tenant1')
|
||||
.and_return('1234567890ABCDEFGH')
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'user', 'name', 'user1',
|
||||
'tenant-id' => '1234567890ABCDEFGH')
|
||||
.and_return('HGFEDCBA0987654321')
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'ec2-credentials', 'tenant', 'tenant1',
|
||||
{ 'user-id' => 'HGFEDCBA0987654321' }, 'access')
|
||||
allow(provider).to receive(:identity_command)
|
||||
.with(resource, 'ec2-credentials-create',
|
||||
{ 'user-id' => 'HGFEDCBA0987654321',
|
||||
'tenant-id' => '1234567890ABCDEFGH' },
|
||||
'admin')
|
||||
allow(provider).to receive(:prettytable_to_array)
|
||||
.and_return([{ 'access' => 'access', 'secret' => 'secret' }])
|
||||
end
|
||||
|
||||
it 'should grant ec2 creds' do
|
||||
provider.run_action(:create_ec2_credentials)
|
||||
expect(resource).to be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context 'when ec2 creds have not already been created' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'tenant', 'name', 'tenant1')
|
||||
.and_return('1234567890ABCDEFGH')
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'user', 'name', 'user1',
|
||||
'tenant-id' => '1234567890ABCDEFGH')
|
||||
.and_return('HGFEDCBA0987654321')
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'ec2-credentials', 'tenant', 'tenant1',
|
||||
{ 'user-id' => 'HGFEDCBA0987654321' }, 'access')
|
||||
.and_return('ABC1234567890DEF')
|
||||
end
|
||||
|
||||
it 'should grant ec2 creds if they already exist' do
|
||||
provider.run_action(:create_ec2_credentials)
|
||||
expect(resource).to_not be_updated
|
||||
end
|
||||
end
|
||||
|
||||
context 'when keystone user command fails' do
|
||||
before do
|
||||
allow(provider).to receive(:identity_uuid)
|
||||
.with(resource, 'tenant', 'name', 'tenant1')
|
||||
.and_raise('Error!')
|
||||
end
|
||||
|
||||
it 'should raise error' do
|
||||
expect { provider.run_action(:create_ec2_credentials) }.to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -8,282 +8,143 @@ describe 'openstack-identity::registration' do
|
|||
let(:node) { runner.node }
|
||||
let(:runner) { ChefSpec::SoloRunner.new(UBUNTU_OPTS) }
|
||||
let(:chef_run) { runner.converge(described_recipe) }
|
||||
let(:node_add_user) do
|
||||
node.set_unless['openstack']['identity']['users'] = {
|
||||
'user1' => {
|
||||
'default_tenant' => 'default_tenant1',
|
||||
'password' => 'secret1',
|
||||
'roles' => {
|
||||
'role1' => ['role_tenant1'],
|
||||
'role2' => ['default_tenant1']
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
include_context 'identity_stubs'
|
||||
|
||||
describe 'tenant registration' do
|
||||
context 'default tenants' do
|
||||
['admin'].each do |tenant_name|
|
||||
it "registers the #{tenant_name} tenant" do
|
||||
expect(chef_run).to create_tenant_openstack_identity_register(
|
||||
"Register '#{tenant_name}' Tenant"
|
||||
).with(
|
||||
auth_uri: 'http://127.0.0.1:35357/v2.0',
|
||||
bootstrap_token: 'bootstrap-token',
|
||||
tenant_name: tenant_name,
|
||||
tenant_description: "#{tenant_name} Tenant"
|
||||
)
|
||||
end
|
||||
connection_params = {
|
||||
openstack_auth_url: 'http://127.0.0.1:35357/v3/auth/tokens',
|
||||
openstack_username: 'admin',
|
||||
openstack_api_key: 'admin',
|
||||
openstack_project_name: 'admin',
|
||||
openstack_domain_name: 'default'
|
||||
}
|
||||
service_name = 'keystone'
|
||||
service_user = 'admin'
|
||||
region = 'RegionOne'
|
||||
project_name = 'admin'
|
||||
role_name = 'admin'
|
||||
password = 'admin'
|
||||
domain_name = 'default'
|
||||
admin_url = 'http://127.0.0.1:35357/v3'
|
||||
public_url = 'http://127.0.0.1:5000/v3'
|
||||
internal_url = 'http://127.0.0.1:5000/v3'
|
||||
|
||||
describe 'keystone bootstrap' do
|
||||
context 'default values' do
|
||||
it 'bootstrap with keystone-manage' do
|
||||
expect(chef_run).to run_execute('bootstrap_keystone'
|
||||
).with(command: "keystone-manage bootstrap \\
|
||||
--bootstrap-password #{password} \\
|
||||
--bootstrap-username #{service_user} \\
|
||||
--bootstrap-project-name #{project_name} \\
|
||||
--bootstrap-role-name #{role_name} \\
|
||||
--bootstrap-service-name #{service_name} \\
|
||||
--bootstrap-region-id #{region} \\
|
||||
--bootstrap-admin-url #{admin_url} \\
|
||||
--bootstrap-public-url #{public_url} \\
|
||||
--bootstrap-internal-url #{internal_url}")
|
||||
end
|
||||
end
|
||||
|
||||
context 'configured tenants from users attribute' do
|
||||
before { node_add_user }
|
||||
['default_tenant1', 'role_tenant1'].each do |tenant_name|
|
||||
it "registers the #{tenant_name} tenant" do
|
||||
expect(chef_run).to create_tenant_openstack_identity_register(
|
||||
"Register '#{tenant_name}' Tenant"
|
||||
).with(
|
||||
auth_uri: 'http://127.0.0.1:35357/v2.0',
|
||||
bootstrap_token: 'bootstrap-token',
|
||||
tenant_name: tenant_name,
|
||||
tenant_description: "#{tenant_name} Tenant"
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'role registration' do
|
||||
context 'default roles' do
|
||||
%w(admin service).each do |role_name|
|
||||
it "registers the #{role_name} role" do
|
||||
expect(chef_run).to create_role_openstack_identity_register(
|
||||
"Register '#{role_name}' Role"
|
||||
).with(
|
||||
auth_uri: 'http://127.0.0.1:35357/v2.0',
|
||||
bootstrap_token: 'bootstrap-token',
|
||||
role_name: role_name
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'configured roles derived from users attribute' do
|
||||
before { node_add_user }
|
||||
|
||||
['role1', 'role2'].each do |role_name|
|
||||
it "registers the #{role_name} role" do
|
||||
expect(chef_run).to create_role_openstack_identity_register(
|
||||
"Register '#{role_name}' Role"
|
||||
).with(
|
||||
auth_uri: 'http://127.0.0.1:35357/v2.0',
|
||||
bootstrap_token: 'bootstrap-token',
|
||||
role_name: role_name
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'user registration' do
|
||||
context 'default users' do
|
||||
user_admin = [
|
||||
'admin', 'admin',
|
||||
['admin', 'service']
|
||||
]
|
||||
|
||||
[user_admin].each do |user, tenant, roles|
|
||||
context "#{user} user" do
|
||||
it "registers the #{user} user" do
|
||||
expect(chef_run).to create_user_openstack_identity_register(
|
||||
"Register '#{user}' User"
|
||||
).with(
|
||||
auth_uri: 'http://127.0.0.1:35357/v2.0',
|
||||
bootstrap_token: 'bootstrap-token',
|
||||
user_name: user,
|
||||
user_pass: 'admin',
|
||||
tenant_name: tenant
|
||||
)
|
||||
end
|
||||
|
||||
roles.each do |role|
|
||||
it "grants '#{role}' role to '#{user}' user in 'admin' tenant" do
|
||||
expect(chef_run).to grant_role_openstack_identity_register(
|
||||
"Grant '#{role}' Role to '#{user}' User in 'admin' Tenant"
|
||||
).with(
|
||||
auth_uri: 'http://127.0.0.1:35357/v2.0',
|
||||
bootstrap_token: 'bootstrap-token',
|
||||
user_name: user,
|
||||
role_name: role,
|
||||
tenant_name: 'admin',
|
||||
action: [:grant_role]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
it 'registers the admin user for ec2' do
|
||||
expect(chef_run).to create_ec2_credentials_openstack_identity_register(
|
||||
"Create EC2 credentials for 'admin' user"
|
||||
).with(
|
||||
auth_uri: 'http://127.0.0.1:35357/v2.0',
|
||||
bootstrap_token: 'bootstrap-token',
|
||||
user_name: user,
|
||||
tenant_name: tenant,
|
||||
admin_tenant_name: 'admin',
|
||||
admin_user: 'admin',
|
||||
admin_pass: 'admin'
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'configured user' do
|
||||
before { node_add_user }
|
||||
|
||||
it 'registers the user1 user' do
|
||||
expect(chef_run).to create_user_openstack_identity_register(
|
||||
"Register 'user1' User"
|
||||
it "registers #{domain_name} domain" do
|
||||
expect(chef_run).to create_openstack_domain(
|
||||
domain_name
|
||||
).with(
|
||||
auth_uri: 'http://127.0.0.1:35357/v2.0',
|
||||
bootstrap_token: 'bootstrap-token',
|
||||
user_name: 'user1',
|
||||
user_pass: 'secret1',
|
||||
tenant_name: 'default_tenant1'
|
||||
connection_params: connection_params
|
||||
)
|
||||
end
|
||||
|
||||
it "grants 'role1' role to 'user1' user in 'role_tenant1' tenant" do
|
||||
expect(chef_run).to grant_role_openstack_identity_register(
|
||||
"Grant 'role1' Role to 'user1' User in 'role_tenant1' Tenant"
|
||||
it "grants #{service_user} user to #{domain_name} domain" do
|
||||
expect(chef_run).to grant_domain_openstack_user(
|
||||
service_user
|
||||
).with(
|
||||
auth_uri: 'http://127.0.0.1:35357/v2.0',
|
||||
bootstrap_token: 'bootstrap-token',
|
||||
user_name: 'user1',
|
||||
role_name: 'role1',
|
||||
tenant_name: 'role_tenant1'
|
||||
domain_name: domain_name,
|
||||
role_name: role_name,
|
||||
connection_params: connection_params
|
||||
)
|
||||
end
|
||||
|
||||
it 'registers the user1 user for ec2' do
|
||||
expect(chef_run).to create_ec2_credentials_openstack_identity_register(
|
||||
"Create EC2 credentials for 'user1' user"
|
||||
it 'create service role' do
|
||||
expect(chef_run).to create_openstack_role(
|
||||
'service'
|
||||
).with(
|
||||
auth_uri: 'http://127.0.0.1:35357/v2.0',
|
||||
bootstrap_token: 'bootstrap-token',
|
||||
user_name: 'user1',
|
||||
tenant_name: 'default_tenant1',
|
||||
admin_tenant_name: 'admin',
|
||||
admin_user: 'admin',
|
||||
admin_pass: 'admin'
|
||||
connection_params: connection_params
|
||||
)
|
||||
end
|
||||
|
||||
it 'create service role' do
|
||||
expect(chef_run).to create_openstack_role(
|
||||
'_member_'
|
||||
).with(
|
||||
connection_params: connection_params
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'service registration' do
|
||||
context 'with templated catalog backend' do
|
||||
context 'all different values' do
|
||||
connection_params_other = {
|
||||
openstack_auth_url: 'https://admin.identity:1234/v3/auth/tokens',
|
||||
openstack_username: 'identity_admin',
|
||||
openstack_api_key: 'identity_admin_pass',
|
||||
openstack_project_name: 'admin_project',
|
||||
openstack_domain_name: 'identity_domain'
|
||||
}
|
||||
before do
|
||||
node.set['openstack']['identity']['catalog']['backend'] = 'templated'
|
||||
node.set['openstack']['endpoints']['admin']['identity']['uri'] =
|
||||
'https://admin.identity:1234/v3'
|
||||
node.set['openstack']['endpoints']['internal']['identity']['uri'] =
|
||||
'https://internal.identity:5678/v3'
|
||||
node.set['openstack']['endpoints']['public']['identity']['uri'] =
|
||||
'https://public.identity:9753/v3'
|
||||
node.set['openstack']['region'] = 'otherRegion'
|
||||
node.set['openstack']['identity']['admin_project'] = 'admin_project'
|
||||
node.set['openstack']['identity']['admin_user'] = 'identity_admin'
|
||||
node.set['openstack']['identity']['admin_role'] = 'identity_role'
|
||||
node.set['openstack']['identity']['admin_domain_name'] =
|
||||
'identity_domain'
|
||||
end
|
||||
|
||||
it 'does not register identity service' do
|
||||
expect(chef_run).to_not create_service_openstack_identity_register(
|
||||
'Register Identity Service'
|
||||
)
|
||||
it 'bootstrap with keystone-manage' do
|
||||
expect(chef_run).to run_execute('bootstrap_keystone'
|
||||
).with(command: "keystone-manage bootstrap \\
|
||||
--bootstrap-password identity_admin_pass \\
|
||||
--bootstrap-username identity_admin \\
|
||||
--bootstrap-project-name admin_project \\
|
||||
--bootstrap-role-name identity_role \\
|
||||
--bootstrap-service-name #{service_name} \\
|
||||
--bootstrap-region-id otherRegion \\
|
||||
--bootstrap-admin-url https://admin.identity:1234/v3 \\
|
||||
--bootstrap-public-url https://public.identity:9753/v3 \\
|
||||
--bootstrap-internal-url https://internal.identity:5678/v3")
|
||||
end
|
||||
end
|
||||
|
||||
context 'with sql catalog backend' do
|
||||
before do
|
||||
node.set['openstack']['identity']['catalog']['backend'] = 'sql'
|
||||
end
|
||||
it 'registers identity service' do
|
||||
expect(chef_run).to create_service_openstack_identity_register(
|
||||
'Register Identity Service'
|
||||
it 'registers identity_domain domain' do
|
||||
expect(chef_run).to create_openstack_domain(
|
||||
'identity_domain'
|
||||
).with(
|
||||
service_name: 'keystone',
|
||||
service_type: 'identity',
|
||||
service_description: 'Keystone Identity Service'
|
||||
connection_params: connection_params_other
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'endpoint registration' do
|
||||
context 'with templated catalog backend' do
|
||||
before do
|
||||
node.set['openstack']['identity']['catalog']['backend'] = 'templated'
|
||||
end
|
||||
|
||||
it 'does not register identity endpoint' do
|
||||
expect(chef_run).to_not create_endpoint_openstack_identity_register(
|
||||
'Register Identity Endpoint'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with sql catalog backend' do
|
||||
before do
|
||||
node.set['openstack']['identity']['catalog']['backend'] = 'sql'
|
||||
end
|
||||
it 'registers identity endpoints' do
|
||||
expect(chef_run).to create_endpoint_openstack_identity_register(
|
||||
'Register Identity Endpoint'
|
||||
it 'grants identity_admin user to identity_domain domain' do
|
||||
expect(chef_run).to grant_domain_openstack_user(
|
||||
'identity_admin'
|
||||
).with(
|
||||
auth_uri: 'http://127.0.0.1:35357/v2.0',
|
||||
bootstrap_token: 'bootstrap-token',
|
||||
service_type: 'identity',
|
||||
endpoint_region: 'RegionOne',
|
||||
endpoint_adminurl: 'http://127.0.0.1:35357/v2.0',
|
||||
endpoint_internalurl: 'http://127.0.0.1:5000/v2.0',
|
||||
endpoint_publicurl: 'http://127.0.0.1:5000/v2.0'
|
||||
domain_name: 'identity_domain',
|
||||
role_name: 'identity_role',
|
||||
connection_params: connection_params_other
|
||||
)
|
||||
end
|
||||
|
||||
it 'overrides identity endpoint region' do
|
||||
node.set['openstack']['identity']['region'] = 'identityRegion'
|
||||
expect(chef_run).to create_endpoint_openstack_identity_register(
|
||||
'Register Identity Endpoint'
|
||||
).with(endpoint_region: 'identityRegion')
|
||||
end
|
||||
|
||||
it 'overrides identity endpoints' do
|
||||
node.set['openstack']['endpoints']['admin']['identity']['host'] = '127.0.0.2'
|
||||
node.set['openstack']['endpoints']['admin']['identity']['port'] = '5002'
|
||||
node.set['openstack']['endpoints']['admin']['identity']['path'] = '/v2.2'
|
||||
node.set['openstack']['endpoints']['internal']['identity']['host'] = '127.0.0.3'
|
||||
node.set['openstack']['endpoints']['internal']['identity']['port'] = '5003'
|
||||
node.set['openstack']['endpoints']['internal']['identity']['path'] = '/v2.3'
|
||||
node.set['openstack']['endpoints']['public']['identity']['host'] = '127.0.0.4'
|
||||
node.set['openstack']['endpoints']['public']['identity']['port'] = '5004'
|
||||
node.set['openstack']['endpoints']['public']['identity']['path'] = '/v2.4'
|
||||
expect(chef_run).to create_endpoint_openstack_identity_register(
|
||||
'Register Identity Endpoint'
|
||||
it 'create service role' do
|
||||
expect(chef_run).to create_openstack_role(
|
||||
'service'
|
||||
).with(
|
||||
endpoint_adminurl: 'http://127.0.0.2:5002/v2.2',
|
||||
endpoint_internalurl: 'http://127.0.0.3:5003/v2.3',
|
||||
endpoint_publicurl: 'http://127.0.0.4:5004/v2.4'
|
||||
connection_params: connection_params_other
|
||||
)
|
||||
end
|
||||
|
||||
it 'register endpoint with all different URLs' do
|
||||
public_url = 'https://public.host:789/public_path'
|
||||
internal_url = 'http://internal.host:456/internal_path'
|
||||
admin_url = 'https://admin.host:123/admin_path'
|
||||
node.set['openstack']['endpoints']['public']['identity']['uri'] = public_url
|
||||
node.set['openstack']['endpoints']['internal']['identity']['uri'] = internal_url
|
||||
node.set['openstack']['endpoints']['admin']['identity']['uri'] = admin_url
|
||||
|
||||
expect(chef_run).to create_endpoint_openstack_identity_register(
|
||||
'Register Identity Endpoint'
|
||||
it 'create service role' do
|
||||
expect(chef_run).to create_openstack_role(
|
||||
'_member_'
|
||||
).with(
|
||||
endpoint_adminurl: admin_url,
|
||||
endpoint_internalurl: internal_url,
|
||||
endpoint_publicurl: public_url
|
||||
connection_params: connection_params_other
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -135,11 +135,6 @@ describe 'openstack-identity::server-apache' do
|
|||
end
|
||||
|
||||
describe '[DEFAULT] section' do
|
||||
it 'has admin token' do
|
||||
r = line_regexp('admin_token = bootstrap-token')
|
||||
expect(chef_run).to render_config_file(path).with_section_content('DEFAULT', r)
|
||||
end
|
||||
|
||||
describe 'syslog configuration' do
|
||||
log_file = %r{^log_dir = /var/log/keystone$}
|
||||
log_conf = %r{^log_config_append = /\w+}
|
||||
|
|
|
@ -12,7 +12,7 @@ REDHAT_OPTS = {
|
|||
}.freeze
|
||||
UBUNTU_OPTS = {
|
||||
platform: 'ubuntu',
|
||||
version: '14.04',
|
||||
version: '16.04',
|
||||
log_level: LOG_LEVEL
|
||||
}.freeze
|
||||
|
||||
|
@ -47,8 +47,8 @@ shared_context 'identity_stubs' do
|
|||
.with('user', 'user1')
|
||||
.and_return('secret1')
|
||||
allow_any_instance_of(Chef::Recipe).to receive(:get_password)
|
||||
.with('token', 'openstack_identity_bootstrap_token')
|
||||
.and_return('bootstrap-token')
|
||||
.with('user', 'identity_admin')
|
||||
.and_return('identity_admin_pass')
|
||||
stub_command('/usr/sbin/apache2 -t')
|
||||
allow_any_instance_of(Chef::Recipe).to receive(:search_for)
|
||||
.with('os-identity').and_return(
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
|
||||
# COMMON OPENSTACK ENVS
|
||||
export OS_USERNAME=<%= @user %>
|
||||
export OS_USER_DOMAIN_NAME=<%= @user_domain_name %>
|
||||
export OS_PASSWORD=<%= @password %>
|
||||
export OS_TENANT_NAME=<%= @tenant %>
|
||||
export OS_PROJECT_NAME=<%= @project %>
|
||||
export OS_PROJECT_DOMAIN_NAME=<%= @project_domain_name %>
|
||||
export OS_IDENTITY_API_VERSION=<%= @api_version %>
|
||||
export OS_AUTH_URL=<%= @identity_endpoint %>
|
||||
export OS_REGION_NAME=<%= node['openstack']['region'] %>
|
||||
|
||||
|
|
Loading…
Reference in New Issue