-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmigrate-db-cloudsql.sh
More file actions
184 lines (155 loc) · 6.99 KB
/
migrate-db-cloudsql.sh
File metadata and controls
184 lines (155 loc) · 6.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#!/bin/bash
INSTANCE_ORIGIN=...
INSTANCE_INTERMEDIATE=...
INSTANCE_DESTINATION=...
POSTGRES_DEST_PASSWORD=...
PROJ_ID=...
BUCKET_MIGRATION=...
DBs=(...)
ROLES=(...)
DEVELOPER_ROLE=...
DEVELOPER_ROLE_PWD=...
USER_ROLE=...
USER_ROLE_PWD=...
POSTGRES_ORIGIN_PWD=...
KUBECTX=...
NAMESPACE=...
# GET PASSWORDS FOR EACH ROLE FOR EACH DB #
kubectx $KUBECTX
kubens $NAMESPACE
PASSWORDS=()
for ROLE in "${ROLES[@]}"
PASSWORDS+=$(eval 'kubectl get secret ${ROLE}-user-credentials -o jsonpath="{.data.SPRING_DATASOURCE_PASSWORD}" | base64 --decode')
#echo $PASSWORDS
# SET PROJECT ID #
gcloud config set project $PROJ_ID
#gcloud auth login
# CREATE DEST INSTANCE #
terraform init
terraform apply --auto-approve # Previous step to create new IP range, it has to run in its entirety before the next cloning step
# CLONE ORIGIN INSTANCE #
gcloud sql instances clone $INSTANCE_ORIGIN $INSTANCE_INTERMEDIATE
# CREATE BUCKET AND ASSIGN PERMISSIONS TO IT #
SA_NAME_ORIGIN=$(gcloud sql instances describe $INSTANCE_INTERMEDIATE --format="value(serviceAccountEmailAddress)")
gcloud storage buckets create $BUCKET_MIGRATION
gsutil iam ch serviceAccount:${SA_NAME_ORIGIN}:objectAdmin $BUCKET_MIGRATION
# Query to fetch the table names from Search, necessary for next step #
INTERMEDIATE_INSTANCE_IP=$(gcloud sql instances describe ${INSTANCE_INTERMEDIATE} --format="value(ipAddresses[0].ipAddress)")
query="SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname != 'pg_catalog' AND schemaname != 'information_schema' AND tablename NOT LIKE 'hsearch%';"
output=$(psql postgresql://postgres:${POSTGRES_ORIGIN_PWD}@${INTERMEDIATE_INSTANCE_IP}/search -A -t -c "$query")
TABLE_NAMES=()
while IFS= read -r line; do
TABLE_NAMES+=("$line")
done <<< "$output"
# EXPORT DATABASES TO GCS #
for DB in "${DBs[@]}"; do
if [[ $DB == "search" ]]; then
for TABLE in "${TABLE_NAMES[@]}"; do
gcloud sql export sql $INSTANCE_INTERMEDIATE ${BUCKET_MIGRATION}/${DB}-${TABLE}.sql --database=$DB --async -t ${TABLE}
gcloud sql operations list --instance=$INSTANCE_INTERMEDIATE --filter='NOT status:done' --format='value(name)' | xargs -I {} gcloud sql operations wait {} --timeout=unlimited
done
else
gcloud sql export sql $INSTANCE_INTERMEDIATE ${BUCKET_MIGRATION}/${DB}.sql --database=$DB --async
gcloud sql operations list --instance=$INSTANCE_INTERMEDIATE --filter='NOT status:done' --format='value(name)' | xargs -I {} gcloud sql operations wait {} --timeout=unlimited
fi
done
# DELETE INTERMEDIATE INSTANCE #
gcloud sql instances delete $INSTANCE_INTERMEDIATE
# DEST INSTANCE CONFIG #
gcloud sql users set-password postgres --instance=${INSTANCE_DESTINATION} --password=${POSTGRES_DEST_PASSWORD}
DEST_INSTANCE_IP=$(gcloud sql instances describe ${INSTANCE_DESTINATION} --format="value(ipAddresses[0].ipAddress)")
# ASSIGN PERMISSIONS TO BUCKET #
SA_NAME_DEST=$(gcloud sql instances describe $INSTANCE_DESTINATION --format="value(serviceAccountEmailAddress)")
gsutil iam ch serviceAccount:${SA_NAME_DEST}:objectAdmin $BUCKET_MIGRATION
# CREATE DEFAULT USERS #
psql postgresql://postgres:${POSTGRES_DEST_PASSWORD}@${DEST_INSTANCE_IP}/postgres << EOF
CREATE role '${DEVELOPER_ROLE}' login encrypted password '${DEVELOPER_ROLE_PWD}';
CREATE role '${USER_ROLE}' login encrypted password '${USER_ROLE_PWD}';
EOF
# FUNCTION TO RUN SQL STATEMENTS #
function run_sql {
psql postgresql://postgres:${POSTGRES_DEST_PASSWORD}@${DEST_INSTANCE_IP}/postgres << EOF
CREATE database ${1};
CREATE role "${3}" login encrypted password '${2}';
GRANT ALL PRIVILEGES ON DATABASE ${1} to "${3}";
GRANT "${3}" to postgres;
GRANT USAGE ON SCHEMA public TO '${DEVELOPER_ROLE}';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO '${DEVELOPER_ROLE}';
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO '${DEVELOPER_ROLE}';
ALTER DEFAULT PRIVILEGES FOR ROLE "${3}" IN SCHEMA public GRANT SELECT ON SEQUENCES to '${DEVELOPER_ROLE}';
ALTER DEFAULT PRIVILEGES FOR ROLE "${3}" IN SCHEMA public GRANT SELECT ON TABLES to '${DEVELOPER_ROLE}';
EOF
}
# CREATE DATABASES AND ROLES IN NEW DB
LEN_DBS=${#DBs[@]}
for ((i=1; i<=$LEN_DBS; i+=1)); do
echo ${DBs[i]}
run_sql ${DBs[i]} ${PASSWORDS[i]} ${ROLES[i]}
done
for ((i=1; i<=$LEN_DBS; i+=1)); do
ALTER TABLE OWNER TO new_role_name;
# IMPORT DATABASES FROM GCS #
for ((i=1; i<=$LEN_DBS; i+=1)); do
echo ${DBs[i]}
if [[ ${DBs[i]} == "search" ]]; then
for TABLE in "${TABLE_NAMES[@]}"; do
gcloud sql import sql $INSTANCE_DESTINATION ${BUCKET_MIGRATION}/${DBs[i]}-${TABLE}.sql --database=${DBs[i]} --user=${ROLES[i]} -q
done
else
gcloud sql import sql $INSTANCE_DESTINATION ${BUCKET_MIGRATION}/${DBs[i]}.sql --database=${DBs[i]} --user=${ROLES[i]} -q
fi
sleep 10
done
# TABLES omitted, retry
for TABLE in "${TABLE_NAMES[@]}"; do
gcloud sql import sql $INSTANCE_DESTINATION ${BUCKET_MIGRATION}/search-${TABLE}.sql --database=search --user=search -q
sleep 10
done
# HIBERNATE-specific
psql postgresql://search:${PASSWORDS[7]}@${DEST_INSTANCE_IP}/search << EOF
create table if not exists hsearch_outbox_event
(
id bigint not null primary key,
entityname varchar(256),
entityid varchar(256),
entityidhash integer,
payload oid,
retries integer,
processafter timestamp,
status integer
);
create index if not exists entityidhash
on hsearch_outbox_event (entityidhash);
create index if not exists processafter
on hsearch_outbox_event (processafter);
create index if not exists status
on hsearch_outbox_event (status);
create table if not exists hsearch_agent
(
id bigint not null primary key,
type integer,
name varchar(255),
expiration timestamp,
state integer,
totalshardcount integer,
assignedshardindex integer,
payload oid
);
create sequence hsearch_outbox_event_generator;
create sequence hsearch_agent_generator;
create sequence base_order_id_sequence start with 1;
create sequence hibernate_sequence start with [REDACTED];
EOF
# IMPORT DATABASES FROM GCS #
for ((i=1; i<=$LEN_DBS; i+=1)); do
echo ${DBs[i]}
psql postgresql://${ROLES[i]}:${PASSWORDS[i]}@${DEST_INSTANCE_IP}/${DBs[i]} << EOF
GRANT SELECT ON ALL TABLES IN SCHEMA public TO '${USER_ROLE}';
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO '${USER_ROLE}';
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO '${USER_ROLE}';
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE, SELECT ON SEQUENCES TO '${USER_ROLE}';
EOF
done
# Delete migration bucket
gcloud storage rm --recursive $BUCKET_MIGRATION
# TODO: Delete the DBs from the old DB