1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
use crate::client::PlatzClient;
use anyhow::Result;
use chrono::prelude::*;
use kv_derive::{prelude::*, IntoVec};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
use uuid::Uuid;

#[derive(Debug, Deserialize, Clone)]
pub enum DeploymentTaskStatus {
    Pending,
    Started,
    Failed,
    Done,
}

pub type JsonDiff = HashMap<String, (Value, Value)>;
#[derive(Default, IntoVec)]
pub struct DeploymentTaskFilters {
    #[kv(optional)]
    pub cluster_id: Option<Uuid>,
    #[kv(optional)]
    pub deployment_id: Option<Uuid>,
    #[kv(optional)]
    pub active_only: Option<bool>,
    #[kv(optional)]
    pub created_from: Option<DateTime<Utc>>,
}

#[derive(Debug, Serialize)]
pub struct ApiNewDeploymentTask {
    pub deployment_id: Uuid,
    pub operation: DeploymentTaskOperation,
    pub execute_at: Option<DateTime<Utc>>,
}

#[derive(Debug, Deserialize, Clone)]
pub struct DeploymentTask {
    pub id: Uuid,
    pub created_at: DateTime<Utc>,
    pub execute_at: DateTime<Utc>,
    pub first_attempted_at: Option<DateTime<Utc>>,
    pub started_at: Option<DateTime<Utc>>,
    pub finished_at: Option<DateTime<Utc>>,
    pub cluster_id: Uuid,
    pub deployment_id: Uuid,
    pub acting_user_id: Option<Uuid>,
    pub acting_deployment_id: Option<Uuid>,
    pub operation: DeploymentTaskOperation,
    pub status: DeploymentTaskStatus,
    pub reason: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum DeploymentTaskOperation {
    Install(DeploymentInstallTask),
    Upgrade(DeploymentUpgradeTask),
    Reinstall(DeploymentReinstallTask),
    Recreate(DeploymentRecreaseTask),
    Uninstall(DeploymentUninstallTask),
    InvokeAction(DeploymentInvokeActionTask),
    RestartK8sResource(DeploymentRestartK8sResourceTask),
}

impl DeploymentTaskOperation {
    pub fn get_type_name(&self) -> String {
        match self {
            Self::Install(_) => "Install".into(),
            Self::Upgrade(_) => "Upgrade".into(),
            Self::Reinstall(_) => "Reinstall".into(),
            Self::Recreate(_) => "Recreate".into(),
            Self::Uninstall(_) => "Uninstall".into(),
            Self::InvokeAction(x) => format!("Invoke Action {}", x.action_id),
            Self::RestartK8sResource(_) => "Restart K8s Resource".into(),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeploymentInstallTask {
    pub helm_chart_id: Uuid,
    pub config_inputs: serde_json::Value,
    pub values_override: Option<serde_json::Value>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeploymentUpgradeTask {
    pub helm_chart_id: Uuid,
    pub prev_helm_chart_id: Option<Uuid>,
    pub config_inputs: serde_json::Value,
    pub config_delta: Option<JsonDiff>,
    pub values_override: Option<serde_json::Value>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeploymentReinstallTask {
    pub reason: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeploymentRecreaseTask {
    pub old_cluster_id: Uuid,
    pub old_namespace: String,
    pub new_cluster_id: Uuid,
    pub new_namespace: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeploymentUninstallTask {}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeploymentInvokeActionTask {
    pub helm_chart_id: Uuid,
    pub action_id: String,
    pub body: serde_json::Value,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeploymentRestartK8sResourceTask {
    pub resource_id: Uuid,
    pub resource_name: String,
}

impl PlatzClient {
    pub async fn deployment_tasks(
        &self,
        filters: DeploymentTaskFilters,
    ) -> Result<Vec<DeploymentTask>> {
        Ok(self
            .request(reqwest::Method::GET, "/api/v2/deployment-tasks")
            .add_to_query(filters.into_vec())
            .paginated()
            .await?)
    }

    pub async fn deployment_task(&self, deployment_task_id: Uuid) -> Result<DeploymentTask> {
        Ok(self
            .request(
                reqwest::Method::GET,
                format!("/api/v2/deployment-tasks/{deployment_task_id}"),
            )
            .send()
            .await?)
    }

    pub async fn create_deployment_task(
        &self,
        new_task: ApiNewDeploymentTask,
    ) -> Result<DeploymentTask> {
        Ok(self
            .request(reqwest::Method::POST, "/api/v2/deployment-tasks")
            .send_with_body(new_task)
            .await?)
    }
}