From 77ca0e1ecf1e2d2a9460fa4de7df5b9528ac2017 Mon Sep 17 00:00:00 2001 From: Periklis Tsirakidis Date: Thu, 27 Aug 2020 12:41:48 +0200 Subject: [PATCH] Bug 1871737: Update status using subresource /status --- ...operator.v4.6.0.clusterserviceversion.yaml | 1 + ...ging.openshift.io_elasticsearches_crd.yaml | 230 +++++++++++++++++- .../logging.openshift.io_kibanas_crd.yaml | 50 +++- hack/generate-crd.sh | 10 - .../4.6/crd-drop-status-validation-patch.yaml | 4 - manifests/4.6/kustomization.yaml | 16 -- ...ging.openshift.io_elasticsearches_crd.yaml | 230 +++++++++++++++++- .../4.6/logging.openshift.io_kibanas_crd.yaml | 50 +++- pkg/apis/logging/v1/elasticsearch_types.go | 40 ++- pkg/apis/logging/v1/kibana_types.go | 15 +- pkg/controller/elasticsearch/controller.go | 3 +- pkg/k8shandler/status.go | 10 +- test/utils/utils.go | 2 +- 13 files changed, 602 insertions(+), 59 deletions(-) delete mode 100644 manifests/4.6/crd-drop-status-validation-patch.yaml delete mode 100644 manifests/4.6/kustomization.yaml diff --git a/bundle/manifests/elasticsearch-operator.v4.6.0.clusterserviceversion.yaml b/bundle/manifests/elasticsearch-operator.v4.6.0.clusterserviceversion.yaml index 1dc975e7e..6729b0f7d 100644 --- a/bundle/manifests/elasticsearch-operator.v4.6.0.clusterserviceversion.yaml +++ b/bundle/manifests/elasticsearch-operator.v4.6.0.clusterserviceversion.yaml @@ -150,6 +150,7 @@ spec: - configmaps - secrets - serviceaccounts + - services/finalizers verbs: - "*" - apiGroups: diff --git a/bundle/manifests/logging.openshift.io_elasticsearches_crd.yaml b/bundle/manifests/logging.openshift.io_elasticsearches_crd.yaml index ed90f7cb4..1571ffc89 100644 --- a/bundle/manifests/logging.openshift.io_elasticsearches_crd.yaml +++ b/bundle/manifests/logging.openshift.io_elasticsearches_crd.yaml @@ -34,7 +34,8 @@ spec: - es singular: elasticsearch scope: Namespaced - subresources: {} + subresources: + status: {} validation: openAPIV3Schema: description: Elasticsearch is the Schema for the elasticsearches API @@ -401,6 +402,233 @@ spec: - redundancyPolicy type: object status: + description: ElasticsearchStatus defines the observed state of Elasticsearch + properties: + cluster: + properties: + activePrimaryShards: + format: int32 + type: integer + activeShards: + format: int32 + type: integer + initializingShards: + format: int32 + type: integer + numDataNodes: + format: int32 + type: integer + numNodes: + format: int32 + type: integer + pendingTasks: + format: int32 + type: integer + relocatingShards: + format: int32 + type: integer + status: + type: string + unassignedShards: + format: int32 + type: integer + required: + - activePrimaryShards + - activeShards + - initializingShards + - numDataNodes + - numNodes + - pendingTasks + - relocatingShards + - status + - unassignedShards + type: object + clusterHealth: + type: string + conditions: + items: + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. + format: date-time + type: string + message: + description: Human-readable message indicating details about last + transition. + type: string + reason: + description: Unique, one-word, CamelCase reason for the condition's + last transition. + type: string + status: + type: string + type: + description: ClusterConditionType is a valid value for ClusterCondition.Type + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + indexManagement: + properties: + lastUpdated: + format: date-time + type: string + mappings: + items: + properties: + conditions: + description: Reasons for the state of the corresponding mapping + for this status + items: + properties: + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + type: object + type: array + lastUpdated: + description: LastUpdated represents the last time that the + status was updated. + format: date-time + type: string + message: + type: string + name: + description: Name of the corresponding mapping for this status + type: string + reason: + type: string + state: + description: State of the corresponding mapping for this status + type: string + type: object + type: array + message: + type: string + policies: + items: + properties: + conditions: + description: Reasons for the state of the corresponding policy + for this status + items: + properties: + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + type: object + type: array + lastUpdated: + description: LastUpdated represents the last time that the + status was updated. + format: date-time + type: string + message: + description: Message about the corresponding policy + type: string + name: + description: Name of the corresponding policy for this status + type: string + reason: + description: Reasons for the state of the corresponding policy + for this status + type: string + state: + description: State of the corresponding policy for this status + type: string + type: object + type: array + reason: + type: string + state: + description: IndexManagementState of IndexManagment + type: string + type: object + nodes: + items: + description: ElasticsearchNodeStatus represents the status of individual + Elasticsearch node + properties: + conditions: + items: + properties: + lastTransitionTime: + description: Last time the condition transitioned from one + status to another. + format: date-time + type: string + message: + description: Human-readable message indicating details about + last transition. + type: string + reason: + description: Unique, one-word, CamelCase reason for the + condition's last transition. + type: string + status: + type: string + type: + description: ClusterConditionType is a valid value for ClusterCondition.Type + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + deploymentName: + type: string + roles: + items: + enum: + - master + - client + - data + type: string + type: array + statefulSetName: + type: string + status: + type: string + upgradeStatus: + properties: + scheduledCertRedeploy: + type: string + scheduledRedeploy: + type: string + scheduledUpgrade: + type: string + underUpgrade: + type: string + upgradePhase: + type: string + type: object + type: object + type: array + pods: + additionalProperties: + additionalProperties: + items: + type: string + type: array + type: object + type: object + shardAllocationEnabled: + type: string type: object type: object version: v1 diff --git a/bundle/manifests/logging.openshift.io_kibanas_crd.yaml b/bundle/manifests/logging.openshift.io_kibanas_crd.yaml index 81cd432be..fd8c30275 100644 --- a/bundle/manifests/logging.openshift.io_kibanas_crd.yaml +++ b/bundle/manifests/logging.openshift.io_kibanas_crd.yaml @@ -156,7 +156,55 @@ spec: - managementState type: object status: - type: object + items: + description: KibanaStatus defines the observed state of Kibana + properties: + clusterCondition: + additionalProperties: + items: + properties: + lastTransitionTime: + description: Last time the condition transitioned from one + status to another. + format: date-time + type: string + message: + description: Human-readable message indicating details about + last transition. + type: string + reason: + description: Unique, one-word, CamelCase reason for the condition's + last transition. + type: string + status: + type: string + type: + description: ClusterConditionType is a valid value for ClusterCondition.Type + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + type: object + deployment: + type: string + pods: + additionalProperties: + items: + type: string + type: array + type: object + replicaSets: + items: + type: string + type: array + replicas: + format: int32 + type: integer + type: object + type: array type: object version: v1 versions: diff --git a/hack/generate-crd.sh b/hack/generate-crd.sh index 7fecb6a39..ddafee790 100755 --- a/hack/generate-crd.sh +++ b/hack/generate-crd.sh @@ -5,8 +5,6 @@ source .bingo/variables.env set -euo pipefail MANIFESTS_DIR=${1:-"manifests/${OCP_VERSION}"} -ES_CRD_FILE="logging.openshift.io_elasticsearches_crd.yaml" -KB_CRD_FILE="logging.openshift.io_kibanas_crd.yaml" echo "--------------------------------------------------------------" echo "Generate k8s golang code" @@ -19,14 +17,6 @@ echo "--------------------------------------------------------------" $OPERATOR_SDK generate crds --crd-version v1beta1 mv deploy/crds/*.yaml "${MANIFESTS_DIR}" -echo "---------------------------------------------------------------" -echo "Kustomize: Patch CRDs for backward-compatibility" -echo "---------------------------------------------------------------" -oc kustomize "${MANIFESTS_DIR}" | \ - awk -v es="${MANIFESTS_DIR}/${ES_CRD_FILE}" \ - -v kb="${MANIFESTS_DIR}/${KB_CRD_FILE}"\ - 'BEGIN{filename = es} /---/ {getline; filename = kb}{print $0> filename}' - echo "---------------------------------------------------------------" echo "Cleanup operator-sdk generation folder" echo "---------------------------------------------------------------" diff --git a/manifests/4.6/crd-drop-status-validation-patch.yaml b/manifests/4.6/crd-drop-status-validation-patch.yaml deleted file mode 100644 index 07362fd7f..000000000 --- a/manifests/4.6/crd-drop-status-validation-patch.yaml +++ /dev/null @@ -1,4 +0,0 @@ -- op: replace - path: /spec/validation/openAPIV3Schema/properties/status - value: - type: object diff --git a/manifests/4.6/kustomization.yaml b/manifests/4.6/kustomization.yaml deleted file mode 100644 index 5030f49fe..000000000 --- a/manifests/4.6/kustomization.yaml +++ /dev/null @@ -1,16 +0,0 @@ -resources: -- logging.openshift.io_elasticsearches_crd.yaml -- logging.openshift.io_kibanas_crd.yaml -patchesJson6902: -- path: crd-drop-status-validation-patch.yaml - target: - group: apiextensions.k8s.io - version: v1beta1 - kind: CustomResourceDefinition - name: elasticsearches.logging.openshift.io -- path: crd-drop-status-validation-patch.yaml - target: - group: apiextensions.k8s.io - version: v1beta1 - kind: CustomResourceDefinition - name: kibanas.logging.openshift.io diff --git a/manifests/4.6/logging.openshift.io_elasticsearches_crd.yaml b/manifests/4.6/logging.openshift.io_elasticsearches_crd.yaml index ed90f7cb4..1571ffc89 100644 --- a/manifests/4.6/logging.openshift.io_elasticsearches_crd.yaml +++ b/manifests/4.6/logging.openshift.io_elasticsearches_crd.yaml @@ -34,7 +34,8 @@ spec: - es singular: elasticsearch scope: Namespaced - subresources: {} + subresources: + status: {} validation: openAPIV3Schema: description: Elasticsearch is the Schema for the elasticsearches API @@ -401,6 +402,233 @@ spec: - redundancyPolicy type: object status: + description: ElasticsearchStatus defines the observed state of Elasticsearch + properties: + cluster: + properties: + activePrimaryShards: + format: int32 + type: integer + activeShards: + format: int32 + type: integer + initializingShards: + format: int32 + type: integer + numDataNodes: + format: int32 + type: integer + numNodes: + format: int32 + type: integer + pendingTasks: + format: int32 + type: integer + relocatingShards: + format: int32 + type: integer + status: + type: string + unassignedShards: + format: int32 + type: integer + required: + - activePrimaryShards + - activeShards + - initializingShards + - numDataNodes + - numNodes + - pendingTasks + - relocatingShards + - status + - unassignedShards + type: object + clusterHealth: + type: string + conditions: + items: + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. + format: date-time + type: string + message: + description: Human-readable message indicating details about last + transition. + type: string + reason: + description: Unique, one-word, CamelCase reason for the condition's + last transition. + type: string + status: + type: string + type: + description: ClusterConditionType is a valid value for ClusterCondition.Type + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + indexManagement: + properties: + lastUpdated: + format: date-time + type: string + mappings: + items: + properties: + conditions: + description: Reasons for the state of the corresponding mapping + for this status + items: + properties: + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + type: object + type: array + lastUpdated: + description: LastUpdated represents the last time that the + status was updated. + format: date-time + type: string + message: + type: string + name: + description: Name of the corresponding mapping for this status + type: string + reason: + type: string + state: + description: State of the corresponding mapping for this status + type: string + type: object + type: array + message: + type: string + policies: + items: + properties: + conditions: + description: Reasons for the state of the corresponding policy + for this status + items: + properties: + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + type: object + type: array + lastUpdated: + description: LastUpdated represents the last time that the + status was updated. + format: date-time + type: string + message: + description: Message about the corresponding policy + type: string + name: + description: Name of the corresponding policy for this status + type: string + reason: + description: Reasons for the state of the corresponding policy + for this status + type: string + state: + description: State of the corresponding policy for this status + type: string + type: object + type: array + reason: + type: string + state: + description: IndexManagementState of IndexManagment + type: string + type: object + nodes: + items: + description: ElasticsearchNodeStatus represents the status of individual + Elasticsearch node + properties: + conditions: + items: + properties: + lastTransitionTime: + description: Last time the condition transitioned from one + status to another. + format: date-time + type: string + message: + description: Human-readable message indicating details about + last transition. + type: string + reason: + description: Unique, one-word, CamelCase reason for the + condition's last transition. + type: string + status: + type: string + type: + description: ClusterConditionType is a valid value for ClusterCondition.Type + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + deploymentName: + type: string + roles: + items: + enum: + - master + - client + - data + type: string + type: array + statefulSetName: + type: string + status: + type: string + upgradeStatus: + properties: + scheduledCertRedeploy: + type: string + scheduledRedeploy: + type: string + scheduledUpgrade: + type: string + underUpgrade: + type: string + upgradePhase: + type: string + type: object + type: object + type: array + pods: + additionalProperties: + additionalProperties: + items: + type: string + type: array + type: object + type: object + shardAllocationEnabled: + type: string type: object type: object version: v1 diff --git a/manifests/4.6/logging.openshift.io_kibanas_crd.yaml b/manifests/4.6/logging.openshift.io_kibanas_crd.yaml index 81cd432be..fd8c30275 100644 --- a/manifests/4.6/logging.openshift.io_kibanas_crd.yaml +++ b/manifests/4.6/logging.openshift.io_kibanas_crd.yaml @@ -156,7 +156,55 @@ spec: - managementState type: object status: - type: object + items: + description: KibanaStatus defines the observed state of Kibana + properties: + clusterCondition: + additionalProperties: + items: + properties: + lastTransitionTime: + description: Last time the condition transitioned from one + status to another. + format: date-time + type: string + message: + description: Human-readable message indicating details about + last transition. + type: string + reason: + description: Unique, one-word, CamelCase reason for the condition's + last transition. + type: string + status: + type: string + type: + description: ClusterConditionType is a valid value for ClusterCondition.Type + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + type: object + deployment: + type: string + pods: + additionalProperties: + items: + type: string + type: array + type: object + replicaSets: + items: + type: string + type: array + replicas: + format: int32 + type: integer + type: object + type: array type: object version: v1 versions: diff --git a/pkg/apis/logging/v1/elasticsearch_types.go b/pkg/apis/logging/v1/elasticsearch_types.go index c1fe1c544..4714d234b 100644 --- a/pkg/apis/logging/v1/elasticsearch_types.go +++ b/pkg/apis/logging/v1/elasticsearch_types.go @@ -15,6 +15,7 @@ const ( // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // +k8s:openapi-gen=true // +kubebuilder:resource:categories=logging;tracing,shortName=es +// +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Management State",JSONPath=".spec.managementState",type=string // +kubebuilder:printcolumn:name="Health",JSONPath=".status.cluster.status",type=string // +kubebuilder:printcolumn:name="Nodes",JSONPath=".status.cluster.numNodes",type=integer @@ -90,13 +91,20 @@ type ElasticsearchSpec struct { // ElasticsearchStatus defines the observed state of Elasticsearch // +k8s:openapi-gen=true type ElasticsearchStatus struct { - Nodes []ElasticsearchNodeStatus `json:"nodes"` - ClusterHealth string `json:"clusterHealth"` - Cluster ClusterHealth `json:"cluster"` - ShardAllocationEnabled ShardAllocationState `json:"shardAllocationEnabled"` - Pods map[ElasticsearchNodeRole]PodStateMap `json:"pods"` - Conditions ClusterConditions `json:"conditions"` - IndexManagementStatus *IndexManagementStatus `json:"indexManagement,omitempty"` + // +optional + Nodes []ElasticsearchNodeStatus `json:"nodes,omitempty"` + // +optional + ClusterHealth string `json:"clusterHealth,omitempty"` + // +optional + Cluster ClusterHealth `json:"cluster,omitempty"` + // +optional + ShardAllocationEnabled ShardAllocationState `json:"shardAllocationEnabled,omitempty"` + // +optional + Pods map[ElasticsearchNodeRole]PodStateMap `json:"pods,omitempty"` + // +optional + Conditions ClusterConditions `json:"conditions,omitempty"` + // +optional + IndexManagementStatus *IndexManagementStatus `json:"indexManagement,omitempty"` } type ClusterHealth struct { @@ -185,12 +193,18 @@ type ElasticsearchStorageSpec struct { // ElasticsearchNodeStatus represents the status of individual Elasticsearch node type ElasticsearchNodeStatus struct { - DeploymentName string `json:"deploymentName,omitempty"` - StatefulSetName string `json:"statefulSetName,omitempty"` - Status string `json:"status,omitempty"` - UpgradeStatus ElasticsearchNodeUpgradeStatus `json:"upgradeStatus,omitempty"` - Roles []ElasticsearchNodeRole `json:"roles,omitempty"` - Conditions ClusterConditions `json:"conditions,omitempty"` + // +optional + DeploymentName string `json:"deploymentName,omitempty"` + // +optional + StatefulSetName string `json:"statefulSetName,omitempty"` + // +optional + Status string `json:"status,omitempty"` + // +optional + UpgradeStatus ElasticsearchNodeUpgradeStatus `json:"upgradeStatus,omitempty"` + // +optional + Roles []ElasticsearchNodeRole `json:"roles,omitempty"` + // +optional + Conditions ClusterConditions `json:"conditions,omitempty"` } type ElasticsearchNodeUpgradeStatus struct { diff --git a/pkg/apis/logging/v1/kibana_types.go b/pkg/apis/logging/v1/kibana_types.go index 5b254410a..20181ebc9 100644 --- a/pkg/apis/logging/v1/kibana_types.go +++ b/pkg/apis/logging/v1/kibana_types.go @@ -45,11 +45,16 @@ type ProxySpec struct { // KibanaStatus defines the observed state of Kibana // +k8s:openapi-gen=true type KibanaStatus struct { - Replicas int32 `json:"replicas"` - Deployment string `json:"deployment"` - ReplicaSets []string `json:"replicaSets"` - Pods PodStateMap `json:"pods"` - Conditions map[string]ClusterConditions `json:"clusterCondition,omitempty"` + // +optional + Replicas int32 `json:"replicas"` + // +optional + Deployment string `json:"deployment"` + // +optional + ReplicaSets []string `json:"replicaSets,omitempty"` + // +optional + Pods PodStateMap `json:"pods,omitempty"` + // +optional + Conditions map[string]ClusterConditions `json:"clusterCondition,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/controller/elasticsearch/controller.go b/pkg/controller/elasticsearch/controller.go index 6f4819c44..d82e198cf 100644 --- a/pkg/controller/elasticsearch/controller.go +++ b/pkg/controller/elasticsearch/controller.go @@ -70,8 +70,7 @@ func (r *ReconcileElasticsearch) Reconcile(request reconcile.Request) (reconcile // Fetch the Elasticsearch instance cluster := &loggingv1.Elasticsearch{} - err := r.client.Get(context.TODO(), - request.NamespacedName, cluster) + err := r.client.Get(context.TODO(), request.NamespacedName, cluster) if err != nil { if apierrors.IsNotFound(err) { diff --git a/pkg/k8shandler/status.go b/pkg/k8shandler/status.go index 471e70139..545f01584 100644 --- a/pkg/k8shandler/status.go +++ b/pkg/k8shandler/status.go @@ -77,7 +77,7 @@ func (er *ElasticsearchRequest) UpdateClusterStatus() error { cluster.Status.ShardAllocationEnabled = clusterStatus.ShardAllocationEnabled cluster.Status.Nodes = clusterStatus.Nodes - if err := er.client.Update(context.TODO(), cluster); err != nil { + if err := er.client.Status().Update(context.TODO(), cluster); err != nil { return err } return nil @@ -125,7 +125,7 @@ func (er *ElasticsearchRequest) updateNodeStatus(status api.ElasticsearchStatus) cluster.Status = status - if err := er.client.Update(context.TODO(), cluster); err != nil { + if err := er.client.Status().Update(context.TODO(), cluster); err != nil { return err } @@ -673,9 +673,11 @@ func updateConditionWithRetry(dpl *api.Elasticsearch, value v1.ConditionStatus, return err } - executeUpdateCondition(&dpl.Status, value) + if changed := executeUpdateCondition(&dpl.Status, value); !changed { + return nil + } - if err := client.Update(context.TODO(), dpl); err != nil { + if err := client.Status().Update(context.TODO(), dpl); err != nil { log.Info("Failed to update Elasticsearch status", "cluster", dpl.Name, "error", err) return err } diff --git a/test/utils/utils.go b/test/utils/utils.go index ea4ec9e97..897ae2bba 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -96,7 +96,7 @@ func WaitForRolloutComplete(t *testing.T, f *test.Framework, namespace string, l } err := wait.Poll(retryInterval, timeout, func() (done bool, err error) { - err = f.Client.Client.List(context.TODO(), pods, opts...) + err = f.Client.List(context.TODO(), pods, opts...) if err != nil { if errors.IsNotFound(err) { t.Logf("Waiting for availability of pods with labels: %v in Namespace: %s \n", labels, namespace)