Merge "common refactor for Pike and Chef 13"
This commit is contained in:
commit
6c6e8d2393
@ -1,6 +1,6 @@
|
||||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config`
|
||||
# on 2017-08-17 14:16:01 +0200 using RuboCop version 0.47.1.
|
||||
# on 2017-11-26 11:38:53 -0800 using RuboCop version 0.49.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,30 +11,17 @@ Lint/NestedMethodDefinition:
|
||||
Exclude:
|
||||
- 'libraries/matchers.rb'
|
||||
|
||||
# Offense count: 11
|
||||
Metrics/AbcSize:
|
||||
Max: 39
|
||||
|
||||
# Offense count: 44
|
||||
# Configuration parameters: CountComments, ExcludedMethods.
|
||||
Metrics/BlockLength:
|
||||
Max: 203
|
||||
|
||||
# Offense count: 1
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 13
|
||||
|
||||
# Offense count: 9
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: nested, compact
|
||||
Style/ClassAndModuleChildren:
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AutoCorrect, EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: predicate, comparison
|
||||
Style/NumericPredicate:
|
||||
Exclude:
|
||||
- 'libraries/cli.rb'
|
||||
- 'libraries/config_helpers.rb'
|
||||
- 'libraries/endpoints.rb'
|
||||
- 'libraries/network.rb'
|
||||
- 'libraries/parse.rb'
|
||||
- 'libraries/passwords.rb'
|
||||
- 'libraries/search.rb'
|
||||
- 'libraries/uri.rb'
|
||||
- 'libraries/wrappers.rb'
|
||||
- 'spec/**/*'
|
||||
- 'libraries/provider_database_mysql_user.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
Style/ZeroLengthPredicate:
|
||||
Exclude:
|
||||
- 'libraries/provider_database_mysql_user.rb'
|
||||
|
@ -1,4 +1,4 @@
|
||||
source "https://supermarket.chef.io"
|
||||
source 'https://supermarket.chef.io'
|
||||
|
||||
metadata
|
||||
|
||||
|
32
Rakefile
32
Rakefile
@ -1,41 +1,41 @@
|
||||
task default: ["test"]
|
||||
task default: ['test']
|
||||
|
||||
task :test => [:syntax, :lint, :unit]
|
||||
task test: [:syntax, :lint, :unit]
|
||||
|
||||
desc "Vendor the cookbooks in the Berksfile"
|
||||
desc 'Vendor the cookbooks in the Berksfile'
|
||||
task :berks_prep do
|
||||
sh %{chef exec berks vendor}
|
||||
sh %(chef exec berks vendor)
|
||||
end
|
||||
|
||||
desc "Run FoodCritic (syntax) tests"
|
||||
desc 'Run FoodCritic (syntax) tests'
|
||||
task :syntax do
|
||||
sh %{chef exec foodcritic --exclude spec -f any .}
|
||||
sh %(chef exec foodcritic --exclude spec -f any .)
|
||||
end
|
||||
|
||||
desc "Run RuboCop (lint) tests"
|
||||
desc 'Run RuboCop (lint) tests'
|
||||
task :lint do
|
||||
sh %{chef exec cookstyle}
|
||||
sh %(chef exec cookstyle)
|
||||
end
|
||||
|
||||
desc "Run RSpec (unit) tests"
|
||||
task :unit => :berks_prep do
|
||||
sh %{chef exec rspec --format documentation}
|
||||
desc 'Run RSpec (unit) tests'
|
||||
task unit: :berks_prep do
|
||||
sh %(chef exec rspec --format documentation)
|
||||
end
|
||||
|
||||
desc "Remove the berks-cookbooks directory and the Berksfile.lock"
|
||||
desc 'Remove the berks-cookbooks directory and the Berksfile.lock'
|
||||
task :clean do
|
||||
rm_rf [
|
||||
'berks-cookbooks',
|
||||
'Berksfile.lock'
|
||||
'Berksfile.lock',
|
||||
]
|
||||
end
|
||||
|
||||
desc "All-in-One Neutron build"
|
||||
task :integration => :common_integration do
|
||||
desc 'All-in-One Neutron build'
|
||||
task integration: :common_integration do
|
||||
# Noop
|
||||
end
|
||||
|
||||
desc "Common task used by all cookbooks for integration test"
|
||||
desc 'Common task used by all cookbooks for integration test'
|
||||
task :common_integration do
|
||||
# Use the berksfile support to make use of the existing patch clones.
|
||||
# Make a sym link from workspace/gate-cookbook-openstack-common-chef-rake-integration
|
||||
|
@ -109,7 +109,6 @@ default['openstack']['db']['options'] = {
|
||||
mysql: "?charset=#{node['openstack']['db']['charset']['mysql']}",
|
||||
'percona-cluster' => "?charset=#{node['openstack']['db']['charset']['percona-cluster']}",
|
||||
mariadb: "?charset=#{node['openstack']['db']['charset']['mariadb']}",
|
||||
postgresql: '',
|
||||
sqlite: '',
|
||||
nosql: '',
|
||||
galera: "?charset=#{node['openstack']['db']['charset']['galera']}",
|
||||
@ -117,7 +116,7 @@ default['openstack']['db']['options'] = {
|
||||
|
||||
# platform and DBMS-specific python client packages
|
||||
default['openstack']['db']['python_packages'] = {
|
||||
postgresql: ['python-psycopg2'],
|
||||
postgresql: [],
|
||||
sqlite: [],
|
||||
}
|
||||
case node['platform_family']
|
||||
@ -128,7 +127,7 @@ when 'rhel'
|
||||
default['openstack']['db']['python_packages']['percona-cluster'] = ['MySQL-python']
|
||||
default['openstack']['db']['python_packages']['galera'] = ['MySQL-python']
|
||||
when 'debian'
|
||||
default['openstack']['db']['service_type'] = 'mysql'
|
||||
default['openstack']['db']['service_type'] = 'mariadb'
|
||||
default['openstack']['db']['python_packages']['mysql'] = ['python-mysqldb']
|
||||
default['openstack']['db']['python_packages']['mariadb'] = ['python-mysqldb']
|
||||
default['openstack']['db']['python_packages']['percona-cluster'] = ['python-mysqldb']
|
||||
@ -140,7 +139,7 @@ case node['platform_family']
|
||||
when 'rhel'
|
||||
default['openstack']['db']['socket'] = '/var/lib/mysql/mysql.sock'
|
||||
when 'debian'
|
||||
default['openstack']['db']['socket'] = '/run/mysql-default/mysqld.sock'
|
||||
default['openstack']['db']['socket'] = '/var/run/mysqld/mysqld.sock'
|
||||
end
|
||||
|
||||
# Database used by the OpenStack services
|
||||
|
@ -292,11 +292,13 @@ default['openstack']['sysctl']['net.ipv4.conf.default.rp_filter'] = 0
|
||||
case node['platform_family']
|
||||
when 'rhel'
|
||||
default['openstack']['common']['platform'] = {
|
||||
'common_client_packages' => ['python-openstackclient'],
|
||||
'package_overrides' => '',
|
||||
}
|
||||
when 'debian'
|
||||
default['openstack']['common']['platform'] = {
|
||||
'package_overrides' => "-o Dpkg::Options::='--force-confold' -o Dpkg::Options::='--force-confdef'",
|
||||
'common_client_packages' => ['python-openstackclient'],
|
||||
'package_overrides' => '',
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -68,8 +68,6 @@ module ::Openstack
|
||||
|
||||
# Normalize to the SQLAlchemy standard db type identifier
|
||||
case type
|
||||
when 'pgsql'
|
||||
type = 'postgresql'
|
||||
when 'mariadb', 'galera', 'percona-cluster'
|
||||
type = 'mysql'
|
||||
end
|
||||
@ -91,7 +89,7 @@ module ::Openstack
|
||||
# Find the specific endpoint type ('internal', 'admin' or
|
||||
# 'public') for the given service.
|
||||
%w(public internal admin).each do |ep_type|
|
||||
define_method "#{ep_type}_endpoint" do |service|
|
||||
define_method("#{ep_type}_endpoint") do |service|
|
||||
uri_from_hash(node['openstack']['endpoints'][ep_type][service])
|
||||
end
|
||||
end
|
||||
|
52
libraries/hashed_password.rb
Normal file
52
libraries/hashed_password.rb
Normal file
@ -0,0 +1,52 @@
|
||||
#
|
||||
# Author:: Maksim Horbul (<max@gorbul.net>)
|
||||
# Cookbook:: openstack-common
|
||||
# Library:: hashed_password
|
||||
#
|
||||
# Copyright:: 2016, Eligible, 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.
|
||||
|
||||
# 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_mysql_database_user')
|
||||
|
||||
class HashedPassword
|
||||
# Initializes an object of the MysqlPassword type
|
||||
# @param [String] hashed_password mysql native hashed password
|
||||
# @return [MysqlPassword]
|
||||
def initialize(hashed_password)
|
||||
@hashed_password = hashed_password
|
||||
end
|
||||
|
||||
# String representation of the object
|
||||
# @return [String] hashed password string
|
||||
def to_s
|
||||
@hashed_password
|
||||
end
|
||||
|
||||
module Helpers
|
||||
# helper method wrappers the string into a MysqlPassword object
|
||||
# @param [String] hashed_password mysql native hashed password
|
||||
# @return [MysqlPassword] object
|
||||
def hashed_password(hashed_password)
|
||||
HashedPassword.new hashed_password
|
||||
end
|
||||
# For backward compatibility, because method was renamed
|
||||
alias_method :mysql_hashed_password, :hashed_password
|
||||
end
|
||||
end
|
||||
|
||||
::Chef::Resource::MysqlDatabaseUser.send(:include, HashedPassword::Helpers)
|
@ -95,4 +95,68 @@ if defined?(ChefSpec)
|
||||
def create_openstack_common_database(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(:openstack_common_database, :create, resource_name)
|
||||
end
|
||||
|
||||
# database
|
||||
#
|
||||
ChefSpec.define_matcher :database
|
||||
|
||||
def create_database(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(:database, :create, resource_name)
|
||||
end
|
||||
|
||||
def drop_database(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(:database, :drop, resource_name)
|
||||
end
|
||||
|
||||
def query_database(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(:database, :query, resource_name)
|
||||
end
|
||||
|
||||
# database user
|
||||
#
|
||||
ChefSpec.define_matcher :database_user
|
||||
|
||||
def create_database_user(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(:database_user, :create, resource_name)
|
||||
end
|
||||
|
||||
def drop_database_user(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(:database_user, :drop, resource_name)
|
||||
end
|
||||
|
||||
def grant_database_user(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(:database_user, :grant, resource_name)
|
||||
end
|
||||
|
||||
# mysql database
|
||||
#
|
||||
ChefSpec.define_matcher :mysql_database
|
||||
|
||||
def create_mysql_database(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(:mysql_database, :create, resource_name)
|
||||
end
|
||||
|
||||
def drop_mysql_database(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(:mysql_database, :drop, resource_name)
|
||||
end
|
||||
|
||||
def query_mysql_database(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(:mysql_database, :query, resource_name)
|
||||
end
|
||||
|
||||
# mysql database user
|
||||
#
|
||||
ChefSpec.define_matcher :mysql_database_user
|
||||
|
||||
def create_mysql_database_user(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(:mysql_database_user, :create, resource_name)
|
||||
end
|
||||
|
||||
def drop_mysql_database_user(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(:mysql_database_user, :drop, resource_name)
|
||||
end
|
||||
|
||||
def grant_mysql_database_user(resource_name)
|
||||
ChefSpec::Matchers::ResourceMatcher.new(:mysql_database_user, :grant, resource_name)
|
||||
end
|
||||
end
|
||||
|
@ -43,13 +43,13 @@ module ::Openstack
|
||||
def encrypted_secret(bag_name, index)
|
||||
key_path = node['openstack']['secret']['key_path']
|
||||
::Chef::Log.info "Loading encrypted databag #{bag_name}.#{index} using key at #{key_path}"
|
||||
secret = ::Chef::EncryptedDataBagItem.load_secret key_path
|
||||
::Chef::EncryptedDataBagItem.load(bag_name, index, secret)[index]
|
||||
secret = ::Chef::EncryptedDataBagItem.load_secret key_path # ~FC086
|
||||
::Chef::EncryptedDataBagItem.load(bag_name, index, secret)[index] # ~FC086
|
||||
end
|
||||
|
||||
def standard_secret(bag_name, index)
|
||||
::Chef::Log.info "Loading databag #{bag_name}.#{index}"
|
||||
::Chef::DataBagItem.load(bag_name, index)[index]
|
||||
::Chef::DataBagItem.load(bag_name, index)[index] # ~FC086
|
||||
end
|
||||
|
||||
def vault_secret(bag_name, index)
|
||||
|
170
libraries/provider_database_mysql.rb
Normal file
170
libraries/provider_database_mysql.rb
Normal file
@ -0,0 +1,170 @@
|
||||
#
|
||||
# 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
|
||||
use_inline_resources
|
||||
|
||||
def whyrun_supported?
|
||||
true
|
||||
end
|
||||
|
||||
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
|
388
libraries/provider_database_mysql_user.rb
Normal file
388
libraries/provider_database_mysql_user.rb
Normal file
@ -0,0 +1,388 @@
|
||||
#
|
||||
# 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
|
||||
use_inline_resources
|
||||
|
||||
def whyrun_supported?
|
||||
true
|
||||
end
|
||||
|
||||
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
|
122
libraries/resource_database.rb
Normal file
122
libraries/resource_database.rb
Normal file
@ -0,0 +1,122 @@
|
||||
#
|
||||
# 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
|
||||
def initialize(name, run_context = nil)
|
||||
super
|
||||
@resource_name = :database
|
||||
@database_name = name
|
||||
@allowed_actions.push(:create, :drop, :query)
|
||||
@action = :create
|
||||
end
|
||||
|
||||
def database_name(arg = nil)
|
||||
set_or_return(
|
||||
:database_name,
|
||||
arg,
|
||||
kind_of: String
|
||||
)
|
||||
end
|
||||
|
||||
def connection(arg = nil)
|
||||
set_or_return(
|
||||
:connection,
|
||||
arg,
|
||||
required: true
|
||||
)
|
||||
end
|
||||
|
||||
def sql(arg = nil, &block)
|
||||
arg ||= block
|
||||
set_or_return(
|
||||
:sql,
|
||||
arg,
|
||||
kind_of: [String, Proc]
|
||||
)
|
||||
end
|
||||
|
||||
def sql_query
|
||||
if sql.is_a?(Proc)
|
||||
sql.call
|
||||
else
|
||||
sql
|
||||
end
|
||||
end
|
||||
|
||||
def template(arg = nil)
|
||||
set_or_return(
|
||||
:template,
|
||||
arg,
|
||||
kind_of: String,
|
||||
default: 'DEFAULT'
|
||||
)
|
||||
end
|
||||
|
||||
def collation(arg = nil)
|
||||
set_or_return(
|
||||
:collation,
|
||||
arg,
|
||||
kind_of: String
|
||||
)
|
||||
end
|
||||
|
||||
def encoding(arg = nil)
|
||||
set_or_return(
|
||||
:encoding,
|
||||
arg,
|
||||
kind_of: String,
|
||||
default: 'DEFAULT'
|
||||
)
|
||||
end
|
||||
|
||||
def tablespace(arg = nil)
|
||||
set_or_return(
|
||||
:tablespace,
|
||||
arg,
|
||||
kind_of: String,
|
||||
default: 'DEFAULT'
|
||||
)
|
||||
end
|
||||
|
||||
def connection_limit(arg = nil)
|
||||
set_or_return(
|
||||
:connection_limit,
|
||||
arg,
|
||||
kind_of: String,
|
||||
default: '-1'
|
||||
)
|
||||
end
|
||||
|
||||
def owner(arg = nil)
|
||||
set_or_return(
|
||||
:owner,
|
||||
arg,
|
||||
kind_of: String
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
118
libraries/resource_database_user.rb
Normal file
118
libraries/resource_database_user.rb
Normal file
@ -0,0 +1,118 @@
|
||||
#
|
||||
# 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
|
||||
def initialize(name, run_context = nil)
|
||||
super
|
||||
@resource_name = :database_user
|
||||
@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)
|
||||
@action = :create
|
||||
end
|
||||
|
||||
def database_name(arg = nil)
|
||||
set_or_return(
|
||||
:database_name,
|
||||
arg,
|
||||
kind_of: String
|
||||
)
|
||||
end
|
||||
|
||||
def username(arg = nil)
|
||||
set_or_return(
|
||||
:username,
|
||||
arg,
|
||||
kind_of: String
|
||||
)
|
||||
end
|
||||
|
||||
def require_ssl(arg = nil)
|
||||
set_or_return(
|
||||
:require_ssl,
|
||||
arg,
|
||||
kind_of: [TrueClass, FalseClass]
|
||||
)
|
||||
end
|
||||
|
||||
def require_x509(arg = nil)
|
||||
set_or_return(
|
||||
:require_x509,
|
||||
arg,
|
||||
kind_of: [TrueClass, FalseClass]
|
||||
)
|
||||
end
|
||||
|
||||
def password(arg = nil)
|
||||
set_or_return(
|
||||
:password,
|
||||
arg,
|
||||
kind_of: String
|
||||
)
|
||||
end
|
||||
|
||||
def table(arg = nil)
|
||||
set_or_return(
|
||||
:table,
|
||||
arg,
|
||||
kind_of: String
|
||||
)
|
||||
end
|
||||
|
||||
def host(arg = nil)
|
||||
set_or_return(
|
||||
:host,
|
||||
arg,
|
||||
kind_of: String
|
||||
)
|
||||
end
|
||||
|
||||
def privileges(arg = nil)
|
||||
set_or_return(
|
||||
:privileges,
|
||||
arg,
|
||||
kind_of: Array
|
||||
)
|
||||
end
|
||||
|
||||
def grant_option(arg = nil)
|
||||
set_or_return(
|
||||
:grant_option,
|
||||
arg,
|
||||
kind_of: [TrueClass, FalseClass], default: false
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
36
libraries/resource_mysql_database.rb
Normal file
36
libraries/resource_mysql_database.rb
Normal file
@ -0,0 +1,36 @@
|
||||
#
|
||||
# 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
|
||||
def initialize(name, run_context = nil)
|
||||
super
|
||||
@resource_name = :mysql_database
|
||||
@provider = Chef::Provider::Database::Mysql
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
44
libraries/resource_mysql_database_user.rb
Normal file
44
libraries/resource_mysql_database_user.rb
Normal file
@ -0,0 +1,44 @@
|
||||
#
|
||||
# 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
|
||||
def initialize(name, run_context = nil)
|
||||
super
|
||||
@resource_name = :mysql_database_user
|
||||
@provider = Chef::Provider::Database::MysqlUser
|
||||
end
|
||||
|
||||
def password(arg = nil)
|
||||
set_or_return(
|
||||
:password,
|
||||
arg,
|
||||
kind_of: [String, HashedPassword]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,7 +1,7 @@
|
||||
name 'openstack-common'
|
||||
maintainer 'openstack-chef'
|
||||
maintainer_email 'openstack-dev@lists.openstack.org'
|
||||
license 'Apache 2.0'
|
||||
license 'Apache-2.0'
|
||||
description 'Common OpenStack attributes, libraries and recipes.'
|
||||
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
|
||||
version '16.0.0'
|
||||
@ -14,14 +14,12 @@ recipe 'openstack-common::sysctl', 'Configures sysctl settings'
|
||||
supports os
|
||||
end
|
||||
|
||||
depends 'apt', '~> 5.0'
|
||||
depends 'database', '~> 6.1'
|
||||
depends 'etcd', '~> 3.0'
|
||||
depends 'mariadb', '~> 1.5'
|
||||
depends 'memcached', '~> 4.1'
|
||||
depends 'mysql', '~> 8.2'
|
||||
depends 'yum', '~> 3.13'
|
||||
depends 'yum-epel', '~> 2.0'
|
||||
depends 'poise-python', '~> 1.5'
|
||||
depends 'selinux'
|
||||
|
||||
issues_url 'https://launchpad.net/openstack-chef' if respond_to?(:issues_url)
|
||||
source_url 'https://github.com/openstack/cookbook-openstack-common' if respond_to?(:source_url)
|
||||
|
@ -38,10 +38,6 @@ end
|
||||
|
||||
def db_types
|
||||
case @db_type
|
||||
when 'postgresql', 'pgsql'
|
||||
@db_prov = ::Chef::Provider::Database::Postgresql
|
||||
@user_prov = ::Chef::Provider::Database::PostgresqlUser
|
||||
@super_user = 'postgres'
|
||||
when 'mysql', 'mariadb', 'percona-cluster', 'galera'
|
||||
@db_prov = ::Chef::Provider::Database::Mysql
|
||||
@user_prov = ::Chef::Provider::Database::MysqlUser
|
||||
|
@ -19,4 +19,10 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package 'python-openstackclient'
|
||||
platform_options = node['openstack']['common']['platform']
|
||||
platform_options['common_client_packages'].each do |pkg|
|
||||
package pkg do
|
||||
options platform_options['package_overrides']
|
||||
action :upgrade
|
||||
end
|
||||
end
|
||||
|
@ -22,9 +22,26 @@ platform_options = node['openstack']['common']['platform']
|
||||
case node['platform_family']
|
||||
when 'debian'
|
||||
if node['openstack']['apt']['update_apt_cache']
|
||||
# Ensure we've done an apt-update first or packages won't be found.
|
||||
include_recipe 'apt'
|
||||
# update the apt cache before installing anything
|
||||
apt_update 'default' do
|
||||
action :update
|
||||
end
|
||||
end
|
||||
|
||||
# populate the necessary apt options
|
||||
# by default, do not overwrite existing configuration files
|
||||
# this alleviates the need to populate package_overrides in every cookbook
|
||||
file '/etc/apt/apt.conf.d/confdef' do
|
||||
owner 'root'
|
||||
group 'root'
|
||||
mode 00644
|
||||
content 'Dpkg::Options {
|
||||
"--force-confdef";
|
||||
"--force-confold";
|
||||
}'
|
||||
action :create
|
||||
end
|
||||
|
||||
package 'ubuntu-cloud-keyring' do
|
||||
options platform_options['package_overrides']
|
||||
action :upgrade
|
||||
@ -36,6 +53,7 @@ when 'debian'
|
||||
uri node['openstack']['apt']['uri']
|
||||
distribution "#{node['lsb']['codename']}-updates/#{node['openstack']['release']}"
|
||||
components apt_components
|
||||
cache_rebuild true # update the cache after a new repo is added
|
||||
end
|
||||
|
||||
# add in the proposed repo, but only if we're in development
|
||||
@ -50,19 +68,18 @@ when 'debian'
|
||||
distribution "#{node['lsb']['codename']}-proposed/#{node['openstack']['release']}"
|
||||
components apt_components
|
||||
action proposed_action
|
||||
cache_rebuild true # update the cache after a new repo is added
|
||||
end
|
||||
end
|
||||
when 'rhel'
|
||||
include_recipe 'yum' if node['openstack']['yum']['update_yum_cache']
|
||||
|
||||
if node['openstack']['yum']['rdo_enabled']
|
||||
repo_action = :add
|
||||
include_recipe 'yum-epel'
|
||||
elsif FileTest.exist? "/etc/yum.repos.d/RDO-#{node['openstack']['release']}.repo"
|
||||
repo_action = :remove
|
||||
else
|
||||
repo_action = :nothing
|
||||
end
|
||||
when 'rhel'
|
||||
repo_action = if node['openstack']['yum']['rdo_enabled']
|
||||
:add
|
||||
elsif FileTest.exist? "/etc/yum.repos.d/RDO-#{node['openstack']['release']}.repo"
|
||||
:remove
|
||||
else
|
||||
:nothing
|
||||
end
|
||||
|
||||
yum_repository "RDO-#{node['openstack']['release']}" do
|
||||
description "OpenStack RDO repo for #{node['openstack']['release']}"
|
||||
|
@ -23,9 +23,8 @@ describe 'openstack-common::default' do
|
||||
}
|
||||
end
|
||||
it 'returns cli enviroment' do
|
||||
allow(subject).to receive(:get_password)
|
||||
.with('user', 'name')
|
||||
.and_return('pass')
|
||||
allow(subject).to receive(:get_password).with(
|
||||
'user', 'name').and_return('pass')
|
||||
|
||||
expect(
|
||||
subject.openstack_command_env('name', 'project', 'default', 'default')
|
||||
@ -112,9 +111,10 @@ describe 'openstack-common::default' do
|
||||
'OS_AUTH_URL' => 'http://127.0.0.1:35357/v3',
|
||||
'OS_IDENTITY_API_VERSION' => 3,
|
||||
}
|
||||
allow(subject).to receive(:openstack_command).with('openstack', 'user list', env, {})
|
||||
allow(subject).to receive(:prettytable_to_array)
|
||||
.and_return([{ 'name' => 'user1', 'id' => '1234567890ABCDEFGH' }])
|
||||
allow(subject).to receive(:openstack_command).with(
|
||||
'openstack', 'user list', env, {})
|
||||
allow(subject).to receive(:prettytable_to_array).and_return(
|
||||
[{ 'name' => 'user1', 'id' => '1234567890ABCDEFGH' }])
|
||||
|
||||
result = subject.identity_uuid('user', 'name', 'user1', env)
|
||||
expect(result).to eq('1234567890ABCDEFGH')
|
||||
@ -135,17 +135,19 @@ describe 'openstack-common::default' do
|
||||
end
|
||||
|
||||
it 'runs glance command to query valid id' do
|
||||
allow(subject).to receive(:openstack_command).with('openstack', 'image list', :env, {})
|
||||
allow(subject).to receive(:prettytable_to_array)
|
||||
.and_return([{ 'ID' => '87f38e15-9737-46cc-a612-7c67ee29a24f', 'Name' => 'cirros' }])
|
||||
allow(subject).to receive(:openstack_command).with(
|
||||
'openstack', 'image list', :env, {})
|
||||
allow(subject).to receive(:prettytable_to_array).and_return(
|
||||
[{ 'ID' => '87f38e15-9737-46cc-a612-7c67ee29a24f', 'Name' => 'cirros' }])
|
||||
|
||||
result = subject.image_id('cirros', :env)
|
||||
expect(result).to eq('87f38e15-9737-46cc-a612-7c67ee29a24f')
|
||||
end
|
||||
|
||||
it 'runs glance command to query invalid id' do
|
||||
allow(subject).to receive(:openstack_command).with('openstack', 'image list', :env, {})
|
||||
.and_raise("No image with a name or ID of 'test' exists. (1)")
|
||||
allow(subject).to receive(:openstack_command).with(
|
||||
'openstack', 'image list', :env, {}).and_raise(
|
||||
"No image with a name or ID of 'test' exists. (1)")
|
||||
|
||||
expect { subject.image_id('test', :env) }.to raise_error(RuntimeError)
|
||||
end
|
||||
@ -163,9 +165,10 @@ describe 'openstack-common::default' do
|
||||
'OS_AUTH_URL' => 'http://127.0.0.1:35357/v3',
|
||||
'OS_IDENTITY_API_VERSION' => 3,
|
||||
}
|
||||
allow(subject).to receive(:openstack_command).with('openstack', 'network list', env, {})
|
||||
allow(subject).to receive(:prettytable_to_array)
|
||||
.and_return([{ 'name' => 'net1', 'id' => '1234567890ABCDEFGH' }])
|
||||
allow(subject).to receive(:openstack_command).with(
|
||||
'openstack', 'network list', env, {})
|
||||
allow(subject).to receive(:prettytable_to_array).and_return(
|
||||
[{ 'name' => 'net1', 'id' => '1234567890ABCDEFGH' }])
|
||||
|
||||
result = subject.network_uuid('network', 'name', 'net1', env)
|
||||
expect(result).to eq('1234567890ABCDEFGH')
|
||||
|
@ -10,7 +10,7 @@ describe 'openstack-common::client' do
|
||||
end
|
||||
|
||||
it do
|
||||
expect(chef_run).to install_package('python-openstackclient')
|
||||
expect(chef_run).to upgrade_package('python-openstackclient')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -30,7 +30,7 @@ describe 'test-openstack-common-database::default' do
|
||||
expect(chef_run).to create_database('create database service_db')
|
||||
.with(
|
||||
provider: ::Chef::Provider::Database::Mysql,
|
||||
connection: { host: 'localhost123', port: 3306, username: 'root', password: 'root_pass', socket: '/run/mysql-default/mysqld.sock' },
|
||||
connection: { host: 'localhost123', port: 3306, username: 'root', password: 'root_pass', socket: '/var/run/mysqld/mysqld.sock' },
|
||||
database_name: 'service_db',
|
||||
encoding: 'utf8'
|
||||
)
|
||||
@ -41,7 +41,7 @@ describe 'test-openstack-common-database::default' do
|
||||
expect(chef_run).to create_database('create database service_db')
|
||||
.with(
|
||||
provider: ::Chef::Provider::Database::Mysql,
|
||||
connection: { host: 'localhost', port: 3306, username: 'root', password: 'root_pass', socket: '/run/mysql-default/mysqld.sock' },
|
||||
connection: { host: 'localhost', port: 3306, username: 'root', password: 'root_pass', socket: '/var/run/mysqld/mysqld.sock' },
|
||||
database_name: 'service_db',
|
||||
encoding: 'utf8'
|
||||
)
|
||||
@ -51,7 +51,7 @@ describe 'test-openstack-common-database::default' do
|
||||
expect(chef_run).to create_database_user('create database user db_user')
|
||||
.with(
|
||||
provider: ::Chef::Provider::Database::MysqlUser,
|
||||
connection: { host: 'localhost', port: 3306, username: 'root', password: 'root_pass', socket: '/run/mysql-default/mysqld.sock' },
|
||||
connection: { host: 'localhost', port: 3306, username: 'root', password: 'root_pass', socket: '/var/run/mysqld/mysqld.sock' },
|
||||
username: 'db_user',
|
||||
password: 'db_pass'
|
||||
)
|
||||
@ -61,7 +61,7 @@ describe 'test-openstack-common-database::default' do
|
||||
expect(chef_run).to grant_database_user('grant database user db_user')
|
||||
.with(
|
||||
provider: ::Chef::Provider::Database::MysqlUser,
|
||||
connection: { host: 'localhost', port: 3306, username: 'root', password: 'root_pass', socket: '/run/mysql-default/mysqld.sock' },
|
||||
connection: { host: 'localhost', port: 3306, username: 'root', password: 'root_pass', socket: '/var/run/mysqld/mysqld.sock' },
|
||||
username: 'db_user',
|
||||
password: 'db_pass',
|
||||
database_name: 'service_db',
|
||||
|
@ -19,7 +19,6 @@ describe 'openstack-common::default' do
|
||||
before do
|
||||
node.set['openstack']['yum']['rdo_enabled'] = true
|
||||
node.set['openstack']['yum']['gpgcheck'] = true
|
||||
node.set['openstack']['yum']['update_yum_cache'] = true
|
||||
end
|
||||
|
||||
it 'adds RDO yum repository' do
|
||||
@ -29,12 +28,12 @@ describe 'openstack-common::default' do
|
||||
.with(gpgcheck: true)
|
||||
end
|
||||
|
||||
it 'includes yum recipe' do
|
||||
expect(chef_run).to include_recipe('yum')
|
||||
it 'does not include yum recipe' do
|
||||
expect(chef_run).to_not include_recipe('yum')
|
||||
end
|
||||
|
||||
it 'includes yum-epel recipe' do
|
||||
expect(chef_run).to include_recipe('yum-epel')
|
||||
it 'does not include yum-epel recipe' do
|
||||
expect(chef_run).to_not include_recipe('yum-epel')
|
||||
end
|
||||
end
|
||||
|
||||
@ -49,8 +48,8 @@ describe 'openstack-common::default' do
|
||||
.with(gpgcheck: false)
|
||||
end
|
||||
|
||||
it 'includes yum-epel recipe' do
|
||||
expect(chef_run).to include_recipe('yum-epel')
|
||||
it 'does not include yum-epel recipe' do
|
||||
expect(chef_run).to_not include_recipe('yum-epel')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -10,13 +10,13 @@ describe 'openstack-common::default' do
|
||||
runner.converge(described_recipe)
|
||||
end
|
||||
|
||||
it 'includes apt for apt-get update' do
|
||||
node.set['openstack']['apt']['update_apt_cache'] = 'true'
|
||||
expect(chef_run).to include_recipe 'apt'
|
||||
it 'does not include apt for apt-get update' do
|
||||
expect(chef_run).to_not include_recipe 'apt'
|
||||
end
|
||||
|
||||
it 'doesnt include apt for apt-get update' do
|
||||
expect(chef_run).to_not include_recipe 'apt'
|
||||
it 'updates apt cache before installing packages' do
|
||||
node.override['openstack']['apt']['update_apt_cache'] = true
|
||||
expect(chef_run).to update_apt_update 'default'
|
||||
end
|
||||
|
||||
it 'upgrades ubuntu-cloud-keyring package' do
|
||||
@ -30,7 +30,8 @@ describe 'openstack-common::default' do
|
||||
expect(chef_run).to add_apt_repository('openstack-ppa').with(
|
||||
uri: 'http://ubuntu-cloud.archive.canonical.com/ubuntu',
|
||||
distribution: 'xenial-updates/pike',
|
||||
components: ['main']
|
||||
components: ['main'],
|
||||
cache_rebuild: true
|
||||
)
|
||||
end
|
||||
|
||||
@ -47,7 +48,8 @@ describe 'openstack-common::default' do
|
||||
expect(chef_run).to add_apt_repository('openstack-ppa-proposed').with(
|
||||
uri: 'http://ubuntu-cloud.archive.canonical.com/ubuntu',
|
||||
distribution: 'xenial-proposed/pike',
|
||||
components: ['main']
|
||||
components: ['main'],
|
||||
cache_rebuild: true
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -16,8 +16,10 @@ describe 'openstack-common::default' do
|
||||
describe '#secret' do
|
||||
it 'returns databag' do
|
||||
value = { 'nova' => 'this' }
|
||||
allow(Chef::EncryptedDataBagItem).to receive(:load_secret).with('/etc/chef/openstack_data_bag_secret').and_return('secret')
|
||||
allow(Chef::EncryptedDataBagItem).to receive(:load).with('passwords', 'nova', 'secret').and_return(value)
|
||||
allow(Chef::EncryptedDataBagItem).to receive(:load_secret).with(
|
||||
'/etc/chef/openstack_data_bag_secret').and_return('secret')
|
||||
allow(Chef::EncryptedDataBagItem).to receive(:load).with(
|
||||
'passwords', 'nova', 'secret').and_return(value)
|
||||
expect(subject.secret('passwords', 'nova')).to eq('this')
|
||||
end
|
||||
end
|
||||
@ -27,7 +29,8 @@ describe 'openstack-common::default' do
|
||||
node.set['openstack']['databag_type'] = 'vault'
|
||||
end
|
||||
it 'returns the data from a chef vault item' do
|
||||
allow(ChefVault::Item).to receive(:load).with('vault_passwords', 'nova')
|
||||
allow(ChefVault::Item).to receive(:load)
|
||||
.with('vault_passwords', 'nova')
|
||||
.and_return('nova' => 'novapassword')
|
||||
expect(subject.secret('passwords', 'nova')).to eq('novapassword')
|
||||
end
|
||||
@ -37,8 +40,10 @@ describe 'openstack-common::default' do
|
||||
%w(service db user).each do |type|
|
||||
it "returns databag value for #{type}" do
|
||||
value = { 'nova' => 'this' }
|
||||
allow(Chef::EncryptedDataBagItem).to receive(:load_secret).with('/etc/chef/openstack_data_bag_secret').and_return('secret')
|
||||
allow(Chef::EncryptedDataBagItem).to receive(:load).with("#{type}_passwords", 'nova', 'secret').and_return(value)
|
||||
allow(Chef::EncryptedDataBagItem).to receive(:load_secret).with(
|
||||
'/etc/chef/openstack_data_bag_secret').and_return('secret')
|
||||
allow(Chef::EncryptedDataBagItem).to receive(:load).with(
|
||||
"#{type}_passwords", 'nova', 'secret').and_return(value)
|
||||
expect(subject.get_password(type, 'nova')).to eq('this')
|
||||
end
|
||||
end
|
||||
@ -65,7 +70,8 @@ describe 'openstack-common::default' do
|
||||
describe '#secret' do
|
||||
it 'returns databag' do
|
||||
value = { 'nova' => 'this' }
|
||||
allow(Chef::DataBagItem).to receive(:load).with('passwords', 'nova').and_return(value)
|
||||
allow(Chef::DataBagItem).to receive(:load)
|
||||
.with('passwords', 'nova').and_return(value)
|
||||
expect(subject.secret('passwords', 'nova')).to eq('this')
|
||||
end
|
||||
end
|
||||
@ -74,7 +80,8 @@ describe 'openstack-common::default' do
|
||||
%w(service db user).each do |type|
|
||||
it "returns databag value for #{type}" do
|
||||
value = { 'nova' => 'this' }
|
||||
allow(Chef::DataBagItem).to receive(:load).with("#{type}_passwords", 'nova').and_return(value)
|
||||
allow(Chef::DataBagItem).to receive(:load).with(
|
||||
"#{type}_passwords", 'nova').and_return(value)
|
||||
expect(subject.get_password(type, 'nova')).to eq('this')
|
||||
end
|
||||
end
|
||||
|
@ -12,7 +12,7 @@ UBUNTU_OPTS = {
|
||||
}.freeze
|
||||
REDHAT_OPTS = {
|
||||
platform: 'redhat',
|
||||
version: '7.1',
|
||||
version: '7.3',
|
||||
log_level: LOG_LEVEL,
|
||||
}.freeze
|
||||
# We set a default platform for non-platform specific test cases
|
||||
|
Loading…
x
Reference in New Issue
Block a user