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
use crate::{data::instance::ScalewayInstanceRoot, ScalewayApi, ScalewayError, ScalewayInstance};
use serde::Serialize;

pub struct ScalewayCreateInstanceBuilder {
    api: ScalewayApi,
    config: CreateInstanceConfig,
}

#[derive(Serialize, Debug)]
struct CreateInstanceConfig {
    name: String,
    commercial_type: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    routed_ip_enabled: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    image: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    boot_type: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    bootscript: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    project: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    public_ip: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    enable_ipv6: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    tags: Option<Vec<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    security_group: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    placement_group: Option<String>,
}

impl ScalewayCreateInstanceBuilder {
    pub fn new(api: ScalewayApi, name: &str, commercial_type: &str) -> Self {
        ScalewayCreateInstanceBuilder {
            api,
            config: CreateInstanceConfig {
                name: name.to_string(),
                commercial_type: commercial_type.to_string(),
                routed_ip_enabled: None,
                image: None,
                boot_type: None,
                bootscript: None,
                enable_ipv6: None,
                public_ip: None,
                project: None,
                tags: None,
                security_group: None,
                placement_group: None,
            },
        }
    }

    /// A positive integer lower or equal to 100 to select the number of items to return.
    pub fn dynamic_ip_required(mut self, b: bool) -> ScalewayCreateInstanceBuilder {
        self.config.routed_ip_enabled = Some(b);
        self
    }

    /// If true, configure the Instance so it uses the new routed IP mode.
    pub fn routed_ip_enabled(mut self, routed_ip_enabled: bool) -> ScalewayCreateInstanceBuilder {
        self.config.routed_ip_enabled = Some(routed_ip_enabled);
        self
    }

    /// Instance image ID.
    pub fn image(mut self, image: &str) -> ScalewayCreateInstanceBuilder {
        self.config.image = Some(image.to_string());
        self
    }

    /// Boot type to use.
    ///
    /// Possible values: local, bootscript, rescue
    pub fn boot_type(mut self, boot_type: &str) -> ScalewayCreateInstanceBuilder {
        self.config.boot_type = Some(boot_type.to_string());
        self
    }

    /// Bootscript ID to use when boot_type is set to bootscript.
    pub fn bootscript(mut self, bootscript: &str) -> ScalewayCreateInstanceBuilder {
        self.config.bootscript = Some(bootscript.to_string());
        self
    }

    /// True if IPv6 is enabled on the server.
    pub fn enable_ipv6(mut self, enable_ipv6: bool) -> ScalewayCreateInstanceBuilder {
        self.config.enable_ipv6 = Some(enable_ipv6);
        self
    }

    /// ID of the reserved IP to attach to the Instance.
    pub fn public_ip(mut self, public_ip: &str) -> ScalewayCreateInstanceBuilder {
        self.config.public_ip = Some(public_ip.to_string());
        self
    }

    /// Instance Project ID.
    pub fn project(mut self, project: &str) -> ScalewayCreateInstanceBuilder {
        self.config.project = Some(project.to_string());
        self
    }

    /// Tags to apply to the instance
    pub fn tags(mut self, tags: Vec<String>) -> Self {
        self.config.tags = Some(tags);
        self
    }

    /// Security group ID.
    pub fn security_group(mut self, security_group: &str) -> ScalewayCreateInstanceBuilder {
        self.config.security_group = Some(security_group.to_string());
        self
    }

    /// Placement group ID if Instance must be part of a placement group.
    pub fn placement_group(mut self, placement_group: &str) -> ScalewayCreateInstanceBuilder {
        self.config.placement_group = Some(placement_group.to_string());
        self
    }

    #[cfg(feature = "blocking")]
    pub fn run(self) -> Result<ScalewayInstance, ScalewayError> {
        let url = format!(
            "https://api.scaleway.com/instance/v1/zones/{zone}/servers",
            zone = self.api.zone
        );
        Ok(self
            .api
            .post(&url, self.config)?
            .json::<ScalewayInstanceRoot>()?
            .instance)
    }

    pub async fn run_async(self) -> Result<ScalewayInstance, ScalewayError> {
        let url = format!(
            "https://api.scaleway.com/instance/v1/zones/{zone}/servers",
            zone = self.api.zone
        );
        Ok(self
            .api
            .post_async(&url, self.config)
            .await?
            .json::<ScalewayInstanceRoot>()
            .await?
            .server)
    }
}