github.com/verrazzano/verrazzano@v1.7.1/tools/vz/pkg/internal/util/cluster/mysql.go (about) 1 // Copyright (c) 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 package cluster 4 5 import ( 6 "fmt" 7 "io" 8 "os" 9 "time" 10 11 "github.com/verrazzano/verrazzano/tools/vz/pkg/constants" 12 "github.com/verrazzano/verrazzano/tools/vz/pkg/internal/util/files" 13 "github.com/verrazzano/verrazzano/tools/vz/pkg/internal/util/report" 14 "go.uber.org/zap" 15 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 16 ) 17 18 // AnalyzeMySQLRelatedIssues is the initial entry function for mySQL related issues, and it returns an error. 19 // It checks to see whether an innoDBCluster is in a state of terminating, and reports an issue based on the length of its termination 20 func AnalyzeMySQLRelatedIssues(log *zap.SugaredLogger, clusterRoot string) (err error) { 21 allNamespacesFound, err := files.FindNamespaces(log, clusterRoot) 22 if err != nil { 23 return err 24 } 25 var issueReporter = report.IssueReporter{ 26 PendingIssues: make(map[string]report.Issue), 27 } 28 timeOfCapture, err := files.GetTimeOfCapture(log, clusterRoot) 29 if err != nil { 30 return err 31 } 32 for _, namespace := range allNamespacesFound { 33 if namespace != "keycloak" { 34 continue 35 } 36 innoDBClusterFile := files.FormFilePathInNamespace(clusterRoot, namespace, constants.InnoDBClusterJSON) 37 innoDBResourceList, err := getInnoDBClusterResources(log, innoDBClusterFile) 38 if err != nil { 39 return err 40 } 41 if innoDBResourceList == nil { 42 continue 43 } 44 for _, item := range innoDBResourceList.Items { 45 isTerminating, message := isInnoDBClusterCurrentlyInTerminatingStatus(&item, timeOfCapture) 46 if isTerminating { 47 reportInnoDBClustersInTerminatingStatusIssue(clusterRoot, &issueReporter, innoDBClusterFile, message) 48 49 } 50 } 51 52 } 53 54 issueReporter.Contribute(log, clusterRoot) 55 return nil 56 } 57 58 // getInnoDBClusterResource returns the InnoDBCluster list that is in the inno-db-cluster.json file 59 func getInnoDBClusterResources(log *zap.SugaredLogger, path string) (innoDBClusterObject *unstructured.UnstructuredList, err error) { 60 resourceToReturn := unstructured.UnstructuredList{} 61 file, err := os.Open(path) 62 defer file.Close() 63 if err != nil { 64 log.Debugf("file %s not found", path) 65 return nil, nil 66 } 67 fileBytes, err := io.ReadAll(file) 68 if err != nil { 69 log.Errorf("Failed reading namespace.json file %s", path) 70 return nil, err 71 } 72 err = resourceToReturn.UnmarshalJSON(fileBytes) 73 if err != nil { 74 log.Errorf("Failed to unmarshal namespace resource at %s", path) 75 return nil, err 76 } 77 return &resourceToReturn, err 78 } 79 80 // isInnoDBClusterCurrentlyInTerminatingStatus checks if an innoDBCluster resource has been in a state of deletion for 10 minutes or greater 81 func isInnoDBClusterCurrentlyInTerminatingStatus(innoDBClusterResource *unstructured.Unstructured, timeOfCapture *time.Time) (bool, string) { 82 var deletionMessage string 83 deletionTimestamp := innoDBClusterResource.GetDeletionTimestamp() 84 if deletionTimestamp == nil || timeOfCapture == nil { 85 return false, deletionMessage 86 } 87 diff := timeOfCapture.Sub(deletionTimestamp.Time) 88 if int(diff.Minutes()) < 10 { 89 return false, deletionMessage 90 } 91 deletionMessage = "The innoDBClusterResource " + innoDBClusterResource.GetName() + " has spent " + fmt.Sprint(int(diff.Minutes())) + " minutes and " + fmt.Sprint(int(diff.Seconds())%60) + " seconds deleting" 92 return true, deletionMessage 93 } 94 95 // reportInnoDBClustersInTerminatingStatusIssue is a helper function that reports an issue if a innoDBCluster resource has been in a state of deletion for more than 10 minutes 96 func reportInnoDBClustersInTerminatingStatusIssue(clusterRoot string, issueReporter *report.IssueReporter, InnoDBClusterFile string, message string) { 97 files := []string{InnoDBClusterFile} 98 messageList := []string{message} 99 issueReporter.AddKnownIssueMessagesFiles(report.InnoDBClusterResourceCurrentlyInTerminatingStateForLongDuration, clusterRoot, messageList, files) 100 101 }