use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub(super) struct ManagedInstance {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) template_slug: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) host: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) region: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) state: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) relay_eligible: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) current_version_semver: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) last_error: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) claimed_at: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) created_at: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub(super) struct AppTemplate {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) slug: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) status: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) source_repo: Option<String>,
}
pub(super) const TEMPLATE_STATUSES: &[&str] = &["draft", "published", "retired"];
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub(super) struct TemplateVersion {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) semver: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) git_ref: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) status: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) published_at: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub(super) struct ClaimLink {
pub(super) claim_url: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) expires_at: Option<String>,
}
pub(super) const INSTANCE_STATES: &[&str] = &[
"provisioning",
"provisioning_failed",
"awaiting_claim",
"awaiting_claim_blocked",
"active",
"suspended",
"destroying",
"destroyed",
];
pub(super) const VARIABLE_KINDS: &[&str] = &["static", "generated", "custom"];
pub(super) const VARIABLE_SCOPES: &[&str] = &["application", "service"];
pub(super) const GENERATOR_TYPES: &[&str] = &[
"32-bytes-base64",
"64-bytes-base64",
"hex-key",
"key-material",
"private-pem",
"public-pem",
];
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub(super) struct TemplateVariable {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) key: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) kind: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) scope: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) service_name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) generator_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) required: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) description: Option<String>,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub(super) struct InstanceVariable {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) key: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) kind: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) scope: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) service_name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) required: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(super) description: Option<String>,
#[serde(
default,
alias = "isSet",
alias = "set",
skip_serializing_if = "Option::is_none"
)]
pub(super) has_value: Option<bool>,
#[serde(default, skip_serializing)]
pub(super) value: Option<String>,
}
#[derive(Debug, PartialEq, Eq)]
pub(super) enum SetState {
Set,
Missing,
Unknown,
}
impl InstanceVariable {
pub(super) fn set_state(&self) -> SetState {
let known = self
.has_value
.or_else(|| self.value.as_ref().map(|value| !value.is_empty()));
match known {
Some(true) => SetState::Set,
Some(false) => SetState::Missing,
None => SetState::Unknown,
}
}
pub(super) fn blocks_provisioning(&self) -> bool {
self.kind.as_deref() == Some("custom")
&& self.required == Some(true)
&& self.set_state() == SetState::Missing
}
}
pub(super) fn dash(value: &Option<String>) -> &str {
value.as_deref().unwrap_or("-")
}
fn yes_no(value: &Option<bool>) -> &'static str {
match value {
Some(true) => "yes",
Some(false) => "no",
None => "-",
}
}
pub(super) fn required_cell(kind: &Option<String>, required: &Option<bool>) -> &'static str {
match kind.as_deref() {
Some("custom") => yes_no(required),
_ => "-",
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn required_reads_as_a_dash_for_the_kinds_it_cannot_apply_to() {
for kind in ["static", "generated"] {
assert_eq!(
required_cell(&Some(kind.to_string()), &Some(false)),
"-",
"{}",
kind
);
}
assert_eq!(
required_cell(&Some("custom".to_string()), &Some(true)),
"yes"
);
assert_eq!(
required_cell(&Some("custom".to_string()), &Some(false)),
"no"
);
assert_eq!(required_cell(&None, &Some(true)), "-");
}
}