1pub mod scripts;
2
3use std::{
4 collections::HashSet,
5 io::{self, Error, ErrorKind},
6 str::FromStr,
7};
8
9use crate::ec2;
10use serde::{Deserialize, Serialize};
11
12#[derive(
14 Deserialize, Serialize, std::clone::Clone, std::cmp::Eq, std::fmt::Debug, std::hash::Hash,
15)]
16pub enum Plugin {
17 #[serde(rename = "imds")]
18 Imds,
19 #[serde(rename = "provider-id")]
20 ProviderId,
21 #[serde(rename = "vercmp")]
22 Vercmp,
23 #[serde(rename = "setup-local-disks")]
24 SetupLocalDisks,
25 #[serde(rename = "mount-bpf-fs")]
26 MountBpfFs,
27
28 #[serde(rename = "time-sync")]
29 TimeSync,
30 #[serde(rename = "system-limit-bump")]
31 SystemLimitBump,
32 #[serde(rename = "aws-cli")]
33 AwsCli,
34 #[serde(rename = "ssm-agent")]
35 SsmAgent,
36 #[serde(rename = "cloudwatch-agent")]
37 CloudwatchAgent,
38
39 #[serde(rename = "static-volume-provisioner")]
40 StaticVolumeProvisioner,
41 #[serde(rename = "static-ip-provisioner")]
42 StaticIpProvisioner,
43
44 #[serde(rename = "anaconda")]
45 Anaconda,
46 #[serde(rename = "python")]
47 Python,
48
49 #[serde(rename = "rust")]
50 Rust,
51 #[serde(rename = "go")]
52 Go,
53
54 #[serde(rename = "docker")]
55 Docker,
56 #[serde(rename = "containerd")]
57 Containerd,
58 #[serde(rename = "runc")]
59 Runc,
60 #[serde(rename = "cni-plugins")]
61 CniPlugins,
62
63 #[serde(rename = "aws-cfn-helper")]
64 AwsCfnHelper,
65 #[serde(rename = "saml2aws")]
66 Saml2Aws,
67 #[serde(rename = "aws-iam-authenticator")]
68 AwsIamAuthenticator,
69 #[serde(rename = "ecr-credential-helper")]
70 EcrCredentialHelper,
71 #[serde(rename = "ecr-credential-provider")]
72 EcrCredentialProvider,
73
74 #[serde(rename = "kubelet")]
75 Kubelet,
76 #[serde(rename = "kubectl")]
77 Kubectl,
78 #[serde(rename = "helm")]
79 Helm,
80 #[serde(rename = "terraform")]
81 Terraform,
82
83 #[serde(rename = "ssh-key-with-email")]
84 SshKeyWithEmail,
85
86 #[serde(rename = "ena")]
90 Ena,
91
92 #[serde(rename = "nvidia-driver")]
93 NvidiaDriver,
94 #[serde(rename = "nvidia-cuda-toolkit")]
95 NvidiaCudaToolkit,
96 #[serde(rename = "nvidia-container-toolkit")]
97 NvidiaContainerToolkit,
98
99 #[serde(rename = "amd-radeon-gpu-driver")]
100 AmdRadeonGpuDriver,
101
102 #[serde(rename = "protobuf-compiler")]
103 ProtobufCompiler,
104 #[serde(rename = "cmake")]
105 Cmake,
106 #[serde(rename = "gcc7")]
107 Gcc7,
108
109 #[serde(rename = "dev-bark")]
110 DevBark,
111 #[serde(rename = "dev-faiss-gpu")]
112 DevFaissGpu,
113
114 #[serde(rename = "eks-worker-node-ami-scratch")]
115 EksWorkerNodeAmiScratch,
116 #[serde(rename = "eks-worker-node-ami-reuse")]
117 EksWorkerNodeAmiReuse,
118
119 #[serde(rename = "ami-info")]
120 AmiInfo,
121 #[serde(rename = "cluster-info")]
122 ClusterInfo,
123
124 #[serde(rename = "post-init-script")]
125 PostInitScript,
126
127 #[serde(rename = "cleanup-image-packages")]
128 CleanupImagePackages,
129 #[serde(rename = "cleanup-image-tmp-dir")]
130 CleanupImageTmpDir,
131 #[serde(rename = "cleanup-image-aws-credentials")]
132 CleanupImageAwsCredentials,
133 #[serde(rename = "cleanup-image-ssh-keys")]
134 CleanupImageSshKeys,
135
136 Unknown(String),
137}
138
139impl std::convert::From<&str> for Plugin {
140 fn from(s: &str) -> Self {
141 match s {
142 "imds" => Plugin::Imds,
143 "provider-id" => Plugin::ProviderId,
144 "vercmp" => Plugin::Vercmp,
145 "setup-local-disks" => Plugin::SetupLocalDisks,
146 "mount-bpf-fs" => Plugin::MountBpfFs,
147 "time-sync" => Plugin::TimeSync,
148 "system-limit-bump" => Plugin::SystemLimitBump,
149 "aws-cli" => Plugin::AwsCli,
150 "ssm-agent" => Plugin::SsmAgent,
151 "cloudwatch-agent" => Plugin::CloudwatchAgent,
152 "static-volume-provisioner" => Plugin::StaticVolumeProvisioner,
153 "static-ip-provisioner" => Plugin::StaticIpProvisioner,
154 "anaconda" => Plugin::Anaconda,
155 "python" => Plugin::Python,
156 "rust" => Plugin::Rust,
157 "go" => Plugin::Go,
158 "docker" => Plugin::Docker,
159 "containerd" => Plugin::Containerd,
160 "runc" => Plugin::Runc,
161 "cni-plugins" => Plugin::CniPlugins,
162 "aws-cfn-helper" => Plugin::AwsCfnHelper,
163 "saml2aws" => Plugin::Saml2Aws,
164 "aws-iam-authenticator" => Plugin::AwsIamAuthenticator,
165 "ecr-credential-helper" => Plugin::EcrCredentialHelper,
166 "ecr-credential-provider" => Plugin::EcrCredentialProvider,
167 "kubelet" => Plugin::Kubelet,
168 "kubectl" => Plugin::Kubectl,
169 "helm" => Plugin::Helm,
170 "terraform" => Plugin::Terraform,
171 "ssh-key-with-email" => Plugin::SshKeyWithEmail,
172 "ena" => Plugin::Ena,
173 "nvidia-driver" => Plugin::NvidiaDriver,
174 "nvidia-cuda-toolkit" => Plugin::NvidiaCudaToolkit,
175 "nvidia-container-toolkit" => Plugin::NvidiaContainerToolkit,
176 "amd-radeon-gpu-driver" => Plugin::AmdRadeonGpuDriver,
177 "protobuf-compiler" => Plugin::ProtobufCompiler,
178 "cmake" => Plugin::Cmake,
179 "gcc7" => Plugin::Gcc7,
180 "dev-bark" => Plugin::DevBark,
181 "dev-faiss-gpu" => Plugin::DevFaissGpu,
182 "eks-worker-node-ami-scratch" => Plugin::EksWorkerNodeAmiScratch,
183 "eks-worker-node-ami-reuse" => Plugin::EksWorkerNodeAmiReuse,
184 "ami-info" => Plugin::AmiInfo,
185 "cluster-info" => Plugin::ClusterInfo,
186 "post-init-script" => Plugin::PostInitScript,
187 "cleanup-image-packages" => Plugin::CleanupImagePackages,
188 "cleanup-image-tmp-dir" => Plugin::CleanupImageTmpDir,
189 "cleanup-image-aws-credentials" => Plugin::CleanupImageAwsCredentials,
190 "cleanup-image-ssh-keys" => Plugin::CleanupImageSshKeys,
191 other => Plugin::Unknown(other.to_owned()),
192 }
193 }
194}
195
196impl std::str::FromStr for Plugin {
197 type Err = std::convert::Infallible;
198
199 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
200 Ok(Plugin::from(s))
201 }
202}
203
204impl Plugin {
205 pub fn as_str(&self) -> &str {
207 match self {
208 Plugin::Imds => "imds",
209 Plugin::ProviderId => "provider-id",
210 Plugin::Vercmp => "vercmp",
211 Plugin::SetupLocalDisks => "setup-local-disks",
212 Plugin::MountBpfFs => "mount-bpf-fs",
213 Plugin::TimeSync => "time-sync",
214 Plugin::SystemLimitBump => "system-limit-bump",
215 Plugin::AwsCli => "aws-cli",
216 Plugin::SsmAgent => "ssm-agent",
217 Plugin::CloudwatchAgent => "cloudwatch-agent",
218 Plugin::StaticVolumeProvisioner => "static-volume-provisioner",
219 Plugin::StaticIpProvisioner => "static-ip-provisioner",
220 Plugin::Anaconda => "anaconda",
221 Plugin::Python => "python",
222 Plugin::Rust => "rust",
223 Plugin::Go => "go",
224 Plugin::Docker => "docker",
225 Plugin::Containerd => "containerd",
226 Plugin::Runc => "runc",
227 Plugin::CniPlugins => "cni-plugins",
228 Plugin::AwsCfnHelper => "aws-cfn-helper",
229 Plugin::Saml2Aws => "saml2aws",
230 Plugin::AwsIamAuthenticator => "aws-iam-authenticator",
231 Plugin::EcrCredentialHelper => "ecr-credential-helper",
232 Plugin::EcrCredentialProvider => "ecr-credential-provider",
233 Plugin::Kubelet => "kubelet",
234 Plugin::Kubectl => "kubectl",
235 Plugin::Helm => "helm",
236 Plugin::Terraform => "terraform",
237 Plugin::SshKeyWithEmail => "ssh-key-with-email",
238 Plugin::Ena => "ena",
239 Plugin::NvidiaDriver => "nvidia-driver",
240 Plugin::NvidiaCudaToolkit => "nvidia-cuda-toolkit",
241 Plugin::NvidiaContainerToolkit => "nvidia-container-toolkit",
242 Plugin::AmdRadeonGpuDriver => "amd-radeon-gpu-driver",
243 Plugin::ProtobufCompiler => "protobuf-compiler",
244 Plugin::Cmake => "cmake",
245 Plugin::Gcc7 => "gcc7",
246 Plugin::DevBark => "dev-bark",
247 Plugin::DevFaissGpu => "dev-faiss-gpu",
248 Plugin::EksWorkerNodeAmiScratch => "eks-worker-node-ami-scratch",
249 Plugin::EksWorkerNodeAmiReuse => "eks-worker-node-ami-reuse",
250 Plugin::AmiInfo => "ami-info",
251 Plugin::ClusterInfo => "cluster-info",
252 Plugin::PostInitScript => "post-init-script",
253 Plugin::CleanupImagePackages => "cleanup-image-packages",
254 Plugin::CleanupImageTmpDir => "cleanup-image-tmp-dir",
255 Plugin::CleanupImageAwsCredentials => "cleanup-image-aws-credentials",
256 Plugin::CleanupImageSshKeys => "cleanup-image-ssh-keys",
257 Plugin::Unknown(s) => s.as_ref(),
258 }
259 }
260
261 pub fn rank(&self) -> u32 {
265 match self {
266 Plugin::Imds => 0,
267 Plugin::ProviderId => 1,
268 Plugin::Vercmp => 2,
269 Plugin::SetupLocalDisks => 3,
270 Plugin::MountBpfFs => 4,
271 Plugin::TimeSync => 5,
272 Plugin::SystemLimitBump => 6,
273 Plugin::AwsCli => 7,
274 Plugin::SsmAgent => 8,
275 Plugin::CloudwatchAgent => 9,
276
277 Plugin::StaticVolumeProvisioner => 20,
278 Plugin::StaticIpProvisioner => 21,
279
280 Plugin::Anaconda => 25,
281 Plugin::Python => 25,
282
283 Plugin::Rust => 26,
284 Plugin::Go => 27,
285 Plugin::Docker => 28,
286 Plugin::Containerd => 29,
287 Plugin::Runc => 30,
288 Plugin::CniPlugins => 31,
289
290 Plugin::AwsCfnHelper => 32,
291 Plugin::Saml2Aws => 33,
292
293 Plugin::AwsIamAuthenticator => 34,
294 Plugin::EcrCredentialHelper => 35,
295 Plugin::EcrCredentialProvider => 36,
296
297 Plugin::Kubelet => 37,
298 Plugin::Kubectl => 38,
299 Plugin::Helm => 50,
300 Plugin::Terraform => 51,
301
302 Plugin::SshKeyWithEmail => 68,
303
304 Plugin::Ena => 100,
305
306 Plugin::NvidiaDriver => 200,
307 Plugin::NvidiaCudaToolkit => 201,
308 Plugin::NvidiaContainerToolkit => 202,
309
310 Plugin::AmdRadeonGpuDriver => 300,
311
312 Plugin::ProtobufCompiler => 60000,
313 Plugin::Cmake => 60001,
314 Plugin::Gcc7 => 60002,
315
316 Plugin::DevBark => 80000,
317 Plugin::DevFaissGpu => 80001,
318
319 Plugin::EksWorkerNodeAmiScratch => 99990,
320 Plugin::EksWorkerNodeAmiReuse => 99991,
321
322 Plugin::AmiInfo => u32::MAX - 2000,
323 Plugin::ClusterInfo => u32::MAX - 1999,
324
325 Plugin::PostInitScript => u32::MAX - 1000,
326
327 Plugin::CleanupImagePackages => u32::MAX - 10,
328 Plugin::CleanupImageTmpDir => u32::MAX - 9,
329 Plugin::CleanupImageAwsCredentials => u32::MAX - 8,
330 Plugin::CleanupImageSshKeys => u32::MAX - 5,
331
332 Plugin::Unknown(_) => u32::MAX,
333 }
334 }
335
336 pub fn values() -> &'static [&'static str] {
338 &[
339 "imds", "provider-id", "vercmp", "setup-local-disks", "mount-bpf-fs", "time-sync", "system-limit-bump", "aws-cli", "ssm-agent", "cloudwatch-agent", "static-volume-provisioner", "static-ip-provisioner", "anaconda", "python", "rust", "go", "docker", "containerd", "runc", "cni-plugins", "protobuf-compiler", "aws-cfn-helper", "saml2aws", "aws-iam-authenticator", "ecr-credential-helper", "ecr-credential-provider", "kubelet", "kubectl", "helm", "terraform", "ssh-key-with-email", "ena", "nvidia-driver", "nvidia-cuda-toolkit", "nvidia-container-toolkit", "amd-radeon-gpu-driver", "cmake", "gcc7", "dev-bark", "dev-faiss-gpu", "eks-worker-node-ami-scratch", "eks-worker-node-ami-reuse", "ami-info", "cluster-info", "post-init-script", "cleanup-image-packages", "cleanup-image-ssh-keys", "cleanup-image-aws-credentials", ]
388 }
389
390 pub fn all() -> Vec<String> {
391 vec![
392 Plugin::Imds.as_str().to_string(),
393 Plugin::ProviderId.as_str().to_string(),
394 Plugin::Vercmp.as_str().to_string(),
395 Plugin::SetupLocalDisks.as_str().to_string(),
396 Plugin::MountBpfFs.as_str().to_string(),
397 Plugin::TimeSync.as_str().to_string(),
398 Plugin::SystemLimitBump.as_str().to_string(),
399 Plugin::AwsCli.as_str().to_string(),
400 Plugin::SsmAgent.as_str().to_string(),
401 Plugin::CloudwatchAgent.as_str().to_string(),
402 Plugin::StaticVolumeProvisioner.as_str().to_string(),
403 Plugin::StaticIpProvisioner.as_str().to_string(),
404 Plugin::Anaconda.as_str().to_string(),
405 Plugin::Python.as_str().to_string(),
406 Plugin::Rust.as_str().to_string(),
407 Plugin::Go.as_str().to_string(),
408 Plugin::Docker.as_str().to_string(),
409 Plugin::Containerd.as_str().to_string(),
410 Plugin::Runc.as_str().to_string(),
411 Plugin::CniPlugins.as_str().to_string(),
412 Plugin::AwsCfnHelper.as_str().to_string(),
413 Plugin::Saml2Aws.as_str().to_string(),
414 Plugin::AwsIamAuthenticator.as_str().to_string(),
415 Plugin::EcrCredentialHelper.as_str().to_string(),
416 Plugin::EcrCredentialProvider.as_str().to_string(),
417 Plugin::Kubelet.as_str().to_string(),
418 Plugin::Kubectl.as_str().to_string(),
419 Plugin::Helm.as_str().to_string(),
420 Plugin::Terraform.as_str().to_string(),
421 Plugin::SshKeyWithEmail.as_str().to_string(),
422 Plugin::Ena.as_str().to_string(),
423 Plugin::NvidiaDriver.as_str().to_string(),
424 Plugin::NvidiaCudaToolkit.as_str().to_string(),
425 Plugin::NvidiaContainerToolkit.as_str().to_string(),
426 Plugin::AmdRadeonGpuDriver.as_str().to_string(),
427 Plugin::ProtobufCompiler.as_str().to_string(),
428 Plugin::Cmake.as_str().to_string(),
429 Plugin::Gcc7.as_str().to_string(),
430 Plugin::DevBark.as_str().to_string(),
431 Plugin::DevFaissGpu.as_str().to_string(),
432 Plugin::EksWorkerNodeAmiScratch.as_str().to_string(),
433 Plugin::EksWorkerNodeAmiReuse.as_str().to_string(),
434 Plugin::AmiInfo.as_str().to_string(),
435 Plugin::ClusterInfo.as_str().to_string(),
436 Plugin::PostInitScript.as_str().to_string(),
437 Plugin::CleanupImagePackages.as_str().to_string(),
438 Plugin::CleanupImageTmpDir.as_str().to_string(),
439 Plugin::CleanupImageAwsCredentials.as_str().to_string(),
440 Plugin::CleanupImageSshKeys.as_str().to_string(),
441 ]
442 }
443
444 pub fn default() -> Vec<String> {
445 vec![
446 Plugin::Imds.as_str().to_string(),
447 Plugin::ProviderId.as_str().to_string(),
448 Plugin::Vercmp.as_str().to_string(),
449 Plugin::SetupLocalDisks.as_str().to_string(),
450 Plugin::MountBpfFs.as_str().to_string(),
451 Plugin::TimeSync.as_str().to_string(),
452 Plugin::SystemLimitBump.as_str().to_string(),
453 Plugin::SsmAgent.as_str().to_string(),
454 Plugin::CloudwatchAgent.as_str().to_string(),
455 Plugin::Anaconda.as_str().to_string(),
456 Plugin::AwsCfnHelper.as_str().to_string(),
457 ]
458 }
459}
460
461impl AsRef<str> for Plugin {
462 fn as_ref(&self) -> &str {
463 self.as_str()
464 }
465}
466
467pub const INIT_SCRIPT_COMPLETE_MSG: &str = "INIT SCRIPT COMPLETE";
469
470pub fn create(
471 arch_type: ec2::ArchType,
472 os_type: ec2::OsType,
473 plugins_str: Vec<String>,
474 require_static_ip_provisioner: bool,
475 s3_bucket: &str,
476 id: &str,
477 region: &str,
478 volume_type: &str,
479 volume_size: u32,
480 volume_iops: u32,
481 volume_throughput: u32,
482 ssh_key_email: Option<String>,
483 aws_secret_key_id: Option<String>,
484 aws_secret_access_key: Option<String>,
485 post_init_script: Option<String>,
486) -> io::Result<(Vec<Plugin>, String)> {
487 let mut plugins_set = HashSet::new();
488 for p in plugins_str.iter() {
489 let plugin = Plugin::from_str(p).map_err(|e| {
490 Error::new(
491 ErrorKind::InvalidInput,
492 format!("failed to convert '{p}' to plugin {}", e),
493 )
494 })?;
495 plugins_set.insert(plugin);
496 }
497
498 if plugins_set.contains(&Plugin::StaticVolumeProvisioner) {
499 if require_static_ip_provisioner {
500 plugins_set.insert(Plugin::StaticIpProvisioner);
501 }
502 }
503 if plugins_set.contains(&Plugin::Anaconda) {
505 if plugins_set.contains(&Plugin::Python) {
506 log::info!("anaconda specifies thus overriding python plugin");
507 plugins_set.remove(&Plugin::Python);
508 }
509 } else if plugins_set.contains(&Plugin::Python) {
510 log::info!("only python plugin, without anaconda");
511 }
512 if arch_type.is_nvidia() {
513 plugins_set.insert(Plugin::NvidiaDriver);
514 }
515
516 if plugins_set.contains(&Plugin::AwsCfnHelper) {
517 if !plugins_set.contains(&Plugin::Anaconda) && !plugins_set.contains(&Plugin::Python) {
518 return Err(Error::new(
519 ErrorKind::InvalidInput,
520 format!(
521 "specified '{}' requires pip/python install plugin",
522 Plugin::AwsCfnHelper.as_str()
523 ),
524 ));
525 }
526 }
527 if plugins_set.contains(&Plugin::EcrCredentialProvider) && !plugins_set.contains(&Plugin::Go) {
528 return Err(Error::new(
529 ErrorKind::InvalidInput,
530 format!(
531 "'{}' requires '{}' plugin",
532 Plugin::EcrCredentialProvider.as_str(),
533 Plugin::Go.as_str(),
534 ),
535 ));
536 }
537 if plugins_set.contains(&Plugin::TimeSync) && !plugins_set.contains(&Plugin::Imds) {
538 return Err(Error::new(
539 ErrorKind::InvalidInput,
540 format!(
541 "'{}' requires '{}' plugin",
542 Plugin::TimeSync.as_str(),
543 Plugin::Imds.as_str(),
544 ),
545 ));
546 }
547 if plugins_set.contains(&Plugin::Ena) && !plugins_set.contains(&Plugin::Imds) {
548 return Err(Error::new(
549 ErrorKind::InvalidInput,
550 format!(
551 "'{}' requires '{}' plugin",
552 Plugin::Ena.as_str(),
553 Plugin::Imds.as_str(),
554 ),
555 ));
556 }
557 if plugins_set.contains(&Plugin::NvidiaCudaToolkit) {
558 if !arch_type.is_nvidia() {
559 return Err(Error::new(
560 ErrorKind::InvalidInput,
561 format!(
562 "specified '{}' but arch type is '{}' (not nvidia)",
563 Plugin::NvidiaCudaToolkit.as_str(),
564 arch_type.as_str()
565 ),
566 ));
567 }
568 if !plugins_set.contains(&Plugin::NvidiaDriver) {
569 return Err(Error::new(
570 ErrorKind::InvalidInput,
571 format!(
572 "specified '{}' but no '{}'",
573 Plugin::NvidiaCudaToolkit.as_str(),
574 Plugin::NvidiaDriver.as_str()
575 ),
576 ));
577 }
578 }
579 if plugins_set.contains(&Plugin::NvidiaCudaToolkit) {
580 if !arch_type.is_nvidia() {
581 return Err(Error::new(
582 ErrorKind::InvalidInput,
583 format!(
584 "specified '{}' but arch type is '{}' (not nvidia)",
585 Plugin::NvidiaCudaToolkit.as_str(),
586 arch_type.as_str()
587 ),
588 ));
589 }
590 if !plugins_set.contains(&Plugin::NvidiaDriver) {
591 return Err(Error::new(
592 ErrorKind::InvalidInput,
593 format!(
594 "specified '{}' but no '{}'",
595 Plugin::NvidiaContainerToolkit.as_str(),
596 Plugin::NvidiaDriver.as_str()
597 ),
598 ));
599 }
600 }
601
602 if plugins_set.contains(&Plugin::DevBark) {
603 if !plugins_set.contains(&Plugin::StaticVolumeProvisioner) {
604 return Err(Error::new(
605 ErrorKind::InvalidInput,
606 format!(
607 "specified '{}' requires '{}'",
608 Plugin::DevBark.as_str(),
609 Plugin::StaticVolumeProvisioner.as_str()
610 ),
611 ));
612 }
613 }
614 if plugins_set.contains(&Plugin::DevFaissGpu) {
615 if !plugins_set.contains(&Plugin::StaticVolumeProvisioner) {
616 return Err(Error::new(
617 ErrorKind::InvalidInput,
618 format!(
619 "specified '{}' requires '{}'",
620 Plugin::DevFaissGpu.as_str(),
621 Plugin::StaticVolumeProvisioner.as_str()
622 ),
623 ));
624 }
625 }
626
627 if plugins_set.contains(&Plugin::EksWorkerNodeAmiScratch)
628 && plugins_set.contains(&Plugin::EksWorkerNodeAmiReuse)
629 {
630 return Err(Error::new(
631 ErrorKind::InvalidInput,
632 format!(
633 "'{}' conflicts with '{}'",
634 Plugin::EksWorkerNodeAmiScratch.as_str(),
635 Plugin::EksWorkerNodeAmiReuse.as_str()
636 ),
637 ));
638 }
639
640 if post_init_script.is_some() {
641 if !plugins_set.contains(&Plugin::PostInitScript) {
642 log::warn!(
643 "'{}' but no post init script specified -- adding to set",
644 Plugin::PostInitScript.as_str()
645 );
646 }
647 plugins_set.insert(Plugin::PostInitScript);
648 }
649
650 let mut plugins = Vec::new();
651 for p in plugins_set.iter() {
652 plugins.push(p.clone());
653 }
654 plugins.sort();
655
656 let provisioner_initial_wait_random_seconds = 10;
658
659 let mut contents = scripts::start(os_type.clone())?;
660 let mut updated_bash_profile = false;
661 for p in plugins.iter() {
662 match p {
663 Plugin::Imds => {
664 let d = scripts::imds(os_type.clone())?;
665 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
666 contents.push_str(&d);
667 }
668 Plugin::ProviderId => {
669 let d = scripts::provider_id(os_type.clone())?;
670 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
671 contents.push_str(&d);
672 }
673 Plugin::Vercmp => {
674 let d = scripts::vercmp(os_type.clone())?;
675 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
676 contents.push_str(&d);
677 }
678 Plugin::SetupLocalDisks => {
679 let d = scripts::setup_local_disks(os_type.clone())?;
680 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
681 contents.push_str(&d);
682 }
683 Plugin::MountBpfFs => {
684 let d = scripts::mount_bpf_fs(os_type.clone())?;
685 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
686 contents.push_str(&d);
687 }
688 Plugin::TimeSync => {
689 let d = scripts::time_sync(os_type.clone())?;
690 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
691 contents.push_str(&d);
692 }
693 Plugin::SystemLimitBump => {
694 let d = scripts::system_limit_bump(os_type.clone())?;
695 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
696 contents.push_str(&d);
697
698 if !updated_bash_profile {
699 updated_bash_profile = true;
700
701 let d = scripts::update_bash_profile(
702 os_type.clone(),
703 plugins_set.contains(&Plugin::Anaconda),
704 plugins_set.contains(&Plugin::Python),
705 plugins_set.contains(&Plugin::Rust),
706 plugins_set.contains(&Plugin::NvidiaCudaToolkit),
707 plugins_set.contains(&Plugin::Go),
708 plugins_set.contains(&Plugin::Kubectl),
709 plugins_set.contains(&Plugin::Helm),
710 plugins_set.contains(&Plugin::StaticVolumeProvisioner),
711 )?;
712 contents.push_str(
713 "###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n",
714 );
715 contents.push_str(&d);
716 }
717 }
718 Plugin::AwsCli => {
719 let d = scripts::aws_cli(arch_type.clone(), os_type.clone())?;
720 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
721 contents.push_str(&d);
722 }
723 Plugin::SsmAgent => {
724 let d = scripts::ssm_agent(os_type.clone())?;
725 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
726 contents.push_str(&d);
727 }
728 Plugin::CloudwatchAgent => {
729 let d = scripts::cloudwatch_agent(os_type.clone())?;
730 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
731 contents.push_str(&d);
732 }
733
734 Plugin::StaticVolumeProvisioner => {
735 let d = scripts::static_volume_provisioner(
744 os_type.clone(),
745 id,
746 region,
747 volume_type,
748 volume_size,
749 volume_iops,
750 volume_throughput,
751 "/dev/xvdb",
752 provisioner_initial_wait_random_seconds,
753 )?;
754 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
755 contents.push_str(&d);
756
757 if !updated_bash_profile {
758 updated_bash_profile = true;
759
760 let d = scripts::update_bash_profile(
761 os_type.clone(),
762 plugins_set.contains(&Plugin::Anaconda),
763 plugins_set.contains(&Plugin::Python),
764 plugins_set.contains(&Plugin::Rust),
765 plugins_set.contains(&Plugin::NvidiaCudaToolkit),
766 plugins_set.contains(&Plugin::Go),
767 plugins_set.contains(&Plugin::Kubectl),
768 plugins_set.contains(&Plugin::Helm),
769 plugins_set.contains(&Plugin::StaticVolumeProvisioner),
770 )?;
771 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
772 contents.push_str(&d);
773 }
774 }
775 Plugin::StaticIpProvisioner => {
776 let d = scripts::static_ip_provisioner(
777 os_type.clone(),
778 id,
779 region,
780 provisioner_initial_wait_random_seconds,
781 )?;
782 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
783 contents.push_str(&d);
784 }
785
786 Plugin::Anaconda => {
787 let d = scripts::anaconda(os_type.clone())?;
788 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
789 contents.push_str(&d);
790 }
791 Plugin::Python => {
792 let d = scripts::python(os_type.clone())?;
793 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
794 contents.push_str(&d);
795 }
796
797 Plugin::Rust => {
798 let d = scripts::rust(os_type.clone())?;
799 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
800 contents.push_str(&d);
801 }
802 Plugin::Go => {
803 let d = scripts::go(os_type.clone())?;
804 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
805 contents.push_str(&d);
806 }
807
808 Plugin::Docker => {
809 let d = scripts::docker(os_type.clone())?;
810 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
811 contents.push_str(&d);
812 }
813 Plugin::Containerd => {
814 let d = scripts::containerd(os_type.clone())?;
815 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
816 contents.push_str(&d);
817 }
818 Plugin::Runc => {
819 let d = scripts::runc(os_type.clone())?;
820 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
821 contents.push_str(&d);
822 }
823 Plugin::CniPlugins => {
824 let d = scripts::cni_plugins(os_type.clone())?;
825 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
826 contents.push_str(&d);
827 }
828
829 Plugin::AwsCfnHelper => {
830 let d = scripts::aws_cfn_helper(
831 os_type.clone(),
832 if plugins_set.contains(&Plugin::Anaconda) {
833 "/home/ubuntu/anaconda3/bin"
834 } else {
835 ""
836 },
837 )?;
838 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
839 contents.push_str(&d);
840 }
841 Plugin::Saml2Aws => {
842 let d = scripts::saml2aws(os_type.clone())?;
843 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
844 contents.push_str(&d);
845 }
846 Plugin::AwsIamAuthenticator => {
847 let d = scripts::aws_iam_authenticator(os_type.clone())?;
848 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
849 contents.push_str(&d);
850 }
851 Plugin::EcrCredentialHelper => {
852 let d = scripts::ecr_credential_helper(os_type.clone())?;
853 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
854 contents.push_str(&d);
855 }
856 Plugin::EcrCredentialProvider => {
857 let d = scripts::ecr_credential_provider(os_type.clone())?;
858 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
859 contents.push_str(&d);
860 }
861
862 Plugin::Kubelet => {
863 let d = scripts::kubelet(os_type.clone())?;
864 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
865 contents.push_str(&d);
866 }
867 Plugin::Kubectl => {
868 let d = scripts::kubectl(os_type.clone())?;
869 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
870 contents.push_str(&d);
871 }
872 Plugin::Helm => {
873 let d = scripts::helm(os_type.clone())?;
874 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
875 contents.push_str(&d);
876 }
877 Plugin::Terraform => {
878 let d = scripts::terraform(os_type.clone())?;
879 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
880 contents.push_str(&d);
881 }
882
883 Plugin::SshKeyWithEmail => {
884 if ssh_key_email.is_none() {
885 return Err(Error::new(
886 ErrorKind::Other,
887 format!(
888 "plugin {} specified but empty email",
889 Plugin::SshKeyWithEmail.as_str()
890 ),
891 ));
892 }
893 let d = scripts::ssh_key_with_email(
894 os_type.clone(),
895 ssh_key_email.clone().unwrap().as_str(),
896 )?;
897 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
898 contents.push_str(&d);
899 }
900
901 Plugin::Ena => {
902 let d = scripts::ena(os_type.clone())?;
903 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
904 contents.push_str(&d);
905 }
906
907 Plugin::NvidiaDriver => {
908 let d = scripts::nvidia_driver(arch_type.clone(), os_type.clone())?;
909 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
910 contents.push_str(&d);
911 }
912 Plugin::NvidiaCudaToolkit => {
913 let d = scripts::nvidia_cuda_toolkit(os_type.clone())?;
914 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
915 contents.push_str(&d);
916 }
917 Plugin::NvidiaContainerToolkit => {
918 let d = scripts::nvidia_container_toolkit(os_type.clone())?;
919 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
920 contents.push_str(&d);
921 }
922
923 Plugin::AmdRadeonGpuDriver => {
924 let d = scripts::amd_radeon_gpu_driver(arch_type.clone(), os_type.clone())?;
925 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
926 contents.push_str(&d);
927 }
928
929 Plugin::ProtobufCompiler => {
930 let d = scripts::protobuf_compiler(os_type.clone())?;
931 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
932 contents.push_str(&d);
933 }
934 Plugin::Cmake => {
935 let d = scripts::cmake(
936 os_type.clone(),
937 if plugins_set.contains(&Plugin::Anaconda) {
938 "/home/ubuntu/anaconda3/bin"
939 } else {
940 ""
941 },
942 )?;
943 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
944 contents.push_str(&d);
945 }
946 Plugin::Gcc7 => {
947 let d = scripts::gcc7(os_type.clone())?;
948 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
949 contents.push_str(&d);
950 }
951
952 Plugin::DevBark => {
953 let d = scripts::dev_bark(
954 os_type.clone(),
955 if plugins_set.contains(&Plugin::Anaconda) {
956 "/home/ubuntu/anaconda3/bin"
957 } else {
958 ""
959 },
960 plugins_set.contains(&Plugin::StaticVolumeProvisioner),
961 )?;
962 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
963 contents.push_str(&d);
964 }
965 Plugin::DevFaissGpu => {
966 let d = scripts::dev_faiss_gpu(
967 os_type.clone(),
968 plugins_set.contains(&Plugin::StaticVolumeProvisioner),
969 )?;
970 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
971 contents.push_str(&d);
972 }
973
974 Plugin::EksWorkerNodeAmiScratch => {
975 let d = scripts::eks_worker_node_ami_scratch(os_type.clone())?;
976 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
977 contents.push_str(&d);
978 }
979 Plugin::EksWorkerNodeAmiReuse => {
980 let d = scripts::eks_worker_node_ami_reuse(os_type.clone())?;
981 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
982 contents.push_str(&d);
983 }
984
985 Plugin::AmiInfo
986 | Plugin::ClusterInfo
987 | Plugin::PostInitScript
988 | Plugin::CleanupImagePackages
989 | Plugin::CleanupImageTmpDir
990 | Plugin::CleanupImageAwsCredentials
991 | Plugin::CleanupImageSshKeys => {
992 log::info!(
993 "skipping {}, saving it to write after bash profile at the end",
994 p.as_str()
995 )
996 }
997
998 _ => {
999 return Err(Error::new(
1000 ErrorKind::Other,
1001 format!("unknown plugin {}", p.as_str()),
1002 ))
1003 }
1004 }
1005 }
1006
1007 if !updated_bash_profile {
1008 let d = scripts::update_bash_profile(
1009 os_type.clone(),
1010 plugins_set.contains(&Plugin::Anaconda),
1011 plugins_set.contains(&Plugin::Python),
1012 plugins_set.contains(&Plugin::Rust),
1013 plugins_set.contains(&Plugin::NvidiaCudaToolkit),
1014 plugins_set.contains(&Plugin::Go),
1015 plugins_set.contains(&Plugin::Kubectl),
1016 plugins_set.contains(&Plugin::Helm),
1017 plugins_set.contains(&Plugin::StaticVolumeProvisioner),
1018 )?;
1019
1020 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
1021 contents.push_str(&d);
1022 }
1023
1024 if let Some(secret_key_id) = &aws_secret_key_id {
1025 let access_key = aws_secret_access_key.clone().unwrap();
1026 let d = scripts::aws_key(os_type.clone(), region, secret_key_id.as_str(), &access_key)?;
1027
1028 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
1029 contents.push_str(&d);
1030 }
1031
1032 if plugins_set.contains(&Plugin::AmiInfo) {
1033 let d = scripts::ami_info(os_type.clone())?;
1034
1035 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
1036 contents.push_str(&d);
1037 }
1038 if plugins_set.contains(&Plugin::ClusterInfo) {
1039 let d = scripts::cluster_info(
1040 s3_bucket,
1041 id,
1042 plugins_set.contains(&Plugin::StaticVolumeProvisioner),
1043 );
1044
1045 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
1046 contents.push_str(&d);
1047 }
1048
1049 if plugins_set.contains(&Plugin::PostInitScript) {
1050 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
1051 contents.push_str("###########################\n# USER-DEFINED POST INIT SCRIPT\n");
1052 contents.push_str(&post_init_script.unwrap());
1053 }
1054
1055 if plugins_set.contains(&Plugin::CleanupImagePackages) {
1056 let d = scripts::cleanup_image_packages(os_type.clone())?;
1057
1058 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
1059 contents.push_str(&d);
1060 }
1061 if plugins_set.contains(&Plugin::CleanupImageTmpDir) {
1062 let d = scripts::cleanup_image_tmp_dir(os_type.clone())?;
1063
1064 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
1065 contents.push_str(&d);
1066 }
1067
1068 if plugins_set.contains(&Plugin::CleanupImageAwsCredentials) {
1069 let d = scripts::cleanup_image_aws_credentials(os_type.clone())?;
1070
1071 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
1072 contents.push_str(&d);
1073 }
1074
1075 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
1077 contents
1078 .push_str(format!("###########################\n# {INIT_SCRIPT_COMPLETE_MSG}\n").as_str());
1079 contents.push_str(format!("echo \"{INIT_SCRIPT_COMPLETE_MSG}\"\n\n").as_str());
1080
1081 if plugins_set.contains(&Plugin::CleanupImageSshKeys) {
1082 let d = scripts::cleanup_image_ssh_keys(os_type.clone())?;
1083
1084 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
1085 contents.push_str(&d);
1086 }
1087
1088 contents.push_str("###########################\nset +x\necho \"\"\necho \"\"\necho \"\"\necho \"\"\necho \"\"\nset -x\n\n\n\n\n");
1089 Ok((plugins, contents))
1090}
1091
1092pub fn to_strings(plugins: Vec<Plugin>) -> Vec<String> {
1093 let mut ss = Vec::new();
1094 for s in plugins.iter() {
1095 ss.push(s.as_str().to_string());
1096 }
1097 ss
1098}
1099
1100impl Ord for Plugin {
1101 fn cmp(&self, plugin: &Plugin) -> std::cmp::Ordering {
1102 self.rank().cmp(&(plugin.rank()))
1103 }
1104}
1105
1106impl PartialOrd for Plugin {
1107 fn partial_cmp(&self, plugin: &Plugin) -> Option<std::cmp::Ordering> {
1108 Some(self.cmp(plugin))
1109 }
1110}
1111
1112impl PartialEq for Plugin {
1113 fn eq(&self, plugin: &Plugin) -> bool {
1114 self.cmp(plugin) == std::cmp::Ordering::Equal
1115 }
1116}
1117
1118#[test]
1120fn test_sort() {
1121 let expected: Vec<Plugin> = vec![
1122 Plugin::Imds,
1123 Plugin::ProviderId,
1124 Plugin::Vercmp,
1125 Plugin::SetupLocalDisks,
1126 Plugin::MountBpfFs,
1127 Plugin::TimeSync,
1128 Plugin::SystemLimitBump,
1129 Plugin::AwsCli,
1130 Plugin::SsmAgent,
1131 Plugin::CloudwatchAgent,
1132 Plugin::Anaconda,
1133 Plugin::Go,
1134 Plugin::Docker,
1135 Plugin::Containerd,
1136 Plugin::Runc,
1137 Plugin::Ena,
1138 Plugin::NvidiaDriver,
1139 Plugin::DevBark,
1140 Plugin::EksWorkerNodeAmiReuse,
1141 Plugin::AmiInfo,
1142 Plugin::PostInitScript,
1143 Plugin::CleanupImagePackages,
1144 Plugin::CleanupImageTmpDir,
1145 Plugin::CleanupImageAwsCredentials,
1146 Plugin::CleanupImageSshKeys,
1147 ];
1148
1149 let mut unsorted: Vec<Plugin> = vec![
1150 Plugin::NvidiaDriver,
1151 Plugin::EksWorkerNodeAmiReuse,
1152 Plugin::CloudwatchAgent,
1153 Plugin::CleanupImageSshKeys,
1154 Plugin::Runc,
1155 Plugin::CleanupImagePackages,
1156 Plugin::CleanupImageTmpDir,
1157 Plugin::PostInitScript,
1158 Plugin::CleanupImageAwsCredentials,
1159 Plugin::SsmAgent,
1160 Plugin::MountBpfFs,
1161 Plugin::Imds,
1162 Plugin::SystemLimitBump,
1163 Plugin::Containerd,
1164 Plugin::Vercmp,
1165 Plugin::DevBark,
1166 Plugin::ProviderId,
1167 Plugin::TimeSync,
1168 Plugin::Docker,
1169 Plugin::SetupLocalDisks,
1170 Plugin::Anaconda,
1171 Plugin::AmiInfo,
1172 Plugin::Go,
1173 Plugin::AwsCli,
1174 Plugin::Ena,
1175 ];
1176 unsorted.sort();
1177
1178 assert_eq!(expected, unsorted);
1179 assert_eq!(unsorted[0], Plugin::Imds);
1180}