Stein fixes

- Switch to Stein release
- Cookstyle fixes
- Update cookbook etcd to ~> 5.6
- Update README
- Add myself to author list and OSU Copyright
- Properly fix completions recipe and ensure it works
- Create and start the etcd service in the etcd recipe
- Update delivery configuration to exclude integration cookbooks
- Refactor and update RenderConfigFileMatcher to work with newer
  ChefSpec. This fixes output which was passing but showing error
  messages.

Depends-On: https://review.opendev.org/701027
Change-Id: Iba3eeabe85ab9303147e43eeb550212a46d190f3
This commit is contained in:
Lance Albertson 2020-01-07 16:33:05 -08:00
parent ea8684d2cf
commit abab7d0ecb
39 changed files with 897 additions and 249 deletions

View File

@ -1 +1,9 @@
remote_file = "https://raw.githubusercontent.com/chef-cookbooks/community_cookbook_tools/master/delivery/project.toml"
[local_phases]
unit = 'rspec spec/'
lint = 'cookstyle --display-cop-names --extra-details'
syntax = "berks install -e integration"
provision = "echo skipping"
deploy = "echo skipping"
smoke = "echo skipping"
functional = "echo skipping"
cleanup = "echo skipping"

View File

@ -15,19 +15,5 @@ AllCops:
- berks-cookbooks/**/*
- .bundle/**/*
Encoding:
Exclude:
- ./metadata.rb
- ./Gemfile
NumericLiterals:
ChefModernize/DefinesChefSpecMatchers:
Enabled: false
LineLength:
Enabled: false
WordArray:
MinSize: 3
MethodLength:
Max: 16

View File

@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2018-08-03 05:25:49 -0700 using RuboCop version 0.55.0.
# on 2020-02-05 22:58:21 +0000 using RuboCop version 0.75.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
@ -11,22 +11,9 @@ Lint/NestedMethodDefinition:
Exclude:
- 'libraries/matchers.rb'
# Offense count: 2
# Cop supports --auto-correct.
Lint/UnneededCopEnableDirective:
Exclude:
- 'libraries/matchers.rb'
# Offense count: 2
# Cop supports --auto-correct.
Style/IfUnlessModifier:
Exclude:
- 'Rakefile'
- 'libraries/matchers.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, EnforcedStyle.
# Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods.
# SupportedStyles: predicate, comparison
Style/NumericPredicate:
Exclude:
@ -38,9 +25,3 @@ Style/NumericPredicate:
Style/ZeroLengthPredicate:
Exclude:
- 'libraries/provider_database_mysql_user.rb'
# Offense count: 178
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https
Metrics/LineLength:
Max: 168

View File

@ -23,9 +23,9 @@ https://docs.openstack.org/latest/install/
Requirements
============
- Chef 14 or higher
- chefdk 3.2.30 for testing (also includes berkshelf for cookbook
dependency resolution)
- Chef 15 or higher
- Chef Workstation 0.15.18 for testing (also includes berkshelf for
cookbook dependency resolution)
Platform
========
@ -39,12 +39,12 @@ Cookbooks
The following cookbooks are dependencies:
- 'etcd', '~> 5.5'
- 'mariadb', '~> 3.1'
- 'memcached', '~> 4.1'
- 'mysql', '~> 8.2'
- 'selinux'
- 'yum-epel'
- 'etcd', '~> 5.6'
- 'mariadb', '~> 3.1'
- 'memcached', '~> 4.1'
- 'mysql', '~> 8.2'
- 'selinux'
- 'yum-epel'
Attributes
==========
@ -90,11 +90,21 @@ openstack-common::client
- Install the common python openstack client package
openstack-common::completions
-----------------------------
- Install bash completions for openstack client
openstack-common::default
-------------------------
- Installs/Configures common recipes
openstack-common::etcd
----------------------
- Installs and starts etcd
openstack-common::logging
-------------------------
@ -104,7 +114,7 @@ openstack-common::sysctl
------------------------
- Iterates over the contents of the ``node['openstack']['sysctl']``
hash and writes the entries to ``/etc/sysctl.d/60-openstack.conf``.
hash and executes the ``sysctl`` resource.
Data Bags
=========

View File

@ -1,25 +1,20 @@
task default: ['test']
task test: [:syntax, :lint, :unit]
task test: [:syntax, :unit]
desc 'Vendor the cookbooks in the Berksfile'
task :berks_prep do
sh %(chef exec berks vendor)
end
desc 'Run FoodCritic (syntax) tests'
desc 'Run CookStyle (syntax & lint) tests'
task :syntax do
sh %(chef exec foodcritic --exclude spec -f any .)
end
desc 'Run RuboCop (lint) tests'
task :lint do
sh %(chef exec cookstyle)
sh %(delivery local lint)
end
desc 'Run RSpec (unit) tests'
task unit: :berks_prep do
sh %(chef exec rspec --format documentation)
sh %(delivery local unit)
end
desc 'Remove the berks-cookbooks directory and the Berksfile.lock'

View File

@ -1,10 +1,10 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# Attributes:: database
#
# Copyright 2012-2013, AT&T Services, Inc.
# Copyright 2013-2014, SUSE Linux GmbH
# Copyright:: 2012-2013, AT&T Services, Inc.
# Copyright:: 2013-2014, SUSE Linux GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,10 +1,11 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# Attributes:: default
#
# Copyright 2012-2013, AT&T Services, Inc.
# Copyright 2013-2014, SUSE Linux GmbH
# Copyright:: 2012-2013, AT&T Services, Inc.
# Copyright:: 2013-2014, SUSE Linux GmbH
# Copyright:: 2016-2020, Oregon State University
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -124,7 +125,7 @@ default['openstack']['secret']['user_passwords_data_bag'] = 'user_passwords'
# needs.
# The coordinated release of OpenStack codename
default['openstack']['release'] = 'rocky'
default['openstack']['release'] = 'stein'
# The Ubuntu Cloud Archive has packages for multiple Ubuntu releases. For
# more information, see: https://wiki.ubuntu.com/ServerTeam/CloudArchive.
@ -292,28 +293,28 @@ case node['platform_family']
when 'rhel'
default['openstack']['common']['platform'] = {
'common_client_packages' => ['python-openstackclient'],
'python_packages' => [
'python',
'python2-pip',
'python2-setuptools',
'python-devel',
'python-virtualenv',
'python-wheel',
],
'python_packages' => %w(
python
python2-pip
python2-setuptools
python-devel
python-virtualenv
python-wheel
),
'package_overrides' => '',
}
when 'debian'
default['openstack']['common']['platform'] = {
'common_client_packages' => ['python3-openstackclient'],
'python_packages' => [
'python3',
'python3-dev',
'python3-pip',
'python3-setuptools',
'python3-virtualenv',
'python3-wheel',
'virtualenv',
],
'python_packages' => %w(
python3
python3-dev
python3-pip
python3-setuptools
python3-virtualenv
python3-wheel
virtualenv
),
'package_overrides' => '',
}
end

View File

@ -1,11 +1,11 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# Attributes:: messaging
#
# Copyright 2012-2013, AT&T Services, Inc.
# Copyright 2013-2014, SUSE Linux GmbH
# Copyright 2013-2014, Rackspace US, Inc.
# Copyright:: 2012-2013, AT&T Services, Inc.
# Copyright:: 2013-2014, SUSE Linux GmbH
# Copyright:: 2013-2014, 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.

View File

@ -1,10 +1,10 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# library:: cli
#
# Copyright 2014, IBM Corp.
# 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.
@ -86,7 +86,7 @@ module ::Openstack
# @param [String] optional uuid field to match
# @return [String] uuid or nil
#
def get_uuid(client, type, key, value, env, args = {}, uuid_field = 'id') # rubocop: disable ParameterLists
def get_uuid(client, type, key, value, env, args = {}, uuid_field = 'id') # rubocop: disable Metrics/ParameterLists
begin
output = openstack_command(client, "#{type} list", env, args)
prettytable_to_array(output).each do |obj|

View File

@ -1,10 +1,10 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# library:: config_helpers
#
# Copyright 2016, cloudbau GmbH
# Copyright:: 2016, cloudbau GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,10 +1,10 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# library:: endpoints
#
# Copyright 2012-2013, AT&T Services, Inc.
# Copyright:: 2012-2013, AT&T Services, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -42,7 +42,7 @@ if defined?(ChefSpec)
class RenderConfigFileMatcher < ChefSpec::Matchers::RenderFileMatcher
def with_section_content(section, expected_content)
@section = section
@expected_content = expected_content
@expected_content << expected_content
self
end
@ -79,16 +79,26 @@ if defined?(ChefSpec)
return false if @actual_content.nil?
if @expected_content.is_a?(Regexp)
@actual_content =~ @expected_content
elsif RSpec::Matchers.is_a_matcher?(@expected_content)
@expected_content.matches?(@actual_content)
else
@actual_content.include?(@expected_content)
# Knock out matches that pass. When we're done, we pass if the list is
# empty. Otherwise, @expected_content is the list of matchers that
# failed
@expected_content.delete_if do |expected|
if expected.is_a?(Regexp)
@actual_content =~ expected
elsif RSpec::Matchers.is_a_matcher?(expected)
expected.matches?(@actual_content)
elsif expected.is_a?(Proc)
expected.call(@actual_content)
# Weird RSpecish, but that block will return false for a negated check,
# so we always return true. The block will raise an exception if the
# assertion fails.
true
else
@actual_content.include?(expected)
end
end
@expected_content.empty?
end
# rubocop:enable MethodLength, CyclomaticComplexity
end
## matchers for openstack_database LWRP

View File

@ -1,10 +1,10 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# library:: network
#
# Copyright 2012-2013, AT&T Services, Inc.
# Copyright:: 2012-2013, AT&T Services, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,10 +1,10 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# library:: parse
#
# Copyright 2013, Craig Tracey <craigtracey@gmail.com>
# 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.
@ -48,7 +48,7 @@ module ::Openstack
# as Property Value pairs. If this is the case, then
# flatten it as expected.
newobj = {}
if indicies == ['Property', 'Value']
if indicies == %w(Property Value)
ret.each { |x| newobj[x['Property']] = x['Value'] }
[newobj]
else

View File

@ -1,11 +1,11 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# library:: passwords
#
# Copyright 2012-2013, AT&T Services, Inc.
# Copyright 2014, SUSE Linux, GmbH.
# Copyright:: 2012-2013, AT&T Services, Inc.
# Copyright:: 2014, SUSE Linux, GmbH.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -0,0 +1,164 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Author:: Sean OMeara (<sean@sean.io>)
# Copyright:: 2011-2016, Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# 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.
#
# this file is originally from the database cookbook, preserved for legacy
# purposes until the functionality can be refactored into a custom resource.
# Original: https://github.com/chef-boneyard/database
class Chef
class Provider
class Database
class Mysql < Chef::Provider::LWRPBase
action :create do
# test
schema_present = nil
begin
test_sql = 'SHOW SCHEMAS;'
Chef::Log.debug("#{new_resource.name}: Performing query [#{test_sql}]")
test_sql_results = test_client.query(test_sql)
test_sql_results.each do |r|
schema_present = true if r['Database'] == new_resource.database_name
end
ensure
close_test_client
end
# repair
unless schema_present
converge_by "Creating schema '#{new_resource.database_name}'" do
begin
repair_sql = "CREATE SCHEMA IF NOT EXISTS `#{new_resource.database_name}`"
repair_sql += " CHARACTER SET = #{new_resource.encoding}" if new_resource.encoding
repair_sql += " COLLATE = #{new_resource.collation}" if new_resource.collation
Chef::Log.debug("#{new_resource.name}: Performing query [#{repair_sql}]")
repair_client.query(repair_sql)
ensure
close_repair_client
end
end
end
end
action :drop do
# test
schema_present = nil
begin
test_sql = 'SHOW SCHEMAS;'
Chef::Log.debug("Performing query [#{test_sql}]")
test_sql_results = test_client.query(test_sql)
test_sql_results.each do |r|
schema_present = true if r['Database'] == new_resource.database_name
end
ensure
close_test_client
end
# repair
if schema_present
converge_by "Dropping schema '#{new_resource.database_name}'" do
begin
repair_sql = "DROP SCHEMA IF EXISTS `#{new_resource.database_name}`"
Chef::Log.debug("Performing query [#{repair_sql}]")
repair_client.query(repair_sql)
ensure
close_repair_client
end
end
end
end
action :query do
begin
query_sql = new_resource.sql_query
Chef::Log.debug("Performing query [#{query_sql}]")
query_client.query(query_sql)
ensure
close_query_client
end
end
private
def test_client
require 'mysql2'
@test_client ||=
Mysql2::Client.new(
host: new_resource.connection[:host],
socket: new_resource.connection[:socket],
username: new_resource.connection[:username],
password: new_resource.connection[:password],
port: new_resource.connection[:port],
default_file: new_resource.connection[:default_file],
default_group: new_resource.connection[:default_group]
)
end
def close_test_client
@test_client.close if @test_client
rescue Mysql2::Error
@test_client = nil
end
def repair_client
require 'mysql2'
@repair_client ||=
Mysql2::Client.new(
host: new_resource.connection[:host],
socket: new_resource.connection[:socket],
username: new_resource.connection[:username],
password: new_resource.connection[:password],
port: new_resource.connection[:port],
default_file: new_resource.connection[:default_file],
default_group: new_resource.connection[:default_group]
)
end
def close_repair_client
@repair_client.close if @repair_client
rescue Mysql2::Error
@repair_client = nil
end
def query_client
require 'mysql2'
@query_client ||=
Mysql2::Client.new(
host: new_resource.connection[:host],
socket: new_resource.connection[:socket],
username: new_resource.connection[:username],
password: new_resource.connection[:password],
port: new_resource.connection[:port],
default_file: new_resource.connection[:default_file],
default_group: new_resource.connection[:default_group],
flags: new_resource.connection[:flags],
database: new_resource.database_name
)
end
def close_query_client
@query_client.close if @query_client
rescue Mysql2::Error
@query_client = nil
end
end
end
end
end

View File

@ -0,0 +1,382 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Author:: Sean OMeara (<sean@sean.io>)
# Copyright:: 2011-2016, Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# 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.
#
# this file is originally from the database cookbook, preserved for legacy
# purposes until the functionality can be refactored into a custom resource.
# Original: https://github.com/chef-boneyard/database
require File.join(File.dirname(__FILE__), 'provider_database_mysql')
class Chef
class Provider
class Database
class MysqlUser < Chef::Provider::Database::Mysql
action :create do
# test
user_present = nil
begin
test_sql = "SELECT User,Host from mysql.user WHERE User='#{new_resource.username}' AND Host='#{new_resource.host}';"
test_sql_results = test_client.query(test_sql)
test_sql_results.each do |r|
user_present = true if r['User'] == new_resource.username
end
password_up_to_date = !user_present || test_user_password
ensure
close_test_client
end
# repair
unless user_present
converge_by "Creating user '#{new_resource.username}'@'#{new_resource.host}'" do
begin
repair_sql = "CREATE USER '#{new_resource.username}'@'#{new_resource.host}'"
if new_resource.password
repair_sql += ' IDENTIFIED BY '
repair_sql += if new_resource.password.is_a?(HashedPassword)
" PASSWORD '#{new_resource.password}'"
else
" '#{new_resource.password}'"
end
end
repair_client.query(repair_sql)
ensure
close_repair_client
end
end
end
update_user_password unless password_up_to_date
end
action :drop do
# test
user_present = nil
begin
test_sql = 'SELECT User,Host'
test_sql += ' from mysql.user'
test_sql += " WHERE User='#{new_resource.username}'"
test_sql += " AND Host='#{new_resource.host}'"
test_sql_results = test_client.query test_sql
test_sql_results.each do |r|
user_present = true if r['User'] == new_resource.username
end
ensure
close_test_client
end
# repair
if user_present
converge_by "Dropping user '#{new_resource.username}'@'#{new_resource.host}'" do
begin
repair_sql = 'DROP USER'
repair_sql += " '#{new_resource.username}'@'#{new_resource.host}'"
repair_client.query repair_sql
ensure
close_repair_client
end
end
end
end
action :grant do
# gratuitous function
def ishash?
return true if /(\A\*[0-9A-F]{40}\z)/i =~ new_resource.password
end
db_name = new_resource.database_name ? "`#{new_resource.database_name}`" : '*'
tbl_name = new_resource.table ? new_resource.table : '*'
test_table = new_resource.database_name ? 'mysql.db' : 'mysql.user'
# Test
incorrect_privs = nil
begin
test_sql = "SELECT * from #{test_table}"
test_sql += " WHERE User='#{new_resource.username}'"
test_sql += " AND Host='#{new_resource.host}'"
test_sql += " AND Db='#{new_resource.database_name}'" if new_resource.database_name
test_sql_results = test_client.query test_sql
incorrect_privs = true if test_sql_results.size.zero?
# These should all be 'Y'
test_sql_results.each do |r|
desired_privs.each do |p|
key = p.to_s.capitalize.tr(' ', '_').gsub('Replication_', 'Repl_').gsub('Create_temporary_tables', 'Create_tmp_table').gsub('Show_databases', 'Show_db')
key = "#{key}_priv"
incorrect_privs = true if r[key] != 'Y'
end
end
password_up_to_date = incorrect_privs || test_user_password
ensure
close_test_client
end
# Repair
if incorrect_privs
converge_by "Granting privs for '#{new_resource.username}'@'#{new_resource.host}'" do
begin
repair_sql = "GRANT #{new_resource.privileges.join(',')}"
repair_sql += " ON #{db_name}.#{tbl_name}"
repair_sql += " TO '#{new_resource.username}'@'#{new_resource.host}' IDENTIFIED BY"
repair_sql += if new_resource.password.is_a?(HashedPassword)
" PASSWORD '#{new_resource.password}'"
else
" '#{new_resource.password}'"
end
repair_sql += ' REQUIRE SSL' if new_resource.require_ssl
repair_sql += ' REQUIRE X509' if new_resource.require_x509
repair_sql += ' WITH GRANT OPTION' if new_resource.grant_option
redacted_sql = redact_password(repair_sql, new_resource.password)
Chef::Log.debug("#{@new_resource}: granting with sql [#{redacted_sql}]")
repair_client.query(repair_sql)
repair_client.query('FLUSH PRIVILEGES')
ensure
close_repair_client
end
end
else
# The grants are correct, but perhaps the password needs updating?
update_user_password unless password_up_to_date
end
end
action :revoke do
db_name = new_resource.database_name ? "`#{new_resource.database_name}`" : '*'
tbl_name = new_resource.table ? new_resource.table : '*'
test_table = new_resource.database_name ? 'mysql.db' : 'mysql.user'
privs_to_revoke = []
begin
test_sql = "SELECT * from #{test_table}"
test_sql += " WHERE User='#{new_resource.username}'"
test_sql += " AND Host='#{new_resource.host}'"
test_sql += " AND Db='#{new_resource.database_name}'" if new_resource.database_name
test_sql_results = test_client.query test_sql
# These should all be 'N'
test_sql_results.each do |r|
desired_privs.each do |p|
key = p.to_s.capitalize.tr(' ', '_').gsub('Replication_', 'Repl_').gsub('Create_temporary_tables', 'Create_tmp_table').gsub('Show_databases', 'Show_db')
key = "#{key}_priv"
privs_to_revoke << revokify_key(p) if r[key] != 'N'
end
end
ensure
close_test_client
end
# Repair
unless privs_to_revoke.empty?
converge_by "Revoking privs for '#{new_resource.username}'@'#{new_resource.host}'" do
begin
revoke_statement = "REVOKE #{privs_to_revoke.join(',')}"
revoke_statement += " ON #{db_name}.#{tbl_name}"
revoke_statement += " FROM `#{@new_resource.username}`@`#{@new_resource.host}` "
Chef::Log.debug("#{@new_resource}: revoking access with statement [#{revoke_statement}]")
repair_client.query(revoke_statement)
repair_client.query('FLUSH PRIVILEGES')
ensure
close_repair_client
end
end
end
end
private
def desired_privs
possible_global_privs = [
:select,
:insert,
:update,
:delete,
:create,
:drop,
:references,
:index,
:alter,
:create_tmp_table,
:lock_tables,
:create_view,
:show_view,
:create_routine,
:alter_routine,
:execute,
:event,
:trigger,
:reload,
:shutdown,
:process,
:file,
:show_db,
:super,
:repl_slave,
:repl_client,
:create_user,
]
possible_db_privs = [
:select,
:insert,
:update,
:delete,
:create,
:drop,
:references,
:index,
:alter,
:create_tmp_table,
:lock_tables,
:create_view,
:show_view,
:create_routine,
:alter_routine,
:execute,
:event,
:trigger,
]
# convert :all to the individual db or global privs
desired_privs = if new_resource.privileges == [:all] && new_resource.database_name
possible_db_privs
elsif new_resource.privileges == [:all]
possible_global_privs
else
new_resource.privileges
end
desired_privs
end
def test_client
require 'mysql2'
@test_client ||=
Mysql2::Client.new(
host: new_resource.connection[:host],
socket: new_resource.connection[:socket],
username: new_resource.connection[:username],
password: new_resource.connection[:password],
port: new_resource.connection[:port],
default_file: new_resource.connection[:default_file],
default_group: new_resource.connection[:default_group]
)
end
def close_test_client
@test_client.close if @test_client
rescue Mysql2::Error
@test_client = nil
end
def repair_client
require 'mysql2'
@repair_client ||=
Mysql2::Client.new(
host: new_resource.connection[:host],
socket: new_resource.connection[:socket],
username: new_resource.connection[:username],
password: new_resource.connection[:password],
port: new_resource.connection[:port],
default_file: new_resource.connection[:default_file],
default_group: new_resource.connection[:default_group]
)
end
def close_repair_client
@repair_client.close if @repair_client
rescue Mysql2::Error
@repair_client = nil
end
def revokify_key(key)
return '' if key.nil?
# Some keys need to be translated as outlined by the table found here:
# https://dev.mysql.com/doc/refman/5.7/en/privileges-provided.html
result = key.to_s.downcase.tr('_', ' ').gsub('repl ', 'replication ').gsub('create tmp table', 'create temporary tables').gsub('show db', 'show databases')
result = result.gsub(/ priv$/, '')
result
end
def test_user_password
if database_has_password_column(test_client)
test_sql = 'SELECT User,Host,Password FROM mysql.user ' \
"WHERE User='#{new_resource.username}' AND Host='#{new_resource.host}' "
test_sql += if new_resource.password.is_a? HashedPassword
"AND Password='#{new_resource.password}'"
else
"AND Password=PASSWORD('#{new_resource.password}')"
end
else
test_sql = 'SELECT User,Host,authentication_string FROM mysql.user ' \
"WHERE User='#{new_resource.username}' AND Host='#{new_resource.host}' " \
"AND plugin='mysql_native_password' "
test_sql += if new_resource.password.is_a? HashedPassword
"AND authentication_string='#{new_resource.password}'"
else
"AND authentication_string=PASSWORD('#{new_resource.password}')"
end
end
test_client.query(test_sql).size > 0
end
def update_user_password
converge_by "Updating password of user '#{new_resource.username}'@'#{new_resource.host}'" do
begin
if database_has_password_column(repair_client)
repair_sql = "SET PASSWORD FOR '#{new_resource.username}'@'#{new_resource.host}' = "
repair_sql += if new_resource.password.is_a? HashedPassword
"'#{new_resource.password}'"
else
" PASSWORD('#{new_resource.password}')"
end
else
# "ALTER USER is now the preferred statement for assigning passwords."
# http://dev.mysql.com/doc/refman/5.7/en/set-password.html
repair_sql = "ALTER USER '#{new_resource.username}'@'#{new_resource.host}' "
repair_sql += if new_resource.password.is_a? HashedPassword
"IDENTIFIED WITH mysql_native_password AS '#{new_resource.password}'"
else
"IDENTIFIED BY '#{new_resource.password}'"
end
end
repair_client.query(repair_sql)
ensure
close_repair_client
end
end
end
def database_has_password_column(client)
client.query('SHOW COLUMNS FROM mysql.user WHERE Field="Password"').size > 0
end
def redact_password(query, password)
if password.nil? || password == ''
query
else
query.gsub(password, 'REDACTED')
end
end
end
end
end
end

View File

@ -0,0 +1,57 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Copyright:: 2011-2016, Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# 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.
#
# this file is originally from the database cookbook, preserved for legacy
# purposes until the functionality can be refactored into a custom resource.
# Original: https://github.com/chef-boneyard/database
require 'chef/resource'
class Chef
class Resource
class Database < Chef::Resource
resource_name :database
default_action :create
def initialize(name, run_context = nil)
super
@database_name = name
@allowed_actions.push(:create, :drop, :query)
end
property :database_name, String
property :connection, required: true
property :sql, [String, Proc]
property :template, String, default: 'DEFAULT'
property :collation, String
property :encoding, String, default: 'DEFAULT'
property :tablespace, String, default: 'DEFAULT'
property :connection_limit, String, default: '-1'
property :owner, String
def sql_query
if sql.is_a?(Proc)
sql.call
else
sql
end
end
end
end
end

View File

@ -0,0 +1,58 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Copyright:: 2011-2016, Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# 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.
#
# this file is originally from the database cookbook, preserved for legacy
# purposes until the functionality can be refactored into a custom resource.
# Original: https://github.com/chef-boneyard/database
require File.join(File.dirname(__FILE__), 'resource_database')
class Chef
class Resource
class DatabaseUser < Chef::Resource::Database
resource_name :database_user
default_action :create
def initialize(name, run_context = nil)
super
@username = name
@database_name = nil
@table = nil
@host = 'localhost'
@privileges = [:all]
@grant_option = false
@require_ssl = false
@require_x509 = false
@allowed_actions.push(:create, :drop, :grant, :revoke)
end
property :database_name, String
property :username, String
property :require_ssl, [true, false]
property :require_x509, [true, false]
property :password, String
property :table, String
property :host, String
property :privileges, Array
property :grant_option, [true, false], default: false
end
end
end

View File

@ -0,0 +1,37 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Author:: Sean OMeara (<sean@sean.io>)
# Copyright:: 2011-2016, Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# 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.
#
# this file is originally from the database cookbook, preserved for legacy
# purposes until the functionality can be refactored into a custom resource.
# Original: https://github.com/chef-boneyard/database
require File.join(File.dirname(__FILE__), 'provider_database_mysql')
class Chef
class Resource
class MysqlDatabase < Chef::Resource::Database
resource_name :mysql_database
def initialize(name, run_context = nil)
super
@provider = Chef::Provider::Database::Mysql
end
end
end
end

View File

@ -0,0 +1,38 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
# Copyright:: 2011-2016, Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# 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.
#
# this file is originally from the database cookbook, preserved for legacy
# purposes until the functionality can be refactored into a custom resource.
# Original: https://github.com/chef-boneyard/database
require File.join(File.dirname(__FILE__), 'resource_database_user')
require File.join(File.dirname(__FILE__), 'provider_database_mysql_user')
class Chef
class Resource
class MysqlDatabaseUser < Chef::Resource::DatabaseUser
resource_name :mysql_database_user
def initialize(name, run_context = nil)
super
@provider = Chef::Provider::Database::MysqlUser
end
property :password, [String, HashedPassword]
end
end
end

View File

@ -1,9 +1,9 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# library:: search
#
# Copyright 2013, AT&T Services, Inc.
# Copyright:: 2013, AT&T Services, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,10 +1,10 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# library:: uri
#
# Copyright 2012-2013, AT&T Services, Inc.
# Copyright:: 2012-2013, AT&T Services, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# library:: wrappers
#
# Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -3,17 +3,13 @@ maintainer 'openstack-chef'
maintainer_email 'openstack-discuss@lists.openstack.org'
license 'Apache-2.0'
description 'Common OpenStack attributes, libraries and recipes.'
version '18.0.0'
recipe 'openstack-common', 'Installs/Configures common recipes'
recipe 'openstack-common::logging', 'Installs/Configures common logging'
recipe 'openstack-common::sysctl', 'Configures sysctl settings'
version '19.0.0'
%w(ubuntu redhat centos).each do |os|
supports os
end
depends 'etcd', '~> 5.5'
depends 'etcd', '~> 5.6'
depends 'mariadb', '~> 3.1'
depends 'memcached', '~> 4.1'
depends 'mysql', '~> 8.2'
@ -22,4 +18,4 @@ depends 'yum-epel'
issues_url 'https://launchpad.net/openstack-chef'
source_url 'https://opendev.org/openstack/cookbook-openstack-common'
chef_version '>= 14.0'
chef_version '>= 15.0'

View File

@ -1,10 +1,10 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# Recipe:: client
#
# Copyright 2014, IBM Corp.
# Copyright 2017, cloudbau GmbH
# Copyright:: 2014, IBM Corp.
# Copyright:: 2017, cloudbau GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,9 +1,10 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# Recipe:: completions
#
# Copyright 2019, x-ion GmbH
# Copyright:: 2019, x-ion GmbH
# Copyright:: 2020, Oregon State University
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -17,9 +18,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
package 'bash-completion'
bash_complete = node['openstack']['common']['bash_complete']
execute 'create OSC bash completions' do
command "openstack complete > #{bash_complete}"
creates bash_complete
command "openstack complete > #{node['openstack']['common']['bash_complete']}"
creates node['openstack']['common']['bash_complete']
end

View File

@ -1,9 +1,9 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# library:: default
#
# Copyright 2012-2013, AT&T Services, Inc.
# Copyright:: 2012-2013, AT&T Services, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -34,7 +34,7 @@ when 'debian'
file '/etc/apt/apt.conf.d/confdef' do
owner 'root'
group 'root'
mode 00644
mode '644'
content 'Dpkg::Options {
"--force-confdef";
"--force-confold";

View File

@ -1,9 +1,10 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# library:: etcd
#
# Copyright 2017, Workday Inc.
# Copyright:: 2017, Workday Inc.
# Copyright:: 2020, Oregon State University
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -19,4 +20,6 @@
#
# create a new etcd installation named 'openstack'
etcd_service 'openstack'
etcd_service 'openstack' do
action [:create, :start]
end

View File

@ -1,9 +1,9 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# library:: logging
#
# Copyright 2012-2013, AT&T Services, Inc.
# Copyright:: 2012-2013, AT&T Services, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -21,7 +21,7 @@
directory '/etc/openstack' do
owner 'root'
group 'root'
mode 0o0755
mode '755'
action :create
end
@ -29,7 +29,7 @@ template '/etc/openstack/logging.conf' do
source 'logging.conf.erb'
owner 'root'
group 'root'
mode 0o0644
mode '644'
variables(
loggers: node['openstack']['logging']['loggers'],
formatters: node['openstack']['logging']['formatters'],

View File

@ -1,39 +0,0 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# recipe:: python
#
# Copyright 2017 Workday 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.
#
# install system packages for Ubuntu/Debian
case node['platform_family']
when 'debian'
python_runtime '3.5' do
provider :system
# Align with eg. OpenStack-Ansible (https://opendev.org/openstack/openstack-ansible/tree/global-requirement-pins.txt)
pip_version '18.0'
setuptools_version '40.0.0'
wheel_version '0.31.1'
end
# use Software Collections for CentOS/RHEL
when 'rhel'
python_runtime '3.5' do
provider :scl
pip_version '18.0'
setuptools_version '40.0.0'
wheel_version '0.31.1'
end
end

View File

@ -1,9 +1,10 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-common
# Cookbook:: openstack-common
# recipe:: sysctl
#
# Copyright 2013, Opscode, Inc.
# Copyright:: 2013, Opscode, Inc.
# Copyright:: 2020, Oregon State University
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -17,21 +18,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
directory '/etc/sysctl.d' do
owner 'root'
group 'root'
mode 0o0755
end
template '/etc/sysctl.d/60-openstack.conf' do
source '60-openstack.conf.erb'
owner 'root'
group 'root'
mode 0o0644
end
execute 'sysctl -p /etc/sysctl.d/60-openstack.conf' do
action :nothing
subscribes :run, 'template[/etc/sysctl.d/60-openstack.conf]', :immediately
node['openstack']['sysctl'].each do |name, value|
sysctl name do
value value
end
end

View File

@ -11,6 +11,9 @@ describe 'openstack-common::completions' do
it 'converges successfully' do
expect { chef_run }.to_not raise_error
end
it do
expect(chef_run).to install_package('bash-completion')
end
it do
expect(chef_run).to run_execute('create OSC bash completions')
.with(

View File

@ -1,7 +1,7 @@
name 'test-openstack-common-database'
maintainer 'openstack-chef'
maintainer_email 'opscode-chef-openstack@googlegroups.com'
license 'Apache 2.0'
license 'Apache-2.0'
description 'Test LWRP openstack_common_databse'
version '1.0.0'

View File

@ -82,10 +82,8 @@ describe 'openstack-common::default' do
end
it 'removes RDO yum repository' do
allow(FileTest).to receive(:exist?).and_call_original
allow(FileTest).to receive(:exist?).with('/etc/yum.repos.d/RDO-testrelease.repo').and_return(true)
# Using cookbook(yum) LWRP custom matcher
# https://github.com/sethvargo/chefspec#packaging-custom-matchers
expect(chef_run).to remove_yum_repository('RDO-testrelease')
end
it 'does include yum-epel recipe' do
@ -104,6 +102,7 @@ describe 'openstack-common::default' do
runner.converge(described_recipe)
end
it 'does nothing when RDO yum repository does not exist' do
allow(FileTest).to receive(:exist?).and_call_original
allow(FileTest).to receive(:exist?).with('/etc/yum.repos.d/RDO-testrelease.repo').and_return(false)
expect(chef_run).to nothing_yum_repository('RDO-testrelease')
end

View File

@ -14,10 +14,6 @@ describe 'openstack-common::default' do
expect { chef_run }.to_not raise_error
end
it 'does not include apt for apt-get update' do
expect(chef_run).to_not include_recipe 'apt'
end
context 'update_apt_cache true' do
cached(:chef_run) do
node.override['openstack']['apt']['update_apt_cache'] = true
@ -33,7 +29,7 @@ describe 'openstack-common::default' do
.with(
owner: 'root',
group: 'root',
mode: 00644,
mode: '644',
content: "Dpkg::Options {\n \"--force-confdef\";\n \"--force-confold\";\n }"
)
end
@ -52,7 +48,7 @@ describe 'openstack-common::default' do
# https://github.com/sethvargo/chefspec#packaging-custom-matchers
expect(chef_run).to add_apt_repository('openstack-ppa').with(
uri: 'http://ubuntu-cloud.archive.canonical.com/ubuntu',
distribution: 'bionic-updates/rocky',
distribution: 'bionic-updates/stein',
components: ['main'],
cache_rebuild: true
)
@ -67,7 +63,7 @@ describe 'openstack-common::default' do
it 'disables openstack live updates' do
expect(chef_run).to_not add_apt_repository('openstack-ppa').with(
uri: 'http://ubuntu-cloud.archive.canonical.com/ubuntu',
distribution: 'bionic-updates/rocky',
distribution: 'bionic-updates/stein',
components: ['main']
)
end
@ -76,7 +72,7 @@ describe 'openstack-common::default' do
it 'configures openstack proposed repository' do
expect(chef_run).to add_apt_repository('openstack-ppa-proposed').with(
uri: 'http://ubuntu-cloud.archive.canonical.com/ubuntu',
distribution: 'bionic-proposed/rocky',
distribution: 'bionic-proposed/stein',
components: ['main'],
cache_rebuild: true
)
@ -90,7 +86,7 @@ describe 'openstack-common::default' do
it 'disables openstack proposed repository' do
expect(chef_run).to_not add_apt_repository('openstack-ppa-proposed').with(
uri: 'http://ubuntu-cloud.archive.canonical.com/ubuntu',
distribution: 'bionic-proposed/rocky',
distribution: 'bionic-proposed/stein',
components: ['main']
)
end

View File

@ -14,7 +14,7 @@ describe 'openstack-common::logging' do
expect(chef_run).to create_directory('/etc/openstack').with(
owner: 'root',
group: 'root',
mode: 0o0755
mode: '755'
)
end
end
@ -26,7 +26,7 @@ describe 'openstack-common::logging' do
expect(chef_run).to create_template(file.name).with(
owner: 'root',
group: 'root',
mode: 0o0644
mode: '644'
)
end

View File

@ -4,7 +4,7 @@ require_relative 'spec_helper'
describe 'openstack-common::sysctl' do
describe 'ubuntu' do
sysctl_kv = {
'systcl_key1' => 'sysctl_value1',
'sysctl_key1' => 'sysctl_value1',
'sysctl_key2' => 'sysctl_value2',
}
let(:runner) { ChefSpec::SoloRunner.new(UBUNTU_OPTS) }
@ -13,37 +13,11 @@ describe 'openstack-common::sysctl' do
node.override['openstack']['sysctl'] = sysctl_kv
runner.converge(described_recipe)
end
describe 'sysctl.d directory' do
it 'should create /etc/systctl.d' do
expect(chef_run).to create_directory('/etc/sysctl.d')
end
it do
expect(chef_run).to apply_sysctl('sysctl_key1').with(value: 'sysctl_value1')
end
describe '60-openstack.conf' do
let(:file) { chef_run.template('/etc/sysctl.d/60-openstack.conf') }
it 'should create the template /etc/systctl.d/60-openstack.conf' do
expect(chef_run).to create_template('/etc/sysctl.d/60-openstack.conf').with(
owner: 'root',
group: 'root',
mode: 0o644
)
end
it 'sets the sysctl attributes' do
sysctl_kv.each do |k, v|
expect(chef_run).to render_file(file.name).with_content(/^#{k} = #{v}$/)
end
end
end
describe 'execute sysctl' do
it 'should execute sysctl for 60-openstack' do
resource = chef_run.execute('sysctl -p /etc/sysctl.d/60-openstack.conf')
expect(resource).to do_nothing
expect(resource).to subscribe_to('template[/etc/sysctl.d/60-openstack.conf]').on(:run).immediately
end
it do
expect(chef_run).to apply_sysctl('sysctl_key2').with(value: 'sysctl_value2')
end
end
end

View File

@ -12,7 +12,7 @@ describe 'Openstack uri' do
hash = {
'port' => 8888,
'path' => '/path',
'uri' => uri,
'uri' => uri,
}
result = subject.uri_from_hash(hash)
expect(result).to be_a URI
@ -23,9 +23,9 @@ describe 'Openstack uri' do
uri = 'https://localhost:8888/path'
hash = {
'scheme' => 'https',
'port' => 8888,
'path' => '/path',
'host' => 'localhost',
'port' => 8888,
'path' => '/path',
'host' => 'localhost',
}
expect(
subject.uri_from_hash(hash).to_s
@ -36,7 +36,7 @@ describe 'Openstack uri' do
uri = 'https://localhost'
hash = {
'scheme' => 'https',
'host' => 'localhost',
'host' => 'localhost',
}
expect(
subject.uri_from_hash(hash).to_s
@ -46,8 +46,8 @@ describe 'Openstack uri' do
it 'constructs with extraneous keys' do
uri = 'http://localhost'
hash = {
'host' => 'localhost',
'network' => 'public' # To emulate the osops-utils::ip_location way...
'host' => 'localhost',
'network' => 'public', # To emulate the osops-utils::ip_location way...
}
expect(
subject.uri_from_hash(hash).to_s