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  }