golem_cli/model/deploy_diff/
api_deployment.rs1use crate::model::api::ApiDeployment;
16use crate::model::app_raw::HttpApiDeployment;
17use crate::model::deploy_diff::DiffSerialize;
18use serde::{Deserialize, Serialize};
19use std::collections::{BTreeMap, BTreeSet};
20use std::ops::Sub;
21
22#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
23#[serde(rename_all = "camelCase", deny_unknown_fields)]
24pub struct DiffableHttpApiDeployment {
25 pub host: String,
26 #[serde(default, skip_serializing_if = "Option::is_none")]
27 pub subdomain: Option<String>,
28 #[serde(default, skip_serializing_if = "BTreeSet::is_empty")]
29 pub definitions: BTreeSet<String>,
30}
31
32impl DiffableHttpApiDeployment {
33 pub fn from_server(api_deployment: ApiDeployment) -> anyhow::Result<Self> {
34 Ok(DiffableHttpApiDeployment {
35 host: api_deployment.site.host,
36 subdomain: api_deployment.site.subdomain,
37 definitions: api_deployment
38 .api_definitions
39 .iter()
40 .map(|api_def| format!("{}@{}", api_def.id, api_def.version))
41 .collect(),
42 })
43 }
44
45 pub fn from_manifest(
46 api_deployment: &HttpApiDeployment,
47 latest_api_definition_versions: &BTreeMap<String, String>,
48 ) -> anyhow::Result<Self> {
49 Ok(DiffableHttpApiDeployment {
50 host: api_deployment.host.clone(),
51 subdomain: api_deployment.subdomain.clone(),
52 definitions: api_deployment
53 .definitions
54 .iter()
55 .map(|api_def| {
56 if api_def.contains("@") {
57 api_def.clone()
58 } else {
59 format!(
60 "{}@{}",
61 api_def,
62 latest_api_definition_versions
63 .get(api_def)
64 .expect("Missing latest version for HTTP API definition")
65 )
66 }
67 })
68 .collect(),
69 })
70 }
71
72 pub fn definitions(&self) -> impl Iterator<Item = (&str, &str)> {
73 self.definitions.iter().map(to_name_and_version)
74 }
75
76 pub fn plan(&self, new: &Self) -> HttpApiDeploymentUpdatePlan {
77 HttpApiDeploymentUpdatePlan {
78 delete: self
79 .definitions
80 .sub(&new.definitions)
81 .iter()
82 .map(to_name_and_version_owned)
83 .collect(),
84 add: new
85 .definitions
86 .sub(&self.definitions)
87 .iter()
88 .map(to_name_and_version_owned)
89 .collect(),
90 }
91 }
92}
93
94impl DiffSerialize for DiffableHttpApiDeployment {
95 fn to_diffable_string(&self) -> anyhow::Result<String> {
96 Ok(serde_yaml::to_string(&self)?)
97 }
98}
99
100pub struct HttpApiDeploymentUpdatePlan {
101 pub delete: BTreeSet<(String, String)>,
102 pub add: BTreeSet<(String, String)>,
103}
104
105fn to_name_and_version<S: AsRef<str>>(api_def_with_version: &S) -> (&str, &str) {
106 let mut parts = api_def_with_version.as_ref().split('@');
107 (
108 parts.next().expect("missing API name"),
109 parts.next().expect("missing version"),
110 )
111}
112
113fn to_name_and_version_owned<S: AsRef<str>>(api_def_with_version: &S) -> (String, String) {
114 let (name, version) = to_name_and_version(api_def_with_version);
115 (name.to_owned(), version.to_owned())
116}