@@ -35,6 +35,7 @@ import (
35
35
"github.com/aws/aws-sdk-go/aws/awserr"
36
36
"github.com/aws/aws-sdk-go/aws/session"
37
37
"github.com/aws/aws-sdk-go/service/ec2"
38
+ "github.com/aws/aws-sdk-go/service/ssm"
38
39
"github.com/google/uuid"
39
40
)
40
41
@@ -352,76 +353,137 @@ func (h *EC2Helper) getInstanceTypes(input *ec2.DescribeInstanceTypesInput) ([]*
352
353
// Define all OS and corresponding AMI name formats
353
354
var osDescs = map [string ]map [string ]string {
354
355
"Amazon Linux" : {
355
- "ebs" : "amzn-ami-hvm-????.??.?.????????.?-*-gp2 " ,
356
- "instance-store" : "amzn-ami-hvm-????.??.?.????????.?-*-s3 " ,
356
+ "ebs" : "amzn-ami-hvm-* " ,
357
+ "instance-store" : "amzn-ami-hvm-* " ,
357
358
},
358
359
"Amazon Linux 2" : {
359
- "ebs" : "amzn2-ami-hvm-2.?.????????.?-*-gp2 " ,
360
+ "ebs" : "amzn2-ami-hvm-* " ,
360
361
},
361
362
"Red Hat" : {
362
- "ebs" : "RHEL-?.?.?_HVM-????????-*-?-Hourly2-GP2 " ,
363
+ "ebs" : "RHEL-9* " ,
363
364
},
364
365
"SUSE Linux" : {
365
- "ebs" : "suse-sles-??-sp?-v????????-hvm-ssd- *" ,
366
+ "ebs" : "suse-sles-*" ,
366
367
},
367
- // Ubuntu 18.04 LTS
368
368
"Ubuntu" : {
369
- "ebs" : "ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-*-server-???????? " ,
370
- "instance-store" : "ubuntu/images/hvm-instance/ubuntu-bionic-18.04-*-server-???????? " ,
369
+ "ebs" : "ubuntu/images/* " ,
370
+ "instance-store" : "ubuntu/images/* " ,
371
371
},
372
- // 64 bit Microsoft Windows Server with Desktop Experience Locale English AMI
373
372
"Windows" : {
374
- "ebs" : "Windows_Server-????-English-Full-Base-????.??.??" ,
373
+ "ebs" : "Windows_Server-*-English-Full-Base*" ,
374
+ },
375
+ }
376
+
377
+ // Define all OS and corresponding AMI public parameters path in Parameter Store
378
+ var osSsmPath = map [string ]map [string ]string {
379
+ "Amazon Linux" : {
380
+ "ebs" : "/aws/service/ami-amazon-linux-latest" ,
381
+ "instance-store" : "/aws/service/ami-amazon-linux-latest" ,
382
+ },
383
+ "Amazon Linux 2" : {
384
+ "ebs" : "/aws/service/ami-amazon-linux-latest" ,
385
+ },
386
+ "Red Hat" : {
387
+ "ebs" : "" ,
388
+ },
389
+ "SUSE Linux" : {
390
+ "ebs" : "/aws/service/suse/sles" ,
391
+ },
392
+ "Ubuntu" : {
393
+ "ebs" : "/aws/service/canonical/ubuntu/server/24.04/stable/current" ,
394
+ "instance-store" : "/aws/service/canonical/ubuntu/server/24.04/stable/current" ,
395
+ },
396
+ "Windows" : {
397
+ "ebs" : "/aws/service/ami-windows-latest" ,
375
398
},
376
399
}
377
400
378
401
// Get the appropriate input for describing images
379
- func getDescribeImagesInputs (rootDeviceType string , architectures []* string ) * map [string ]ec2.DescribeImagesInput {
402
+ func (h * EC2Helper ) GetDescribeImagesInputs (rootDeviceType string , architectures []* string ) * map [string ]ec2.DescribeImagesInput {
403
+ ssmClient := ssm .New (h .Sess )
404
+
380
405
// Construct all the inputs
381
406
imageInputs := map [string ]ec2.DescribeImagesInput {}
382
407
for osName , rootDeviceTypes := range osDescs {
383
408
384
409
// Only add inputs if the corresponding root device type is applicable for the specified os
385
410
desc , found := rootDeviceTypes [rootDeviceType ]
386
- if found {
387
- imageInputs [osName ] = ec2.DescribeImagesInput {
388
- Filters : []* ec2.Filter {
389
- {
390
- Name : aws .String ("name" ),
391
- Values : []* string {
392
- aws .String (desc ),
393
- },
394
- },
395
- {
396
- Name : aws .String ("state" ),
397
- Values : []* string {
398
- aws .String ("available" ),
399
- },
411
+ if ! found {
412
+ continue
413
+ }
414
+ imageInputs [osName ] = ec2.DescribeImagesInput {
415
+ Filters : []* ec2.Filter {
416
+ {
417
+ Name : aws .String ("name" ),
418
+ Values : []* string {
419
+ aws .String (desc ),
400
420
},
401
- {
402
- Name : aws . String ( "root-device-type" ),
403
- Values : [] * string {
404
- aws . String ( rootDeviceType ),
405
- } ,
421
+ },
422
+ {
423
+ Name : aws . String ( "state" ),
424
+ Values : [] * string {
425
+ aws . String ( "available" ) ,
406
426
},
407
- {
408
- Name : aws .String ("architecture" ),
409
- Values : architectures ,
427
+ },
428
+ {
429
+ Name : aws .String ("root-device-type" ),
430
+ Values : []* string {
431
+ aws .String (rootDeviceType ),
410
432
},
411
- {
412
- Name : aws .String ("owner-alias" ),
413
- Values : []* string {
414
- aws .String ("amazon" ),
415
- },
433
+ },
434
+ {
435
+ Name : aws .String ("architecture" ),
436
+ Values : architectures ,
437
+ },
438
+ {
439
+ Name : aws .String ("owner-alias" ),
440
+ Values : []* string {
441
+ aws .String ("amazon" ),
416
442
},
417
443
},
418
- }
444
+ },
445
+ }
446
+ ssmPath , found := osSsmPath [osName ][rootDeviceType ]
447
+ if ! found || ssmPath == "" {
448
+ continue
449
+ }
450
+ if imageIds , err := h .GetImageIdsFromSSM (ssmClient , ssmPath ); err == nil {
451
+ input := imageInputs [osName ]
452
+ input .ImageIds = imageIds
453
+ imageInputs [osName ] = input
419
454
}
420
455
}
421
456
422
457
return & imageInputs
423
458
}
424
459
460
+ func (h * EC2Helper ) GetImageIdsFromSSM (ssmClient * ssm.SSM , ssmPath string ) ([]* string , error ) {
461
+ var imageIds []* string
462
+
463
+ input := & ssm.GetParametersByPathInput {
464
+ Path : aws .String (ssmPath ),
465
+ Recursive : aws .Bool (true ),
466
+ WithDecryption : aws .Bool (false ),
467
+ }
468
+
469
+ err := ssmClient .GetParametersByPathPages (input ,
470
+ func (page * ssm.GetParametersByPathOutput , lastPage bool ) bool {
471
+ for _ , parameter := range page .Parameters {
472
+ if ! strings .HasPrefix (* parameter .Value , "ami" ) {
473
+ continue
474
+ }
475
+ imageIds = append (imageIds , parameter .Value )
476
+ }
477
+ return ! lastPage
478
+ })
479
+
480
+ if err != nil {
481
+ return nil , fmt .Errorf ("error getting parameters from SSM: %v" , err )
482
+ }
483
+
484
+ return imageIds , nil
485
+ }
486
+
425
487
// Sort interface for images
426
488
type byCreationDate []* ec2.Image
427
489
@@ -436,9 +498,9 @@ Empty result is allowed.
436
498
func (h * EC2Helper ) GetLatestImages (rootDeviceType * string , architectures []* string ) (* map [string ]* ec2.Image , error ) {
437
499
var inputs * map [string ]ec2.DescribeImagesInput
438
500
if rootDeviceType == nil {
439
- inputs = getDescribeImagesInputs ("ebs" , architectures )
501
+ inputs = h . GetDescribeImagesInputs ("ebs" , architectures )
440
502
} else {
441
- inputs = getDescribeImagesInputs (* rootDeviceType , architectures )
503
+ inputs = h . GetDescribeImagesInputs (* rootDeviceType , architectures )
442
504
}
443
505
444
506
images := map [string ]* ec2.Image {}
0 commit comments