2022-03-28 04:27:07 +00:00
|
|
|
use crate::{
|
2022-10-01 00:38:11 +00:00
|
|
|
config::primitives::{AudioCodec, ImageFormat, LogFormat, Targets, VideoCodec},
|
2022-03-28 04:27:07 +00:00
|
|
|
serde_str::Serde,
|
|
|
|
};
|
2022-03-28 00:10:06 +00:00
|
|
|
use clap::{Parser, Subcommand};
|
|
|
|
use std::{net::SocketAddr, path::PathBuf};
|
|
|
|
use url::Url;
|
|
|
|
|
2022-03-28 04:27:07 +00:00
|
|
|
impl Args {
|
|
|
|
pub(super) fn into_output(self) -> Output {
|
|
|
|
let Args {
|
|
|
|
config_file,
|
|
|
|
old_db_path,
|
|
|
|
log_format,
|
|
|
|
log_targets,
|
|
|
|
console_address,
|
|
|
|
console_buffer_capacity,
|
|
|
|
opentelemetry_url,
|
|
|
|
opentelemetry_service_name,
|
|
|
|
opentelemetry_targets,
|
|
|
|
save_to,
|
|
|
|
command,
|
|
|
|
} = self;
|
|
|
|
|
|
|
|
let old_db = OldDb { path: old_db_path };
|
|
|
|
|
|
|
|
let tracing = Tracing {
|
|
|
|
logging: Logging {
|
|
|
|
format: log_format,
|
|
|
|
targets: log_targets.map(Serde::new),
|
|
|
|
},
|
|
|
|
console: Console {
|
|
|
|
address: console_address,
|
|
|
|
buffer_capacity: console_buffer_capacity,
|
|
|
|
},
|
|
|
|
opentelemetry: OpenTelemetry {
|
|
|
|
url: opentelemetry_url,
|
|
|
|
service_name: opentelemetry_service_name,
|
|
|
|
targets: opentelemetry_targets.map(Serde::new),
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
match command {
|
|
|
|
Command::Run(Run {
|
|
|
|
address,
|
|
|
|
api_key,
|
2022-03-29 17:51:16 +00:00
|
|
|
worker_id,
|
2023-06-23 16:20:20 +00:00
|
|
|
client_pool_size,
|
2022-09-25 20:17:33 +00:00
|
|
|
media_preprocess_steps,
|
2022-03-28 04:27:07 +00:00
|
|
|
media_skip_validate_imports,
|
|
|
|
media_max_width,
|
|
|
|
media_max_height,
|
|
|
|
media_max_area,
|
|
|
|
media_max_file_size,
|
2022-09-25 22:36:07 +00:00
|
|
|
media_max_frame_count,
|
2023-02-04 23:32:36 +00:00
|
|
|
media_gif_max_width,
|
|
|
|
media_gif_max_height,
|
|
|
|
media_gif_max_area,
|
2022-03-28 04:27:07 +00:00
|
|
|
media_enable_silent_video,
|
2022-09-25 22:36:07 +00:00
|
|
|
media_enable_full_video,
|
2022-10-01 00:38:11 +00:00
|
|
|
media_video_codec,
|
|
|
|
media_audio_codec,
|
2022-03-28 04:27:07 +00:00
|
|
|
media_filters,
|
|
|
|
media_format,
|
|
|
|
store,
|
|
|
|
}) => {
|
2022-03-29 17:51:16 +00:00
|
|
|
let server = Server {
|
|
|
|
address,
|
|
|
|
api_key,
|
|
|
|
worker_id,
|
2023-06-23 16:20:20 +00:00
|
|
|
client_pool_size,
|
2022-03-29 17:51:16 +00:00
|
|
|
};
|
2023-02-04 23:32:36 +00:00
|
|
|
let gif = if media_gif_max_width.is_none()
|
|
|
|
&& media_gif_max_height.is_none()
|
|
|
|
&& media_gif_max_area.is_none()
|
|
|
|
{
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(Gif {
|
|
|
|
max_width: media_gif_max_width,
|
|
|
|
max_height: media_gif_max_height,
|
|
|
|
max_area: media_gif_max_area,
|
|
|
|
})
|
|
|
|
};
|
2022-03-28 04:27:07 +00:00
|
|
|
let media = Media {
|
2022-09-25 20:17:33 +00:00
|
|
|
preprocess_steps: media_preprocess_steps,
|
2022-03-28 04:27:07 +00:00
|
|
|
skip_validate_imports: media_skip_validate_imports,
|
|
|
|
max_width: media_max_width,
|
|
|
|
max_height: media_max_height,
|
|
|
|
max_area: media_max_area,
|
|
|
|
max_file_size: media_max_file_size,
|
2022-09-25 22:36:07 +00:00
|
|
|
max_frame_count: media_max_frame_count,
|
2023-02-04 23:32:36 +00:00
|
|
|
gif,
|
2022-03-28 04:27:07 +00:00
|
|
|
enable_silent_video: media_enable_silent_video,
|
2022-09-25 22:36:07 +00:00
|
|
|
enable_full_video: media_enable_full_video,
|
2022-10-01 00:38:11 +00:00
|
|
|
video_codec: media_video_codec,
|
|
|
|
audio_codec: media_audio_codec,
|
2022-03-28 04:27:07 +00:00
|
|
|
filters: media_filters,
|
|
|
|
format: media_format,
|
|
|
|
};
|
|
|
|
let operation = Operation::Run;
|
|
|
|
|
|
|
|
match store {
|
|
|
|
Some(RunStore::Filesystem(RunFilesystem { system, repo })) => {
|
|
|
|
let store = Some(Store::Filesystem(system));
|
|
|
|
Output {
|
|
|
|
config_format: ConfigFormat {
|
|
|
|
server,
|
|
|
|
old_db,
|
|
|
|
tracing,
|
|
|
|
media,
|
|
|
|
store,
|
|
|
|
repo,
|
|
|
|
},
|
|
|
|
operation,
|
|
|
|
config_file,
|
|
|
|
save_to,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Some(RunStore::ObjectStorage(RunObjectStorage { storage, repo })) => {
|
|
|
|
let store = Some(Store::ObjectStorage(storage));
|
|
|
|
Output {
|
|
|
|
config_format: ConfigFormat {
|
|
|
|
server,
|
|
|
|
old_db,
|
|
|
|
tracing,
|
|
|
|
media,
|
|
|
|
store,
|
|
|
|
repo,
|
|
|
|
},
|
|
|
|
operation,
|
|
|
|
config_file,
|
|
|
|
save_to,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => Output {
|
|
|
|
config_format: ConfigFormat {
|
|
|
|
server,
|
|
|
|
old_db,
|
|
|
|
tracing,
|
|
|
|
media,
|
|
|
|
store: None,
|
|
|
|
repo: None,
|
|
|
|
},
|
|
|
|
operation,
|
|
|
|
config_file,
|
|
|
|
save_to,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2023-06-20 20:59:08 +00:00
|
|
|
Command::MigrateStore(MigrateStore {
|
|
|
|
skip_missing_files,
|
|
|
|
store,
|
|
|
|
}) => {
|
2022-03-28 04:27:07 +00:00
|
|
|
let server = Server::default();
|
|
|
|
let media = Media::default();
|
|
|
|
|
2023-06-20 20:59:08 +00:00
|
|
|
match store {
|
|
|
|
MigrateStoreFrom::Filesystem(MigrateFilesystem { from, to }) => match to {
|
|
|
|
MigrateStoreTo::Filesystem(MigrateFilesystemInner { to, repo }) => Output {
|
2022-03-28 04:27:07 +00:00
|
|
|
config_format: ConfigFormat {
|
|
|
|
server,
|
|
|
|
old_db,
|
|
|
|
tracing,
|
|
|
|
media,
|
|
|
|
store: None,
|
|
|
|
repo,
|
|
|
|
},
|
|
|
|
operation: Operation::MigrateStore {
|
2023-06-20 20:59:08 +00:00
|
|
|
skip_missing_files,
|
2022-03-28 04:27:07 +00:00
|
|
|
from: from.into(),
|
|
|
|
to: to.into(),
|
|
|
|
},
|
|
|
|
config_file,
|
|
|
|
save_to,
|
|
|
|
},
|
2023-06-20 20:59:08 +00:00
|
|
|
MigrateStoreTo::ObjectStorage(MigrateObjectStorageInner { to, repo }) => {
|
2022-03-28 04:27:07 +00:00
|
|
|
Output {
|
|
|
|
config_format: ConfigFormat {
|
|
|
|
server,
|
|
|
|
old_db,
|
|
|
|
tracing,
|
|
|
|
media,
|
|
|
|
store: None,
|
|
|
|
repo,
|
|
|
|
},
|
|
|
|
operation: Operation::MigrateStore {
|
2023-06-20 20:59:08 +00:00
|
|
|
skip_missing_files,
|
2022-03-28 04:27:07 +00:00
|
|
|
from: from.into(),
|
|
|
|
to: to.into(),
|
|
|
|
},
|
|
|
|
config_file,
|
|
|
|
save_to,
|
|
|
|
}
|
|
|
|
}
|
2023-06-20 20:59:08 +00:00
|
|
|
},
|
|
|
|
MigrateStoreFrom::ObjectStorage(MigrateObjectStorage { from, to }) => {
|
|
|
|
match to {
|
|
|
|
MigrateStoreTo::Filesystem(MigrateFilesystemInner { to, repo }) => {
|
|
|
|
Output {
|
|
|
|
config_format: ConfigFormat {
|
|
|
|
server,
|
|
|
|
old_db,
|
|
|
|
tracing,
|
|
|
|
media,
|
|
|
|
store: None,
|
|
|
|
repo,
|
|
|
|
},
|
|
|
|
operation: Operation::MigrateStore {
|
|
|
|
skip_missing_files,
|
|
|
|
from: from.into(),
|
|
|
|
to: to.into(),
|
|
|
|
},
|
|
|
|
config_file,
|
|
|
|
save_to,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MigrateStoreTo::ObjectStorage(MigrateObjectStorageInner {
|
|
|
|
to,
|
2022-03-28 04:27:07 +00:00
|
|
|
repo,
|
2023-06-20 20:59:08 +00:00
|
|
|
}) => Output {
|
|
|
|
config_format: ConfigFormat {
|
|
|
|
server,
|
|
|
|
old_db,
|
|
|
|
tracing,
|
|
|
|
media,
|
|
|
|
store: None,
|
|
|
|
repo,
|
|
|
|
},
|
|
|
|
operation: Operation::MigrateStore {
|
|
|
|
skip_missing_files,
|
|
|
|
from: from.into(),
|
|
|
|
to: to.into(),
|
|
|
|
},
|
|
|
|
config_file,
|
|
|
|
save_to,
|
2022-03-28 04:27:07 +00:00
|
|
|
},
|
2023-06-20 20:59:08 +00:00
|
|
|
}
|
|
|
|
}
|
2022-03-28 04:27:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) struct Output {
|
|
|
|
pub(super) config_format: ConfigFormat,
|
|
|
|
pub(super) operation: Operation,
|
|
|
|
pub(super) save_to: Option<PathBuf>,
|
|
|
|
pub(super) config_file: Option<PathBuf>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(clippy::large_enum_variant)]
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub(crate) enum Operation {
|
|
|
|
Run,
|
|
|
|
MigrateStore {
|
2023-06-20 20:59:08 +00:00
|
|
|
skip_missing_files: bool,
|
2022-03-28 04:27:07 +00:00
|
|
|
from: crate::config::primitives::Store,
|
|
|
|
to: crate::config::primitives::Store,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Default, serde::Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
pub(super) struct ConfigFormat {
|
|
|
|
server: Server,
|
|
|
|
old_db: OldDb,
|
|
|
|
tracing: Tracing,
|
|
|
|
media: Media,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
repo: Option<Repo>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
store: Option<Store>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Default, serde::Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
struct Server {
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
address: Option<SocketAddr>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2022-03-29 17:51:16 +00:00
|
|
|
worker_id: Option<String>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2022-03-28 04:27:07 +00:00
|
|
|
api_key: Option<String>,
|
2023-06-23 16:20:20 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
client_pool_size: Option<usize>,
|
2022-03-28 04:27:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Default, serde::Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
struct Tracing {
|
|
|
|
logging: Logging,
|
|
|
|
console: Console,
|
|
|
|
opentelemetry: OpenTelemetry,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Default, serde::Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
struct Logging {
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
format: Option<LogFormat>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
targets: Option<Serde<Targets>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Default, serde::Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
struct Console {
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
address: Option<SocketAddr>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
buffer_capacity: Option<usize>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Default, serde::Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
struct OpenTelemetry {
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
url: Option<Url>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
service_name: Option<String>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
targets: Option<Serde<Targets>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Default, serde::Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
struct OldDb {
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
path: Option<PathBuf>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Default, serde::Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
struct Media {
|
2022-09-25 20:17:33 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
preprocess_steps: Option<String>,
|
2022-03-28 04:27:07 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
max_width: Option<usize>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
max_height: Option<usize>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
max_area: Option<usize>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
max_file_size: Option<usize>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2022-09-25 22:36:07 +00:00
|
|
|
max_frame_count: Option<usize>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2023-02-04 23:32:36 +00:00
|
|
|
gif: Option<Gif>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2022-03-28 04:27:07 +00:00
|
|
|
enable_silent_video: Option<bool>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2022-09-25 22:36:07 +00:00
|
|
|
enable_full_video: Option<bool>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2022-10-01 00:38:11 +00:00
|
|
|
video_codec: Option<VideoCodec>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
audio_codec: Option<AudioCodec>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2022-03-28 04:27:07 +00:00
|
|
|
filters: Option<Vec<String>>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
format: Option<ImageFormat>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
skip_validate_imports: Option<bool>,
|
|
|
|
}
|
|
|
|
|
2023-02-04 23:32:36 +00:00
|
|
|
#[derive(Debug, Default, serde::Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
struct Gif {
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
max_width: Option<usize>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
max_height: Option<usize>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
max_area: Option<usize>,
|
|
|
|
}
|
|
|
|
|
2022-03-28 00:10:06 +00:00
|
|
|
/// Run the pict-rs application
|
|
|
|
#[derive(Debug, Parser)]
|
2022-09-28 23:23:41 +00:00
|
|
|
#[command(author, version, about, long_about = None)]
|
2022-03-28 04:27:07 +00:00
|
|
|
pub(super) struct Args {
|
2022-03-28 00:10:06 +00:00
|
|
|
/// Path to the pict-rs configuration file
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(short, long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
config_file: Option<PathBuf>,
|
|
|
|
|
|
|
|
/// Path to the old pict-rs sled database
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
old_db_path: Option<PathBuf>,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
|
|
|
/// Format of logs printed to stdout
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
log_format: Option<LogFormat>,
|
2022-03-28 00:10:06 +00:00
|
|
|
/// Log levels to print to stdout, respects RUST_LOG formatting
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
log_targets: Option<Targets>,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
|
|
|
/// Address and port to expose tokio-console metrics
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
console_address: Option<SocketAddr>,
|
2022-03-28 00:10:06 +00:00
|
|
|
/// Capacity of the console-subscriber Event Buffer
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
console_buffer_capacity: Option<usize>,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
|
|
|
/// URL to send OpenTelemetry metrics
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
opentelemetry_url: Option<Url>,
|
2022-03-28 00:10:06 +00:00
|
|
|
/// Service Name to use for OpenTelemetry
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
opentelemetry_service_name: Option<String>,
|
2022-03-28 00:10:06 +00:00
|
|
|
/// Log levels to use for OpenTelemetry, respects RUST_LOG formatting
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
opentelemetry_targets: Option<Targets>,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
|
|
|
/// File to save the current configuration for reproducible runs
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
save_to: Option<PathBuf>,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
2022-09-28 23:23:41 +00:00
|
|
|
#[command(subcommand)]
|
2022-03-28 04:27:07 +00:00
|
|
|
command: Command,
|
2022-03-28 00:10:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Subcommand)]
|
2022-03-28 04:27:07 +00:00
|
|
|
enum Command {
|
2022-03-28 00:10:06 +00:00
|
|
|
/// Runs the pict-rs web server
|
|
|
|
Run(Run),
|
|
|
|
|
|
|
|
/// Migrates from one provided media store to another
|
|
|
|
MigrateStore(MigrateStore),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Parser)]
|
2022-03-28 04:27:07 +00:00
|
|
|
struct Run {
|
2022-03-28 00:10:06 +00:00
|
|
|
/// The address and port to bind the pict-rs web server
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(short, long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
address: Option<SocketAddr>,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
|
|
|
/// The API KEY required to access restricted routes
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
api_key: Option<String>,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
2022-09-25 20:17:33 +00:00
|
|
|
/// ID of this pict-rs node. Doesn't do much yet
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-29 17:51:16 +00:00
|
|
|
worker_id: Option<String>,
|
|
|
|
|
2023-06-23 16:20:20 +00:00
|
|
|
/// Number of connections the internel HTTP client should maintain in its pool
|
|
|
|
///
|
|
|
|
/// This number defaults to 100, and the total number is multiplied by the number of cores
|
|
|
|
/// available to the program. This means that running on a 2 core system will result in 200
|
|
|
|
/// pooled connections, and running on a 32 core system will result in 3200 pooled connections.
|
|
|
|
#[arg(long)]
|
|
|
|
client_pool_size: Option<usize>,
|
|
|
|
|
2022-09-25 20:17:33 +00:00
|
|
|
/// Optional pre-processing steps for uploaded media.
|
|
|
|
///
|
|
|
|
/// All still images will be put through these steps before saving
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-09-25 20:17:33 +00:00
|
|
|
media_preprocess_steps: Option<String>,
|
|
|
|
|
2022-03-28 00:10:06 +00:00
|
|
|
/// Whether to validate media on the "import" endpoint
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
media_skip_validate_imports: Option<bool>,
|
2022-03-28 00:10:06 +00:00
|
|
|
/// The maximum width, in pixels, for uploaded media
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
media_max_width: Option<usize>,
|
2022-03-28 00:10:06 +00:00
|
|
|
/// The maximum height, in pixels, for uploaded media
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
media_max_height: Option<usize>,
|
2022-03-28 00:10:06 +00:00
|
|
|
/// The maximum area, in pixels, for uploaded media
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
media_max_area: Option<usize>,
|
2022-03-28 00:10:06 +00:00
|
|
|
/// The maximum size, in megabytes, for uploaded media
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
media_max_file_size: Option<usize>,
|
2022-09-25 22:36:07 +00:00
|
|
|
/// The maximum number of frames allowed for uploaded GIF and MP4s.
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-09-25 22:36:07 +00:00
|
|
|
media_max_frame_count: Option<usize>,
|
2023-02-04 23:32:36 +00:00
|
|
|
/// Maximum width allowed for gif uploads.
|
|
|
|
///
|
2023-02-04 23:52:23 +00:00
|
|
|
/// If an upload exceeds this value, it will be transcoded to a video format or rejected,
|
2023-02-04 23:32:36 +00:00
|
|
|
/// depending on whether video uploads are enabled.
|
|
|
|
#[arg(long)]
|
|
|
|
media_gif_max_width: Option<usize>,
|
|
|
|
/// Maximum height allowed for gif uploads
|
|
|
|
///
|
2023-02-04 23:52:23 +00:00
|
|
|
/// If an upload exceeds this value, it will be transcoded to a video format or rejected,
|
2023-02-04 23:32:36 +00:00
|
|
|
/// depending on whether video uploads are enabled.
|
|
|
|
#[arg(long)]
|
|
|
|
media_gif_max_height: Option<usize>,
|
|
|
|
/// Maximum area allowed for gif uploads
|
|
|
|
///
|
2023-02-04 23:52:23 +00:00
|
|
|
/// If an upload exceeds this value, it will be transcoded to a video format or rejected,
|
2023-02-04 23:32:36 +00:00
|
|
|
/// depending on whether video uploads are enabled.
|
|
|
|
#[arg(long)]
|
|
|
|
media_gif_max_area: Option<usize>,
|
2022-10-01 00:38:11 +00:00
|
|
|
/// Whether to enable GIF and silent video uploads
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
media_enable_silent_video: Option<bool>,
|
2022-10-01 00:38:11 +00:00
|
|
|
/// Whether to enable full video uploads
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-09-25 22:36:07 +00:00
|
|
|
media_enable_full_video: Option<bool>,
|
2022-10-01 00:38:11 +00:00
|
|
|
/// Enforce a specific video codec for uploaded videos
|
|
|
|
#[arg(long)]
|
|
|
|
media_video_codec: Option<VideoCodec>,
|
|
|
|
/// Enforce a specific audio codec for uploaded videos
|
|
|
|
#[arg(long)]
|
|
|
|
media_audio_codec: Option<AudioCodec>,
|
2022-03-28 00:10:06 +00:00
|
|
|
/// Which media filters should be enabled on the `process` endpoint
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
media_filters: Option<Vec<String>>,
|
2022-03-28 00:10:06 +00:00
|
|
|
/// Enforce uploaded media is transcoded to the provided format
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
media_format: Option<ImageFormat>,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
2022-09-28 23:23:41 +00:00
|
|
|
#[command(subcommand)]
|
2022-03-28 04:27:07 +00:00
|
|
|
store: Option<RunStore>,
|
2022-03-28 00:10:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Configure the provided storage
|
2022-03-28 04:27:07 +00:00
|
|
|
#[derive(Clone, Debug, Subcommand, serde::Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
#[serde(tag = "type")]
|
2023-07-11 18:01:58 +00:00
|
|
|
// allow large enum variant - this is an instantiated-once config
|
|
|
|
#[allow(clippy::large_enum_variant)]
|
2022-03-28 04:27:07 +00:00
|
|
|
enum Store {
|
2022-03-28 00:10:06 +00:00
|
|
|
/// configure filesystem storage
|
|
|
|
Filesystem(Filesystem),
|
|
|
|
|
|
|
|
/// configure object storage
|
|
|
|
ObjectStorage(ObjectStorage),
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Run pict-rs with the provided storage
|
|
|
|
#[derive(Debug, Subcommand)]
|
2023-07-11 18:01:58 +00:00
|
|
|
// allow large enum variant - this is an instantiated-once config
|
|
|
|
#[allow(clippy::large_enum_variant)]
|
2022-03-28 04:27:07 +00:00
|
|
|
enum RunStore {
|
2022-03-28 00:10:06 +00:00
|
|
|
/// Run pict-rs with filesystem storage
|
|
|
|
Filesystem(RunFilesystem),
|
|
|
|
|
|
|
|
/// Run pict-rs with object storage
|
|
|
|
ObjectStorage(RunObjectStorage),
|
|
|
|
}
|
|
|
|
|
2023-06-20 20:59:08 +00:00
|
|
|
#[derive(Debug, Parser)]
|
|
|
|
struct MigrateStore {
|
|
|
|
/// Normally, pict-rs will keep retrying when errors occur during migration. This flag tells
|
|
|
|
/// pict-rs to ignore errors that are caused by files not existing.
|
|
|
|
#[arg(long)]
|
|
|
|
skip_missing_files: bool,
|
|
|
|
|
|
|
|
#[command(subcommand)]
|
|
|
|
store: MigrateStoreFrom,
|
|
|
|
}
|
|
|
|
|
2022-03-28 00:10:06 +00:00
|
|
|
/// Configure the pict-rs storage migration
|
|
|
|
#[derive(Debug, Subcommand)]
|
2023-07-11 18:01:58 +00:00
|
|
|
// allow large enum variant - this is an instantiated-once config
|
|
|
|
#[allow(clippy::large_enum_variant)]
|
2023-06-20 20:59:08 +00:00
|
|
|
enum MigrateStoreFrom {
|
2022-03-28 00:10:06 +00:00
|
|
|
/// Migrate from the provided filesystem storage
|
|
|
|
Filesystem(MigrateFilesystem),
|
|
|
|
|
|
|
|
/// Migrate from the provided object storage
|
|
|
|
ObjectStorage(MigrateObjectStorage),
|
|
|
|
}
|
|
|
|
|
2022-03-28 04:27:07 +00:00
|
|
|
/// Configure the destination storage for pict-rs storage migration
|
|
|
|
#[derive(Debug, Subcommand)]
|
2023-07-11 18:01:58 +00:00
|
|
|
// allow large enum variant - this is an instantiated-once config
|
|
|
|
#[allow(clippy::large_enum_variant)]
|
2023-06-20 20:59:08 +00:00
|
|
|
enum MigrateStoreTo {
|
2022-03-28 04:27:07 +00:00
|
|
|
/// Migrate to the provided filesystem storage
|
|
|
|
Filesystem(MigrateFilesystemInner),
|
|
|
|
|
|
|
|
/// Migrate to the provided object storage
|
|
|
|
ObjectStorage(MigrateObjectStorageInner),
|
|
|
|
}
|
|
|
|
|
2022-03-28 00:10:06 +00:00
|
|
|
/// Migrate pict-rs' storage from the provided filesystem storage
|
|
|
|
#[derive(Debug, Parser)]
|
2022-03-28 04:27:07 +00:00
|
|
|
struct MigrateFilesystem {
|
2022-09-28 23:23:41 +00:00
|
|
|
#[command(flatten)]
|
2023-06-19 20:04:36 +00:00
|
|
|
from: Filesystem,
|
2022-03-28 04:27:07 +00:00
|
|
|
|
2022-09-28 23:23:41 +00:00
|
|
|
#[command(subcommand)]
|
2023-06-20 20:59:08 +00:00
|
|
|
to: MigrateStoreTo,
|
2022-03-28 04:27:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Migrate pict-rs' storage to the provided filesystem storage
|
|
|
|
#[derive(Debug, Parser)]
|
|
|
|
struct MigrateFilesystemInner {
|
2022-09-28 23:23:41 +00:00
|
|
|
#[command(flatten)]
|
2023-06-19 20:04:36 +00:00
|
|
|
to: Filesystem,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
2022-09-28 23:23:41 +00:00
|
|
|
#[command(subcommand)]
|
2022-03-28 04:27:07 +00:00
|
|
|
repo: Option<Repo>,
|
2022-03-28 00:10:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Migrate pict-rs' storage from the provided object storage
|
|
|
|
#[derive(Debug, Parser)]
|
2022-03-28 04:27:07 +00:00
|
|
|
struct MigrateObjectStorage {
|
2022-09-28 23:23:41 +00:00
|
|
|
#[command(flatten)]
|
2022-03-28 04:27:07 +00:00
|
|
|
from: crate::config::primitives::ObjectStorage,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
2022-09-28 23:23:41 +00:00
|
|
|
#[command(subcommand)]
|
2023-06-20 20:59:08 +00:00
|
|
|
to: MigrateStoreTo,
|
2022-03-28 04:27:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Migrate pict-rs' storage to the provided object storage
|
|
|
|
#[derive(Debug, Parser)]
|
|
|
|
struct MigrateObjectStorageInner {
|
2022-09-28 23:23:41 +00:00
|
|
|
#[command(flatten)]
|
2022-03-28 04:27:07 +00:00
|
|
|
to: crate::config::primitives::ObjectStorage,
|
|
|
|
|
2022-09-28 23:23:41 +00:00
|
|
|
#[command(subcommand)]
|
2022-03-28 04:27:07 +00:00
|
|
|
repo: Option<Repo>,
|
2022-03-28 00:10:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Run pict-rs with the provided filesystem storage
|
|
|
|
#[derive(Debug, Parser)]
|
2022-03-28 04:27:07 +00:00
|
|
|
struct RunFilesystem {
|
2022-09-28 23:23:41 +00:00
|
|
|
#[command(flatten)]
|
2022-03-28 04:27:07 +00:00
|
|
|
system: Filesystem,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
2022-09-28 23:23:41 +00:00
|
|
|
#[command(subcommand)]
|
2022-03-28 04:27:07 +00:00
|
|
|
repo: Option<Repo>,
|
2022-03-28 00:10:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Run pict-rs with the provided object storage
|
|
|
|
#[derive(Debug, Parser)]
|
2022-03-28 04:27:07 +00:00
|
|
|
struct RunObjectStorage {
|
2022-09-28 23:23:41 +00:00
|
|
|
#[command(flatten)]
|
2022-03-28 04:27:07 +00:00
|
|
|
storage: ObjectStorage,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
2022-09-28 23:23:41 +00:00
|
|
|
#[command(subcommand)]
|
2022-03-28 04:27:07 +00:00
|
|
|
repo: Option<Repo>,
|
2022-03-28 00:10:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Configuration for data repositories
|
2022-03-28 04:27:07 +00:00
|
|
|
#[derive(Debug, Subcommand, serde::Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
#[serde(tag = "type")]
|
|
|
|
enum Repo {
|
2022-03-28 00:10:06 +00:00
|
|
|
/// Run pict-rs with the provided sled-backed data repository
|
|
|
|
Sled(Sled),
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Configuration for filesystem media storage
|
2022-03-28 04:27:07 +00:00
|
|
|
#[derive(Clone, Debug, Parser, serde::Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
2023-06-19 20:04:36 +00:00
|
|
|
pub(super) struct Filesystem {
|
2022-03-28 00:10:06 +00:00
|
|
|
/// The path to store uploaded media
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(short, long)]
|
2023-06-19 20:04:36 +00:00
|
|
|
pub(super) path: Option<PathBuf>,
|
2022-03-28 00:10:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Configuration for Object Storage
|
2022-03-28 04:27:07 +00:00
|
|
|
#[derive(Clone, Debug, Parser, serde::Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
struct ObjectStorage {
|
2022-09-24 19:18:49 +00:00
|
|
|
/// The base endpoint for the object storage
|
|
|
|
///
|
|
|
|
/// Examples:
|
|
|
|
/// - `http://localhost:9000`
|
|
|
|
/// - `https://s3.dualstack.eu-west-1.amazonaws.com`
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(short, long)]
|
2022-09-24 19:18:49 +00:00
|
|
|
endpoint: Url,
|
|
|
|
|
|
|
|
/// Determines whether to use path style or virtualhost style for accessing objects
|
|
|
|
///
|
|
|
|
/// When this is true, objects will be fetched from {endpoint}/{bucket_name}/{object}
|
|
|
|
/// When false, objects will be fetched from {bucket_name}.{endpoint}/{object}
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(short, long)]
|
2022-09-24 19:18:49 +00:00
|
|
|
use_path_style: bool,
|
|
|
|
|
2022-03-28 00:10:06 +00:00
|
|
|
/// The bucket in which to store media
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(short, long)]
|
2023-07-11 18:01:58 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2022-03-28 04:27:07 +00:00
|
|
|
bucket_name: Option<String>,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
|
|
|
/// The region the bucket is located in
|
2022-09-24 19:18:49 +00:00
|
|
|
///
|
|
|
|
/// For minio deployments, this can just be 'minio'
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(short, long)]
|
2023-07-11 18:01:58 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2022-09-24 19:18:49 +00:00
|
|
|
region: Option<String>,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
|
|
|
/// The Access Key for the user accessing the bucket
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(short, long)]
|
2023-07-11 18:01:58 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2022-03-28 04:27:07 +00:00
|
|
|
access_key: Option<String>,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
|
|
|
/// The secret key for the user accessing the bucket
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(short, long)]
|
2023-07-11 18:01:58 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2022-03-28 04:27:07 +00:00
|
|
|
secret_key: Option<String>,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
|
|
|
/// The session token for accessing the bucket
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(long)]
|
2023-07-11 18:01:58 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2022-03-28 04:27:07 +00:00
|
|
|
session_token: Option<String>,
|
2023-07-11 18:01:58 +00:00
|
|
|
|
|
|
|
/// How long signatures for object storage requests are valid (in seconds)
|
|
|
|
///
|
|
|
|
/// This defaults to 15 seconds
|
|
|
|
#[arg(long)]
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
signature_duration: Option<u64>,
|
|
|
|
|
|
|
|
/// How long a client can wait on an object storage request before giving up (in seconds)
|
|
|
|
///
|
|
|
|
/// This defaults to 30 seconds
|
|
|
|
#[arg(long)]
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
client_timeout: Option<u64>,
|
2022-03-28 00:10:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Configuration for the sled-backed data repository
|
2022-03-28 04:27:07 +00:00
|
|
|
#[derive(Debug, Parser, serde::Serialize)]
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
struct Sled {
|
2022-03-28 00:10:06 +00:00
|
|
|
/// The path to store the sled database
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(short, long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
path: Option<PathBuf>,
|
2022-03-28 00:10:06 +00:00
|
|
|
|
|
|
|
/// The cache capacity, in bytes, allowed to sled for in-memory operations
|
2022-09-28 23:23:41 +00:00
|
|
|
#[arg(short, long)]
|
2022-03-28 04:27:07 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
cache_capacity: Option<u64>,
|
2023-07-08 22:35:57 +00:00
|
|
|
|
2023-07-09 00:56:26 +00:00
|
|
|
#[arg(short, long)]
|
2023-07-08 22:35:57 +00:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
export_path: Option<PathBuf>,
|
2022-03-28 00:10:06 +00:00
|
|
|
}
|