1use crate::client::{Paginated, PlatzClient};
2use anyhow::Result;
3use chrono::prelude::*;
4use kv_derive::{prelude::*, IntoVec};
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7use std::collections::HashMap;
8use uuid::Uuid;
9
10#[derive(Debug, Deserialize, Clone)]
11pub enum DeploymentTaskStatus {
12 Pending,
13 Started,
14 Failed,
15 Canceled,
16 Done,
17}
18
19pub type JsonDiff = HashMap<String, (Value, Value)>;
20#[derive(Default, IntoVec)]
21pub struct DeploymentTaskFilters {
22 #[kv(optional)]
23 pub cluster_id: Option<Uuid>,
24 #[kv(optional)]
25 pub deployment_id: Option<Uuid>,
26 #[kv(optional)]
27 pub active_only: Option<bool>,
28 #[kv(optional)]
29 pub show_future: Option<bool>,
30 #[kv(optional)]
31 pub created_from: Option<DateTime<Utc>>,
32}
33
34#[derive(Debug, Serialize)]
35pub struct ApiNewDeploymentTask {
36 pub deployment_id: Uuid,
37 pub operation: DeploymentTaskOperation,
38 pub execute_at: Option<DateTime<Utc>>,
39}
40
41#[derive(Debug, Deserialize, Clone)]
42pub struct DeploymentTask {
43 pub id: Uuid,
44 pub created_at: DateTime<Utc>,
45 pub execute_at: DateTime<Utc>,
46 pub first_attempted_at: Option<DateTime<Utc>>,
47 pub started_at: Option<DateTime<Utc>>,
48 pub finished_at: Option<DateTime<Utc>>,
49 pub cluster_id: Uuid,
50 pub deployment_id: Uuid,
51 pub acting_user_id: Option<Uuid>,
52 pub acting_deployment_id: Option<Uuid>,
53 pub operation: DeploymentTaskOperation,
54 pub status: DeploymentTaskStatus,
55 pub reason: Option<String>,
56 pub canceled_by_user_id: Option<Uuid>,
57 pub canceled_by_deployment_id: Option<Uuid>,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
61pub enum DeploymentTaskOperation {
62 Install(DeploymentInstallTask),
63 Upgrade(DeploymentUpgradeTask),
64 Reinstall(DeploymentReinstallTask),
65 Recreate(DeploymentRecreaseTask),
66 Uninstall(DeploymentUninstallTask),
67 InvokeAction(DeploymentInvokeActionTask),
68 RestartK8sResource(DeploymentRestartK8sResourceTask),
69}
70
71impl DeploymentTaskOperation {
72 pub fn get_type_name(&self) -> String {
73 match self {
74 Self::Install(_) => "Install".into(),
75 Self::Upgrade(_) => "Upgrade".into(),
76 Self::Reinstall(_) => "Reinstall".into(),
77 Self::Recreate(_) => "Recreate".into(),
78 Self::Uninstall(_) => "Uninstall".into(),
79 Self::InvokeAction(x) => format!("Invoke Action {}", x.action_id),
80 Self::RestartK8sResource(_) => "Restart K8s Resource".into(),
81 }
82 }
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct DeploymentInstallTask {
87 pub helm_chart_id: Uuid,
88 pub config_inputs: serde_json::Value,
89 pub values_override: Option<serde_json::Value>,
90}
91
92#[derive(Debug, Clone, Serialize, Deserialize)]
93pub struct DeploymentUpgradeTask {
94 pub helm_chart_id: Uuid,
95 pub prev_helm_chart_id: Option<Uuid>,
96 pub config_inputs: serde_json::Value,
97 pub config_delta: Option<JsonDiff>,
98 pub values_override: Option<serde_json::Value>,
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct DeploymentReinstallTask {
103 pub reason: String,
104}
105#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct DeploymentRecreaseTask {
107 pub old_cluster_id: Uuid,
108 pub old_namespace: String,
109 pub new_cluster_id: Uuid,
110 pub new_namespace: String,
111}
112
113#[derive(Debug, Clone, Serialize, Deserialize)]
114pub struct DeploymentUninstallTask {}
115
116#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct DeploymentInvokeActionTask {
118 pub helm_chart_id: Uuid,
119 pub action_id: String,
120 pub body: serde_json::Value,
121}
122
123#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct DeploymentRestartK8sResourceTask {
125 pub resource_id: Uuid,
126 pub resource_name: String,
127}
128
129#[derive(Debug, Clone, Serialize, Deserialize)]
130pub struct CancelDeploymentTask {
131 pub reason: Option<String>,
132}
133
134impl PlatzClient {
135 pub async fn deployment_tasks(
136 &self,
137 filters: DeploymentTaskFilters,
138 ) -> Result<Vec<DeploymentTask>> {
139 Ok(self
140 .request(reqwest::Method::GET, "/api/v2/deployment-tasks")
141 .add_to_query(filters.into_vec())
142 .paginated()
143 .await?)
144 }
145
146 pub async fn deployment_task(&self, deployment_task_id: Uuid) -> Result<DeploymentTask> {
147 Ok(self
148 .request(
149 reqwest::Method::GET,
150 format!("/api/v2/deployment-tasks/{deployment_task_id}"),
151 )
152 .send()
153 .await?)
154 }
155
156 pub async fn last_deployment_task(&self, deployment_id: Uuid) -> Result<DeploymentTask> {
157 let single_page_tasks: Paginated<DeploymentTask> = self
158 .request(reqwest::Method::GET, "/api/v2/deployment-tasks")
159 .add_to_query(
160 DeploymentTaskFilters {
161 deployment_id: Some(deployment_id),
162 ..DeploymentTaskFilters::default()
163 }
164 .into_vec(),
165 )
166 .single_page(1, Some(1))
167 .await?;
168 Ok(single_page_tasks.items.first().unwrap().to_owned())
169 }
170
171 pub async fn cancel_deployment_task(
172 &self,
173 deployment_task_id: Uuid,
174 info: CancelDeploymentTask,
175 ) -> Result<DeploymentTask> {
176 Ok(self
177 .request(
178 reqwest::Method::DELETE,
179 format!("/api/v2/deployment-tasks/{deployment_task_id}"),
180 )
181 .send_with_body(info)
182 .await?)
183 }
184
185 pub async fn create_deployment_task(
186 &self,
187 new_task: ApiNewDeploymentTask,
188 ) -> Result<DeploymentTask> {
189 Ok(self
190 .request(reqwest::Method::POST, "/api/v2/deployment-tasks")
191 .send_with_body(new_task)
192 .await?)
193 }
194}