rs_nomad/types.rs
1/*
2MIT License
3
4Copyright (c) 2023 Roblox
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25use serde::{Deserialize, Serialize};
26use smart_default::SmartDefault;
27use std::collections::HashMap;
28use std::time::Duration;
29
30use crate::serialization_helpers::*;
31
32/// Represents a single job summary as part of the [Nomad::list_jobs](nomad::Nomad::list_jobs) api.
33#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
34#[serde(rename_all = "PascalCase")]
35pub struct ConciseJob {
36 /// The ID of the nomad job.
37 #[serde(rename = "ID")]
38 pub id: String,
39 /// The job ID of the parent nomad job.
40 #[serde(rename = "ParentID")]
41 pub parent_id: Option<String>,
42 /// The type of the nomad job. See [JobType](nomad::types::JobType)
43 #[serde(rename = "Type")]
44 pub job_type: JobType,
45 /// The name of the nomad job.
46 pub name: String,
47 /// The nomad datacenters for this nomad job.
48 pub datacenters: Vec<String>,
49 /// The priority of the nomad job. Can be between 1 and 100.
50 pub priority: u8,
51 /// Whether the job is scheduled at a fixed date/time/interval.
52 pub periodic: bool,
53 /// Whether the job is dispatched using a custom payload.
54 pub parameterized_job: bool,
55 /// Whether the job is stopped.
56 pub stop: bool,
57 /// The status of the job.
58 pub status: Option<JobStatus>,
59 /// The status description of the job.
60 pub status_description: Option<String>,
61 /// The create index.
62 pub create_index: u64,
63 /// The modify index.
64 pub modify_index: u64,
65 /// The modify index of the job.
66 pub job_modify_index: u64,
67 /// The time the job was submitted as a unix timestamp.
68 pub submit_time: i64,
69 /// The summary of the job. See also [JobSummary](nomad::types::JobSummary)
70 pub job_summary: JobSummary,
71}
72
73/// The summary for instances of a particular job.
74#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
75#[serde(rename_all = "PascalCase")]
76pub struct SummaryInfo {
77 /// The number of instances of this job that have been queued.
78 pub queued: u32,
79 /// The number of instances of this job that have completed.
80 pub complete: u32,
81 /// The number of instances of this job that have failed.
82 pub failed: u32,
83 /// The number of instances of this job that are running.
84 pub running: u32,
85 /// The number of instances of this job that are starting.
86 pub starting: u32,
87 /// The number of instances of this job that have been lost.
88 pub lost: u32,
89}
90
91/// The summary information for a particular job.
92#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
93#[serde(rename_all = "PascalCase")]
94pub struct JobSummary {
95 /// The ID of the job.
96 #[serde(rename = "JobID")]
97 job_id: String,
98 /// The namespace of the job.
99 namespace: String,
100 /// The children of the given job. See also [Children](nomad::types::Children)
101 children: Option<Children>,
102 /// The summary of the job. See also [SummaryInfo](nomad::types::SummaryInfo)
103 /// This is always a single element.
104 summary: HashMap<String, SummaryInfo>,
105}
106
107/// The request to create or update a job. See also [list_jobs](nomad::Nomad::list_jobs)
108#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq)]
109#[serde(rename_all = "PascalCase")]
110pub struct JobRegisterRequest {
111 /// The job to create or update. See also [Job](nomad::types::Job)
112 pub job: Job,
113 /// If set, the job will only be registered if the passed job_modify_index matches the current job's index.
114 /// If the index is zero, the register only occurs if the job is new. This paradigm allows check-and-set style job updating.
115 pub enforce_index: bool,
116 /// Specifies the job_modify_index to enforce the current job at.
117 pub job_modify_index: u64,
118 /// If set, any soft mandatory Sentinel policies will be overridden. This allows a job to be registered when it would be denied by policy.
119 pub policy_override: bool,
120 /// If set, preserves the count of instances of the job.
121 pub preserve_counts: bool,
122}
123
124/// The response from nomad for a create or update a job request. See also [list_jobs](nomad::Nomad::list_jobs)
125#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
126#[serde(rename_all = "PascalCase")]
127pub struct JobRegisterResponse {
128 /// The ID of the evaluation for this request.
129 #[serde(rename = "EvalID")]
130 pub eval_id: String,
131 /// Specifies the index of the current evaluation for this job.
132 pub eval_create_index: u64,
133 /// Specifies the job_modify_index to enforce the current job at.
134 pub job_modify_index: u64,
135}
136
137/// The instance summary of the children for the current job.
138#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
139#[serde(rename_all = "PascalCase")]
140pub struct Children {
141 /// The number of instances in pending for the current job.
142 pub pending: u32,
143 /// The number of instances running for the current job.
144 pub running: u32,
145 /// The number of dead instances for the current job.
146 pub dead: u32,
147}
148
149/// The request to create the plan to create or update a job.
150#[derive(Serialize, Debug, Clone, PartialEq)]
151#[serde(rename_all = "PascalCase")]
152pub struct CreateJobPlanRequest<'a> {
153 /// The job to create or update. See also [Job](nomad::types::Job)
154 pub job: &'a Job,
155 /// If set, then the resulting difference report will be included in the response.
156 pub diff: bool,
157 /// If set, any soft mandatory Sentinel policies will be overridden. This allows a job to be registered when it would be denied by policy.
158 pub policy_override: bool,
159}
160
161/// The request to create the plan to create or update a job.
162#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
163#[serde(rename_all = "PascalCase")]
164pub struct CreateJobPlanResponse {
165 /// The modify index of the job.
166 pub job_modify_index: u64,
167 /// Annotations for the generated plan.
168 pub annotations: PlanAnnotations,
169 /// The difference report for the deployed job.
170 pub diff: JobDiff,
171 /// The next launch of this periodic job, if it is one.
172 #[serde(deserialize_with = "deserialize_duration_option")]
173 #[serde(serialize_with = "serialize_duration_option")]
174 pub next_periodic_launch: Option<Duration>,
175 // TODO: Add CreatedEvals []*Evaluation
176 // TODO: Add:FailedTGAllocs map[string]*AllocationMetric
177 /// Contains any warnings about the given job. These may include deprecation warnings.
178 pub warnings: String,
179}
180
181/// Contains annotations for the generated plan.
182#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
183#[serde(rename_all = "PascalCase")]
184pub struct PlanAnnotations {
185 /// Statistics about desired updates on a per-taskgroup basis.
186 #[serde(rename = "DesiredTGUpdates")]
187 pub desired_task_group_updates: HashMap<String, DesiredUpdates>,
188 // TODO: PreemptedAllocs
189}
190
191/// Statistics about desired updates.
192#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
193#[serde(rename_all = "PascalCase")]
194pub struct DesiredUpdates {
195 /// Number of deployed groups to ignore.
196 pub ignore: u64,
197 /// Number of groups to newly place.
198 pub place: u64,
199 /// Number of groups to migrate.
200 pub migrate: u64,
201 /// Number of groups to stop.
202 pub stop: u64,
203 /// Number of deployed groups to update in-place.
204 pub in_place_update: u64,
205 /// Number of deployed groups to destroy.
206 pub destructive_update: u64,
207 /// Number of canary groups.
208 pub canary: u64,
209 /// TODO: What is this?
210 pub preemptions: u64,
211}
212
213/// The type of action for a given difference.
214#[derive(Debug, Deserialize, Eq, PartialEq, Serialize, Clone)]
215pub enum DiffType {
216 /// There was no change.
217 None,
218 /// Something was added.
219 Added,
220 /// Something was deleted.
221 Deleted,
222 /// Something was edited.
223 Edited,
224}
225
226/// A difference report between a deployed job and another revision.
227#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
228#[serde(rename_all = "PascalCase")]
229pub struct JobDiff {
230 /// The type of change.
231 pub r#type: DiffType,
232 /// The ID of the job in question.
233 #[serde(rename = "ID")]
234 pub id: String,
235 /// Difference between fields.
236 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
237 pub fields: Vec<FieldDiff>,
238 /// Difference between objects.
239 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
240 pub objects: Vec<ObjectDiff>,
241 /// Difference between task groups.
242 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
243 pub task_groups: Vec<TaskGroupDiff>,
244}
245
246/// Difference for a given field.
247#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
248#[serde(rename_all = "PascalCase")]
249pub struct FieldDiff {
250 /// The type of change.
251 pub r#type: DiffType,
252 /// The name of the changed field.
253 pub name: String,
254 /// The previous value.
255 pub old: String,
256 /// The new value.
257 pub new: String,
258 /// Any annotations.
259 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
260 pub annotations: Vec<String>,
261}
262
263/// Difference for a given object.
264#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
265#[serde(rename_all = "PascalCase")]
266pub struct ObjectDiff {
267 /// The type of change.
268 pub r#type: DiffType,
269 /// The name of the changed object.
270 pub name: String,
271 /// Changed fields for this object.
272 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
273 pub fields: Vec<FieldDiff>,
274 /// Changed children objects.
275 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
276 pub objects: Vec<ObjectDiff>,
277}
278
279/// Difference for a task group.
280#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
281#[serde(rename_all = "PascalCase")]
282pub struct TaskGroupDiff {
283 /// The type of change.
284 pub r#type: DiffType,
285 /// The name of the changed object.
286 pub name: String,
287 /// Changed fields for this object.
288 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
289 pub fields: Vec<FieldDiff>,
290 /// Changed children objects.
291 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
292 pub objects: Vec<ObjectDiff>,
293 /// Difference between tasks.
294 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
295 pub tasks: Vec<TaskDiff>,
296 /// TODO: What is this?
297 pub updates: Option<HashMap<String, u64>>,
298}
299
300/// Difference for a task.
301#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
302#[serde(rename_all = "PascalCase")]
303pub struct TaskDiff {
304 /// The type of change.
305 pub r#type: DiffType,
306 /// The name of the changed object.
307 pub name: String,
308 /// Changed fields for this object.
309 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
310 pub fields: Vec<FieldDiff>,
311 /// Changed children objects.
312 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
313 pub objects: Vec<ObjectDiff>,
314 /// Any annotations.
315 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
316 pub annotations: Vec<String>,
317}
318
319/// The nomad job specification, representing a single job.
320#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, PartialEq)]
321#[serde(rename_all = "PascalCase")]
322pub struct Job {
323 /// The ID of the current job.
324 #[serde(rename = "ID")]
325 pub id: String,
326 /// The ID of the parent of the current job.
327 #[serde(rename = "ParentID")]
328 pub parent_id: Option<String>,
329 /// The type of the nomad job. See [JobType](nomad::types::JobType)
330 #[serde(rename = "Type")]
331 pub job_type: JobType,
332 /// Whether the job should be stopped.
333 pub stop: bool,
334 #[default = "global"]
335 /// The region of the job. Defaults to global.
336 pub region: String,
337 /// The namespace of the job. Defaults to default.
338 #[default = "default"]
339 pub namespace: String,
340 /// The name of the job.
341 pub name: String,
342 /// The priority for the job. Valid values are between 1 and 100, both inclusive. Defaults to 50.
343 #[default = 50]
344 pub priority: u32,
345 /// Controls whether the scheduler can make partial placements if optimistic scheduling resulted in an oversubscribed node.
346 /// This does not control whether all allocations for the job, where all would be the desired count for each task group, must be placed atomically.
347 /// This should only be used for special circumstances. Defaults to false.
348 pub all_at_once: bool,
349 /// The nomad datacenters to place this job in.
350 pub datacenters: Vec<String>,
351 /// The placement constraints for this job. See also [Constraint](nomad::types::Constraint)
352 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
353 pub constraints: Vec<Constraint>,
354 /// The task groups for this job. See also [TaskGroup](nomad::types::TaskGroup)
355 pub task_groups: Vec<TaskGroup>,
356 /// The update strategy for this job. See also [UpdateStrategy](nomad::types::UpdateStrategy)
357 pub update: Option<UpdateStrategy>,
358 /// The periodic schedule for this job. See also [PeriodicConfig](nomad::types::PeriodicConfig)
359 pub periodic: Option<PeriodicConfig>,
360 /// Specifies the job as a parameterized job such that it can be dispatched against a custom payload.
361 pub parameterized_job: Option<ParameterizedJobConfig>,
362 /// Whether the job was dispatched as with a parameterized payload.
363 pub dispatched: bool,
364 /// The payload may not be set when submitting a job but may appear in a dispatched job.
365 /// The Payload will be a base64 encoded string containing the payload that the job was dispatched with.
366 /// The payload has a maximum size of 16 KiB.
367 pub payload: Option<Vec<u8>>,
368 /// Specifies a reschedule policy to be applied to all task groups within the job.
369 /// When specified both at the job level and the task group level, the reschedule blocks are merged, with the task group's taking precedence.
370 pub reschedule: Option<ReschedulePolicy>,
371 /// A key-value map that annotates the task group with metadata opaque to nomad.
372 pub meta: Option<HashMap<String, String>>,
373 /// The consul token to use for authentication.
374 pub consul_token: Option<String>,
375 /// The vault token to authentication.
376 pub vault_token: Option<String>,
377 /// The status of the job.
378 pub status: Option<JobStatus>,
379 /// The status description of the job.
380 pub status_description: Option<String>,
381 /// Specifies whether the job should be marked as stable or not.
382 pub stable: bool,
383 /// Specifies the version of the job.
384 pub version: u64,
385 /// The time the job was submitted as a unix timestamp.
386 pub submit_time: i64,
387 /// The create index.
388 pub create_index: u64,
389 /// The modify index.
390 pub modify_index: u64,
391 /// The modify index of the job.
392 pub job_modify_index: u64,
393}
394
395/// The task groups defined for a particular job.
396#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, PartialEq)]
397#[serde(rename_all = "PascalCase")]
398pub struct TaskGroup {
399 /// The placement constraints for this job. See also [Constraint](nomad::types::Constraint)
400 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
401 pub constraints: Vec<Constraint>,
402 /// A list to define placement preferences on nodes where a job can be run. See also [Affinity](nomad::types::Affinity)
403 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
404 pub affinities: Vec<Affinity>,
405 /// A list to define allocation spread across attributes. See also [Spread](nomad::types::Spread)
406 #[serde(default)]
407 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
408 pub spreads: Vec<Spread>,
409 /// Specifies the number of the task groups that should be running. Must be non-negative, defaults to one.
410 #[default = 1]
411 pub count: u32,
412 /// A key-value map that annotates the task group with metadata opaque to nomad.
413 pub meta: Option<HashMap<String, String>>,
414 /// Specifies a migration strategy to be applied during node drains. See also [MigrateStrategy](nomad::types::MigrateStrategy)
415 pub migrate: MigrateStrategy,
416 /// The name of the task group. Must be specified.
417 pub name: String,
418 /// Specifies the restart policy to be applied to tasks in this group.
419 /// If omitted, a default policy for batch and non-batch jobs is used based on the job type.
420 /// See also [RestartPolicy](nomad::types::RestartPolicy)
421 pub restart_policy: Option<RestartPolicy>,
422 /// Specifies the reschedule policy to be applied to tasks in this group.
423 /// If omitted, a default policy is used for batch and service jobs.
424 /// System jobs are not eligible for rescheduling.
425 /// See also [ReschedulePolicy](nomad::types::ReschedulePolicy)
426 pub reschedule_policy: Option<ReschedulePolicy>,
427 /// Specifies the autoscaling policy for the task group.
428 /// This is primarily for supporting external autoscalers.
429 /// See also [Scaling](nomad::types::Scaling)
430 #[serde(default)]
431 pub scaling: Option<Scaling>,
432 /// Specifies the group's ephemeral disk requirements.
433 /// See also [EphemeralDisk](nomad::types::EphemeralDisk)
434 pub ephemeral_disk: EphemeralDisk,
435 /// Specifies an update strategy to be applied to all task groups within the job.
436 /// When specified both at the job level and the task group level, the update blocks are merged with the task group's taking precedence.
437 /// See also [UpdateStrategy](nomad::types::UpdateStrategy)
438 pub update: UpdateStrategy,
439 /// A list of Task object that are part of the task group.
440 /// See also [Task](nomad::types::Task)
441 pub tasks: Vec<Task>,
442 /// A list of network objects.
443 #[serde(rename = "Networks")]
444 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
445 pub networks: Vec<NetworkConfig>,
446 /// A Service object represents a routable and discoverable service on the network.
447 /// Nomad integrates with Consul for service discovery and it automatically registers when a task is started and de-registers it when the task transitions to the dead state.
448 /// See also [Service](nomad::types::Service)
449 /// Note that this is deprecated and replaced by the services stanza at the task group level.
450 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
451 pub services: Vec<Service>,
452}
453
454/// A map of key-value configuration passed into the driver to start the task.
455/// The details of configurations are specific to each driver.
456#[derive(Debug, Deserialize, PartialEq, Serialize, SmartDefault, Clone)]
457#[serde(untagged)]
458pub enum DriverConfig {
459 /// A boolean value.
460 Bool(bool),
461 /// A string value.
462 #[default]
463 String(String),
464 /// An integer value.
465 Int(i64),
466 /// A float value.
467 Float(f64),
468 /// An array/vector value.
469 Vector(Vec<DriverConfig>),
470 /// A map value to represent arbitrarily nested key-values.
471 Map(HashMap<String, DriverConfig>),
472}
473
474/// Represents a task within a task group.
475#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, PartialEq)]
476#[serde(rename_all = "PascalCase")]
477pub struct Task {
478 /// Represents the artifacts to download for this task.
479 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
480 pub artifacts: Vec<Artifact>,
481 /// A map of key-value configuration passed into the driver to start the task.
482 /// The details of configurations are specific to each driver.
483 pub config: Option<HashMap<String, DriverConfig>>,
484 /// The placement constraints for this job. See also [Constraint](nomad::types::Constraint)
485 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
486 pub constraints: Vec<Constraint>,
487 /// A list to define placement preferences on nodes where a job can be run. See also [Affinity](nomad::types::Affinity)
488 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
489 pub affinities: Vec<Affinity>,
490 /// A list to define allocation spread across attributes. See also [Spread](nomad::types::Spread)
491 #[serde(default)]
492 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
493 pub spreads: Vec<Spread>,
494 /// Configures the task to have access to dispatch payloads.
495 /// See also [DispatchPayload](nomad::types::DispatchPayload)
496 pub dispatch_payload: Option<DispatchPayload>,
497 /// Specifies the task driver that should be used to run the task.
498 /// See the [driver documentation](https://www.nomadproject.io/docs/drivers) for what is available.
499 /// Examples include docker, qemu, java, and exec.
500 pub driver: String,
501 /// A map of key-value representing environment variables that will be passed along to the running process.
502 /// Nomad variables are interpreted when set in the environment variable values.
503 pub env: Option<HashMap<String, String>>,
504 /// Specifies a configurable kill signal for a task, where the default is SIGINT.
505 /// Note that this is only supported for drivers which accept sending signals
506 #[default = "SIGINT"]
507 pub kill_signal: String,
508 /// KillTimeout is a time duration in nanoseconds.
509 /// It can be used to configure the time between signaling a task it will be killed and actually killing it.
510 /// Drivers first sends a task the SIGINT signal and then sends SIGTERM if the task doesn't die after the KillTimeout duration has elapsed.
511 /// The default KillTimeout is 5 seconds.
512 #[default(_code = "Duration::from_secs(5)")]
513 #[serde(deserialize_with = "deserialize_duration")]
514 #[serde(serialize_with = "serialize_duration")]
515 pub kill_timeout: Duration,
516 /// Specifies whether the task is the leader task of the task group.
517 /// If set to true, when the leader task completes, all other tasks within the task group will be gracefully shutdown.
518 pub leader: bool,
519 /// This allows configuring log rotation for the stdout and stderr buffers of a Task.
520 pub log_config: LogConfig,
521 /// A key-value map that annotates the Consul service with user-defined metadata.
522 /// String interpolation is supported in meta.
523 pub meta: Option<HashMap<String, String>>,
524 /// The name of the task.
525 pub name: String,
526 /// Provides the resource requirements of the task.
527 /// See also [Resources](nomad::types::Resources)
528 pub resources: Resources,
529 /// Specifies the restart policy to be applied to tasks in this group.
530 /// If omitted, a default policy for batch and non-batch jobs is used based on the job type.
531 /// See also [RestartPolicy](nomad::types::RestartPolicy)
532 pub restart_policy: RestartPolicy,
533 /// A Service object represents a routable and discoverable service on the network.
534 /// Nomad integrates with Consul for service discovery and it automatically registers when a task is started and de-registers it when the task transitions to the dead state.
535 /// See also [Service](nomad::types::Service)
536 /// Note that this is deprecated and replaced by the services stanza at the task group level.
537 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
538 pub services: Vec<Service>,
539 /// Specifies the duration to wait when killing a task between removing it from Consul and sending it a shutdown signal.
540 /// Ideally services would fail healthchecks once they receive a shutdown signal.
541 /// Alternatively ShutdownDelay may be set to give in flight requests time to complete before shutting down.
542 #[serde(deserialize_with = "deserialize_duration")]
543 #[serde(serialize_with = "serialize_duration")]
544 pub shutdown_delay: Duration,
545 /// Specifies the set of Template objects to render for the task.
546 /// Templates can be used to inject both static and dynamic configuration with data populated from environment variables, Consul and Vault.
547 /// See also [Template](nomad::types::Template)
548 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
549 pub templates: Vec<Template>,
550 /// Set the user that will run the task. It defaults to the same user the Nomad client is being run as.
551 /// This can only be set on Linux platforms.
552 pub user: Option<String>,
553 /// The vault configuration, if any.
554 pub vault: Option<Vault>,
555 /// The lifecycle configuration for the task, if any.
556 /// See also [Template](nomad::types::Lifecycle)
557 pub lifecycle: Option<Lifecycle>,
558}
559
560/// The lifecycle block in Nomad is used to define the order in which tasks are executed within a task group.
561/// Main tasks are those without a lifecycle block,
562/// and tasks with lifecycle hooks specify their execution timing relative to the main tasks. For more information
563/// See https://developer.hashicorp.com/nomad/docs/job-specification/lifecycle for more details.
564#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
565#[serde(rename_all = "PascalCase")]
566pub struct Lifecycle {
567 /// Specifies when a task should be run within the lifecycle of a group.
568 pub hook: String,
569 /// Controls whether a task is ephemeral or long-lived within the task group.
570 /// If a lifecycle task is ephemeral (sidecar = false), the task will not be restarted after it completes successfully.
571 /// If a lifecycle task is long-lived (sidecar = true) and terminates, it will be restarted as long as the allocation is running.
572 pub sidecar: bool,
573}
574
575/// The Template block instantiates an instance of a template renderer.
576/// This creates a convenient way to ship configuration files that are populated from environment variables, Consul data, Vault secrets, or just general configurations within a Nomad task.
577/// Nomad utilizes a tool called [Consul Template](https://github.com/hashicorp/consul-template).
578/// Since Nomad v0.5.3, the template can reference [Nomad's runtime environment variables](https://www.nomadproject.io/docs/runtime/environment).
579/// For a full list of the API template functions, please refer to the [Consul Template README](https://github.com/hashicorp/consul-template).
580#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
581#[serde(rename_all = "PascalCase")]
582pub struct Template {
583 /// Specifies the behavior Nomad should take if the rendered template changes.
584 /// The default value is `ChangeMode::Restart`
585 /// See also [ChangeMode](nomad::types::ChangeMode)
586 pub change_mode: ChangeMode,
587 /// Specifies the signal to send to the task as a string like "SIGUSR1" or "SIGINT".
588 /// This option is required if the change_mode is signal. Defaults to empty.
589 #[default(Some("".to_string()))]
590 pub change_signal: Option<String>,
591 /// Specifies the location where the resulting template should be rendered, relative to the task directory.
592 pub dest_path: String,
593 /// Specifies the raw template to execute.
594 /// One of source_path or embedded_tmpl must be specified, but not both.
595 /// This is useful for smaller templates, but we recommend using SourcePath for larger templates.
596 pub embedded_tmpl: Option<String>,
597 /// Specifies whether the template should be read back as environment variables for the task.
598 pub envvars: bool,
599 /// Specifies the left delimiter to use in the template.
600 /// The default is "{{" for some templates, it may be easier to use a different delimiter that does not conflict with the output file itself.
601 #[default = "{{"]
602 pub left_delim: String,
603 /// Specifies the right delimiter to use in the template.
604 /// The default is "}}" for some templates, it may be easier to use a different delimiter that does not conflict with the output file itself.
605 #[default = "}}"]
606 pub right_delim: String,
607 /// Specifies the rendered template's permissions.
608 /// File permissions are given as octal of the Unix file permissions rwxrwxrwx.
609 /// Defaults to 644.
610 #[default = "644"]
611 pub perms: String,
612 /// Specifies the path to the template to be rendered.
613 /// source_path is mutually exclusive with EmbeddedTmpl attribute. The source can be fetched using an Artifact resource. The template must exist on the machine prior to starting the task; it is not possible to reference a template inside of a Docker container, for example.
614 pub source_path: Option<String>,
615 /// Specifies a random amount of time to wait between 0 ms and the given splay value before invoking the change mode.
616 /// Defaults to 5 seconds.
617 #[serde(deserialize_with = "deserialize_duration")]
618 #[serde(serialize_with = "serialize_duration")]
619 #[default(_code = "Duration::from_secs(5)")]
620 pub splay: Duration,
621}
622
623/// Represents the CPU resource requirements of a task.
624/// Defaults to `Cores(1)`
625#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
626pub enum CpuResource {
627 /// Specify the CPU in megahertz. See https://www.nomadproject.io/docs/job-specification/resources#cpu.
628 #[serde(rename = "CPU")]
629 Megahertz(u32),
630 /// Specify the CPU in cores. See https://www.nomadproject.io/docs/job-specification/resources#cores.
631 #[serde(rename = "Cores")]
632 Cores(u32),
633}
634
635impl Default for CpuResource {
636 fn default() -> Self {
637 CpuResource::Cores(1)
638 }
639}
640
641/// Represents the resource requirements of a task.
642#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
643pub struct Resources {
644 /// The CPU required, mutually exclusively specified as cores or megahertz.
645 #[serde(flatten)]
646 pub cpu: CpuResource,
647 /// The memory required in MB.
648 #[serde(rename = "MemoryMB")]
649 pub memory_mb: u32,
650 /// The max memory allowed in MB. See https://www.nomadproject.io/docs/job-specification/resources#memory-oversubscription for more details.
651 #[serde(rename = "MemoryMaxMB")]
652 #[serde(skip_serializing_if = "Option::is_none")]
653 pub memory_max_mb: Option<u32>,
654 /// A list of network objects.
655 /// Note that this is deprecated and moved to the task group level.
656 #[serde(rename = "Networks")]
657 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
658 pub networks: Vec<NetworkConfig>,
659 /// A list of device objects.
660 #[serde(rename = "Devices")]
661 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
662 pub devices: Vec<Device>,
663}
664
665/// The network configuration for a task.
666#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
667#[serde(rename_all = "PascalCase")]
668pub struct NetworkConfig {
669 /// The mode of the network.
670 pub mode: String,
671 /// The device for the network.
672 pub device: String,
673 /// The CIDR representation for the network address.
674 #[serde(rename = "CIDR")]
675 pub cidr: String,
676 /// The ip of network device.
677 #[serde(rename = "IP")]
678 pub ip: String,
679 /// The number of MBits in bandwidth required.
680 pub m_bits: u32,
681 /// The reserved ports for this task. See also [Port](nomad::types::Port)
682 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
683 pub reserved_ports: Vec<Port>,
684 /// The dynamic ports for this task. See also [Port](nomad::types::Port)
685 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
686 pub dynamic_ports: Vec<Port>,
687 /// A list of DNS servers to use instead of the DNS servers configured
688 /// for the host.
689 pub dns: Option<DnsSettings>,
690}
691
692/// The dns configuration for a Network
693#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
694#[serde(rename_all = "PascalCase")]
695pub struct DnsSettings {
696 /// A list of DNS servers, e.g., ["8.8.8.8", "8.8.4.4"]
697 pub servers: Vec<String>,
698 /// A list of search domains for hostname lookup, e.g., ["The.Best.Domain"]
699 pub searches: Vec<String>,
700}
701
702/// The port configuration for a Network.
703#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
704#[serde(rename_all = "PascalCase")]
705pub struct Port {
706 /// The port number for static/reserved ports.
707 /// If the port is dynamic, then this attribute is ignored
708 pub value: u32,
709 /// The label to annotate a port so that it can be referred in the service discovery block or environment variables.
710 pub label: String,
711 /// The static port this network points to on the driver.
712 pub to: u32,
713}
714
715/// The device configuration for a task resource.
716#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
717#[serde(rename_all = "PascalCase")]
718pub struct Device {
719 /// Specifies the device required.
720 /// Possible values can be:
721 /// - <device_type>
722 /// - vendor>/<device_type>
723 /// - <vendor>/<device_type>/<model>
724 pub name: String,
725 /// The count of devices being requested per task. Defaults to 1.
726 #[default = 1]
727 pub count: u32,
728 /// The placement constraints for this task. See also [Constraint](nomad::types::Constraint)
729 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
730 pub constraints: Vec<Constraint>,
731 /// A list to define placement preferences on nodes where a task can be run. See also [Affinity](nomad::types::Affinity)
732 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
733 pub affinities: Vec<Affinity>,
734}
735
736/// Represents a parameterized job that can be dispatched with a custom payload.
737#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
738#[serde(rename_all = "PascalCase")]
739pub struct ParameterizedJobConfig {
740 /// Specifies the set of metadata keys that may be provided when dispatching against the job as a string array.
741 pub meta_optional: Vec<String>,
742 /// Specifies the set of metadata keys that must be provided when dispatching against the job as a string array.
743 pub meta_required: Vec<String>,
744 /// Specifies the requirement of providing a payload when dispatching against the parameterized job. The default value is `PayloadRequirement::Optional`.
745 pub payload: PayloadRequirement,
746}
747
748/// Specifies that the job can be scheduled at fixed times, dates or intervals.
749/// The periodic expression is always evaluated in the UTC timezone to ensure consistent evaluation when Nomad Servers span multiple time zones.
750#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
751#[serde(rename_all = "PascalCase")]
752pub struct PeriodicConfig {
753 /// Enabled determines whether the periodic job will spawn child jobs.
754 pub enabled: bool,
755 /// Specifies the time zone to evaluate the next launch interval against.
756 /// This is useful when wanting to account for day light savings in various time zones.
757 /// The time zone must be parsable by Golang's [LoadLocation](https://golang.org/pkg/time/#LoadLocation). The default is UTC.
758 #[default = "UTC"]
759 pub time_zone: String,
760 /// SpecType determines how Nomad is going to interpret the periodic expression.
761 /// `SpecType::cron` is the only supported SpecType currently.
762 pub spec_type: SpecType,
763 /// A cron expression configuring the interval the job is launched at.
764 /// Supports predefined expressions such as "@daily" and "@weekly"
765 pub spec: String,
766 /// `ProhibitOverlap` can be set to true to enforce that the periodic job doesn't spawn a new instance of the job if any of the previous jobs are still running.
767 /// It is defaulted to false.
768 pub prohibit_overlap: bool,
769}
770
771/// CheckRestart is an object which enables restarting of tasks based upon Consul health checks.
772#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
773#[serde(rename_all = "PascalCase")]
774pub struct CheckRestart {
775 /// The number of unhealthy checks allowed before the service is restarted. Defaults to 0 which disables health-based restarts.
776 pub limit: u32,
777 /// The duration to wait after a task starts or restarts before counting unhealthy checks count against the limit.
778 /// Defaults to 1 second.
779 #[default(_code = "Duration::from_secs(1)")]
780 #[serde(deserialize_with = "deserialize_duration")]
781 #[serde(serialize_with = "serialize_duration")]
782 pub grace: Duration,
783 /// Treat checks that are warning as passing. Defaults to false which means warnings are considered unhealthy.
784 pub ignore_warnings: bool,
785}
786
787/// A Service object represents a routable and discoverable service on the network.
788/// Nomad integrates with Consul for [service discovery](https://www.nomadproject.io/docs/integrations/consul-integration#service-discovery).
789/// Nomad automatically registers when a task is started and de-registers it when the task transitions to the dead state.
790#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq)]
791#[serde(rename_all = "PascalCase")]
792pub struct Service {
793 /// An explicit name for the Service.
794 /// Nomad will replace ${JOB}, ${TASKGROUP} and ${TASK} by the name of the job, task group or task, respectively.
795 /// ${BASE} expands to the equivalent of ${JOB}-${TASKGROUP}-${TASK}, and is the default name for a Service.
796 /// Each service defined for a given task must have a distinct name, so if a task has multiple services only one of them can use the default name and the others must be explicitly named.
797 /// Names must adhere to [RFC-1123 §2.1](https://tools.ietf.org/html/rfc1123#section-2) and are limited to alphanumeric and hyphen characters (i.e. [a-z0-9\-]), and be less than 64 characters in length.
798 pub name: String,
799 /// A list of string tags associated with this Service.
800 /// String interpolation is supported in tags.
801 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
802 pub tags: Vec<String>,
803 /// A key-value map that annotates the Consul service with user-defined metadata.
804 /// String interpolation is supported in meta
805 pub meta: Option<HashMap<String, String>>,
806 /// A list of string tags associated with this Service while it is a canary.
807 /// Once the canary is promoted, the registered tags will be updated to the set defined in the Tags field.
808 /// String interpolation is supported in tags.
809 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
810 pub canary_tags: Vec<String>,
811 /// A key-value map that annotates this Service while it is a canary.
812 /// Once the canary is promoted, the registered meta will be updated to the set defined in the Meta field or removed if the Meta field is not set.
813 /// String interpolation is supported in meta keys and values.
814 pub canary_meta: Option<HashMap<String, String>>,
815 /// This is used to associate a port with the service.
816 /// If specified, the port label must match one defined in the resources block.
817 /// This could be a label of either a dynamic or a static port.
818 pub port_label: Option<String>,
819 /// Specifies what address (host or driver-specific) this service should advertise.
820 /// This setting is supported in Docker since Nomad 0.6 and rkt since Nomad 0.7.
821 pub address_mode: AddressMode,
822 /// Checks define health checks associated with the service.
823 /// Nomad supports the script, http and tcp Consul Checks.
824 /// See also [ConsulCheck](nomad::types::ConsulCheck)
825 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
826 pub checks: Vec<ConsulCheck>,
827 /// [Nomad Configuration](https://www.nomadproject.io/docs/job-specification/connect) for [ConsulConnect](https://www.nomadproject.io/docs/integrations/consul-connect)
828 pub connect: Option<HashMap<String, DriverConfig>>,
829}
830
831/// Specifies what address (host or driver-specific) this service should advertise.
832#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
833#[serde(rename_all = "snake_case")]
834pub enum AddressMode {
835 /// Can be unspecified for ConsulCheck.
836 #[serde(rename = "")]
837 None,
838 /// Allows the driver to determine whether the host or driver address should be used.
839 /// Defaults to host and only implemented by Docker.
840 /// If you use a Docker network plugin such as weave, Docker will automatically use its address.
841 #[default]
842 Auto,
843 /// Use the IP specified by the driver, and the port specified in a port map.
844 /// A numeric port may be specified since port maps aren't required by all network plugins. Useful for advertising SDN and overlay network addresses. Task will fail if driver network cannot be determined.
845 /// Only implemented for Docker and rkt.
846 Driver,
847 /// Use the host IP and port.
848 Host,
849}
850
851/// Configures the task to have access to dispatch payloads.
852#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
853pub struct DispatchPayload {
854 /// Specifies the file name to write the content of dispatch payload to.
855 /// The file is written relative to the task's local directory.
856 #[serde(rename = "File")]
857 pub file: String,
858}
859
860/// Checks define health checks associated with the service.
861/// Nomad supports the script, http and tcp Consul Checks.
862#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
863#[serde(rename_all = "PascalCase")]
864pub struct ConsulCheck {
865 /// This indicates the check types supported by Nomad.
866 #[serde(rename = "Type")]
867 pub check_type: CheckType,
868 /// The name of the health check.
869 pub name: String,
870 /// The command to execute.
871 pub command: String,
872 /// The arguments to provide the command.
873 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
874 pub args: Vec<String>,
875 /// The path or route to use.
876 pub path: Option<String>,
877 /// The protocol to use. See also [Protocol](nomad::types::Protocol)
878 pub protocol: Option<Protocol>,
879 /// Whether to expose the check.
880 pub expose: bool,
881 /// The address mode to use. See also [AddressMode](nomad::types::AddressMode)
882 pub address_mode: AddressMode,
883 /// The port label to use.
884 pub port_label: String,
885 /// This indicates the frequency of the health checks that Consul will perform.
886 #[serde(deserialize_with = "deserialize_duration")]
887 #[serde(serialize_with = "serialize_duration")]
888 pub interval: Duration,
889 /// This indicates how long Consul will wait for a health check query to succeed.
890 #[serde(deserialize_with = "deserialize_duration")]
891 #[serde(serialize_with = "serialize_duration")]
892 pub timeout: Duration,
893 /// The initial status of the check.
894 pub initial_status: Option<String>,
895 /// If true, Consul will not attempt to verify the certificate when performing HTTPS checks.
896 /// Requires Consul >= 0.7.2.
897 #[serde(rename = "TLSSkipVerify")]
898 pub tls_skip_verify: bool,
899 /// The HTTP method to use for HTTP checks.
900 /// Defaults to `HttpMethod::GET`.
901 #[default(HttpMethod::Get)]
902 pub method: HttpMethod,
903 /// Headers for HTTP checks.
904 /// Headers will be written once for each value.
905 #[serde(rename = "Header")]
906 pub header: Option<HashMap<String, Vec<String>>>,
907 /// The grpc healthcheck.
908 #[serde(rename = "GRPCService")]
909 pub grpc_service: String,
910 /// Whether the grpc healthcheck uses TLS.
911 #[serde(rename = "GRPCUseTLS")]
912 pub grpc_use_tls: bool,
913 /// The name of the task for the check.
914 #[serde(rename = "TaskName")]
915 pub task_name: String,
916 /// CheckRestart is an object which enables restarting of tasks based upon Consul health checks.
917 #[serde(rename = "CheckRestart")]
918 pub check_restart: CheckRestart,
919}
920
921/// This indicates the check types supported by Nomad.
922#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
923#[serde(rename_all = "snake_case")]
924pub enum CheckType {
925 /// Script based check.
926 #[default]
927 Script,
928 /// Http based check.
929 Http,
930 /// Https based check.
931 Tcp,
932 /// Grpc based check.
933 Grpc,
934}
935
936/// The protocol (http/https)
937#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
938#[serde(rename_all = "snake_case")]
939pub enum Protocol {
940 /// Unspecified.
941 #[default]
942 #[serde(rename = "")]
943 None,
944 /// http
945 Http,
946 /// https
947 Https,
948}
949
950/// The HTTP Method type.
951#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
952#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
953pub enum HttpMethod {
954 /// GET
955 #[default]
956 Get,
957 /// PUT
958 Put,
959 /// POST
960 Post,
961 /// DELETE
962 Delete,
963 /// OPTIONS
964 Options,
965 /// HEAD
966 Head,
967 /// TRACE
968 Trace,
969 /// CONNECT
970 Connect,
971 /// PATCH
972 Patch,
973 /// None
974 #[serde(untagged)]
975 Unknown(String),
976}
977
978/// The LogConfig object configures the log rotation policy for a task's stdout and stderr
979#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
980#[serde(rename_all = "PascalCase")]
981pub struct LogConfig {
982 /// The maximum number of rotated files Nomad will retain for stdout and stderr, each tracked individually.
983 pub max_files: u32,
984 /// The size of each rotated file. The size is specified in MB.
985 #[serde(rename = "MaxFileSizeMB")]
986 pub max_file_size_in_mb: u32,
987}
988
989/// Nomad downloads artifacts using [go-getter](https://github.com/hashicorp/go-getter).
990/// The go-getter library allows downloading of artifacts from various sources using a URL as the input source.
991/// The key-value pairs given in the options block map directly to parameters appended to the supplied source URL.
992/// These are then used by go-getter to appropriately download the artifact.
993/// Nomad allows downloading http, https, and S3 artifacts.
994/// If these artifacts are archives (zip, tar.gz, bz2, etc.), these will be unarchived before the task is started.
995#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
996#[serde(rename_all = "PascalCase")]
997pub struct Artifact {
998 /// The path to the artifact to download.
999 pub getter_source: String,
1000 /// An optional path to download the artifact into relative to the root of the task's directory.
1001 /// If omitted, it will default to local/.
1002 #[default = "local/"]
1003 pub relative_dest: String,
1004 /// A map[string]string block of options for go-getter. [Details](https://github.com/hashicorp/go-getter/tree/ef5edd3d8f6f482b775199be2f3734fd20e04d4a#protocol-specific-options-1)
1005 pub getter_options: HashMap<String, String>,
1006}
1007
1008/// SpecType determines how Nomad is going to interpret the periodic expression.
1009#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
1010#[serde(rename_all = "snake_case")]
1011pub enum SpecType {
1012 /// cron is the only supported SpecType currently.
1013 #[default]
1014 Cron,
1015}
1016
1017/// Specifies the requirement of providing a payload when dispatching against the parameterized job.
1018#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
1019#[serde(rename_all = "snake_case")]
1020pub enum PayloadRequirement {
1021 /// Optional. This is the default value.
1022 #[default]
1023 Optional,
1024 /// Required.
1025 Required,
1026 /// Forbidden.
1027 Forbidden,
1028}
1029
1030/// Specifies the group's ephemeral disk requirements.
1031#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
1032#[serde(rename_all = "PascalCase")]
1033pub struct EphemeralDisk {
1034 /// Specifies that the Nomad client should make a best-effort attempt to migrate the data from a remote machine if placement cannot be made on the original node.
1035 /// During data migration, the task will block starting until the data migration has completed.
1036 /// Defaults to false.
1037 pub migrate: bool,
1038 /// Specifies the size of the ephemeral disk in MB.
1039 /// Defaults to 300.
1040 #[default = 300]
1041 #[serde(rename = "SizeMB")]
1042 pub size_in_mb: u32,
1043 /// Specifies that Nomad should make a best-effort attempt to place the updated allocation on the same machine.
1044 /// This will move the local/ and alloc/data directories to the new allocation.
1045 /// Defaults to false.
1046 pub sticky: bool,
1047}
1048
1049/// Scaling policies allow operators to attach autoscaling configuration to a task group.
1050/// This information can be queried by [external autoscalers](https://github.com/hashicorp/nomad-autoscaler).
1051#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, PartialEq)]
1052#[serde(rename_all = "PascalCase")]
1053pub struct Scaling {
1054 /// The minimum allowable count for the task group.
1055 /// This is optional; if absent, the default is the Count specified in the task group.
1056 /// Attempts to set the task group Count below Min will result in a 400 error during job registration.
1057 pub min: Option<u32>,
1058 /// The maximum allowable count for the task group.
1059 /// This is required if a scaling policy is provided.
1060 /// This must be larger than Min.
1061 /// Attempts to set the task group Count above Max wil result in a 400 error during job registration.
1062 pub max: u32,
1063 /// An optional boolean (default: true).
1064 /// This indicates to the autoscaler that this scaling policy should be ignored.
1065 /// It is intended to allow autoscaling to be temporarily disabled for a task group.
1066 #[default = true]
1067 pub enabled: bool,
1068 /// An optional JSON block.
1069 /// This is opaque to Nomad; see the [documentation](https://github.com/hashicorp/nomad-autoscaler) for the external autoscaler.
1070 pub policy: HashMap<String, DriverConfig>,
1071}
1072
1073/// Specifies the reschedule policy to be applied to tasks in this group.
1074/// If omitted, a default policy is used for batch and service jobs.
1075/// System jobs are not eligible for rescheduling.
1076#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
1077#[serde(rename_all = "PascalCase")]
1078pub struct ReschedulePolicy {
1079 /// Attempts is the number of reschedule attempts allowed in an interval.
1080 pub attempts: u32,
1081 /// The Interval is a sliding window within which at most Attempts number of reschedule attempts are permitted.
1082 #[serde(deserialize_with = "deserialize_duration")]
1083 #[serde(serialize_with = "serialize_duration")]
1084 pub interval: Duration,
1085 /// A duration to wait before attempting rescheduling.
1086 #[serde(deserialize_with = "deserialize_duration")]
1087 #[serde(serialize_with = "serialize_duration")]
1088 pub delay: Duration,
1089 /// Specifies the function that is used to calculate subsequent reschedule delays.
1090 /// The initial delay is specified by the Delay parameter.
1091 pub delay_function: DelayFunction,
1092 /// max_delay is an upper bound on the delay beyond which it will not increase.
1093 /// This parameter is used when DelayFunction is exponential or fibonacci, and is ignored when constant delay is used.
1094 #[serde(deserialize_with = "deserialize_duration")]
1095 #[serde(serialize_with = "serialize_duration")]
1096 pub max_delay: Duration,
1097 /// Unlimited enables unlimited reschedule attempts.
1098 /// If this is set to true the Attempts and Interval fields are not used.
1099 pub unlimited: bool,
1100}
1101
1102/// Specifies the function that is used to calculate subsequent reschedule delays.
1103#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
1104#[serde(rename_all = "snake_case")]
1105pub enum DelayFunction {
1106 /// The delay between reschedule attempts stays at the Delay value.
1107 #[default]
1108 Constant,
1109 /// The delay between reschedule attempts doubles.
1110 Exponential,
1111 /// The delay between reschedule attempts is calculated by adding the two most recent delays applied.
1112 Fibonacci,
1113}
1114
1115/// Specifies the job type and switches which scheduler is used.
1116/// Nomad provides the service, system and batch schedulers, and defaults to service
1117#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
1118#[serde(rename_all = "snake_case")]
1119pub enum JobType {
1120 /// The service scheduler is designed for scheduling long lived services that should never go down.
1121 /// As such, the service scheduler ranks a large portion of the nodes that meet the job's constraints and selects the optimal node to place a task group on.
1122 #[default]
1123 Service,
1124 /// The system scheduler is used to register jobs that should be run on all clients that meet the job's constraints.
1125 /// The system scheduler is also invoked when clients join the cluster or transition into the ready state.
1126 /// This means that all registered system jobs will be re-evaluated and their tasks will be placed on the newly available nodes if the constraints are met.
1127 Batch,
1128 /// Batch jobs are much less sensitive to short term performance fluctuations and are short lived, finishing in a few minutes to a few days.
1129 /// Although the batch scheduler is very similar to the service scheduler, it makes certain optimizations for the batch workload.
1130 System,
1131}
1132
1133/// Specifies the job status. https://developer.hashicorp.com/nomad/api-docs/jobs#status
1134#[derive(Clone, Debug, Deserialize, Eq, SmartDefault, Serialize, PartialEq)]
1135#[serde(rename_all = "snake_case")]
1136pub enum JobStatus {
1137 /// All of the job's allocations and evaluations are terminal.
1138 #[default]
1139 Dead,
1140 /// The job has non-terminal allocations.
1141 Running,
1142 /// The job is currently waiting on scheduling.
1143 Pending,
1144 /// The job is currently paused.
1145 Paused,
1146 /// The job failed.
1147 Failed,
1148 /// The job deployment was successful.
1149 Successful,
1150 /// The job deployment was cancelled.
1151 Cancelled,
1152 /// The job deployment is initializing.
1153 Initializing,
1154 /// The job deployment is blocked.
1155 Blocked,
1156 /// The job deployment is unblocking.
1157 Unblocking,
1158}
1159
1160/// Specifies the behavior Nomad should take if the rendered template changes.
1161#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
1162#[serde(rename_all = "snake_case")]
1163pub enum ChangeMode {
1164 /// take no action (continue running the task)
1165 Noop,
1166 /// restart the task (this is the default)
1167 #[default]
1168 Restart,
1169 /// end a configurable signal to the task
1170 Signal,
1171}
1172
1173/// Specifies a migration strategy to be applied during [node drains](https://www.nomadproject.io/docs/commands/node/drain).
1174#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
1175#[serde(rename_all = "PascalCase")]
1176pub struct MigrateStrategy {
1177 /// Specifies how many allocations may be migrated at once.
1178 /// Defaults to 1.
1179 #[default = 1]
1180 pub max_parallel: u32,
1181 /// Indicates how task health should be determined: either via Consul health checks or whether the task was able to run successfully.
1182 /// See also [HealthCheck](nomad::types::HealthCheck)
1183 #[serde(deserialize_with = "deserialize_healthcheck")]
1184 pub health_check: HealthCheck,
1185 /// Specifies duration a task must be considered healthy before the migration is considered healthy.
1186 /// Defaults to 10 seconds.
1187 #[serde(deserialize_with = "deserialize_duration")]
1188 #[serde(serialize_with = "serialize_duration")]
1189 #[default(_code = "Duration::from_secs(10)")]
1190 pub min_healthy_time: Duration,
1191 /// Specifies duration a task must become healthy within before it is considered unhealthy.
1192 /// Defaults to 5 minutes.
1193 #[serde(deserialize_with = "deserialize_duration")]
1194 #[serde(serialize_with = "serialize_duration")]
1195 #[default(_code = "Duration::from_secs(300)")]
1196 pub healthy_deadline: Duration,
1197}
1198
1199/// Specifies the task group update strategy.
1200/// When omitted, rolling updates are disabled.
1201/// The update stanza can be specified at the job or task group level.
1202/// When specified at the job, the update stanza is inherited by all task groups.
1203/// When specified in both the job and in a task group, the stanzas are merged with the task group's taking precedence.
1204#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
1205#[serde(rename_all = "PascalCase")]
1206pub struct UpdateStrategy {
1207 /// Specifies the number of tasks that can be updated at the same time.
1208 /// Defaults to 1.
1209 #[default = 1]
1210 pub max_parallel: u32,
1211 /// Specifies the mechanism in which allocations health is determined.
1212 /// See also [HealthCheck](nomad::types::HealthCheck)
1213 #[serde(deserialize_with = "deserialize_healthcheck")]
1214 pub health_check: HealthCheck,
1215 /// Specifies the minimum time the allocation must be in the healthy state before it is marked as healthy and unblocks further allocations from being updated.
1216 /// Defaults to 10 seconds.
1217 #[serde(deserialize_with = "deserialize_duration")]
1218 #[serde(serialize_with = "serialize_duration")]
1219 #[default(_code = "Duration::from_secs(10)")]
1220 pub min_healthy_time: Duration,
1221 /// Specifies the deadline in which the allocation must be marked as healthy after which the allocation is automatically transitioned to unhealthy.
1222 /// Defaults to 5 minutes.
1223 #[serde(deserialize_with = "deserialize_duration")]
1224 #[serde(serialize_with = "serialize_duration")]
1225 #[default(_code = "Duration::from_secs(300)")]
1226 pub healthy_deadline: Duration,
1227 /// Specifies the deadline in which an allocation must be marked as healthy.
1228 /// The deadline begins when the first allocation for the deployment is created and is reset whenever an allocation as part of the deployment transitions to a healthy state.
1229 /// If no allocation transitions to the healthy state before the progress deadline, the deployment is marked as failed.
1230 /// If the progress_deadline is set to 0, the first allocation to be marked as unhealthy causes the deployment to fail.
1231 /// Defaults to 10 minutes.
1232 #[serde(deserialize_with = "deserialize_duration")]
1233 #[serde(serialize_with = "serialize_duration")]
1234 #[default(_code = "Duration::from_secs(600)")]
1235 pub progress_deadline: Duration,
1236 /// Specifies if the job should auto-revert to the last stable job on deployment failure.
1237 /// A job is marked as stable if all the allocations as part of its deployment were marked healthy.
1238 /// Defaults to false.
1239 pub auto_revert: bool,
1240 /// Specifies that changes to the job that would result in destructive updates should create the specified number of canaries without stopping any previous allocations.
1241 /// Once the operator determines the canaries are healthy, they can be promoted which unblocks a rolling update of the remaining allocations at a rate of max_parallel.
1242 /// Defaults to 0.
1243 pub canary: u32,
1244 /// specifies if the job should automatically promote to the new deployment if all canaries become healthy.
1245 /// Defaults to false.
1246 pub auto_promote: bool,
1247 /// Specifies the delay between migrating allocations off nodes marked for draining.
1248 /// Defaults to 30 seconds.
1249 #[serde(deserialize_with = "deserialize_duration")]
1250 #[serde(serialize_with = "serialize_duration")]
1251 #[default(_code = "Duration::from_secs(30)")]
1252 pub stagger: Duration,
1253}
1254
1255/// Specifies the restart policy in case of task failure.
1256#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
1257#[serde(rename_all = "PascalCase")]
1258pub struct RestartPolicy {
1259 /// Attempts is the number of restarts allowed in an Interval.
1260 /// Defaults to 1.
1261 #[default = 1]
1262 pub attempts: u32,
1263 /// The Interval begins when the first task starts and ensures that only Attempts number of restarts happens within it.
1264 /// If more than Attempts number of failures happen, behavior is controlled by Mode.
1265 /// Defaults to 30 minutes.
1266 #[serde(deserialize_with = "deserialize_duration")]
1267 #[serde(serialize_with = "serialize_duration")]
1268 #[default(_code = "Duration::from_secs(1800)")]
1269 pub interval: Duration,
1270 /// A duration to wait before restarting a task.
1271 /// A random jitter of up to 25% is added to the delay.
1272 /// Defaults to 15 seconds.
1273 #[serde(deserialize_with = "deserialize_duration")]
1274 #[serde(serialize_with = "serialize_duration")]
1275 #[default(_code = "Duration::from_secs(15)")]
1276 pub delay: Duration,
1277 /// Mode controls the behavior when the task fails more than Attempts times in an Interval.
1278 /// See also [RestartMode](nomad::types::RestartMode)
1279 pub mode: RestartMode,
1280}
1281
1282/// Indicates how task health should be determined: either via Consul health checks or whether the task was able to run successfully.
1283#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
1284#[serde(rename_all = "snake_case")]
1285pub enum HealthCheck {
1286 /// Specifies that the allocation should be considered healthy when all of its tasks are running and their associated checks are healthy, and unhealthy if any of the tasks fail or not all checks become healthy.
1287 /// This is a superset of "task_states" mode.
1288 #[default]
1289 Checks,
1290 /// Specifies that the allocation should be considered healthy when all its tasks are running and unhealthy if tasks fail.
1291 TaskStates,
1292 /// Specifies that Nomad should not automatically determine health and that the operator will specify allocation health using the HTTP API.
1293 Manual,
1294}
1295
1296/// This controls the behavior when the task fails more than Attempts times in an Interval
1297#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
1298#[serde(rename_all = "snake_case")]
1299pub enum RestartMode {
1300 /// delay will delay the next restart until the next Interval is reached.
1301 #[default]
1302 Delay,
1303 /// fail will not restart the task again.
1304 Fail,
1305}
1306
1307/// Spread allow operators to target specific percentages of allocations based on any node attribute or metadata.
1308#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
1309#[serde(rename_all = "PascalCase")]
1310pub struct Spread {
1311 /// Specifies the attribute to examine for the spread.
1312 pub attribute: String,
1313 /// Specifies a list of attribute values and percentages.
1314 /// This is an optional field, when left empty Nomad will evenly spread allocations across values of the attribute.
1315 #[serde(default)]
1316 pub target: Vec<SpreadTarget>,
1317 /// A non zero weight, valid values are from -100 to 100. Used to express relative preference when there is more than one spread or affinity.
1318 pub weight: u8,
1319}
1320
1321/// Specifies a list of attribute values and percentages.
1322#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
1323#[serde(rename_all = "PascalCase")]
1324pub struct SpreadTarget {
1325 /// The value of a specific target attribute, like "dc1" for ${node.datacenter}.
1326 pub value: String,
1327 /// Desired percentage of allocations for this attribute value. The sum of all spread target percentages must add up to 100.
1328 pub percent: u8,
1329}
1330
1331/// A representation of placement preferences on nodes where a job can be run.
1332#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
1333#[serde(rename_all = "PascalCase")]
1334pub struct Affinity {
1335 /// Specifies the attribute to examine for the affinity.
1336 pub l_target: Option<String>,
1337 /// specifies the value to compare the attribute against. This can be a literal value, another attribute or a regular expression if the Operator is in "regexp" mode.
1338 pub r_target: Option<String>,
1339 /// Specifies the test to be performed on the two targets.
1340 /// See also [AffinityOperator](nomad::types::AffinityOperator)
1341 pub operand: AffinityOperator,
1342 /// A non zero weight, valid values are from -100 to 100. Used to express relative preference when there is more than one affinity.
1343 pub weight: i8,
1344}
1345
1346/// A representation to define additional constraints where a job can be run.
1347#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
1348#[serde(rename_all = "PascalCase")]
1349pub struct Constraint {
1350 /// Specifies the attribute to examine for the constraint.
1351 pub l_target: Option<String>,
1352 /// Specifies the value to compare the attribute against.
1353 /// This can be a literal value, another attribute or a regular expression if the Operator is in "regexp" mode.
1354 pub r_target: Option<String>,
1355 /// Specifies the test to be performed on the two targets.
1356 pub operand: ConstraintOperator,
1357}
1358
1359/// Vault configuration for a given job/task group/task.
1360#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
1361#[serde(rename_all = "PascalCase")]
1362pub struct Vault {
1363 /// The policies to load.
1364 #[serde(deserialize_with = "deserialize_vec_with_null_as_empty")]
1365 pub policies: Vec<String>,
1366 /// The Vault namespace to use, if any.
1367 pub namespace: Option<String>,
1368 /// The ChangeMode, if any.
1369 pub change_mode: Option<ChangeMode>,
1370 /// The ChangeSignal, if ChangeMode is set to [`ChangeMode::Signal`].
1371 pub change_signal: Option<String>,
1372}
1373
1374/// The operand for [Constraint](nomad::types::Constraint)
1375#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
1376pub enum ConstraintOperator {
1377 /// Equals
1378 #[default]
1379 #[serde(rename = "=")]
1380 Equals,
1381 /// Does not equal
1382 #[serde(rename = "!=")]
1383 NotEquals,
1384 /// Greater than
1385 #[serde(rename = ">")]
1386 GreaterThan,
1387 /// Greater than or equal to
1388 #[serde(rename = ">=")]
1389 GreaterThanOrEqual,
1390 /// Less than
1391 #[serde(rename = "<")]
1392 LessThan,
1393 /// Less than or equal to
1394 #[serde(rename = "<=")]
1395 LessThanOrEqual,
1396 /// Distinct hosts
1397 #[serde(rename = "distinct_hosts")]
1398 DistinctHosts,
1399 /// Distinct property
1400 #[serde(rename = "distinct_property")]
1401 DistinctProperty,
1402 /// Regular expression
1403 #[serde(rename = "regexp")]
1404 RegularExpression,
1405 /// Set contains
1406 #[serde(rename = "set_contains")]
1407 SetContains,
1408 /// Version
1409 #[serde(rename = "version")]
1410 Version,
1411 /// Semantic version
1412 #[serde(rename = "semver")]
1413 SemanticVersion,
1414 /// Is set
1415 #[serde(rename = "is_set")]
1416 IsSet,
1417 /// Is not set
1418 #[serde(rename = "is_not_set")]
1419 IsNotSet,
1420}
1421
1422/// The operand for [Affinity](nomad::types::Affinity)
1423#[derive(Serialize, Deserialize, SmartDefault, Debug, Clone, Eq, PartialEq)]
1424pub enum AffinityOperator {
1425 /// Equals
1426 #[default]
1427 #[serde(rename = "=")]
1428 Equals,
1429 /// Does not equal
1430 #[serde(rename = "!=")]
1431 NotEquals,
1432 /// Greater than
1433 #[serde(rename = ">")]
1434 GreaterThan,
1435 /// Greater than or equal to
1436 #[serde(rename = ">=")]
1437 GreaterThanOrEqual,
1438 /// Less than
1439 #[serde(rename = "<")]
1440 LessThan,
1441 /// Less than or equal to
1442 #[serde(rename = "<=")]
1443 LessThanOrEqual,
1444 /// Regular expression
1445 #[serde(rename = "regexp")]
1446 RegularExpression,
1447 /// Set contains all
1448 #[serde(rename = "set_contains_all")]
1449 SetContainsAll,
1450 /// Set contains any
1451 #[serde(rename = "set_contains_any")]
1452 SetContainsAny,
1453 /// Version
1454 #[serde(rename = "version")]
1455 Version,
1456}
1457
1458/// A nomad job deployment , representing a single deployment of a job.
1459#[derive(Serialize, Deserialize, SmartDefault, Debug, Eq, PartialEq)]
1460#[serde(rename_all = "PascalCase")]
1461pub struct JobDeployment {
1462 /// The ID of the nomad job deployment.
1463 #[serde(rename = "ID")]
1464 pub id: String,
1465 /// The ID of the nomad job .
1466 #[serde(rename = "JobID")]
1467 pub job_id: String,
1468 /// Specifies the version of the job.
1469 pub job_version: u64,
1470 /// The status of the job.
1471 pub status: Option<JobStatus>,
1472 /// The status description of the job.
1473 pub status_description: Option<String>,
1474 // In the future we can add, if needed
1475 // the following:
1476 // JobModifyIndex, JobCreateIndex, TaskGroups, CreateIndex, ModifyIndex
1477}
1478
1479#[cfg(test)]
1480mod tests {
1481 use super::*;
1482
1483 #[test]
1484 fn test_deserialize_resources_with_megahertz() {
1485 let content = r#"
1486 {
1487 "CPU": 2000,
1488 "MemoryMB": 20,
1489 "Networks": [],
1490 "Devices": []
1491 }
1492 "#;
1493
1494 let resources: Resources = serde_json::from_str(content).expect("serialization to succeed");
1495
1496 assert_eq!(resources.cpu, CpuResource::Megahertz(2000));
1497 assert_eq!(resources.memory_mb, 20);
1498 }
1499
1500 #[test]
1501 fn test_deserialize_resources_with_cores() {
1502 let content = r#"
1503 {
1504 "Cores": 4,
1505 "MemoryMB": 20,
1506 "Networks": [],
1507 "Devices": []
1508 }
1509 "#;
1510
1511 let resources: Resources = serde_json::from_str(content).expect("serialization to succeed");
1512
1513 assert_eq!(resources.cpu, CpuResource::Cores(4));
1514 assert_eq!(resources.memory_mb, 20);
1515 }
1516}