github.com/verrazzano/verrazzano@v1.7.1/tools/psr/backend/pkg/opensearch/opensearch.go (about) 1 // Copyright (c) 2022, 2023, 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 "context" 8 "fmt" 9 vmov1 "github.com/verrazzano/verrazzano-monitoring-operator/pkg/apis/vmcontroller/v1" 10 "github.com/verrazzano/verrazzano/pkg/k8s/ready" 11 "github.com/verrazzano/verrazzano/pkg/log/vzlog" 12 vzv1alpha1 "github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1alpha1" 13 "github.com/verrazzano/verrazzano/platform-operator/constants" 14 "github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/component/opensearch" 15 "github.com/verrazzano/verrazzano/tools/psr/backend/config" 16 corev1 "k8s.io/api/core/v1" 17 "k8s.io/apimachinery/pkg/labels" 18 "k8s.io/apimachinery/pkg/selection" 19 "sigs.k8s.io/controller-runtime/pkg/client" 20 21 "k8s.io/apimachinery/pkg/types" 22 ) 23 24 const ( 25 nodeNamePrefix = "vmi-system-%s" 26 componentName = "opensearch" 27 28 MasterTier = "master" 29 DataTier = "data" 30 IngestTier = "ingest" 31 ) 32 33 // IsOSReady checks if the OpenSearch resources are ready 34 func IsOSReady(ctrlRuntimeClient client.Client, cr *vzv1alpha1.Verrazzano) bool { 35 prefix := fmt.Sprintf("Component %s", componentName) 36 for _, node := range cr.Spec.Components.Elasticsearch.Nodes { 37 if !IsOSNodeReady(ctrlRuntimeClient, node, prefix) { 38 return false 39 } 40 } 41 // return common.IsVMISecretReady(ctx) 42 return true 43 } 44 45 // IsOSNodeReady returns true if the OpenSearch tier is ready 46 func IsOSNodeReady(client client.Client, node vzv1alpha1.OpenSearchNode, prefix string) bool { 47 if node.Replicas == nil || *node.Replicas < 1 { 48 return true 49 } 50 nodeControllerName := getNodeControllerName(node) 51 52 // If a node has the master role, it is a statefulset 53 if hasRole(node.Roles, vmov1.MasterRole) { 54 return opensearch.AreOpensearchStsReady(vzlog.DefaultLogger(), client, []types.NamespacedName{{ 55 Name: nodeControllerName, 56 Namespace: constants.VerrazzanoSystemNamespace, 57 }}, *node.Replicas, prefix) 58 } 59 60 // Data nodes have N = node.Replicas number of deployment objects. 61 if hasRole(node.Roles, vmov1.DataRole) { 62 return ready.DeploymentsAreReady(vzlog.DefaultLogger(), client, dataDeploymentObjectKeys(node, nodeControllerName), 1, prefix) 63 } 64 65 // Ingest nodes can be handled like normal deployments 66 return ready.DeploymentsAreReady(vzlog.DefaultLogger(), client, []types.NamespacedName{{ 67 Name: nodeControllerName, 68 Namespace: constants.VerrazzanoSystemNamespace, 69 }}, *node.Replicas, prefix) 70 } 71 72 func getNodeControllerName(node vzv1alpha1.OpenSearchNode) string { 73 return fmt.Sprintf(nodeNamePrefix, node.Name) 74 } 75 76 func hasRole(roles []vmov1.NodeRole, roleToHave vmov1.NodeRole) bool { 77 for _, role := range roles { 78 if role == roleToHave { 79 return true 80 } 81 } 82 return false 83 } 84 85 func dataDeploymentObjectKeys(node vzv1alpha1.OpenSearchNode, nodeControllerName string) []types.NamespacedName { 86 var dataDeployments []types.NamespacedName 87 if node.Replicas == nil { 88 return dataDeployments 89 } 90 var i int32 91 for i = 0; i < *node.Replicas; i++ { 92 dataDeploymentName := fmt.Sprintf("%s-%d", nodeControllerName, i) 93 dataDeployments = append(dataDeployments, types.NamespacedName{ 94 Name: dataDeploymentName, 95 Namespace: constants.VerrazzanoSystemNamespace, 96 }) 97 } 98 return dataDeployments 99 } 100 101 // GetPodsForTier returns pods for a given tier 102 func GetPodsForTier(ctrlRuntimeClient client.Client, tier string) ([]corev1.Pod, error) { 103 var label string 104 switch tier { 105 case MasterTier: 106 label = "opensearch.verrazzano.io/role-master" 107 case DataTier: 108 label = "opensearch.verrazzano.io/role-data" 109 case IngestTier: 110 label = "opensearch.verrazzano.io/role-ingest" 111 } 112 req, _ := labels.NewRequirement(label, selection.Equals, []string{"true"}) 113 // req, _ := labels.NewRequirement(label, selection.Exists, []string{}) 114 115 pods, err := getPodsByLabels(ctrlRuntimeClient, constants.VerrazzanoSystemNamespace, *req) 116 if err != nil { 117 return nil, err 118 } 119 return pods, nil 120 } 121 122 // getConfigMapsByLabels gets the configmaps by label 123 func getPodsByLabels(ctrlRuntimeClient client.Client, namespace string, requirements ...labels.Requirement) ([]corev1.Pod, error) { 124 // Find the scenario configmaps in the cluster 125 selector := labels.NewSelector() 126 for _, req := range requirements { 127 selector = selector.Add(req) 128 } 129 podList := corev1.PodList{} 130 err := ctrlRuntimeClient.List(context.TODO(), &podList, &client.ListOptions{Namespace: namespace, LabelSelector: selector}) 131 if err != nil { 132 return nil, err 133 } 134 return podList.Items, nil 135 } 136 137 // ValidateOpenSeachTier validates the envvar is a correct opensearch tier 138 func ValidateOpenSeachTier(opensearchTierEnvVar string) (string, error) { 139 tier := config.PsrEnv.GetEnv(opensearchTierEnvVar) 140 if tier != MasterTier && tier != DataTier && tier != IngestTier { 141 return "", fmt.Errorf("error, %s not a valid OpenSearch tier to restart", tier) 142 } 143 return tier, nil 144 }