github.com/verrazzano/verrazzano-monitoring-operator@v0.0.30/pkg/opensearch/health.go (about) 1 // Copyright (C) 2022, 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 opensearch 5 6 import ( 7 "encoding/json" 8 "fmt" 9 vmcontrollerv1 "github.com/verrazzano/verrazzano-monitoring-operator/pkg/apis/vmcontroller/v1" 10 "github.com/verrazzano/verrazzano-monitoring-operator/pkg/config" 11 "github.com/verrazzano/verrazzano-monitoring-operator/pkg/resources" 12 nodetool "github.com/verrazzano/verrazzano-monitoring-operator/pkg/resources/nodes" 13 "net/http" 14 ) 15 16 type ( 17 ClusterHealth struct { 18 Status string `json:"status"` 19 } 20 21 NodeSettings struct { 22 Nodes map[string]interface{} `json:"nodes"` 23 } 24 25 Node struct { 26 Version string `json:"version"` 27 Roles []string `json:"roles"` 28 } 29 ) 30 31 const ( 32 HealthGreen = "green" 33 MinDataNodesForResize = 2 34 ) 35 36 func (o *OSClient) opensearchHealth(vmo *vmcontrollerv1.VerrazzanoMonitoringInstance, checkNodeCount bool, waitForVersion bool) error { 37 // Verify that the cluster is Green 38 clusterHealth, err := o.getOpenSearchClusterHealth(vmo) 39 if err != nil { 40 return err 41 } 42 if !(clusterHealth.Status == HealthGreen) { 43 return fmt.Errorf("OpenSearch health is %s", clusterHealth.Status) 44 } 45 46 // Verify that the nodes are running the expected version 47 nodes, err := o.getOpenSearchNodes(vmo) 48 if err != nil { 49 return err 50 } 51 52 if checkNodeCount { 53 // Verify the node count 54 expectedNodes := int(nodetool.GetNodeCount(vmo).Replicas) 55 if len(nodes) < expectedNodes { 56 return fmt.Errorf("Expected %d OpenSearch nodes, got %d", expectedNodes, len(nodes)) 57 } 58 } 59 60 if waitForVersion { 61 // If any node is not running the expected version, the cluster is not ready 62 for _, node := range nodes { 63 if node.Version != config.ESWaitTargetVersion { 64 return fmt.Errorf("Not all OpenSearch nodes are upgrade to %s version", config.ESWaitTargetVersion) 65 } 66 } 67 } 68 69 return nil 70 } 71 72 func (o *OSClient) getOpenSearchNodes(vmo *vmcontrollerv1.VerrazzanoMonitoringInstance) ([]Node, error) { 73 url := resources.GetOpenSearchHTTPEndpoint(vmo) + "/_nodes/settings" 74 req, err := http.NewRequest("GET", url, nil) 75 if err != nil { 76 return nil, err 77 } 78 resp, err := o.DoHTTP(req) 79 if err != nil { 80 return nil, err 81 } 82 defer resp.Body.Close() 83 if resp.StatusCode != http.StatusOK { 84 return nil, fmt.Errorf("failed to get node settings: %s", resp.Status) 85 } 86 87 nodeSettings := &NodeSettings{} 88 if err := json.NewDecoder(resp.Body).Decode(nodeSettings); err != nil { 89 return nil, err 90 } 91 92 var nodes []Node 93 for nodeKey := range nodeSettings.Nodes { 94 b, err := json.Marshal(nodeSettings.Nodes[nodeKey]) 95 if err != nil { 96 return nil, err 97 } 98 99 node := &Node{} 100 if err := json.Unmarshal(b, node); err != nil { 101 return nil, err 102 } 103 nodes = append(nodes, *node) 104 } 105 106 return nodes, nil 107 } 108 109 func (o *OSClient) getOpenSearchClusterHealth(vmo *vmcontrollerv1.VerrazzanoMonitoringInstance) (*ClusterHealth, error) { 110 url := resources.GetOpenSearchHTTPEndpoint(vmo) + "/_cluster/health" 111 req, err := http.NewRequest("GET", url, nil) 112 if err != nil { 113 return nil, err 114 } 115 resp, err := o.DoHTTP(req) 116 if err != nil { 117 return nil, err 118 } 119 defer resp.Body.Close() 120 if resp.StatusCode != http.StatusOK { 121 return nil, fmt.Errorf("failed to get cluster health: %s", resp.Status) 122 } 123 124 clusterHealth := &ClusterHealth{} 125 if err := json.NewDecoder(resp.Body).Decode(clusterHealth); err != nil { 126 return nil, err 127 } 128 return clusterHealth, nil 129 }