I have Hiera running in combination with puppet/vagrant .
Say I have a puppet exec doing following
exec { create-project-database:
command => 'mysql -u root -e "CREATE DATABASE project_db DEFAULT CHARACTER SET = \'utf8\';"',
unless => 'mysql -u root information_schema -e "select * from information_schema.schemata;" | grep "project_db"',
require => Package[mysql-server],
}
I want to replace the string "project_db" with a variable I have inside my common.yaml of hiera
---
machine_message: 'This is the dev machine!'
codes_path: '/vagrant/code/laravel/'
project_db: 'project_db'
How I go about this? The syntax is not clear for me, and something like this brings errors:
command => 'mysql -u root -e "CREATE DATABASE 'hiera('project_db)' DEFAULT CHARACTER SET = \'utf8\';"',
You have an issue with your quotes in 'hiera('project_db)' (i.e. you're not closing before the parentheses so hiera('project_db') should be correct)
usually I do declare variables from hiera before so something like this
$DB_NAME = hiera('project_db')
exec { create-project-database:
command => "mysql -u root -e \"CREATE DATABASE $DB_NAME DEFAULT CHARACTER SET = 'utf8';\"",
unless => 'mysql -u root information_schema -e "select * from information_schema.schemata;" | grep "project_db"',
require => Package[mysql-server],
}
Related
I need in a bash script a IF condition on the existence of a role in a PostgreSQL database. I have found solutions in SQL code [1, 2], but I need something I can use directly in bash, I assume with the help of psql. In [2] there are also psql solutions, but I don't manage to adapt it in a IF statement.
I have tried this unsuccessfully (I am a PostgreSQL and bash newbie):
psql_USER=my
if [ "$( psql -h db -U postgres --no-psqlrc --single-transaction --pset=pager=off --tuples-only --set=ON_ERROR_STOP=1 -tc "SELECT 1 FROM pg_user WHERE usename = $psql_USER" | grep -q 1 )" == '1' ] > /dev/null 2> /dev/null; then
echo "HOURRA !"
fi;
Result is:
Password for user postgres:
ERROR: column « my » does not exist
LINE 1: SELECT 1 FROM pg_user WHERE usename = my
^
I would avoid the quoting problem like this:
if psql -Atq -c "SELECT '#' || usename || '#' FROM pg_user" | grep -q '#'"$psql_USER"'#'
then
echo yes
fi
The psql invocation selects a list of all usernames, prefixed and suffixed with #. The grep has return code 0 if psql_USER contains one of these user names, else 1. The then branch of if is only taken if the return code of the pipeline is 0, that is, if the user exists in the database.
I have a bash function where I check if a PostgreSQL database already exists.
I capture the output. If database exist PostgreSQL returns the database name as response.
function is_database() {
local database=$1
local output=$(sudo -u postgres psql -c "SELECT datname FROM pg_catalog.pg_database WHERE datname=\"$database\";")
if [[ $output = *"${1}"* ]]
then
return 0
else
return 1
fi
}
is_database test
I get the following error:
column "test" does not exist
I am not searching for a table, but a database.
Use single quotes for string literals:
sudo -u postgres psql \
-c "SELECT datname FROM pg_catalog.pg_database WHERE datname='$database'"
Your code as it is won't work for database names like has spaces or has'quotes.
The normal and formal here doc in bash script is as below.
clear-mysql(){
mysqlword="xxxxx"
port="22"
ip="11.22.33.44"
tmpdb="xxxx"
ssh -p $port root#{$ip} "mysql -u root -p$mysqlword <<EOF
use ${tmpdb};
UPDATE xx SET yy = replace(post_content, 'domain', '"http://$ip/wp"');
EOF"
}
And you can use another right format(a tab and <<- )in this kind of bash.
clear-mysql(){
mysqlword="xxxxx"
port="22"
ip="11.22.33.44"
tmpdb="xxxx"
ssh -p $port root#{$ip} "mysql -u root -p$mysqlword <<-EOF
use ${tmpdb};
UPDATE xx SET yy = replace(post_content, 'domain', '"http://$ip/wp"');
EOF"
}
Now i write a wrong format (two tabs and <<-) for this simple bash snippet as below.
clear-mysql(){
mysqlword="xxxxx"
port="22"
ip="11.22.33.44"
tmpdb="xxxx"
ssh -p $port root#{$ip} "mysql -u root -p$mysqlword <<-EOF
use ${tmpdb};
UPDATE xx SET yy = replace(post_content, 'domain', '"http://$ip/wp"');
EOF"
}
Copy and paste it into terminal.
I knew it is a wrong format and i knew the right here string format in bash.
What confused me is that why two tabs and <<-EOF and EOF result in listing all files in current directory?
Yes ,two tabs triggered auto completion,
[root#localhost tmp]#
Display all 1137 possibilities? (y or n)
Tab and tab will display all 1137 ,instead of listing files in current directory.
I have in my recipe this block:
bash "Create admin database tables" do
code "mysql -u root -D admindb < /vagrant/files/admin.sql"
not_if shell_out("mysql -u root -s --skip-column-names -e 'SELECT COUNT(DISTINCT table_name)>0 FROM information_schema.columns WHERE table_schema = \"admindb\";'").stdout().chomp()
end
Result of select query is 0 or 1 written to stdout (nothing more). I would like to run shell command only, if result of query will be 0. How can I achieve it?
You just need to use a Ruby equality operator inside the block. Since you said "only if" the output is 0, it would be simpler to do this with only_if rather than not_if:
only_if { shell_out("mysql -u root -s --skip-column-names -e 'SELECT COUNT(DISTINCT table_name)>0 FROM information_schema.columns WHERE table_schema = \"admindb\";'").stdout.chomp == '0' }
I am using the following construct to set a multiline string in bash shell. But this always returns false which does not work when I set set -e. How can I make this to return success?
#!/bin/bash
set -x
set -e
read -d '' QUERY <<EOF
UPDATE table_name SET
field1 = 'value',
field2 = 'value'
WHERE id = 1;
EOF
mysql table_name -e "$QUERY"
While not an answer to your original question, this does get your problem solved. Consider using substitution and e.g. cat
QUERY=$(cat <<EOM
test
test2
EOM
)
mysql table_name -e "$QUERY"
Please, be aware of safety issues if you're reading those values from unsanitized input.