Migrations infra & working instance-control + commands
This commit is contained in:
105
src/db.scm
105
src/db.scm
@@ -33,6 +33,7 @@
|
||||
(chicken string)
|
||||
(chicken port)
|
||||
(chicken io)
|
||||
(chicken sort)
|
||||
postgresql
|
||||
sql-null
|
||||
srfi-1
|
||||
@@ -295,7 +296,9 @@ returning users.user_id;"
|
||||
(nextcloud . "nextcloud_version")
|
||||
(ghost . "ghost_version")
|
||||
(nassella . "nassella_version")
|
||||
(log-viewer . "log_viewer_version")))
|
||||
(log-viewer . "log_viewer_version")
|
||||
(instance-control . "instance_control_version")
|
||||
))
|
||||
|
||||
(define *user-selected-apps-reverse-column-map*
|
||||
(map (lambda (config)
|
||||
@@ -493,7 +496,7 @@ returning users.user_id;"
|
||||
(map-in-order (lambda (d) (string-append "d." (cdr d))) *deployments-column-map*)
|
||||
", ")
|
||||
", uac.root_domain, uac.config_enc, uac.instance_id, "
|
||||
"usa.wg_easy_version, usa.nextcloud_version, usa.log_viewer_version, usa.ghost_version, usa.nassella_version "
|
||||
"usa.wg_easy_version, usa.nextcloud_version, usa.log_viewer_version, usa.ghost_version, usa.nassella_version, usa.instance_control_version "
|
||||
"from instances as i "
|
||||
"join (select instance_id, max(id) as id from deployments group by instance_id) d2 "
|
||||
"on d2.instance_id = i.instance_id "
|
||||
@@ -515,6 +518,7 @@ returning users.user_id;"
|
||||
(ghost_version . ghost)
|
||||
(nassella_version . nassella)
|
||||
(log_viewer_version . log-viewer)
|
||||
(instance_control_version . instance-control)
|
||||
,@*deployments-reverse-column-map*))))
|
||||
`(,config . ,(if (sql-null? value)
|
||||
#f
|
||||
@@ -553,8 +557,92 @@ returning users.user_id;"
|
||||
""
|
||||
(user-decrypt-from-db (alist-ref 'state_backup_enc res) user-key user-iv user-id)))))))
|
||||
|
||||
;; (define (instance-config-for-export conn user-id instance-id)
|
||||
;; (receive (user-key user-iv auth-user-id)
|
||||
;; (get-decrypted-user-key-and-iv conn user-id)
|
||||
;; (let ((res (row-alist
|
||||
;; (query conn
|
||||
;; "
|
||||
;; select
|
||||
;; instances.ssh_key_priv_enc,
|
||||
;; instances.ssh_key_pub_enc,
|
||||
;; instances.restic_password_enc,
|
||||
;; user_service_configs.cloudflare_api_token_enc,
|
||||
;; user_service_configs.cloudflare_account_id_enc,
|
||||
;; user_service_configs.cloudflare_zone_id_enc,
|
||||
;; user_service_configs.digitalocean_api_token_enc,
|
||||
;; user_service_configs.digitalocean_region,
|
||||
;; user_service_configs.digitalocean_size,
|
||||
;; user_service_configs.backblaze_application_key_enc,
|
||||
;; user_service_configs.backblaze_key_id_enc,
|
||||
;; user_service_configs.backblaze_bucket_url_enc,
|
||||
;; user_selected_apps.wg_easy_version,
|
||||
;; user_selected_apps.nextcloud_version,
|
||||
;; user_selected_apps.nassella_version,
|
||||
;; user_selected_apps.log_viewer_version,
|
||||
;; user_selected_apps.ghost_version,
|
||||
;; user_app_configs.root_domain,
|
||||
;; user_apps_configs.config_end
|
||||
;; from instances
|
||||
;; join user_service_configs on user_service_configs.user_id = instances.user_id and user_service_configs.instance_id = instances.instance_id
|
||||
;; join user_selected_apps on user_selected_apps.user_id = instances.user_id and user_selected_apps.instance_id = instances.instance_id
|
||||
;; join user_app_configs on user_apps_configs.user_id = instances.user_id and user_app_configs.instance_id = instances.instance_id
|
||||
;; where instances.user_id=$1 and instance.instance_id=$2;"
|
||||
;; user-id instance-id))))
|
||||
;; `((state . ,(if (or (sql-null? (alist-ref 'config_enc res))
|
||||
;; (sql-null? (alist-ref 'state_enc res)))
|
||||
;; ""
|
||||
;; (user-decrypt-from-db (alist-ref 'state_enc res) user-key user-iv user-id)))
|
||||
;; (backup . ,(if (or (sql-null? (alist-ref 'config_enc res))
|
||||
;; (sql-null? (alist-ref 'state_backup_enc res)))
|
||||
;; ""
|
||||
;; (user-decrypt-from-db (alist-ref 'state_backup_enc res) user-key user-iv user-id)))))))
|
||||
|
||||
;; TODO can/should this be removed? I don't remember why I put this here
|
||||
(debug-log (current-error-port))
|
||||
|
||||
;; An a-list of migrations. The car is the migration_id in the migrations
|
||||
;; table and the cdr is name of the file containing sql for the migration.
|
||||
;; The file name is appended with "-up.sql" and "-down.sql", depending on if
|
||||
;; an up or down migration should be run.
|
||||
;;
|
||||
;; After a migration has been run, it's migration id (the car in the alist) is
|
||||
;; added to the database so the migration does not get re-run.
|
||||
;;
|
||||
;; To create a new migration:
|
||||
;; add it to the end of this list with the car being one number higher than
|
||||
;; the previous migration and the cdr being the filename containing sql statements
|
||||
;; to run (not including a prefix of the ID or the suffic -up.sql or -down.sql).
|
||||
;; add two sql files in the "migrations" folder, one ending in -up.sql and one ending
|
||||
;; in -down.sql.
|
||||
;; So to for a migration called "my-migration" with id "13 create two files in the
|
||||
;; migrations directory: 13-my-migration-up.sql and 13-my-migration-down.sql
|
||||
;;
|
||||
;; The "up" file is called to run the migration and the "down" file is called to
|
||||
;; "undo" the migration.
|
||||
(define *migrations*
|
||||
'((0 . "adding-instance-control-app")))
|
||||
|
||||
(define (run-pending-migrations conn)
|
||||
(let* ((migration-ids (sort (map car *migrations*) <))
|
||||
(migration-rows (query conn "select migration_id from migrations;"))
|
||||
(applied-migration-ids (if (> (row-count migration-rows) 0)
|
||||
(row-values migration-rows)
|
||||
'())))
|
||||
(for-each
|
||||
(lambda (id)
|
||||
(when (not (member id applied-migration-ids))
|
||||
(log-to (debug-log) "running migration: ~A" id)
|
||||
(for-each
|
||||
(lambda (statement)
|
||||
(query conn (conc statement ";")))
|
||||
(string-split (with-input-from-file
|
||||
(conc "migrations/" id "-" (alist-ref id *migrations*) "-up.sql")
|
||||
read-string)
|
||||
";"))
|
||||
(query conn "insert into migrations(migration_id) values ($1);" id)))
|
||||
migration-ids)))
|
||||
|
||||
(define (db-init)
|
||||
(with-db/transaction
|
||||
(lambda (db)
|
||||
@@ -571,7 +659,18 @@ returning users.user_id;"
|
||||
(log-to (debug-log) "table creation finished")
|
||||
(log-to (debug-log) "creating test user")
|
||||
(create-user db "me@example.com" "username")
|
||||
(log-to (debug-log) "test user creation finished"))))))
|
||||
(log-to (debug-log) "test user creation finished")))
|
||||
;; originally there was no migrations table, so first add it if it doesn't exist
|
||||
(if (value-at (query db "SELECT EXISTS (SELECT FROM pg_tables WHERE schemaname = 'public' AND tablename = 'migrations');"))
|
||||
#t
|
||||
(begin
|
||||
(log-to (debug-log) "migrations table not found in db. Creating...")
|
||||
(query db "create table migrations(
|
||||
id bigserial primary key,
|
||||
migration_id integer not null unique
|
||||
);")
|
||||
(log-to (debug-log) "migrations table creation finished")))
|
||||
(run-pending-migrations db))))
|
||||
|
||||
(define (db-clean)
|
||||
(with-db/transaction
|
||||
|
||||
Reference in New Issue
Block a user