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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
use crate::{LinodeApi, LinodeError, LinodeInstance};
use serde::Serialize;
pub struct LinodeCreateInstanceBuilder {
api: LinodeApi,
config: CreateInstanceConfig,
}
#[derive(Serialize, Debug)]
struct CreateInstanceConfigMetadata {
user_data: Option<String>,
}
#[derive(Serialize, Debug)]
struct CreateInstanceConfig {
#[serde(skip_serializing_if = "Option::is_none")]
authorized_keys: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
authorized_users: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
backup_id: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
backups_enabled: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
booted: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
firewall_id: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
group: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
image: Option<String>,
//#[serde(skip_serializing_if = "Option::is_none")]
//interfaces: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
label: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
metadata: Option<CreateInstanceConfigMetadata>,
#[serde(skip_serializing_if = "Option::is_none")]
private_ip: Option<bool>,
region: String,
#[serde(skip_serializing_if = "Option::is_none")]
root_pass: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
stackscript_data: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
stackscript_id: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
swap_size: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
tags: Option<Vec<String>>,
#[serde(rename = "type")]
ltype: String,
}
impl LinodeCreateInstanceBuilder {
/// region: The Region where the Linode will be located.
///
/// ltype: The Linode Type of the Linode you are creating.
pub fn new(api: LinodeApi, region: &str, ltype: &str) -> Self {
LinodeCreateInstanceBuilder {
api,
config: CreateInstanceConfig {
authorized_keys: None,
authorized_users: None,
backup_id: None,
backups_enabled: None,
booted: None,
firewall_id: None,
group: None,
image: None,
label: None,
metadata: None,
private_ip: None,
region: region.to_string(),
root_pass: None,
stackscript_data: None,
stackscript_id: None,
swap_size: None,
tags: None,
ltype: ltype.to_string(),
},
}
}
/// A list of public SSH keys that will be automatically appended to the root user’s
/// ~/.ssh/authorized_keys file when deploying from an Image.
pub fn authorized_keys(mut self, authorized_keys: Vec<String>) -> LinodeCreateInstanceBuilder {
self.config.authorized_keys = Some(authorized_keys);
self
}
/// A list of usernames. If the usernames have associated SSH keys, the keys
/// will be appended to the root users ~/.ssh/authorized_keys file automatically when deploying from an Image.
pub fn authorized_users(
mut self,
authorized_users: Vec<String>,
) -> LinodeCreateInstanceBuilder {
self.config.authorized_users = Some(authorized_users);
self
}
/// A Backup ID from another Linode’s available backups. Your User must have read_write access
/// to that Linode, the Backup must have a status of successful, and the Linode must be deployed
/// to the same region as the Backup. See GET /linode/instances/{linodeId}/backups for a Linode’s available backups.
///
/// This field and the image field are mutually exclusive.
pub fn backup_id(mut self, backup_id: u64) -> LinodeCreateInstanceBuilder {
self.config.backup_id = Some(backup_id);
self
}
/// If this field is set to true, the created Linode will automatically be enrolled in the
/// Linode Backup service. This will incur an additional charge. The cost for the Backup service
/// is dependent on the Type of Linode deployed.
///
/// This option is always treated as true if the account-wide backups_enabled setting is true. See account settings for more information.
///
/// Backup pricing is included in the response from /linodes/types
pub fn backups_enabled(mut self, backups_enabled: bool) -> LinodeCreateInstanceBuilder {
self.config.backups_enabled = Some(backups_enabled);
self
}
/// This field defaults to true if the Linode is created with an Image or from a Backup. If it is deployed
/// from an Image or a Backup and you wish it to remain offline after deployment, set this to false.
pub fn booted(mut self, booted: bool) -> LinodeCreateInstanceBuilder {
self.config.booted = Some(booted);
self
}
/// The id of the Firewall to attach this Linode to upon creation.
pub fn firewall_id(mut self, firewall_id: u64) -> LinodeCreateInstanceBuilder {
self.config.firewall_id = Some(firewall_id);
self
}
/// A deprecated property denoting a group label for this Linode.
pub fn group(mut self, group: &str) -> LinodeCreateInstanceBuilder {
self.config.group = Some(group.to_string());
self
}
/// An Image ID to deploy the Linode Disk from.
///
/// Access the Images List (GET /images) endpoint with authentication to view all available Images.
/// Official Linode Images start with linode/, while your Account’s Images start with private/.
/// Creating a disk from a Private Image requires read_only or read_write permissions for that Image.
/// Access the User’s Grant Update (PUT /account/users/{username}/grants) endpoint to adjust permissions for an Account Image.
pub fn image(mut self, image: &str) -> LinodeCreateInstanceBuilder {
self.config.image = Some(image.to_string());
self
}
/// The Linode’s label is for display purposes only. If no label is provided for a Linode, a default will be assigned.
///
/// Linode labels have the following constraints:
/// * 3..64 characters
/// * Must begin and end with an alphanumeric character.
/// * May only consist of alphanumeric characters, dashes (-), underscores (_) or periods (.).
/// * Cannot have two dashes (--), underscores (__) or periods (..) in a row.
pub fn label(mut self, label: &str) -> LinodeCreateInstanceBuilder {
self.config.label = Some(label.to_string());
self
}
/// Base64-encoded cloud-config data.
///
/// Cannot be modified after provisioning. To update, use either the Linode Clone or Linode Rebuild commands.
///
/// Must not be included when cloning to an existing Linode.
///
/// Unencoded data must not exceed 65535 bytes, or about 16kb encoded.
pub fn user_data(mut self, user_data: &str) -> LinodeCreateInstanceBuilder {
self.config.metadata = Some(CreateInstanceConfigMetadata {
user_data: Some(user_data.to_string()),
});
self
}
/// If true, the created Linode will have private networking enabled and assigned a private IPv4 address.
pub fn private_ip(mut self, private_ip: bool) -> LinodeCreateInstanceBuilder {
self.config.private_ip = Some(private_ip);
self
}
/// If true, the created Linode will have private networking enabled and assigned a private IPv4 address.
pub fn root_pass(mut self, root_pass: &str) -> LinodeCreateInstanceBuilder {
self.config.root_pass = Some(root_pass.to_string());
self
}
/// Default: 512
///
/// When deploying from an Image, this field is optional, otherwise it is ignored.
/// This is used to set the swap disk size for the newly-created Linode.
pub fn swap_size(mut self, swap_size: u64) -> LinodeCreateInstanceBuilder {
self.config.swap_size = Some(swap_size);
self
}
/// An array of tags applied to this object. Tags are for organizational purposes only.
pub fn tags(mut self, tags: Vec<String>) -> LinodeCreateInstanceBuilder {
self.config.tags = Some(tags);
self
}
#[cfg(feature = "blocking")]
pub fn run(self) -> Result<LinodeInstance, LinodeError> {
Ok(self
.api
.post("https://api.linode.com/v4/linode/instances", self.config)?
.json::<LinodeInstance>()?)
}
pub async fn run_async(self) -> Result<LinodeInstance, LinodeError> {
Ok(self
.api
.post_async("https://api.linode.com/v4/linode/instances", self.config)
.await?
.json::<LinodeInstance>()
.await?)
}
}