Skip to main content

lightshuttle_export/
model.rs

1//! Neutral intermediate representation produced by the lowering step
2//! and consumed by every emitter.
3
4use std::path::PathBuf;
5
6use lightshuttle_manifest::ExportConfig;
7use lightshuttle_spec::ContainerSpec;
8
9/// Target-agnostic model of a stack ready to be emitted.
10#[derive(Debug, Clone)]
11pub struct ExportModel {
12    /// Project metadata carried from the manifest.
13    pub project: ExportProject,
14    /// Services in manifest declaration order.
15    pub services: Vec<ExportService>,
16    /// Raw `export:` section, resolved per target by each emitter.
17    pub export: Option<ExportConfig>,
18}
19
20/// Project metadata relevant to an export.
21#[derive(Debug, Clone)]
22pub struct ExportProject {
23    /// Project name, used as the default namespace and chart name.
24    pub name: String,
25    /// Free-form project version, used as the default chart version.
26    pub version: Option<String>,
27}
28
29/// One service in the export model: a resolved container specification
30/// plus the resources it depends on.
31#[derive(Debug, Clone)]
32pub struct ExportService {
33    /// Resolved container specification (image, env, ports, volumes,
34    /// healthcheck) as produced by `lightshuttle-spec`.
35    pub spec: ContainerSpec,
36    /// Names of the resources this service depends on.
37    pub depends_on: Vec<String>,
38}
39
40/// Supported export targets.
41#[derive(Debug, Clone, Copy, PartialEq, Eq)]
42pub enum Target {
43    /// A `docker-compose.yml` file.
44    Compose,
45    /// Plain Kubernetes manifests.
46    Kubernetes,
47    /// A Helm chart.
48    Helm,
49}
50
51impl Target {
52    /// Stable lower-case label, also used as the CLI argument value and
53    /// the default output sub-directory.
54    #[must_use]
55    pub fn label(self) -> &'static str {
56        match self {
57            Self::Compose => "compose",
58            Self::Kubernetes => "kubernetes",
59            Self::Helm => "helm",
60        }
61    }
62}
63
64impl std::fmt::Display for Target {
65    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66        f.write_str(self.label())
67    }
68}
69
70/// A set of named files produced by an emitter, written to disk by the
71/// CLI.
72#[derive(Debug, Clone, Default)]
73pub struct ExportArtifacts {
74    /// Files in deterministic emission order.
75    pub files: Vec<ExportFile>,
76}
77
78impl ExportArtifacts {
79    /// Build an empty artifact set.
80    #[must_use]
81    pub fn new() -> Self {
82        Self::default()
83    }
84
85    /// Append a file at `path` with `contents`.
86    pub fn push(&mut self, path: impl Into<PathBuf>, contents: impl Into<String>) {
87        self.files.push(ExportFile {
88            path: path.into(),
89            contents: contents.into(),
90        });
91    }
92}
93
94/// A single emitted file: a relative path and its textual contents.
95#[derive(Debug, Clone)]
96pub struct ExportFile {
97    /// Path relative to the export output directory.
98    pub path: PathBuf,
99    /// Full textual contents of the file.
100    pub contents: String,
101}