github.com/verrazzano/verrazzano@v1.7.1/tools/vz/pkg/internal/util/cluster/deployments.go (about) 1 // Copyright (c) 2021, 2024, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 // Package cluster handles cluster analysis 5 package cluster 6 7 import ( 8 encjson "encoding/json" 9 "io" 10 "os" 11 "sync" 12 13 "go.uber.org/zap" 14 appsv1 "k8s.io/api/apps/v1" 15 ) 16 17 var deploymentListMap = make(map[string]*appsv1.DeploymentList) 18 var deploymentCacheMutex = &sync.Mutex{} 19 20 // GetDeploymentList gets an deployment list 21 func GetDeploymentList(log *zap.SugaredLogger, path string) (deploymentList *appsv1.DeploymentList, err error) { 22 // Check the cache first 23 deploymentList = getDeploymentListIfPresent(path) 24 if deploymentList != nil { 25 log.Debugf("Returning cached deploymentList for %s", path) 26 return deploymentList, nil 27 } 28 29 // Not found in the cache, get it from the file 30 file, err := os.Open(path) 31 if err != nil { 32 log.Debugf("file %s not found", path) 33 return nil, err 34 } 35 defer file.Close() 36 37 fileBytes, err := io.ReadAll(file) 38 if err != nil { 39 log.Debugf("Failed reading Json file %s", path) 40 return nil, err 41 } 42 err = encjson.Unmarshal(fileBytes, &deploymentList) 43 if err != nil { 44 log.Debugf("Failed to unmarshal deploymentList at %s", path) 45 return nil, err 46 } 47 putDeploymentListIfNotPresent(path, deploymentList) 48 return deploymentList, nil 49 } 50 51 // IsDeploymentProblematic returns a boolean indicating whether a deployment is deemed problematic or not 52 func IsDeploymentProblematic(deployment *appsv1.Deployment) bool { 53 // If we can't determine the status conditions, we skip it 54 if len(deployment.Status.Conditions) == 0 { 55 return false 56 } 57 // If any conditions aren't in Available, flag this deployment as problematic 58 // Note that it could be progressing normally, but flagging it for now as it could be stuck 59 for _, condition := range deployment.Status.Conditions { 60 if condition.Type == appsv1.DeploymentAvailable { 61 continue 62 } 63 return true 64 } 65 return false 66 } 67 68 // FindProblematicDeployments will find and return all deployments deemed problematic in the deploymentList 69 func FindProblematicDeployments(deploymentList *appsv1.DeploymentList) (deployments []appsv1.Deployment) { 70 for i, deployment := range deploymentList.Items { 71 if IsDeploymentProblematic(&deploymentList.Items[i]) { 72 deployments = append(deployments, deployment) 73 } 74 } 75 return deployments 76 } 77 78 func getDeploymentListIfPresent(path string) (deploymentList *appsv1.DeploymentList) { 79 deploymentCacheMutex.Lock() 80 deploymentListTest := deploymentListMap[path] 81 if deploymentListTest != nil { 82 deploymentList = deploymentListTest 83 } 84 deploymentCacheMutex.Unlock() 85 return deploymentList 86 } 87 88 func putDeploymentListIfNotPresent(path string, deploymentList *appsv1.DeploymentList) { 89 deploymentCacheMutex.Lock() 90 deploymentListInMap := deploymentListMap[path] 91 if deploymentListInMap == nil { 92 deploymentListMap[path] = deploymentList 93 } 94 deploymentCacheMutex.Unlock() 95 }