sigs.k8s.io/cluster-api-provider-aws@v1.5.5/pkg/eks/addons/plan.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 addons
    18  
    19  import (
    20  	"context"
    21  
    22  	"github.com/aws/aws-sdk-go/service/eks"
    23  	"github.com/aws/aws-sdk-go/service/eks/eksiface"
    24  
    25  	infrav1 "sigs.k8s.io/cluster-api-provider-aws/api/v1beta1"
    26  	"sigs.k8s.io/cluster-api-provider-aws/pkg/planner"
    27  )
    28  
    29  // NewPlan creates a new Plan to manage EKS addons.
    30  func NewPlan(clusterName string, desiredAddons, installedAddons []*EKSAddon, client eksiface.EKSAPI) planner.Plan {
    31  	return &plan{
    32  		installedAddons: installedAddons,
    33  		desiredAddons:   desiredAddons,
    34  		eksClient:       client,
    35  		clusterName:     clusterName,
    36  	}
    37  }
    38  
    39  // Plan is a plan that will manage EKS addons.
    40  type plan struct {
    41  	installedAddons []*EKSAddon
    42  	desiredAddons   []*EKSAddon
    43  	eksClient       eksiface.EKSAPI
    44  	clusterName     string
    45  }
    46  
    47  // Create will create the plan (i.e. list of procedures) for managing EKS addons.
    48  func (a *plan) Create(ctx context.Context) ([]planner.Procedure, error) {
    49  	procedures := []planner.Procedure{}
    50  
    51  	// Handle create and update
    52  	for i := range a.desiredAddons {
    53  		desired := a.desiredAddons[i]
    54  		installed := a.getInstalled(*desired.Name)
    55  		if installed == nil {
    56  			// Need to add the addon
    57  			procedures = append(procedures, &CreateAddonProcedure{plan: a, name: *desired.Name})
    58  			procedures = append(procedures, &WaitAddonActiveProcedure{plan: a, name: *desired.Name, includeDegraded: true})
    59  		} else {
    60  			// Check if its just the tags that need updating
    61  			diffTags := desired.Tags.Difference(installed.Tags)
    62  			if len(diffTags) > 0 {
    63  				procedures = append(procedures, &UpdateAddonTagsProcedure{plan: a, name: *installed.Name})
    64  			}
    65  			// Check if we also need to update the addon
    66  			if !desired.IsEqual(installed, false) {
    67  				procedures = append(procedures, &UpdateAddonProcedure{plan: a, name: *installed.Name})
    68  				procedures = append(procedures, &WaitAddonActiveProcedure{plan: a, name: *desired.Name, includeDegraded: true})
    69  			} else if *installed.Status != eks.AddonStatusActive {
    70  				// If the desired and installed are the same make sure its active
    71  				procedures = append(procedures, &WaitAddonActiveProcedure{plan: a, name: *desired.Name, includeDegraded: true})
    72  			}
    73  		}
    74  	}
    75  
    76  	// look for deletions & unchanged
    77  	for i := range a.installedAddons {
    78  		installed := a.installedAddons[i]
    79  		desired := a.getDesired(*installed.Name)
    80  		if desired == nil {
    81  			if *installed.Status != eks.AddonStatusDeleting {
    82  				procedures = append(procedures, &DeleteAddonProcedure{plan: a, name: *installed.Name})
    83  			}
    84  			procedures = append(procedures, &WaitAddonDeleteProcedure{plan: a, name: *installed.Name})
    85  		}
    86  	}
    87  
    88  	return procedures, nil
    89  }
    90  
    91  func (a *plan) getInstalled(name string) *EKSAddon {
    92  	for i := range a.installedAddons {
    93  		installed := a.installedAddons[i]
    94  		if *installed.Name == name {
    95  			return installed
    96  		}
    97  	}
    98  
    99  	return nil
   100  }
   101  
   102  func (a *plan) getDesired(name string) *EKSAddon {
   103  	for i := range a.desiredAddons {
   104  		desired := a.desiredAddons[i]
   105  		if *desired.Name == name {
   106  			return desired
   107  		}
   108  	}
   109  
   110  	return nil
   111  }
   112  
   113  func convertTags(tags infrav1.Tags) map[string]*string {
   114  	converted := map[string]*string{}
   115  
   116  	for k, v := range tags {
   117  		copiedVal := v
   118  		converted[k] = &copiedVal
   119  	}
   120  
   121  	return converted
   122  }