sigs.k8s.io/cluster-api-provider-aws@v1.5.5/cmd/clusterawsadm/ami/list.go (about)

     1  /*
     2  Copyright 2021 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package ami
    18  
    19  import (
    20  	"fmt"
    21  	"time"
    22  
    23  	"github.com/aws/aws-sdk-go/aws"
    24  	"github.com/aws/aws-sdk-go/aws/session"
    25  	"github.com/aws/aws-sdk-go/service/ec2"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  
    28  	amiv1 "sigs.k8s.io/cluster-api-provider-aws/cmd/clusterawsadm/api/ami/v1beta1"
    29  )
    30  
    31  // ListInput defines the specs required to construct an AWSAMIList.
    32  type ListInput struct {
    33  	Region            string
    34  	KubernetesVersion string
    35  	OperatingSystem   string
    36  	OwnerID           string
    37  }
    38  
    39  const lastNReleases = 3
    40  
    41  // List will create an AWSAMIList from a given ListInput.
    42  func List(input ListInput) (*amiv1.AWSAMIList, error) {
    43  	supportedOsList := []string{}
    44  	if input.OperatingSystem == "" {
    45  		supportedOsList = getSupportedOsList()
    46  	} else {
    47  		supportedOsList = append(supportedOsList, input.OperatingSystem)
    48  	}
    49  	imageRegionList := []string{}
    50  	if input.Region == "" {
    51  		imageRegionList = getimageRegionList()
    52  	} else {
    53  		imageRegionList = append(imageRegionList, input.Region)
    54  	}
    55  
    56  	supportedVersions := []string{}
    57  	if input.KubernetesVersion == "" {
    58  		var err error
    59  		supportedVersions, err = getSupportedKubernetesVersions(lastNReleases)
    60  		if err != nil {
    61  			fmt.Println("Failed to calculate supported Kubernetes versions")
    62  			return nil, err
    63  		}
    64  	} else {
    65  		supportedVersions = append(supportedVersions, input.KubernetesVersion)
    66  	}
    67  	listByVersion := amiv1.AWSAMIList{
    68  		TypeMeta: metav1.TypeMeta{
    69  			Kind:       amiv1.AWSAMIListKind,
    70  			APIVersion: amiv1.SchemeGroupVersion.String(),
    71  		},
    72  		Items: []amiv1.AWSAMI{},
    73  	}
    74  	for _, region := range imageRegionList {
    75  		imageMap := make(map[string][]*ec2.Image)
    76  		sess, err := session.NewSessionWithOptions(session.Options{
    77  			SharedConfigState: session.SharedConfigEnable,
    78  			Config:            aws.Config{Region: aws.String(region)},
    79  		})
    80  		if err != nil {
    81  			return nil, err
    82  		}
    83  
    84  		ec2Client := ec2.New(sess)
    85  		imagesForRegion, err := getAllImages(ec2Client, input.OwnerID)
    86  		if err != nil {
    87  			return nil, err
    88  		}
    89  
    90  		for key, image := range imagesForRegion {
    91  			images, ok := imageMap[key]
    92  			if !ok {
    93  				images = make([]*ec2.Image, 0)
    94  			}
    95  			imageMap[key] = append(images, image...)
    96  		}
    97  		for _, version := range supportedVersions {
    98  			for _, os := range supportedOsList {
    99  				image, err := findAMI(imageMap, os, version)
   100  				if err != nil {
   101  					return nil, err
   102  				}
   103  				if image == nil {
   104  					continue
   105  				}
   106  				creationTimestamp, err := time.Parse(time.RFC3339, aws.StringValue(image.CreationDate))
   107  				if err != nil {
   108  					return nil, err
   109  				}
   110  
   111  				listByVersion.Items = append(listByVersion.Items, amiv1.AWSAMI{
   112  					TypeMeta: metav1.TypeMeta{
   113  						Kind:       amiv1.AWSAMIKind,
   114  						APIVersion: amiv1.SchemeGroupVersion.String(),
   115  					},
   116  					ObjectMeta: metav1.ObjectMeta{
   117  						Name:              aws.StringValue(image.Name),
   118  						CreationTimestamp: metav1.NewTime(creationTimestamp),
   119  					},
   120  					Spec: amiv1.AWSAMISpec{
   121  						OS:                os,
   122  						Region:            region,
   123  						ImageID:           aws.StringValue(image.ImageId),
   124  						KubernetesVersion: version,
   125  					},
   126  				})
   127  			}
   128  		}
   129  	}
   130  
   131  	return &listByVersion, nil
   132  }