Skip to content

Commit 30fee70

Browse files
committed
fix: Upgrade infrastructure configuration
1 parent 3bbbb30 commit 30fee70

File tree

25 files changed

+593
-330
lines changed

25 files changed

+593
-330
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/bin/bash
2+
3+
# This Source Code Form is subject to the terms of the Mozilla Public
4+
# License, v. 2.0. If a copy of the MPL was not distributed with this
5+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
6+
#
7+
# OpenCRVS is also distributed under the terms of the Civil Registration
8+
# & Healthcare Disclaimer located at http://opencrvs.org/license.
9+
#
10+
# Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS.
11+
12+
#------------------------------------------------------------------------------------------------------------------
13+
# By default OpenCRVS saves a backup of all data on a cron job every day in case of an emergency data loss incident
14+
# This script downloads all the data based on --label (defaults to current day)
15+
#------------------------------------------------------------------------------------------------------------------
16+
17+
set -e
18+
19+
print_usage_and_exit() {
20+
echo 'Usage: ./rotate_backups.sh --backup_dir=/home/backup/backups --amount_to_keep=7'
21+
exit 1
22+
}
23+
24+
for i in "$@"; do
25+
case $i in
26+
--backup_dir=*)
27+
BACKUP_DIR="${i#*=}"
28+
shift
29+
;;
30+
--amount_to_keep=*)
31+
AMOUNT_TO_KEEP="${i#*=}"
32+
shift
33+
;;
34+
*) ;;
35+
esac
36+
done
37+
38+
39+
if ! [[ "$AMOUNT_TO_KEEP" =~ ^[0-9]+$ ]]; then
40+
echo "Script must be passed a positive integer number of backups to keep, got $AMOUNT_TO_KEEP"
41+
print_usage_and_exit
42+
fi
43+
44+
BACKUP_DIR=${BACKUP_DIR:-/home/backup/backups}
45+
46+
if [ ! -d "$BACKUP_DIR" ]; then
47+
echo "Error: BACKUP_DIR ($BACKUP_DIR) doesn't exist"
48+
print_usage_and_exit
49+
fi
50+
51+
# Delete subdirectories but keep latest according to AMOUNT_TO_KEEP
52+
find "$BACKUP_DIR" -mindepth 1 -type d -print | sort -r | tail -n +$(("$AMOUNT_TO_KEEP" + 1)) | xargs rm -rf --

infrastructure-k8s/environments/setup-environment.ts

Lines changed: 144 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ const githubQuestions = [
238238
{
239239
name: 'githubRepository',
240240
type: 'text' as const,
241-
message: 'What is your Github repository?',
241+
message: 'What is your Github infrastructure repository?',
242242
validate: notEmpty,
243243
initial: process.env.GITHUB_REPOSITORY,
244244
scope: 'REPOSITORY' as const
@@ -316,41 +316,63 @@ const countryQuestions = [
316316

317317
const infrastructureQuestions = [
318318
{
319-
name: 'numberOfServers',
320-
type: 'number' as const,
321-
message:
322-
'What is the number of servers? Note: This should be 1 for development, qa and staging. For "production" environment server cluster should consists of 2, 3 or 5 servers.',
319+
name: 'domain',
320+
type: 'text' as const,
321+
message: 'What is the web domain applied after all subdomains in URLs?',
323322
valueType: 'VARIABLE' as const,
324323
validate: notEmpty,
325-
valueLabel: 'NUMBER_OF_SERVERS',
326-
initial: process.env.NUMBER_OF_SERVERS ? parseInt(process.env.NUMBER_OF_SERVERS, 10) : 1,
324+
valueLabel: 'DOMAIN',
325+
initial: process.env.DOMAIN,
327326
scope: 'ENVIRONMENT' as const
328327
},
329328
{
330-
name: 'diskSpace',
329+
name: 'kubeAPIHost',
331330
type: 'text' as const,
332-
message: `What is the amount of diskspace that should be dedicated to OpenCRVS data and will become the size of an encrypted cryptfs data directory.
333-
\n${kleur.red('DO NOT USE ALL DISKSPACE FOR OPENCRVS!')}
334-
\nLeave at least 50g available for OS use.`,
331+
message:
332+
`Please enter Kubernetes hosts/IP to expose API endpoint, (default: first ethernet IP address):`,
335333
valueType: 'VARIABLE' as const,
336-
validate: notEmpty,
337-
valueLabel: 'DISK_SPACE',
338-
initial: process.env.DISK_SPACE || '200g',
334+
// validate: notEmpty,
335+
valueLabel: 'KUBE_API_HOST',
336+
initial: process.env.KUBE_API_HOST || '',
339337
scope: 'ENVIRONMENT' as const
340338
},
341339
{
342-
name: 'domain',
340+
name: 'workerNodes',
343341
type: 'text' as const,
344-
message: 'What is the web domain applied after all subdomains in URLs?',
342+
message:
343+
`Please enter Kubernetes workers hosts/IP addresses (comma-separated), (default: no workers):`,
345344
valueType: 'VARIABLE' as const,
346-
validate: notEmpty,
347-
valueLabel: 'DOMAIN',
348-
initial: process.env.DOMAIN,
349-
scope: 'ENVIRONMENT' as const
345+
// validate: notEmpty,
346+
valueLabel: 'WORKER_NODES',
347+
initial: process.env.WORKER_NODES || '',
348+
scope: 'ENVIRONMENT' as const,
349+
},
350+
{
351+
name: 'backupHost',
352+
type: 'text' as const,
353+
message:
354+
`Please enter backup server host/IP address, (default: no backup):`,
355+
valueType: 'VARIABLE' as const,
356+
// validate: ,
357+
valueLabel: 'BACKUP_HOST',
358+
initial: process.env.BACKUP_HOST || '',
359+
scope: 'ENVIRONMENT' as const,
350360
},
351361
]
352362

353363
const databaseAndMonitoringQuestions = [
364+
{
365+
name: 'diskSpace',
366+
type: 'text' as const,
367+
message: `What is the amount of diskspace that should be dedicated to OpenCRVS data and will become the size of an encrypted cryptfs data directory.
368+
\n${kleur.red('DO NOT USE ALL DISKSPACE FOR OPENCRVS!')}
369+
\nLeave at least 150g available for OS & Docker use.`,
370+
valueType: 'VARIABLE' as const,
371+
validate: notEmpty,
372+
valueLabel: 'DISK_SPACE',
373+
initial: process.env.DISK_SPACE || '200g',
374+
scope: 'ENVIRONMENT' as const
375+
},
354376
{
355377
name: 'kibanaUsername',
356378
type: 'text' as const,
@@ -512,17 +534,17 @@ const emailQuestions = [
512534
}
513535
]
514536

515-
const vpnHostQuestions = [
516-
{
517-
name: 'vpnAdminPassword',
518-
type: 'text' as const,
519-
message: `Admin password for Wireguard UI`,
520-
initial: generateLongPassword(),
521-
valueType: 'SECRET' as const,
522-
valueLabel: 'VPN_ADMIN_PASSWORD',
523-
scope: 'ENVIRONMENT' as const
524-
}
525-
]
537+
// const vpnHostQuestions = [
538+
// {
539+
// name: 'vpnAdminPassword',
540+
// type: 'text' as const,
541+
// message: `Admin password for Wireguard UI`,
542+
// initial: generateLongPassword(),
543+
// valueType: 'SECRET' as const,
544+
// valueLabel: 'VPN_ADMIN_PASSWORD',
545+
// scope: 'ENVIRONMENT' as const
546+
// }
547+
// ]
526548

527549
const sentryQuestions = [
528550
{
@@ -697,15 +719,15 @@ const metabaseAdminQuestions = [
697719

698720
ALL_QUESTIONS.push(
699721
...githubTokenQuestion,
700-
// Temporarily disable Docker Hub questions
701722
...dockerhubQuestions,
702723
...infrastructureQuestions,
703724
...countryQuestions,
704725
...databaseAndMonitoringQuestions,
705726
...notificationTransportQuestions,
706727
...smsQuestions,
707728
...emailQuestions,
708-
...vpnHostQuestions,
729+
// TODO: remove vpn questions
730+
// ...vpnHostQuestions,
709731
...sentryQuestions,
710732
...derivedVariables,
711733
...metabaseAdminQuestions
@@ -838,71 +860,78 @@ ALL_QUESTIONS.push(
838860

839861
await promptAndStoreAnswer(environment, dockerhubQuestions, existingValues)
840862

841-
log('\n', kleur.bold().underline('Databases & monitoring'))
863+
864+
log('\n', kleur.bold().underline('Kubernetes & Runtime'))
842865

843-
const infrastructure = await promptAndStoreAnswer(
844-
environment,
845-
infrastructureQuestions,
846-
existingValues
847-
)
848-
const number_of_servers = parseInt(infrastructure.numberOfServers, 10);
849-
generateInventory(environment, number_of_servers, {})
850-
copyChartsValues(environment, { env: environment})
851-
await promptAndStoreAnswer(
852-
environment,
853-
databaseAndMonitoringQuestions,
854-
existingValues
855-
)
856-
log('\n', kleur.bold().underline('Sentry'))
857-
const sentryDSNExists = findExistingValue(
858-
'SENTRY_DSN',
859-
'SECRET',
860-
'ENVIRONMENT',
861-
existingValues
866+
const infrastructure = await promptAndStoreAnswer(
867+
environment,
868+
infrastructureQuestions,
869+
existingValues
870+
)
871+
// FIXME: Review
872+
const workerNodes = infrastructure.workerNodes
873+
? infrastructure.workerNodes.split(',').map((ip: string) => ip.trim())
874+
: []
875+
const backupHost = infrastructure.backupHost || ''
876+
generateInventory(environment, {worker_nodes: workerNodes, backup_host: backupHost, kube_api_host: infrastructure.kubeAPIHost})
877+
copyChartsValues(environment, { env: environment})
878+
879+
log('\n', kleur.bold().underline('Databases & monitoring'))
880+
await promptAndStoreAnswer(
881+
environment,
882+
databaseAndMonitoringQuestions,
883+
existingValues
884+
)
885+
log('\n', kleur.bold().underline('Sentry'))
886+
const sentryDSNExists = findExistingValue(
887+
'SENTRY_DSN',
888+
'SECRET',
889+
'ENVIRONMENT',
890+
existingValues
891+
)
892+
893+
if (sentryDSNExists) {
894+
await promptAndStoreAnswer(environment, sentryQuestions, existingValues)
895+
} else {
896+
const { useSentry } = await prompts(
897+
[
898+
{
899+
name: 'useSentry',
900+
type: 'confirm' as const,
901+
message: 'Do you want to use Sentry?',
902+
scope: 'ENVIRONMENT' as const,
903+
initial: Boolean(process.env.SENTRY_DNS)
904+
}
905+
].map(questionToPrompt)
862906
)
863907

864-
if (sentryDSNExists) {
908+
if (useSentry) {
865909
await promptAndStoreAnswer(environment, sentryQuestions, existingValues)
866-
} else {
867-
const { useSentry } = await prompts(
868-
[
869-
{
870-
name: 'useSentry',
871-
type: 'confirm' as const,
872-
message: 'Do you want to use Sentry?',
873-
scope: 'ENVIRONMENT' as const,
874-
initial: Boolean(process.env.SENTRY_DNS)
875-
}
876-
].map(questionToPrompt)
877-
)
878-
879-
if (useSentry) {
880-
await promptAndStoreAnswer(environment, sentryQuestions, existingValues)
881-
}
882910
}
911+
}
883912

884-
log('\n', kleur.bold().underline('METABASE ADMIN'))
885-
await promptAndStoreAnswer(
886-
environment,
887-
metabaseAdminQuestions,
888-
existingValues
889-
)
913+
log('\n', kleur.bold().underline('METABASE ADMIN'))
914+
await promptAndStoreAnswer(
915+
environment,
916+
metabaseAdminQuestions,
917+
existingValues
918+
)
890919

891-
log('\n', kleur.bold().underline('SMTP'))
892-
await promptAndStoreAnswer(environment, emailQuestions, existingValues)
920+
log('\n', kleur.bold().underline('SMTP'))
921+
await promptAndStoreAnswer(environment, emailQuestions, existingValues)
893922

894-
log('\n', kleur.bold().underline('Notification'))
923+
log('\n', kleur.bold().underline('Notification'))
895924

896-
const { notificationTransport } = await promptAndStoreAnswer(
897-
environment,
898-
notificationTransportQuestions,
899-
existingValues
900-
)
925+
const { notificationTransport } = await promptAndStoreAnswer(
926+
environment,
927+
notificationTransportQuestions,
928+
existingValues
929+
)
930+
931+
if (notificationTransport.includes('sms')) {
932+
await promptAndStoreAnswer(environment, smsQuestions, existingValues)
933+
}
901934

902-
if (notificationTransport.includes('sms')) {
903-
await promptAndStoreAnswer(environment, smsQuestions, existingValues)
904-
}
905-
906935

907936
const allAnswers = ALL_ANSWERS.reduce((acc, answer) => {
908937
return { ...acc, ...answer }
@@ -1500,6 +1529,33 @@ ALL_QUESTIONS.push(
15001529
`Successfully updated Github secrets and variables for environment ${environment}`
15011530
)
15021531
)
1532+
1533+
const worker_message = workerNodes.length > 0 ?
1534+
`
1535+
-----------------------
1536+
➡️ ${kleur.bold().yellow('COPY the SSH public key from the master VM to your clipboard')}
1537+
-----------------------
1538+
➡️ ${kleur.bold().yellow('Run following command on Kubernetes worker VM to create provision user and setup SSH key:')}
1539+
1540+
curl -sfL https://raw.githubusercontent.com/opencrvs/infrastructure/refs/heads/ocrvs-9792/scripts/bootstrap/opencrvs-bootstrap.sh -o opencrvs-bootstrap.sh && \\
1541+
bash opencrvs-bootstrap.sh --ssh-public-key ${kleur.bold('[PUT PROVISION USER PUBLIC KEY FROM MASTER NODE]')}` : ''
1542+
1543+
log(`
1544+
${kleur.yellow('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')}
1545+
Follow the steps below to complete the setup of your environment:
1546+
${kleur.yellow('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')}
1547+
➡️ ${kleur.bold().yellow('Run following command on Kubernetes master VM to bootstrap self-hosted runner:')}
1548+
1549+
curl -sfL https://raw.githubusercontent.com/opencrvs/infrastructure/refs/heads/ocrvs-9792/scripts/bootstrap/opencrvs-bootstrap.sh -o opencrvs-bootstrap.sh && \\
1550+
bash opencrvs-bootstrap.sh --owner ${githubOrganisation} \\
1551+
--repo ${githubRepository} \\
1552+
--env ${environment} \\
1553+
--token ${githubToken} \\
1554+
--enable-runner
1555+
${worker_message}
1556+
1557+
${kleur.yellow('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')}
1558+
`)
15031559
log('\nAll variables stored in', kleur.cyan(`.env.${environment}`))
15041560
log(kleur.bold().yellow('DO NOT COMMIT THIS FILE TO GIT!'))
15051561
})()

0 commit comments

Comments
 (0)