Skip to main content

elasticctl_api/data_views_ops/
defaults.rs

1use super::{
2    DataViewSummary, Error, ErrorKind, MutationPlan, Result, Transport, data_views, invalid_plan,
3    resolve_from_summaries,
4};
5
6#[derive(Debug, Clone, PartialEq)]
7pub struct DefaultPlan {
8    pub preview: MutationPlan,
9    pub before: Option<String>,
10    pub after: Option<String>,
11}
12pub async fn plan_default_set(transport: &Transport, selector: &str) -> Result<DefaultPlan> {
13    let views = data_views::list(transport).await?;
14    let target = resolve_from_summaries(&views, selector)?;
15    let before = data_views::get_default(transport).await?;
16    let label = default_label(&target);
17    Ok(default_plan(before, Some(target.id), Some(label)))
18}
19
20pub async fn plan_default_unset(transport: &Transport) -> Result<DefaultPlan> {
21    Ok(default_plan(
22        data_views::get_default(transport).await?,
23        None,
24        None,
25    ))
26}
27
28pub async fn apply_default(transport: &Transport, plan: &DefaultPlan) -> Result<()> {
29    validate_default_plan(plan)?;
30    let current = data_views::get_default(transport).await?;
31    if current != plan.before {
32        return Err(Error::new(
33            ErrorKind::Conflict,
34            "default data view changed since preview",
35        ));
36    }
37    if plan.before == plan.after {
38        return Ok(());
39    }
40    data_views::set_default(transport, plan.after.as_deref()).await
41}
42
43fn default_plan(
44    before: Option<String>,
45    after: Option<String>,
46    target_label: Option<String>,
47) -> DefaultPlan {
48    let (preview_action, preview_details, targets) = match (&before, &after) {
49        (before, Some(after)) => {
50            let label = target_label.expect("set default plans always have a resolved label");
51            let detail = if before.as_deref() == Some(after) {
52                format!("{after}  already default")
53            } else {
54                format!(
55                    "{}  default -> {after}",
56                    before.as_deref().unwrap_or("none")
57                )
58            };
59            (
60                format!("Set default data view to {after} ({label})"),
61                vec![detail],
62                vec![after.clone()],
63            )
64        }
65        (Some(before), None) => (
66            format!("Unset default data view {before}"),
67            vec![format!("{before}  default -> unset")],
68            vec![before.clone()],
69        ),
70        (None, None) => (
71            "Unset default data view".into(),
72            vec!["no default data view set".into()],
73            Vec::new(),
74        ),
75    };
76    DefaultPlan {
77        preview: MutationPlan {
78            preview_action,
79            preview_details,
80            targets,
81        },
82        before,
83        after,
84    }
85}
86
87fn default_label(view: &DataViewSummary) -> String {
88    view.name.clone().unwrap_or_else(|| view.title.clone())
89}
90
91fn validate_default_plan(plan: &DefaultPlan) -> Result<()> {
92    for id in [&plan.before, &plan.after].into_iter().flatten() {
93        if id.trim().is_empty() {
94            return invalid_plan("default data-view ids must not be empty");
95        }
96    }
97    match (&plan.before, &plan.after) {
98        (Some(before), Some(after)) if before == after => {
99            if plan.preview.targets != [after.clone()]
100                || plan.preview.preview_details != [format!("{after}  already default")]
101                || !plan
102                    .preview
103                    .preview_action
104                    .starts_with(&format!("Set default data view to {after} ("))
105                || !plan.preview.preview_action.ends_with(')')
106            {
107                return invalid_plan("default preview does not match its snapshots");
108            }
109        }
110        (before, Some(after)) => {
111            if plan.preview.targets != [after.clone()]
112                || plan.preview.preview_details
113                    != [format!(
114                        "{}  default -> {after}",
115                        before.as_deref().unwrap_or("none")
116                    )]
117                || !plan
118                    .preview
119                    .preview_action
120                    .starts_with(&format!("Set default data view to {after} ("))
121                || !plan.preview.preview_action.ends_with(')')
122            {
123                return invalid_plan("default preview does not match its snapshots");
124            }
125        }
126        (Some(before), None) => {
127            if plan.preview.targets != [before.clone()]
128                || plan.preview.preview_action != format!("Unset default data view {before}")
129                || plan.preview.preview_details != [format!("{before}  default -> unset")]
130            {
131                return invalid_plan("default preview does not match its snapshots");
132            }
133        }
134        (None, None) => {
135            if !plan.preview.targets.is_empty()
136                || plan.preview.preview_action != "Unset default data view"
137                || plan.preview.preview_details != ["no default data view set"]
138            {
139                return invalid_plan("default preview does not match its snapshots");
140            }
141        }
142    }
143    Ok(())
144}