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

refactor: make admin compile, scope project models to backends #1371

Merged
merged 1 commit into from Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Expand Up @@ -17,7 +17,7 @@ recipe.json
.idea/

# Credentials for running ACME commands
acme.json
acme*.json

# VS Code
.vscode/
Expand Down
5 changes: 2 additions & 3 deletions admin/src/args.rs
@@ -1,7 +1,6 @@
use std::{fs, io, path::PathBuf};

use clap::{Error, Parser, Subcommand};
use shuttle_common::models::project::ProjectName;

#[derive(Parser, Debug)]
pub struct Args {
Expand Down Expand Up @@ -54,7 +53,7 @@ pub enum AcmeCommand {

/// Project to request certificate for
#[arg(long)]
project: ProjectName,
project: String,

/// Path to acme credentials file
/// This should have been created with `acme create-account`
Expand All @@ -70,7 +69,7 @@ pub enum AcmeCommand {

/// Project to renew the certificate for
#[arg(long)]
project: ProjectName,
project: String,

/// Path to acme credentials file
/// This should have been created with `acme create-account`
Expand Down
11 changes: 4 additions & 7 deletions admin/src/client.rs
@@ -1,9 +1,6 @@
use anyhow::{Context, Result};
use serde::{de::DeserializeOwned, Serialize};
use shuttle_common::models::{
project::{AdminResponse, ProjectName},
stats, ToJson,
};
use shuttle_common::models::{admin::ProjectResponse, stats, ToJson};
use tracing::trace;

pub struct Client {
Expand Down Expand Up @@ -36,7 +33,7 @@ impl Client {
pub async fn acme_request_certificate(
&self,
fqdn: &str,
project_name: &ProjectName,
project_name: &str,
credentials: &serde_json::Value,
) -> Result<String> {
let path = format!("/admin/acme/request/{project_name}/{fqdn}");
Expand All @@ -46,7 +43,7 @@ impl Client {
pub async fn acme_renew_custom_domain_certificate(
&self,
fqdn: &str,
project_name: &ProjectName,
project_name: &str,
credentials: &serde_json::Value,
) -> Result<String> {
let path = format!("/admin/acme/renew/{project_name}/{fqdn}");
Expand All @@ -61,7 +58,7 @@ impl Client {
self.post(&path, Some(credentials)).await
}

pub async fn get_projects(&self) -> Result<Vec<AdminResponse>> {
pub async fn get_projects(&self) -> Result<Vec<ProjectResponse>> {
self.get("/admin/projects").await
}

Expand Down
12 changes: 12 additions & 0 deletions common/src/models/admin.rs
@@ -0,0 +1,12 @@
use serde::{Deserialize, Serialize};

#[cfg(feature = "openapi")]
use utoipa::ToSchema;

#[derive(Deserialize, Serialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[cfg_attr(feature = "openapi", schema(as = shuttle_common::models::admin::ProjectResponse))]
pub struct ProjectResponse {
pub project_name: String,
pub account_name: String,
}
16 changes: 14 additions & 2 deletions common/src/models/error.rs
Expand Up @@ -5,8 +5,6 @@ use http::StatusCode;
use serde::{Deserialize, Serialize};
use tracing::{error, warn};

use super::project::InvalidProjectName;

#[derive(Serialize, Deserialize, Debug)]
pub struct ApiError {
pub message: String,
Expand Down Expand Up @@ -169,6 +167,20 @@ impl From<StatusCode> for ApiError {
}
}

// Note: The string "Invalid project name" is used by cargo-shuttle to determine what type of error was returned.
// Changing it is breaking.
#[derive(Debug, Clone, PartialEq, thiserror::Error)]
#[error(
"Invalid project name. Project names must:
1. only contain lowercase alphanumeric characters or dashes `-`.
2. not start or end with a dash.
3. not be empty.
4. be shorter than 64 characters.
5. not contain any profanities.
6. not be a reserved word."
)]
pub struct InvalidProjectName;

#[cfg(feature = "backend")]
pub mod axum {
use async_trait::async_trait;
Expand Down
2 changes: 2 additions & 0 deletions common/src/models/mod.rs
@@ -1,5 +1,7 @@
pub mod admin;
pub mod deployment;
pub mod error;
#[cfg(feature = "backend")]
pub mod project;
pub mod resource;
pub mod secret;
Expand Down
25 changes: 2 additions & 23 deletions common/src/models/project.rs
Expand Up @@ -17,10 +17,11 @@ use strum::EnumString;

#[cfg(feature = "openapi")]
use crate::ulid_type;

#[cfg(feature = "openapi")]
use utoipa::ToSchema;

use super::error::InvalidProjectName;

/// Timeframe before a project is considered idle
pub const DEFAULT_IDLE_MINUTES: u64 = 30;

Expand Down Expand Up @@ -188,14 +189,6 @@ pub struct Config {
pub idle_minutes: u64,
}

#[derive(Deserialize, Serialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[cfg_attr(feature = "openapi", schema(as = shuttle_common::models::project::AdminResponse))]
pub struct AdminResponse {
pub project_name: String,
pub account_name: String,
}

pub fn get_projects_table(
projects: &Vec<Response>,
page: u32,
Expand Down Expand Up @@ -317,20 +310,6 @@ impl ProjectName {
}
}

// Note: The string "Invalid project name" is used by cargo-shuttle to determine what type of error was returned.
// Changing it is breaking.
#[derive(Debug, Clone, PartialEq, thiserror::Error)]
#[error(
"Invalid project name. Project names must:
1. only contain lowercase alphanumeric characters or dashes `-`.
2. not start or end with a dash.
3. not be empty.
4. be shorter than 64 characters.
5. not contain any profanities.
6. not be a reserved word."
)]
pub struct InvalidProjectName;

impl std::ops::Deref for ProjectName {
type Target = String;

Expand Down
5 changes: 3 additions & 2 deletions gateway/src/api/latest.rs
Expand Up @@ -25,6 +25,7 @@ use shuttle_common::constants::limits::{MAX_PROJECTS_DEFAULT, MAX_PROJECTS_EXTRA
use shuttle_common::models::error::axum::CustomErrorPath;
use shuttle_common::models::error::ErrorKind;
use shuttle_common::models::{
admin::ProjectResponse,
project::{self, ProjectName},
stats,
};
Expand Down Expand Up @@ -844,7 +845,7 @@ async fn renew_gateway_acme_certificate(
)]
async fn get_projects(
State(RouterState { service, .. }): State<RouterState>,
) -> Result<AxumJson<Vec<project::AdminResponse>>, Error> {
) -> Result<AxumJson<Vec<ProjectResponse>>, Error> {
let projects = service
.iter_projects_detailed()
.await?
Expand Down Expand Up @@ -891,7 +892,7 @@ impl Modify for SecurityAddon {
components(schemas(
shuttle_common::models::project::Response,
shuttle_common::models::stats::LoadResponse,
shuttle_common::models::project::AdminResponse,
shuttle_common::models::admin::ProjectResponse,
shuttle_common::models::stats::LoadResponse,
shuttle_common::models::project::State
))
Expand Down
2 changes: 1 addition & 1 deletion gateway/src/lib.rs
Expand Up @@ -160,7 +160,7 @@ pub struct ProjectDetails {
pub account_name: AccountName,
}

impl From<ProjectDetails> for shuttle_common::models::project::AdminResponse {
impl From<ProjectDetails> for shuttle_common::models::admin::ProjectResponse {
fn from(project: ProjectDetails) -> Self {
Self {
project_name: project.project_name.to_string(),
Expand Down