Add new cli method

Add new method for calling openstack clis
Add new method for getting uuid via cli
These methods are based upon the identity register provider ones
Add tests
Related change in network: I89dd47c802a544bdd998059b36884cb10f628223

Change-Id: I2b2f1d94dbd67550ad3a352c2205a532173f6065
Implements: blueprint neutron-icehouse-default-changes
This commit is contained in:
Mark Vanderwiel 2014-04-08 21:46:30 -05:00
parent 10bab59e86
commit f121e39060
5 changed files with 199 additions and 1 deletions

3
CHANGELOG.md Normal file → Executable file

@ -1,6 +1,9 @@
# CHANGELOG for cookbook-openstack-common
This file is used to list changes made in each version of cookbook-openstack-common.
## 9.1.1
* Add new library method for making cli calls and one for getting uuids
## 9.1.0
* Added python-openstackclient support

1
README.md Normal file → Executable file

@ -94,6 +94,7 @@ Libraries
This cookbook exposes a set of default library routines:
* `cli` -- Used to call openstack CLIs
* `endpoint` -- Used to return a `::URI` object representing the named OpenStack endpoint
* `endpoints` -- Useful for operating on all OpenStack endpoints
* `db` -- Returns a Hash of information about a named OpenStack database

90
libraries/cli.rb Executable file

@ -0,0 +1,90 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# library:: cli
#
# Copyright 2014, IBM Corp.
#
# 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
require 'uri'
module ::Openstack # rubocop:disable Documentation
# return an environment suitable for calling openstack commands.
#
# @param [String] user name
# @param [String] tenant name
# @return [Hash] environment
def openstack_command_env(name, tenant)
identity_admin_endpoint = endpoint 'identity-admin'
auth_uri = ::URI.decode identity_admin_endpoint.to_s
pass = get_password 'user', name
{
'OS_USERNAME' => name,
'OS_PASSWORD' => pass,
'OS_TENANT_NAME' => tenant,
'OS_AUTH_URL' => auth_uri
}
end
# return stdout from calling an openstack command.
#
# @param [String] command to run
# @param [String] command options
# @param [Hash] environment to use
# @param [Hash] optional command argument/values pairs
# @return [String] stdout or fail
#
# TODO: this was taken from the identity register provider, will need to
# update the provider to use this.
#
def openstack_command(cmd, options = '', env = {}, args = {})
openstackcmd = [cmd] << options
args.each do |key, val|
openstackcmd << "--#{key}" << val.to_s
end
Chef::Log.debug("Running openstack command: #{openstackcmd} with environment: #{env}")
result = shell_out(openstackcmd, env: env)
fail "#{result.stderr} (#{result.exitstatus})" if result.exitstatus != 0
result.stdout
end
# return uuid for an identity resource.
#
# @param [String] type of resource (user, service, tenant, endpoint, role)
# @param [String] key of resource to match
# @param [String] value of resource key to match
# @param [Hash] environment to use.
# @param [Hash] optional command argument/values pairs
# @param [String] optional uuid field to match
# @return [String] uuid or nil
#
# TODO: this was taken from the identity register provider, will need to
# update the provider to use this.
#
def identity_uuid(type, key, value, env, args = {}, uuid_field = 'id') # rubocop: disable ParameterLists
begin
output = openstack_command('keystone', "#{type}-list", env, args)
prettytable_to_array(output).each do |obj|
return obj[uuid_field] if obj.key?(uuid_field) && obj[key] == value
end
rescue RuntimeError => e
raise "Could not lookup uuid for #{type}:#{key}=>#{value}. Error was #{e.message}"
end
nil
end
end

2
metadata.rb Normal file → Executable file

@ -4,7 +4,7 @@ maintainer_email 'cookbooks@lists.tfoundry.com'
license 'Apache 2.0'
description 'Common OpenStack attributes, libraries and recipes.'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '9.1.0'
version '9.1.1'
recipe 'openstack-common', 'Installs/Configures common recipes'
recipe 'openstack-common::set_endpoints_by_interface', 'Set endpoints by interface'

104
spec/cli_spec.rb Executable file

@ -0,0 +1,104 @@
# encoding: UTF-8
require_relative 'spec_helper'
require ::File.join ::File.dirname(__FILE__), '..', 'libraries', 'cli'
describe 'openstack-common::default' do
describe 'Openstack CLI' do
let(:runner) { ChefSpec::Runner.new(CHEFSPEC_OPTS) }
let(:node) { runner.node }
let(:chef_run) do
runner.converge(described_recipe)
end
let(:subject) { Object.new.extend(Openstack) }
include_context 'library-stubs'
describe 'openstack_command_env' do
it 'returns cli enviroment' do
subject.stub(:get_password)
.with('user', 'name')
.and_return('pass')
expect(
subject.openstack_command_env('name', 'tenant')
).to eq(
'OS_USERNAME' => 'name',
'OS_PASSWORD' => 'pass',
'OS_TENANT_NAME' => 'tenant',
'OS_AUTH_URL' => 'http://127.0.0.1:35357/v2.0'
)
end
end
describe 'openstack_command' do
it 'runs openstack command' do
env =
{
'OS_USERNAME' => 'name',
'OS_PASSWORD' => 'pass',
'OS_TENANT_NAME' => 'tenant',
'OS_AUTH_URL' => 'http://127.0.0.1:35357/v2.0'
}
subject.stub(:shell_out).with(
['keystone', 'user-list'],
env: env
).and_return double('shell_out', exitstatus: 0, stdout: 'good', stderr: '')
result = subject.openstack_command('keystone', 'user-list', env)
expect(result).to eq('good')
end
it 'runs openstack command with args' do
env =
{
'OS_USERNAME' => 'name',
'OS_PASSWORD' => 'pass',
'OS_TENANT_NAME' => 'tenant',
'OS_AUTH_URL' => 'http://127.0.0.1:35357/v2.0'
}
subject.stub(:shell_out).with(
%w(keystone user-list --key1 value1 --key2 value2),
env: env
).and_return double('shell_out', exitstatus: 0, stdout: 'good', stderr: '')
result = subject.openstack_command('keystone', 'user-list', env, 'key1' => 'value1', 'key2' => 'value2')
expect(result).to eq('good')
end
it 'runs openstack command with failure' do
env =
{
'OS_USERNAME' => 'name',
'OS_PASSWORD' => 'pass',
'OS_TENANT_NAME' => 'tenant',
'OS_AUTH_URL' => 'http://127.0.0.1:35357/v2.0'
}
subject.stub(:shell_out).with(
['keystone', 'user-list'],
env: env
).and_return double('shell_out', exitstatus: 123, stdout: 'fail', stderr: '')
# TODO: need to figure out why this won't work.
# expect(subject.openstack_command('keystone', 'user-list', env)).to fail
end
end
describe 'identity_uuid' do
it 'runs identity command to query uuid' do
env =
{
'OS_USERNAME' => 'name',
'OS_PASSWORD' => 'pass',
'OS_TENANT_NAME' => 'tenant',
'OS_AUTH_URL' => 'http://127.0.0.1:35357/v2.0'
}
subject.stub(:openstack_command).with('keystone', 'user-list', env, {})
subject.stub(:prettytable_to_array)
.and_return([{ 'name' => 'user1', 'id' => '1234567890ABCDEFGH' }])
result = subject.identity_uuid('user', 'name', 'user1', env)
expect(result).to eq('1234567890ABCDEFGH')
end
end
end
end