Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

etcd to postgres #26

Merged
merged 42 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
8937578
changed database deployment from etcd to postgresql
Kek5chen Apr 26, 2024
d00f94f
refactor: changed config example
Kek5chen Apr 26, 2024
01a92ae
vicky: removed etcd-client added diesel
Kek5chen Apr 26, 2024
aad13df
vicky: added migrations and schema
Kek5chen Apr 26, 2024
252b81a
vickylib: renamed documents module to database
Kek5chen Apr 26, 2024
ba04be8
vickylib: have rust schema be generated in src/lib/database
Kek5chen Apr 26, 2024
78205fc
vickylib: added database schema
Kek5chen Apr 26, 2024
d0e298b
vickylib: renamed to TaskDatabase
Kek5chen Apr 26, 2024
715ed2e
vickylib: fix schema and up migration
Kek5chen Apr 26, 2024
8fab0b7
vickylib: remove etcd client
Kek5chen Apr 26, 2024
51ae0ed
vickylib: split mod into entities
Kek5chen Apr 26, 2024
5f14320
vickylib: add uuid feature to diesel for Uuid de/serialization
Kek5chen Apr 26, 2024
dc8d1dd
comment postgres-passwd
Kek5chen Apr 29, 2024
2002f90
add diesel error to thiserror VickyError
Kek5chen Apr 29, 2024
abefc83
update migration with nonnull and features
Kek5chen Apr 29, 2024
2c11eac
added into for TaskStatus from &str
Kek5chen Apr 29, 2024
de365e2
change ToString to Display
Kek5chen Apr 29, 2024
b083273
added async_trait to TaskDatabase
Kek5chen Apr 29, 2024
dc5f5f8
added get all tasks from database
Kek5chen Apr 29, 2024
4df0f43
added itertools
Kek5chen Apr 29, 2024
fef4464
added get_task function
Kek5chen Apr 29, 2024
bd09a7e
made get_all_tasks better
Kek5chen Apr 29, 2024
02c1c3f
function to put a task into the database
Kek5chen Apr 29, 2024
f5db967
removed etcd and changed to PgConnection
Kek5chen Apr 29, 2024
086fa4a
remove unused imports
Kek5chen Apr 29, 2024
43b0539
rustfmt
Kek5chen Apr 29, 2024
e99436b
changed Into<..> to From<..>
Kek5chen Apr 29, 2024
42fd6c4
removed clone from Uuid field t.id
Kek5chen Apr 29, 2024
0f23979
added r2d2 diesel integration and rocket_sync_db for connection pooling
Kek5chen Apr 29, 2024
890925f
removed old database config options
Kek5chen Apr 29, 2024
20e0037
PgConnection can't be async
Kek5chen Apr 29, 2024
c26a1dd
added Database type for connection pooling
Kek5chen Apr 29, 2024
af14b0b
maneuvered database to a connection pool
Kek5chen Apr 29, 2024
28ba688
add new struct to dblock to push into database
Kek5chen Apr 29, 2024
8ff3a24
format migration
Kek5chen Apr 30, 2024
8a868f5
add update_task to update database tasks
Kek5chen Apr 30, 2024
b3c2dc1
make use of pg arrays
Kek5chen May 2, 2024
11ec64c
use update instead of upsert
Kek5chen May 2, 2024
c666092
add comment for -1 in DbLock
Kek5chen May 2, 2024
335303d
use TryFrom for TaskStatus instead for now
Kek5chen May 2, 2024
cc6e1ac
mark dead code for CI since User.role is used
Kek5chen May 2, 2024
a665df0
restructured modules and formatted
Kek5chen May 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
436 changes: 120 additions & 316 deletions Cargo.lock

Large diffs are not rendered by default.

33 changes: 12 additions & 21 deletions deployment/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,28 +1,19 @@
services:
etcd:
image: quay.io/coreos/etcd:v3.5.9
entrypoint: /usr/local/bin/etcd
postgres:
image: postgres
ports:
- "2379:2379"
- "2380:2380"
- 5432:5432
restart: always

command:
- '--data-dir=/etcd-data'
- '--name=node1'
- '--initial-advertise-peer-urls=http://127.0.0.1:2380'
- '--listen-peer-urls=http://0.0.0.0:2380'
- '--advertise-client-urls=https://127.0.0.1:2379'
- '--listen-client-urls=https://0.0.0.0:2379'
- '--initial-cluster=node1=http://127.0.0.1:2380'
- '--trusted-ca-file=/certs/ca.crt'
- '--client-cert-auth'
- '--cert-file=/certs/cert.crt'
- '--key-file=/certs/cert.key'
volumes:
- "./data/etcd_data:/etcd-data"
- "../certs/Vicky_CA.crt:/certs/ca.crt"
- "../certs/etcd.crt:/certs/cert.crt"
- "../certs/etcd.key:/certs/cert.key"
# - "./config/postgres-passwd:/run/secrets/postgres-passwd"
- "./data/postgres_data:/var/lib/postgresql/data"
environment:
# POSTGRES_PASSWORD_FILE: /run/secrets/postgres-passwd
POSTGRES_USER: vicky
POSTGRES_PASSWORD: vicky
POSTGRES_DB: vicky

minio:
image: minio/minio
ports:
Expand Down
11 changes: 6 additions & 5 deletions vicky/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,23 @@ edition = "2021"
anyhow = "1.0.72"
clap = { version = "4.3.17", features = ["derive"] }
env_logger = "0.10.0"
etcd-client = { version = "0.11.1", features = ["tls"] }
log = "0.4.19"
rand = "0.8.5"
thiserror = "1.0.43"
tokio = { version = "1", features = ["full", "sync"] }
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"
serde_json = "1.0"
async-trait = "0.1.71"
aws-sdk-s3 = "0.28.0"
aws-config = "0.55.3"
uuid = { version="1.4.1", features = ["fast-rng", "v4", "serde"] }
rocket = { version="0.5.0", features = ["json", "secrets"] }
uuid = { version = "1.4.1", features = ["fast-rng", "v4", "serde"] }
rocket = { version = "0.5.0", features = ["json", "secrets"] }
rocket_dyn_templates = { version = "0.1.0", features = ["tera"] }
reqwest = { version="0.11.20", features = ["json"]}
rocket_sync_db_pools = { version = "0.1", features = ["diesel_postgres_pool"] }
reqwest = { version = "0.11.20", features = ["json"] }
jwtk = "0.3.0"
diesel = { version = "2.1.6", features = ["postgres", "uuid", "r2d2"] }
itertools = { version = "0.12.1" }

[[bin]]
name = "vicky"
Expand Down
8 changes: 2 additions & 6 deletions vicky/Rocket.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@ machines = [
"abc1234"
]

[default.etcd_config]
endpoints = [ "https://localhost:2379" ]
[default.etcd_config.tls_options]
ca_file = "../certs/Vicky_CA.crt"
certificate_file = "../certs/Vicky.crt"
key_file = "../certs/Vicky.key"
[default.databases]
postgres_db = { url = "postgres://vicky:vicky@localhost/vicky" }

[default.s3_config]
endpoint = "http://localhost:9000"
Expand Down
9 changes: 9 additions & 0 deletions vicky/diesel.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# For documentation on how to configure this file,
# see https://diesel.rs/guides/configuring-diesel-cli

[print_schema]
file = "src/lib/database/schema.rs"
custom_type_derives = ["diesel::query_builder::QueryId"]

[migrations_directory]
dir = "migrations"
Empty file added vicky/migrations/.keep
Empty file.
6 changes: 6 additions & 0 deletions vicky/migrations/00000000000000_diesel_initial_setup/down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-- This file was automatically created by Diesel to setup helper functions
-- and other internal bookkeeping. This file is safe to edit, any future
-- changes will be added to existing projects as new migrations.

DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass);
DROP FUNCTION IF EXISTS diesel_set_updated_at();
36 changes: 36 additions & 0 deletions vicky/migrations/00000000000000_diesel_initial_setup/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
-- This file was automatically created by Diesel to setup helper functions
-- and other internal bookkeeping. This file is safe to edit, any future
-- changes will be added to existing projects as new migrations.




-- Sets up a trigger for the given table to automatically set a column called
-- `updated_at` whenever the row is modified (unless `updated_at` was included
-- in the modified columns)
--
-- # Example
--
-- ```sql
-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW());
--
-- SELECT diesel_manage_updated_at('users');
-- ```
CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$
BEGIN
EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s
FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl);
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$
BEGIN
IF (
NEW IS DISTINCT FROM OLD AND
NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at
) THEN
NEW.updated_at := current_timestamp;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
2 changes: 2 additions & 0 deletions vicky/migrations/2024-04-26-080445_create_tasks/down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DROP TABLE locks;
DROP TABLE tasks;
20 changes: 20 additions & 0 deletions vicky/migrations/2024-04-26-080445_create_tasks/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
CREATE TABLE tasks
(
id uuid PRIMARY KEY,
display_name VARCHAR NOT NULL,
status VARCHAR NOT NULL,
features text[] NOT NULL,
flake_ref_uri VARCHAR NOT NULL,
flake_ref_args text[] NOT NULL
);

CREATE TABLE locks
(
id SERIAL PRIMARY KEY,
task_id uuid NOT NULL,
name VARCHAR NOT NULL,
type VARCHAR NOT NULL,
CONSTRAINT fk_task
FOREIGN KEY (task_id)
REFERENCES tasks (id)
);
1 change: 1 addition & 0 deletions vicky/src/bin/vicky/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub enum Role {
Admin,
}

#[allow(dead_code)]
#[derive(Deserialize)]
pub struct User {
pub full_name: String,
Expand Down
56 changes: 5 additions & 51 deletions vicky/src/bin/vicky/main.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
use std::time::Duration;

use aws_sdk_s3::config::{Credentials, Region};
use etcd_client::{Certificate, ConnectOptions, Identity, TlsOptions};
use jwtk::jwk::RemoteJwksVerifier;
use log::info;

use rand::Rng;
use rocket::fairing::AdHoc;
use rocket::figment::providers::{Env, Format, Toml};
use rocket::figment::{Figment, Profile};
use rocket::routes;
use serde::Deserialize;
use tokio::sync::broadcast;
use vickylib::etcd::election::{Election, NodeId};
use vickylib::database::entities::Database;
use vickylib::logs::LogDrain;
use vickylib::s3::client::S3Client;

Expand All @@ -30,18 +27,6 @@ mod events;
mod tasks;
mod user;

#[derive(Deserialize)]
pub struct TlsConfigOptions {
ca_file: String,
certificate_file: String,
key_file: String,
}
#[derive(Deserialize)]
pub struct EtcdConfig {
endpoints: Vec<String>,
tls_options: Option<TlsConfigOptions>,
}

#[derive(Deserialize)]
pub struct S3Config {
endpoint: String,
Expand All @@ -61,15 +46,16 @@ pub struct OIDCConfig {
pub struct Config {
machines: Vec<String>,

etcd_config: EtcdConfig,
s3_config: S3Config,

oidc_config: OIDCConfig,
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
env_logger::builder().filter_module("vicky", log::LevelFilter::Debug).init();
env_logger::builder()
.filter_module("vicky", log::LevelFilter::Debug)
.init();

// Took from rocket source code and added .split("__") to be able to add keys in nested structures.
let rocket_config_figment = Figment::from(rocket::Config::default())
Expand All @@ -89,28 +75,6 @@ async fn main() -> anyhow::Result<()> {

let app_config = build_rocket.figment().extract::<Config>()?;

let options = match app_config.etcd_config.tls_options {
Some(tls_options) => {
let server_root_ca_cert = std::fs::read_to_string(tls_options.ca_file)?;
let server_root_ca_cert = Certificate::from_pem(server_root_ca_cert);
let client_cert = std::fs::read_to_string(tls_options.certificate_file)?;
let client_key = std::fs::read_to_string(tls_options.key_file)?;
let client_identity = Identity::from_pem(client_cert, client_key);

Some(
TlsOptions::new()
.ca_certificate(server_root_ca_cert)
.identity(client_identity),
)
}
None => None,
};

let connect_options =
options.map(|options: TlsOptions| ConnectOptions::new().with_tls(options));
let etcd_client =
etcd_client::Client::connect(app_config.etcd_config.endpoints, connect_options).await?;

let jwks_verifier = RemoteJwksVerifier::new(
app_config.oidc_config.jwks_url,
None,
Expand All @@ -136,26 +100,16 @@ async fn main() -> anyhow::Result<()> {
let s3_ext_client_drain = S3Client::new(s3_client.clone(), aws_cfg.log_bucket.clone());
let s3_ext_client = S3Client::new(s3_client, aws_cfg.log_bucket.clone());

let mut rng = rand::thread_rng();
let node_id: NodeId = format!("node_{}", rng.gen::<i32>()).to_string();
info!("Generated unique node id as {}", node_id);

let mut election = Election::new(&etcd_client, node_id);
election.keep_alive();

election.elect().await?;
info!("Leader election won, we are now the leader!");

let log_drain = LogDrain::new(s3_ext_client_drain);

let (tx_global_events, _rx_task_events) = broadcast::channel::<GlobalEvent>(5);

build_rocket
.manage(etcd_client)
.manage(s3_ext_client)
.manage(log_drain)
.manage(jwks_verifier)
.manage(tx_global_events)
.attach(Database::fairing())
.attach(AdHoc::config::<Config>())
.mount("/api/v1/user", routes![get_user])
.mount("/api/v1/events", routes![get_global_events])
Expand Down
Loading
Loading