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 }