use std::path::{Path, PathBuf};
use semver::Version;
use uuid::Uuid;
use crate::compose::{ComposeClient, ShellComposeClient};
use crate::docker::DockerServiceClient;
use crate::docker::{DockerImageClient, ImageImportError, ImageImportService};
use crate::domain::{ImageImportRecord, ServiceCatalog, UpdateAttemptRecord, ValidationRecord};
use crate::package::{PackageIntakeError, PackageIntakeService};
use crate::persistence::{FilesystemStore, StateStore};
use crate::update::{UpdateError, UpdateService};
#[derive(Debug, Clone)]
pub struct ValidatePackageRequest {
pub package_path: PathBuf,
}
#[derive(Debug, Clone)]
pub struct ImportValidatedImageRequest {
pub validation_record: ValidationRecord,
}
#[derive(Debug, Clone)]
pub struct ApplyCandidateReleaseRequest {
pub candidate_release_id: Uuid,
}
#[derive(Debug)]
pub struct ValidationApp<S> {
package_intake: PackageIntakeService<S>,
staging_root: PathBuf,
}
impl ValidationApp<FilesystemStore> {
pub fn filesystem(
catalog: ServiceCatalog,
store: FilesystemStore,
current_updater_version: Version,
) -> Self {
let staging_root = store.root().join("staging");
Self {
package_intake: PackageIntakeService::new(catalog, store, current_updater_version),
staging_root,
}
}
}
impl<S> ValidationApp<S>
where
S: StateStore,
{
pub fn validate_package(
&self,
request: ValidatePackageRequest,
) -> Result<ValidationRecord, PackageIntakeError> {
self.package_intake
.validate_package(request.package_path, &self.staging_root)
}
#[must_use]
pub fn staging_root(&self) -> &Path {
&self.staging_root
}
}
#[derive(Debug)]
pub struct ImageImportApp<D, S> {
image_import: ImageImportService<D, S>,
}
impl<D> ImageImportApp<D, FilesystemStore>
where
D: DockerImageClient,
{
pub fn filesystem(docker: D, store: FilesystemStore) -> Self {
Self {
image_import: ImageImportService::new(docker, store),
}
}
}
#[derive(Debug)]
pub struct UpdateApp<D, C, S> {
updates: UpdateService<D, C, S>,
}
impl<D> UpdateApp<D, ShellComposeClient, FilesystemStore>
where
D: DockerServiceClient,
{
pub fn filesystem(catalog: ServiceCatalog, docker: D, store: FilesystemStore) -> Self {
Self {
updates: UpdateService::new(catalog, docker, ShellComposeClient, store),
}
}
}
impl<D, S> ImageImportApp<D, S>
where
D: DockerImageClient,
S: StateStore,
{
pub fn import_validated_image(
&self,
request: ImportValidatedImageRequest,
) -> Result<ImageImportRecord, ImageImportError> {
self.image_import
.import_validated_package(&request.validation_record)
}
}
impl<D, C, S> UpdateApp<D, C, S>
where
D: DockerServiceClient,
C: ComposeClient,
S: StateStore,
{
pub fn new(catalog: ServiceCatalog, docker: D, compose: C, store: S) -> Self {
Self {
updates: UpdateService::new(catalog, docker, compose, store),
}
}
pub fn apply_candidate_release(
&self,
request: ApplyCandidateReleaseRequest,
) -> Result<UpdateAttemptRecord, UpdateError> {
self.updates
.apply_candidate_release(request.candidate_release_id)
}
}