-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add rdbms to playbook-website (#3778)
**What does this PR do?** Add a mysql database cluster to playbook's website. Depends on: - powerhome/software#869 - powerhome/pac-namespaces#447 The UX team asked Forever People to help add a MySQL cluster to the playbook-website's Rails app. This PR: - Adds the percona-xtradb-cluster-operator to the playbook namespaces to manage the `pxc` Kubernetes Custom Resource - Adds a `pxc` custom resource to represent the mysql cluster - Adds a migration hook / pod to run Rails migrations in the deployment pipeline before the new application image is started - Adds the ability to add and manage DB users, passwords, and grants via the application configuration (values.yaml and secrets.yaml) #### Checklist: - [ ] **LABELS** Add a label: `enhancement`, `bug`, `improvement`, `new kit`, `deprecated`, or `breaking`. See [Changelog & Labels](https://github.com/powerhome/playbook/wiki/Changelog-&-Labels) for details. - [ ] **DEPLOY** I have added the `milano` label to show I'm ready for a review. - [ ] **TESTS** I have added test coverage to my code.
- Loading branch information
1 parent
e36f8da
commit e64b8dc
Showing
24 changed files
with
656 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
class ApplicationRecord < ActiveRecord::Base | ||
primary_abstract_class | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
#!/bin/bash | ||
|
||
set -eo pipefail | ||
|
||
: ${baseline:="review"} | ||
|
||
function setup_colors() { | ||
if [[ -t 2 ]] && [[ -z "${NO_COLOR-}" ]] && [[ "${TERM-}" != "dumb" ]]; then | ||
NOFORMAT='\033[0m' | ||
RED='\033[0;31m' | ||
GREEN='\033[0;32m' | ||
ORANGE='\033[0;33m' | ||
BLUE='\033[0;34m' | ||
PURPLE='\033[0;35m' | ||
CYAN='\033[0;36m' | ||
YELLOW='\033[1;33m' | ||
else | ||
NOFORMAT='' RED='' GREEN='' ORANGE='' BLUE='' PURPLE='' CYAN='' YELLOW='' | ||
fi | ||
} | ||
export -f setup_colors | ||
setup_colors | ||
|
||
function begin { | ||
local message=$1 | ||
|
||
echo "\ | ||
======================================= | ||
BEGIN: $message | ||
======================================= | ||
" | ||
} | ||
export -f begin | ||
|
||
function succeed { | ||
local message=$1 | ||
|
||
echo -e "\ | ||
${GREEN} | ||
======================================= | ||
SUCCESS: $message | ||
======================================= | ||
${NOFORMAT}" | ||
} | ||
export -f succeed | ||
|
||
function fail { | ||
local message=$1 | ||
|
||
echo -e "\ | ||
#{RED} | ||
======================================= | ||
ERROR: $message | ||
======================================= | ||
#{NOFORMAT}" | ||
exit 1 | ||
} | ||
export -f fail | ||
|
||
function instance_name { | ||
local inst=$environment | ||
echo "$inst" | ||
} | ||
export -f instance_name | ||
|
||
function log() { | ||
echo >&2 -e "[$cluster][$namespace][$task_name] ${1-}" | ||
} | ||
|
||
log "BEGIN: $task_name" | ||
trap 'log "${RED:-}ERROR: $task_name - $cluster / $namespace${NOFORMAT:-}"' ERR | ||
|
||
function decrypt() { | ||
local encrypted_file_path= | ||
encrypted_file_path="$1" | ||
|
||
local decrypted_file_path= | ||
decrypted_file_path="$2" | ||
|
||
secrets="$(sops --decrypt "$encrypted_file_path")" | ||
if [ ! -e "$decrypted_file_path" ] | ||
then | ||
log "writing decrypted secrets for: $encrypted_file_path" | ||
echo -n "$secrets" > "$decrypted_file_path" | ||
fi | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
#!/bin/bash | ||
|
||
cluster="$1" | ||
namespace="$2" | ||
|
||
ctrl="kubectl --context $cluster -n $namespace" | ||
|
||
mysql_pod=$($ctrl get pods --no-headers -o custom-columns=":metadata.name" | grep 'pxc-0$') | ||
secret_po_name=$($ctrl get pxc -o jsonpath='{.items[0].spec.secretsName}') | ||
root_pwd=$(eval "$ctrl get secrets $secret_po_name -o jsonpath='{.data.root}'" | base64 --decode ) | ||
|
||
if [ -z "$mysql_pod" ]; then | ||
exit 0 | ||
fi | ||
|
||
mysql_pod="$mysql_pod -c pxc" | ||
|
||
users=$($ctrl get configmap mysql-users-playbook -o=jsonpath='{.data.users}' | sed 's/^"//;s/"$//;s/\\\"/\"/g') | ||
|
||
custom_users=() | ||
mysql_commands=() | ||
|
||
clean_up_users() { | ||
local percona_users=("root" "clustercheck" "monitor" "operator" "pmmserver" "proxyadmin" "replication" "xtrabackup") | ||
local target_users=("$@") | ||
|
||
if [ ${#target_users[@]} -gt 0 ]; then | ||
for element in "${target_users[@]}"; do | ||
percona_users+=("$element") | ||
done | ||
fi | ||
|
||
excluded_users_list=$(printf "'%s'," "${percona_users[@]}") | ||
excluded_users_list=${excluded_users_list%,} | ||
|
||
command="SELECT CONCAT(\"'\", user, \"'@'\", host, \"'\") FROM mysql.user WHERE NOT (user LIKE 'mysql%' OR user IN ($excluded_users_list));" | ||
|
||
users_to_delete=$($ctrl exec $mysql_pod -- mysql -uroot -p$root_pwd -N -e"$command") | ||
|
||
echo "--- List of MySQL users to delete:" | ||
echo $users_to_delete | ||
# Loop through the list of users and execute DROP USER statements | ||
# we can't use `delete from` statement as if it will be once deleted, | ||
# we will be unable to recreate it with the same name/password/grants due to mysql security policy | ||
for user in $users_to_delete; do | ||
$($ctrl exec $mysql_pod -- mysql -uroot -p$root_pwd -e "DROP USER $user;") | ||
done | ||
} | ||
|
||
if [ -z "$users" ]; then | ||
clean_up_users "${custom_users[@]}" | ||
exit 0 | ||
fi | ||
|
||
# Extract the count of user objects | ||
count=$(echo "$users" | grep -o '{' | wc -l) | ||
|
||
if [ "$count" -eq 0 ]; then | ||
clean_up_users "${custom_users[@]}" | ||
exit 0 | ||
fi | ||
|
||
for (( i=1; i<=$count; i++ )); do | ||
# Extracting each user block | ||
block=$(echo "$users" | awk -v RS='},' 'NR=='$i'') | ||
|
||
name=$(echo "$block" | grep -o '"name":"[^"]*"' | awk -F\" '{print $4}') | ||
grant=$(echo "$block" | grep -o '"grant":"[^"]*"' | awk -F\" '{print $4}') | ||
user_pwd=$(eval "$ctrl get secrets $secret_po_name -o jsonpath='{.data.$name}'" ) | ||
|
||
custom_users+=("$name") | ||
|
||
if [ -z "$user_pwd" ]; then | ||
echo "No password in $secret_po_name for user $name" | ||
exit 1 | ||
else | ||
user_pwd=$(echo "$user_pwd" | base64 --decode) | ||
fi | ||
|
||
mysql_commands+=("CREATE USER IF NOT EXISTS '$name'@'%' IDENTIFIED BY '$user_pwd'") | ||
|
||
# Extract dbs and append '.*' to each one | ||
dbs_raw=$(echo "$block" | grep -o '"dbs":\["[^]]*"' | sed 's/"dbs":\["//' | sed 's/"//g' | sed 's/,/, /g') | ||
IFS=', ' read -ra dbs_array <<< "$dbs_raw" | ||
for db in "${dbs_array[@]}"; do | ||
mysql_commands+=("GRANT $grant ON ${db}.* TO '$name'@'%'") | ||
done | ||
done | ||
|
||
clean_up_users "${custom_users[@]}" | ||
|
||
# get list of users with 'mysql_native_password' plugin | ||
users_w_deprecated_auth=$($ctrl exec $mysql_pod -- mysql -uroot -p$root_pwd -Bse "SELECT CONCAT(user, '@', host) FROM mysql.user WHERE plugin = 'mysql_native_password';") | ||
|
||
# alter authentication plugin | ||
for user in $users_w_deprecated_auth; do | ||
uname=$(echo "$user" | cut -d "@" -f 1) | ||
user_pwd=$(eval "$ctrl get secrets $secret_po_name -o jsonpath='{.data.$uname}'" ) | ||
if [ -n "$user_pwd" ]; then | ||
user_pwd=$(echo "$user_pwd" | base64 --decode) | ||
quoted_username=$(echo "$user" | sed "s/\(.*\)@\(.*\)/'\1'@'\2'/") | ||
mysql_commands+=("ALTER USER $quoted_username IDENTIFIED WITH caching_sha2_password BY '$user_pwd'") | ||
fi | ||
done | ||
|
||
mysql_commands+=("FLUSH PRIVILEGES;") | ||
|
||
IFS=';' | ||
joint_output="${mysql_commands[*]}" | ||
unset IFS | ||
|
||
$($ctrl exec $mysql_pod -- mysql -uroot -p$root_pwd -e "$joint_output") | ||
|
||
if [ $? -eq 0 ]; then | ||
echo "$joint_output" | sed "s/BY '[^']*'/BY '***'/g" | tr ';' '\n' | ||
echo "--- Users CREATED with password and granted permissions." | ||
else | ||
echo "--- User creation and permission granting FAILED" | ||
exit 1 | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#!/bin/bash | ||
|
||
task_name="Predeployment" | ||
source "$(dirname $(realpath $0))/deployment_helpers" | ||
|
||
log ">>> Installing dependencies at $tag into $environment ($cluster # $namespace)" | ||
|
||
instance=$(environment=$environment instance_name) | ||
|
||
operatorResources=$(krane render \ | ||
--filenames=/app/config/deploy/templates/operators \ | ||
--current-sha=${tag}) || exit $? | ||
echo "$operatorResources" | krane deploy ${namespace} ${cluster} \ | ||
--selector="app.kubernetes.io/component=operator" \ | ||
--verbose-log-prefix \ | ||
--global-timeout=300s \ | ||
--stdin | ||
|
||
log "${GREEN}SUCCESS: $task_name - $cluster / $namespace${NOFORMAT}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#!/bin/bash | ||
|
||
priorityResources=$(krane render \ | ||
--filenames="$(pwd)/config/deploy/templates/priority" \ | ||
--bindings="@${workDir}/config/deploy/values.yaml" $environmentValuesFile $environmentSecretsFile "image_tag=${tag}" "environment=${environment}" $extraBindings \ | ||
--current-sha=${tag}) || exit $? | ||
|
||
echo "$priorityResources" | krane deploy ${namespace} ${cluster} \ | ||
--selector="app.kubernetes.io/name=playbook,app.kubernetes.io/part-of=priority-deploy" \ | ||
--verbose-log-prefix \ | ||
--global-timeout=10m \ | ||
--stdin | ||
|
||
### run post priority scripts | ||
"${workDir}/bin/mysql/user-setup.sh" "$cluster" "$namespace" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.