istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/autoregistration/internal/state/store.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package state 16 17 import ( 18 "fmt" 19 20 "k8s.io/apimachinery/pkg/api/errors" 21 22 "istio.io/api/meta/v1alpha1" 23 "istio.io/istio/pilot/pkg/model" 24 "istio.io/istio/pilot/pkg/model/status" 25 "istio.io/istio/pkg/config" 26 "istio.io/istio/pkg/config/schema/gvk" 27 istiolog "istio.io/istio/pkg/log" 28 ) 29 30 var log = istiolog.RegisterScope("wle", "wle controller debugging") 31 32 // Store knows how to keep internal state as part of a WorkloadEntry resource. 33 type Store struct { 34 store model.ConfigStoreController 35 cb StoreCallbacks 36 } 37 38 // StoreCallbacks represents a contract between a Store and 39 // a autoregistration.Controller. 40 type StoreCallbacks interface { 41 // IsControllerOf returns true if a given WorkloadEntry is connected 42 // to this istiod instance. 43 IsControllerOf(wle *config.Config) bool 44 } 45 46 // NewStore returns a new Store instance. 47 func NewStore(store model.ConfigStoreController, cb StoreCallbacks) *Store { 48 return &Store{ 49 store: store, 50 cb: cb, 51 } 52 } 53 54 // UpdateHealth updates the associated WorkloadEntries health status 55 // based on the corresponding health check performed by istio-agent. 56 func (s *Store) UpdateHealth(proxyID, entryName, entryNs string, condition *v1alpha1.IstioCondition) error { 57 // get previous status 58 cfg := s.store.Get(gvk.WorkloadEntry, entryName, entryNs) 59 if cfg == nil { 60 return fmt.Errorf("failed to update health status for %v: WorkloadEntry %v not found", proxyID, entryNs) 61 } 62 // The workloadentry has reconnected to the other istiod 63 if !s.cb.IsControllerOf(cfg) { 64 return nil 65 } 66 67 // check if the existing health status is newer than this one 68 wleStatus, ok := cfg.Status.(*v1alpha1.IstioStatus) 69 if ok { 70 healthCondition := status.GetCondition(wleStatus.Conditions, status.ConditionHealthy) 71 if healthCondition != nil { 72 if healthCondition.LastProbeTime.AsTime().After(condition.LastProbeTime.AsTime()) { 73 return nil 74 } 75 } 76 } 77 78 // replace the updated status 79 wle := status.UpdateConfigCondition(*cfg, condition) 80 // update the status 81 _, err := s.store.UpdateStatus(wle) 82 if err != nil { 83 return fmt.Errorf("error while updating WorkloadEntry health status for %s: %w", proxyID, err) 84 } 85 log.Debugf("updated health status of %v to %v", proxyID, condition) 86 return nil 87 } 88 89 // DeleteHealthCondition updates WorkloadEntry of a workload that is not using auto-registration 90 // to remove information about the health status (since we can no longer be certain about it). 91 func (s *Store) DeleteHealthCondition(wle config.Config) error { 92 wle = status.DeleteConfigCondition(wle, status.ConditionHealthy) 93 // update the status 94 _, err := s.store.UpdateStatus(wle) 95 if err != nil && !errors.IsNotFound(err) { 96 return fmt.Errorf("error while removing WorkloadEntry health status for %s/%s: %v", wle.Namespace, wle.Name, err) 97 } 98 return nil 99 }