456 lines
18 KiB
Ruby
456 lines
18 KiB
Ruby
# encoding: UTF-8
|
|
require 'chefspec'
|
|
require 'chefspec/berkshelf'
|
|
|
|
ChefSpec::Coverage.start! { add_filter 'openstack-orchestration' }
|
|
|
|
require 'chef/application'
|
|
|
|
LOG_LEVEL = :fatal
|
|
REDHAT_OPTS = {
|
|
platform: 'redhat',
|
|
version: '7.0',
|
|
log_level: ::LOG_LEVEL
|
|
}
|
|
UBUNTU_OPTS = {
|
|
platform: 'ubuntu',
|
|
version: '14.04',
|
|
log_level: ::LOG_LEVEL
|
|
}
|
|
SUSE_OPTS = {
|
|
platform: 'suse',
|
|
version: '11.3',
|
|
log_level: ::LOG_LEVEL
|
|
}
|
|
|
|
shared_context 'orchestration_stubs' do
|
|
before do
|
|
allow_any_instance_of(Chef::Recipe).to receive(:rabbit_servers)
|
|
.and_return '1.1.1.1:5672,2.2.2.2:5672'
|
|
allow_any_instance_of(Chef::Recipe).to receive(:address_for)
|
|
.with('lo')
|
|
.and_return '127.0.1.1'
|
|
allow_any_instance_of(Chef::Recipe).to receive(:get_secret)
|
|
.with('openstack_identity_bootstrap_token')
|
|
.and_return 'bootstrap-token'
|
|
|
|
allow_any_instance_of(Chef::Recipe).to receive(:get_password)
|
|
.with('db', 'heat')
|
|
.and_return 'heat'
|
|
allow_any_instance_of(Chef::Recipe).to receive(:get_password)
|
|
.with('user', 'guest')
|
|
.and_return 'mq-pass'
|
|
allow_any_instance_of(Chef::Recipe).to receive(:get_password)
|
|
.with('user', 'admin-user')
|
|
.and_return 'admin-pass'
|
|
allow_any_instance_of(Chef::Recipe).to receive(:get_password)
|
|
.with('user', 'heat_stack_admin')
|
|
.and_return 'heat_stack_domain_admin_password'
|
|
allow_any_instance_of(Chef::Recipe).to receive(:get_password)
|
|
.with('service', 'openstack-orchestration')
|
|
.and_return 'heat-pass'
|
|
allow_any_instance_of(Chef::Recipe).to receive(:get_password)
|
|
.with('user', 'stack_domain_admin')
|
|
.and_return 'stack_domain_admin_pass'
|
|
allow_any_instance_of(Chef::Recipe).to receive(:get_password)
|
|
.with('user', 'admin')
|
|
.and_return 'admin_pass'
|
|
allow(Chef::Application).to receive(:fatal!)
|
|
end
|
|
end
|
|
|
|
shared_examples 'expect runs openstack orchestration common recipe' do
|
|
it 'runs orchestration common recipe' do
|
|
expect(chef_run).to include_recipe 'openstack-orchestration::common'
|
|
end
|
|
end
|
|
|
|
shared_examples 'expect installs python keystoneclient' do
|
|
it 'installs python-keystoneclient' do
|
|
expect(chef_run).to upgrade_package 'python-keystoneclient'
|
|
end
|
|
end
|
|
|
|
shared_examples 'expect runs openstack common logging recipe' do
|
|
it 'runs logging recipe if node attributes say to' do
|
|
expect(chef_run).to include_recipe 'openstack-common::logging'
|
|
end
|
|
end
|
|
|
|
def expect_creates_api_paste(service, action = :restart) # rubocop:disable MethodLength
|
|
describe 'api-paste.ini' do
|
|
let(:template) { chef_run.template('/etc/heat/api-paste.ini') }
|
|
|
|
it 'creates the heat.conf file' do
|
|
expect(chef_run).to create_template(template.name).with(
|
|
owner: 'heat',
|
|
group: 'heat',
|
|
mode: 0644
|
|
)
|
|
end
|
|
|
|
it 'notifies heat-api restart' do
|
|
expect(template).to notify(service).to(action)
|
|
end
|
|
end
|
|
end
|
|
|
|
shared_examples 'expect installs common heat package' do
|
|
it 'installs the openstack-heat package' do
|
|
expect(chef_run).to upgrade_package 'openstack-heat'
|
|
end
|
|
end
|
|
|
|
shared_examples 'expect installs mysql package' do
|
|
it 'installs mysql python packages by default' do
|
|
expect(chef_run).to upgrade_package 'MySQL-python'
|
|
end
|
|
end
|
|
|
|
shared_examples 'expect runs db migrations' do
|
|
it 'runs db migrations' do
|
|
expect(chef_run).to run_execute('heat-manage db_sync').with(user: 'heat', group: 'heat')
|
|
end
|
|
end
|
|
|
|
shared_examples 'expects to create heat directories' do
|
|
it 'creates /etc/heat' do
|
|
expect(chef_run).to create_directory('/etc/heat').with(
|
|
owner: 'heat',
|
|
group: 'heat',
|
|
mode: 0700
|
|
)
|
|
end
|
|
|
|
it 'creates /etc/heat/environment.d' do
|
|
expect(chef_run).to create_directory('/etc/heat/environment.d').with(
|
|
owner: 'heat',
|
|
group: 'heat',
|
|
mode: 0700
|
|
)
|
|
end
|
|
|
|
it 'creates /var/cache/heat' do
|
|
expect(chef_run).to create_directory('/var/cache/heat').with(
|
|
owner: 'heat',
|
|
group: 'heat',
|
|
mode: 0700
|
|
)
|
|
end
|
|
end
|
|
|
|
shared_examples 'expects to create heat conf' do
|
|
describe 'heat.conf' do
|
|
let(:file) { chef_run.template('/etc/heat/heat.conf') }
|
|
|
|
it 'creates the heat.conf file' do
|
|
expect(chef_run).to create_template(file.name).with(
|
|
owner: 'heat',
|
|
group: 'heat',
|
|
mode: 0640
|
|
)
|
|
end
|
|
|
|
it 'uses default values for these attributes and they are not set' do
|
|
expect(chef_run).not_to render_file(file.name).with_content(
|
|
/^memcached_servers=/)
|
|
expect(chef_run).not_to render_file(file.name).with_content(
|
|
/^memcache_security_strategy=/)
|
|
expect(chef_run).not_to render_file(file.name).with_content(
|
|
/^memcache_secret_key=/)
|
|
expect(chef_run).not_to render_file(file.name).with_content(
|
|
/^cafile=/)
|
|
end
|
|
|
|
it 'sets memcached server(s)' do
|
|
node.set['openstack']['orchestration']['api']['auth']['memcached_servers'] = 'localhost:11211'
|
|
expect(chef_run).to render_file(file.name).with_content(/^memcached_servers=localhost:11211$/)
|
|
end
|
|
|
|
it 'sets memcache security strategy' do
|
|
node.set['openstack']['orchestration']['api']['auth']['memcache_security_strategy'] = 'MAC'
|
|
expect(chef_run).to render_file(file.name).with_content(/^memcache_security_strategy=MAC$/)
|
|
end
|
|
|
|
it 'sets memcache secret key' do
|
|
node.set['openstack']['orchestration']['api']['auth']['memcache_secret_key'] = '0123456789ABCDEF'
|
|
expect(chef_run).to render_file(file.name).with_content(/^memcache_secret_key=0123456789ABCDEF$/)
|
|
end
|
|
|
|
it 'sets cafile' do
|
|
node.set['openstack']['orchestration']['api']['auth']['cafile'] = 'dir/to/path'
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^cafile=dir/to/path$})
|
|
end
|
|
|
|
it 'sets token hash algorithms' do
|
|
node.set['openstack']['orchestration']['api']['auth']['hash_algorithms'] = 'sha2'
|
|
expect(chef_run).to render_file(file.name).with_content(/^hash_algorithms=sha2$/)
|
|
end
|
|
|
|
it 'sets insecure' do
|
|
node.set['openstack']['orchestration']['api']['auth']['insecure'] = false
|
|
expect(chef_run).to render_file(file.name).with_content(/^insecure=false$/)
|
|
end
|
|
|
|
describe 'default values for certificates files' do
|
|
it 'has no such values' do
|
|
[
|
|
/^ca_file=/,
|
|
/^cert_file=/,
|
|
/^key_file=/
|
|
].each do |line|
|
|
expect(chef_run).not_to render_file(file.name).with_content(line)
|
|
end
|
|
end
|
|
|
|
it 'sets clients ca_file cert_file key_file insecure' do
|
|
node.set['openstack']['orchestration']['clients']['ca_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients']['cert_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients']['key_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients']['insecure'] = true
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^ca_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^cert_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^key_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(/^insecure=true$/)
|
|
end
|
|
|
|
it 'sets clients_ceilometer ca_file cert_file key_file insecure' do
|
|
node.set['openstack']['orchestration']['clients_ceilometer']['ca_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_ceilometer']['cert_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_ceilometer']['key_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_ceilometer']['insecure'] = true
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^ca_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^cert_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^key_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(/^insecure=true$/)
|
|
end
|
|
|
|
it 'sets clients_cinder ca_file cert_file key_file insecure' do
|
|
node.set['openstack']['orchestration']['clients_cinder']['ca_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_cinder']['cert_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_cinder']['key_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_cinder']['insecure'] = true
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^ca_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^cert_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^key_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(/^insecure=true$/)
|
|
end
|
|
|
|
it 'sets clients_glance ca_file cert_file key_file insecure' do
|
|
node.set['openstack']['orchestration']['clients_glance']['ca_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_glance']['cert_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_glance']['key_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_glance']['insecure'] = true
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^ca_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^cert_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^key_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(/^insecure=true$/)
|
|
end
|
|
|
|
it 'sets clients_heat ca_file cert_file key_file insecure' do
|
|
node.set['openstack']['orchestration']['clients_heat']['ca_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_heat']['cert_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_heat']['key_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_heat']['insecure'] = true
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^ca_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^cert_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^key_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(/^insecure=true$/)
|
|
end
|
|
|
|
it 'sets clients_keystone ca_file cert_file key_file insecure' do
|
|
node.set['openstack']['orchestration']['clients_keystone']['ca_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_keystone']['cert_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_keystone']['key_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_keystone']['insecure'] = true
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^ca_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^cert_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^key_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(/^insecure=true$/)
|
|
end
|
|
|
|
it 'sets clients_neutron ca_file cert_file key_file insecure' do
|
|
node.set['openstack']['orchestration']['clients_neutron']['ca_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_neutron']['cert_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_neutron']['key_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_neutron']['insecure'] = true
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^ca_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^cert_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^key_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(/^insecure=true$/)
|
|
end
|
|
|
|
it 'sets clients_nova ca_file cert_file key_file insecure' do
|
|
node.set['openstack']['orchestration']['clients_nova']['ca_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_nova']['cert_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_nova']['key_file'] = 'dir/to/path'
|
|
node.set['openstack']['orchestration']['clients_nova']['insecure'] = true
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^ca_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^cert_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^key_file=dir/to/path$})
|
|
expect(chef_run).to render_file(file.name).with_content(/^insecure=true$/)
|
|
end
|
|
end
|
|
|
|
describe 'default values' do
|
|
it 'has default conf values' do
|
|
[
|
|
%r{^sql_connection=mysql://heat:heat@127.0.0.1:3306/heat\?charset=utf8$},
|
|
%r{^heat_metadata_server_url=http://127.0.0.1:8000$},
|
|
%r{^heat_waitcondition_server_url=http://127.0.0.1:8000/v1/waitcondition$},
|
|
%r{^heat_watch_server_url=http://127.0.0.1:8003$},
|
|
%r{^signing_dir=/var/cache/heat$},
|
|
/^debug=False$/,
|
|
/^verbose=False$/,
|
|
/^notification_driver = heat.openstack.common.notifier.rpc_notifier$/,
|
|
/^default_notification_level = INFO$/,
|
|
/^default_publisher_id = $/,
|
|
/^list_notifier_drivers = heat.openstack.common.notifier.no_op_notifier$/,
|
|
/^notification_topics = notifications$/,
|
|
/^rpc_thread_pool_size=64$/,
|
|
/^rpc_conn_pool_size=30$/,
|
|
/^rpc_response_timeout=60$/,
|
|
/^amqp_durable_queues=false$/,
|
|
/^amqp_auto_delete=false$/,
|
|
/^rabbit_host=127.0.0.1$/,
|
|
/^rabbit_port=5672$/,
|
|
/^rabbit_ha_queues=False$/,
|
|
/^rabbit_use_ssl=false$/,
|
|
/^rabbit_userid=guest$/,
|
|
/^rabbit_password=mq-pass$/,
|
|
/^rabbit_virtual_host=\/$/,
|
|
/^bind_host=127.0.0.1$/,
|
|
/^bind_port=8004$/,
|
|
/^auth_host=127.0.0.1$/,
|
|
/^auth_port=35357$/,
|
|
/^auth_protocol=http$/,
|
|
%r{^auth_uri=http://127.0.0.1:5000/v2.0$},
|
|
/^auth_version=v2.0$/,
|
|
/^hash_algorithms=md5$/,
|
|
/^insecure=false$/,
|
|
/^admin_user=heat$/,
|
|
/^admin_password=heat-pass$/,
|
|
/^admin_tenant_name=service$/,
|
|
/^deferred_auth_method=trusts$/,
|
|
%r{^signing_dir=/var/cache/heat$},
|
|
/^region_name_for_services=RegionOne$/
|
|
].each do |line|
|
|
expect(chef_run).to render_file(file.name).with_content(line)
|
|
end
|
|
end
|
|
|
|
it 'overrides the schemes' do
|
|
node.set['openstack']['endpoints']['orchestration-api-cfn']['scheme'] = 'https'
|
|
node.set['openstack']['endpoints']['orchestration-api-cloudwatch']['scheme'] = 'https'
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^heat_metadata_server_url=https://127.0.0.1:8000$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^heat_waitcondition_server_url=https://127.0.0.1:8000/v1/waitcondition$})
|
|
expect(chef_run).to render_file(file.name).with_content(%r{^heat_watch_server_url=https://127.0.0.1:8003$})
|
|
end
|
|
end
|
|
|
|
describe 'domain values' do
|
|
it 'has no default domain values' do
|
|
[
|
|
/^heat_stack_user_role=/,
|
|
/^stack_user_domain_name=/,
|
|
/^stack_user_domain_id=/,
|
|
/^stack_domain_admin=/,
|
|
/^stack_domain_admin_password=/
|
|
].each do |line|
|
|
expect(chef_run).not_to render_file(file.name).with_content(line)
|
|
end
|
|
end
|
|
|
|
it 'has domain override values' do
|
|
node.set['openstack']['orchestration']['heat_stack_user_role'] = 'heat_stack_user'
|
|
node.set['openstack']['orchestration']['stack_user_domain_name'] = 'heat'
|
|
node.set['openstack']['orchestration']['stack_user_domain_id'] = '123'
|
|
node.set['openstack']['orchestration']['stack_domain_admin'] = 'heat_stack_admin'
|
|
[
|
|
/^heat_stack_user_role=heat_stack_user$/,
|
|
/^stack_user_domain_name=heat$/,
|
|
/^stack_user_domain_id=123$/,
|
|
/^stack_domain_admin=heat_stack_admin$/,
|
|
/^stack_domain_admin_password=heat_stack_domain_admin_password$/
|
|
].each do |line|
|
|
expect(chef_run).to render_file(file.name).with_content(line)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'has qpid values' do
|
|
it 'has default qpid_* values' do
|
|
node.set['openstack']['mq']['orchestration']['service_type'] = 'qpid'
|
|
|
|
[
|
|
/^qpid_hostname=127.0.0.1$/,
|
|
/^qpid_port=5672$/,
|
|
/^qpid_username=guest$/,
|
|
/^qpid_password=mq-pass$/,
|
|
/^qpid_sasl_mechanisms=$/,
|
|
/^qpid_heartbeat=60$/,
|
|
/^qpid_protocol=tcp$/,
|
|
/^qpid_tcp_nodelay=true$/,
|
|
/^qpid_reconnect_timeout=0$/,
|
|
/^qpid_reconnect_limit=0$/,
|
|
/^qpid_reconnect_interval_min=0$/,
|
|
/^qpid_reconnect_interval_max=0$/,
|
|
/^qpid_reconnect_interval=0$/,
|
|
/^qpid_topology_version=1$/
|
|
].each do |line|
|
|
expect(chef_run).to render_file(file.name).with_content(line)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'has rabbit values' do
|
|
it 'has rabbit ha values' do
|
|
node.set['openstack']['mq']['orchestration']['service_type'] = 'rabbitmq'
|
|
node.set['openstack']['mq']['orchestration']['rabbit']['ha'] = true
|
|
[
|
|
/^rabbit_hosts=1.1.1.1:5672,2.2.2.2:5672$/,
|
|
/^rabbit_ha_queues=True$/
|
|
].each do |line|
|
|
expect(chef_run).to render_file(file.name).with_content(line)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
shared_examples 'expects to create heat default.yaml' do
|
|
describe 'default.yaml' do
|
|
let(:file) { chef_run.template('/etc/heat/environment.d/default.yaml') }
|
|
|
|
it 'creates the default.yaml file' do
|
|
expect(chef_run).to create_template(file.name).with(
|
|
owner: 'heat',
|
|
group: 'heat',
|
|
mode: 0644
|
|
)
|
|
end
|
|
end
|
|
end
|
|
|
|
shared_examples 'logging' do
|
|
context 'with logging enabled' do
|
|
before do
|
|
node.set['openstack']['orchestration']['syslog']['use'] = true
|
|
end
|
|
|
|
it 'runs logging recipe if node attributes say to' do
|
|
expect(chef_run).to include_recipe 'openstack-common::logging'
|
|
end
|
|
end
|
|
|
|
context 'with logging disabled' do
|
|
before do
|
|
node.set['openstack']['orchestration']['syslog']['use'] = false
|
|
end
|
|
|
|
it "doesn't run logging recipe" do
|
|
expect(chef_run).not_to include_recipe 'openstack-common::logging'
|
|
end
|
|
end
|
|
end
|