commit
afdba0f672
11 changed files with 214 additions and 6 deletions
|
@ -1,12 +1,19 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||||
<data-source source="LOCAL" name="acrate" uuid="8258414e-095d-430b-a0a5-b48e72af23a9">
|
<data-source source="LOCAL" name="local" uuid="8258414e-095d-430b-a0a5-b48e72af23a9">
|
||||||
<driver-ref>postgresql</driver-ref>
|
<driver-ref>postgresql</driver-ref>
|
||||||
<synchronize>true</synchronize>
|
<synchronize>true</synchronize>
|
||||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
||||||
<jdbc-url>jdbc:postgresql:///acrate</jdbc-url>
|
<jdbc-url>jdbc:postgresql:///acrate</jdbc-url>
|
||||||
<working-dir>$ProjectFileDir$</working-dir>
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
</data-source>
|
</data-source>
|
||||||
|
<data-source source="LOCAL" name="docker" uuid="b2437e47-6342-4bd6-8877-18b7dfe8c732">
|
||||||
|
<driver-ref>postgresql</driver-ref>
|
||||||
|
<synchronize>true</synchronize>
|
||||||
|
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
||||||
|
<jdbc-url>jdbc:postgresql://localhost:5432/postgres</jdbc-url>
|
||||||
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
|
</data-source>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
25
.idea/jsonSchemas.xml
Normal file
25
.idea/jsonSchemas.xml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JsonSchemaMappingsProjectConfiguration">
|
||||||
|
<state>
|
||||||
|
<map>
|
||||||
|
<entry key="docker-compose.yml">
|
||||||
|
<value>
|
||||||
|
<SchemaInfo>
|
||||||
|
<option name="name" value="docker-compose.yml" />
|
||||||
|
<option name="relativePathToSchema" value="https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json" />
|
||||||
|
<option name="applicationDefined" value="true" />
|
||||||
|
<option name="patterns">
|
||||||
|
<list>
|
||||||
|
<Item>
|
||||||
|
<option name="path" value="compose.yml" />
|
||||||
|
</Item>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</SchemaInfo>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
|
</project>
|
20
.idea/runConfigurations/Check.xml
Normal file
20
.idea/runConfigurations/Check.xml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Check" type="CargoCommandRunConfiguration" factoryName="Cargo Command" nameIsGenerated="true">
|
||||||
|
<option name="buildProfileId" value="dev" />
|
||||||
|
<option name="command" value="check" />
|
||||||
|
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||||
|
<envs />
|
||||||
|
<option name="emulateTerminal" value="true" />
|
||||||
|
<option name="channel" value="DEFAULT" />
|
||||||
|
<option name="requiredFeatures" value="true" />
|
||||||
|
<option name="allFeatures" value="false" />
|
||||||
|
<option name="withSudo" value="false" />
|
||||||
|
<option name="buildTarget" value="REMOTE" />
|
||||||
|
<option name="backtrace" value="SHORT" />
|
||||||
|
<option name="isRedirectInput" value="false" />
|
||||||
|
<option name="redirectInputPath" value="" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="CARGO.BUILD_TASK_PROVIDER" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
|
@ -13,7 +13,7 @@ categories = ["database"]
|
||||||
diesel = { version = "2.2.4", features = ["postgres", "uuid"] }
|
diesel = { version = "2.2.4", features = ["postgres", "uuid"] }
|
||||||
diesel-async = { version = "0.5.1", features = ["postgres"] }
|
diesel-async = { version = "0.5.1", features = ["postgres"] }
|
||||||
diesel_migrations = { version = "2.2.0", optional = true }
|
diesel_migrations = { version = "2.2.0", optional = true }
|
||||||
log = "0.4.22"
|
log = { version = "0.4.22", features = ["std", "max_level_trace", "release_max_level_debug"] }
|
||||||
mediatype = "0.19.18"
|
mediatype = "0.19.18"
|
||||||
micronfig = { version = "0.3.0", optional = true }
|
micronfig = { version = "0.3.0", optional = true }
|
||||||
mime = "0.3.17"
|
mime = "0.3.17"
|
||||||
|
|
32
acrate_docker/Dockerfile
Normal file
32
acrate_docker/Dockerfile
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
FROM rust AS base_builder
|
||||||
|
WORKDIR /usr/src/acrate
|
||||||
|
COPY --from=source ./acrate_database ./acrate_database
|
||||||
|
COPY --from=source ./acrate_nodeinfo ./acrate_nodeinfo
|
||||||
|
COPY --from=source ./acrate_rd ./acrate_rd
|
||||||
|
COPY --from=source ./acrate_rdserver ./acrate_rdserver
|
||||||
|
COPY --from=source ./Cargo.toml ./Cargo.toml
|
||||||
|
COPY --from=source ./Cargo.lock ./Cargo.lock
|
||||||
|
|
||||||
|
FROM rust:slim AS base_runner
|
||||||
|
RUN apt-get update
|
||||||
|
RUN apt-get upgrade --assume-yes
|
||||||
|
RUN apt-get install --assume-yes libpq5
|
||||||
|
WORKDIR /usr/local/bin
|
||||||
|
ENV RUST_LOG="warn"
|
||||||
|
|
||||||
|
FROM base_builder AS migrate_build
|
||||||
|
RUN cargo build --release --package=acrate_database --features=bin --bin=acrate_database_migrate
|
||||||
|
|
||||||
|
FROM base_runner AS migrate
|
||||||
|
COPY --from=migrate_build /usr/src/acrate/target/release/acrate_database_migrate /usr/local/bin/acrate_database_migrate
|
||||||
|
ENTRYPOINT ["acrate_database_migrate"]
|
||||||
|
ENV RUST_LOG="warn,acrate_database_migrate=info"
|
||||||
|
|
||||||
|
FROM base_builder AS rdserver_build
|
||||||
|
RUN cargo build --release --package=acrate_rdserver --bin=acrate_rdserver
|
||||||
|
|
||||||
|
FROM base_runner AS rdserver
|
||||||
|
COPY --from=rdserver_build /usr/src/acrate/target/release/acrate_rdserver /usr/local/bin/acrate_rdserver
|
||||||
|
ENTRYPOINT ["acrate_rdserver"]
|
||||||
|
HEALTHCHECK CMD ["curl", "http://127.0.0.1/.healthcheck"]
|
||||||
|
ENV RUST_LOG="warn,acrate_rdserver=info"
|
95
acrate_docker/compose.yml
Normal file
95
acrate_docker/compose.yml
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
# Full acrate stack, running on a single machine for experimental purposes
|
||||||
|
|
||||||
|
x-config:
|
||||||
|
ingress_config_dir: &ingress_config_dir "./config/caddy"
|
||||||
|
|
||||||
|
name: "acrate"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
ingress_data:
|
||||||
|
ingress_config:
|
||||||
|
postgres_data:
|
||||||
|
|
||||||
|
services:
|
||||||
|
# Public ingress node
|
||||||
|
ingress:
|
||||||
|
image: "caddy"
|
||||||
|
restart: "unless-stopped"
|
||||||
|
cap_add:
|
||||||
|
- "NET_ADMIN"
|
||||||
|
ports:
|
||||||
|
- protocol: "tcp"
|
||||||
|
target: 80
|
||||||
|
published: 80
|
||||||
|
- protocol: "tcp"
|
||||||
|
target: 443
|
||||||
|
published: 443
|
||||||
|
- protocol: "udp"
|
||||||
|
target: 443
|
||||||
|
published: 443
|
||||||
|
volumes:
|
||||||
|
- type: "volume"
|
||||||
|
source: "ingress_data"
|
||||||
|
target: "/data"
|
||||||
|
- type: "volume"
|
||||||
|
source: "ingress_config"
|
||||||
|
target: "/config"
|
||||||
|
- type: "bind"
|
||||||
|
source: *ingress_config_dir
|
||||||
|
target: "/etc/caddy"
|
||||||
|
|
||||||
|
# Main database
|
||||||
|
database:
|
||||||
|
image: "postgres"
|
||||||
|
restart: "unless-stopped"
|
||||||
|
environment:
|
||||||
|
# Make sure the password is the same for both client and server tools
|
||||||
|
POSTGRES_PASSWORD: &postgres_password "acrate"
|
||||||
|
PGUSER: "postgres"
|
||||||
|
PGPASS: *postgres_password
|
||||||
|
volumes:
|
||||||
|
- type: "volume"
|
||||||
|
source: "postgres_data"
|
||||||
|
target: "/var/lib/postgresql/data"
|
||||||
|
ports:
|
||||||
|
# FIXME: for development purposes only
|
||||||
|
- protocol: "tcp"
|
||||||
|
host_ip: "127.0.0.1"
|
||||||
|
target: 5432
|
||||||
|
published: 5432
|
||||||
|
expose:
|
||||||
|
- 5432
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready"]
|
||||||
|
|
||||||
|
# Migrations
|
||||||
|
migrate:
|
||||||
|
build:
|
||||||
|
dockerfile: "./Dockerfile"
|
||||||
|
additional_contexts:
|
||||||
|
- "source=.."
|
||||||
|
target: "migrate"
|
||||||
|
environment:
|
||||||
|
ACRATE_DATABASE_DATABASE_URL: &database_url "postgres:///postgres?host=database&user=postgres&password=acrate" # TODO: Split parameters off to their own envvars
|
||||||
|
depends_on:
|
||||||
|
database:
|
||||||
|
condition: "service_healthy"
|
||||||
|
|
||||||
|
# Resource descriptor server
|
||||||
|
rdserver:
|
||||||
|
build:
|
||||||
|
dockerfile: "./Dockerfile"
|
||||||
|
additional_contexts:
|
||||||
|
- "source=.."
|
||||||
|
target: "rdserver"
|
||||||
|
restart: "unless-stopped"
|
||||||
|
environment:
|
||||||
|
ACRATE_WEBFINGER_BIND_ADDRESS: "0.0.0.0:80"
|
||||||
|
ACRATE_WEBFINGER_DATABASE_URL: *database_url
|
||||||
|
expose:
|
||||||
|
- 80
|
||||||
|
depends_on:
|
||||||
|
database:
|
||||||
|
condition: "service_healthy"
|
||||||
|
migrate:
|
||||||
|
condition: "service_completed_successfully"
|
16
acrate_docker/config/caddy/Caddyfile
Normal file
16
acrate_docker/config/caddy/Caddyfile
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# replace with your HTTPS domain
|
||||||
|
:80 {
|
||||||
|
@rdserver {
|
||||||
|
path "/.well-known/webfinger"
|
||||||
|
path "/.well-known/host-meta"
|
||||||
|
path "/.well-known/host-meta.xml"
|
||||||
|
path "/.well-known/host-meta.json"
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse_proxy @rdserver {
|
||||||
|
to "http://rdserver"
|
||||||
|
|
||||||
|
health_uri "/.healthcheck"
|
||||||
|
health_status "204"
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ categories = ["web-programming"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
acrate_rd = { path = "../acrate_rd" }
|
acrate_rd = { path = "../acrate_rd" }
|
||||||
log = "0.4.22"
|
log = { version = "0.4.22", features = ["std", "max_level_trace", "release_max_level_debug"] }
|
||||||
mediatype = { version = "0.19.18", features = ["serde"] }
|
mediatype = { version = "0.19.18", features = ["serde"] }
|
||||||
reqwest = { version = "0.12.9", features = ["json", "stream"] }
|
reqwest = { version = "0.12.9", features = ["json", "stream"] }
|
||||||
serde = { version = "1.0.214", features = ["derive"] }
|
serde = { version = "1.0.214", features = ["derive"] }
|
||||||
|
|
|
@ -15,7 +15,7 @@ acrate_rd = { path = "../acrate_rd" }
|
||||||
anyhow = "1.0.93"
|
anyhow = "1.0.93"
|
||||||
axum = { version = "0.7.7", features = ["macros"] }
|
axum = { version = "0.7.7", features = ["macros"] }
|
||||||
axum-extra = { version = "0.9.4", features = ["query"] }
|
axum-extra = { version = "0.9.4", features = ["query"] }
|
||||||
log = "0.4.22"
|
log = { version = "0.4.22", features = ["std", "max_level_trace", "release_max_level_debug"] }
|
||||||
micronfig = "0.3.0"
|
micronfig = "0.3.0"
|
||||||
minijinja = "2.5.0"
|
minijinja = "2.5.0"
|
||||||
pretty_env_logger = "0.5.0"
|
pretty_env_logger = "0.5.0"
|
||||||
|
|
|
@ -21,6 +21,7 @@ async fn main() -> anyhow::Result<std::convert::Infallible> {
|
||||||
log::trace!("Creating Axum router...");
|
log::trace!("Creating Axum router...");
|
||||||
let app = axum::Router::new()
|
let app = axum::Router::new()
|
||||||
.route("/*path", axum::routing::get(route::webfinger_handler))
|
.route("/*path", axum::routing::get(route::webfinger_handler))
|
||||||
|
.route("/.healthcheck", axum::routing::get(route::healthcheck_handler))
|
||||||
.layer(Extension(Arc::new(mj)));
|
.layer(Extension(Arc::new(mj)));
|
||||||
log::trace!("Axum router created successfully!");
|
log::trace!("Axum router created successfully!");
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ async fn main() -> anyhow::Result<std::convert::Infallible> {
|
||||||
.context("failed to bind listener to address")?;
|
.context("failed to bind listener to address")?;
|
||||||
log::trace!("Tokio listener bound to: {bind_address}");
|
log::trace!("Tokio listener bound to: {bind_address}");
|
||||||
|
|
||||||
log::debug!("Starting server...");
|
log::info!("Starting server...");
|
||||||
axum::serve(listener, app)
|
axum::serve(listener, app)
|
||||||
.await
|
.await
|
||||||
.context("server exited with error")?;
|
.context("server exited with error")?;
|
||||||
|
|
|
@ -13,6 +13,18 @@ use acrate_rd::jrd::ResourceDescriptorLinkJRD;
|
||||||
use acrate_rd::xrd::{ResourceDescriptorLinkXRD, ResourceDescriptorPropertyXRD, ResourceDescriptorTitleXRD};
|
use acrate_rd::xrd::{ResourceDescriptorLinkXRD, ResourceDescriptorPropertyXRD, ResourceDescriptorTitleXRD};
|
||||||
use crate::config;
|
use crate::config;
|
||||||
|
|
||||||
|
pub async fn healthcheck_handler() -> Result<StatusCode, StatusCode> {
|
||||||
|
log::debug!("Handling an healthcheck request!");
|
||||||
|
|
||||||
|
log::trace!("Making sure the database is up...");
|
||||||
|
let _conn = AsyncPgConnection::establish(config::ACRATE_WEBFINGER_DATABASE_URL())
|
||||||
|
.await
|
||||||
|
.map_err(|_| StatusCode::BAD_GATEWAY)?;
|
||||||
|
|
||||||
|
log::trace!("Healthcheck successful! Everything's fine!");
|
||||||
|
Ok(StatusCode::NO_CONTENT)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
pub struct WebfingerQuery {
|
pub struct WebfingerQuery {
|
||||||
pub resource: Option<String>,
|
pub resource: Option<String>,
|
||||||
|
@ -27,7 +39,7 @@ pub async fn webfinger_handler(
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
Extension(mj): Extension<Arc<minijinja::Environment<'static>>>,
|
Extension(mj): Extension<Arc<minijinja::Environment<'static>>>,
|
||||||
) -> Result<Response<String>, StatusCode> {
|
) -> Result<Response<String>, StatusCode> {
|
||||||
log::info!("Handling a WebFinger request!");
|
log::debug!("Handling a WebFinger request!");
|
||||||
|
|
||||||
let resource = resource.unwrap_or_else(|| "".to_string());
|
let resource = resource.unwrap_or_else(|| "".to_string());
|
||||||
log::debug!("Resource is: {resource:#?}");
|
log::debug!("Resource is: {resource:#?}");
|
||||||
|
|
Loading…
Reference in a new issue