diff --git a/charts/app/bookkeeper-cluster.yaml b/charts/app/bookkeeper-cluster.yaml new file mode 100644 index 00000000..216b68bf --- /dev/null +++ b/charts/app/bookkeeper-cluster.yaml @@ -0,0 +1,41 @@ +apiVersion: app.k8s.io/v1beta1 +kind: Application +metadata: + name: "bookkeeper-cluster" + labels: + product: "streamingdata" + app.kubernetes.io/name: "bookkeeper-cluster" + annotations: + com.dellemc.kahm.subscribed: "true" + nautilus.dellemc.com/chart-version: "latest" +spec: + assemblyPhase: "Pending" + selector: + matchLabels: + app.kubernetes.io/name: "bookkeeper-cluster" + componentKinds: + - group: core + kind: Service + - group: core + kind: Pod + - group: apps + kind: StatefulSet + - group: core + kind: ConfigMap + - group: core + kind: Secret + - group: core + kind: PersistentVolumeClaim + - group: core + kind: ServiceAccount + - group: pravega.pravega.io + kind: BookkeeperCluster + descriptor: + type: "bookkeeper-cluster" + version: "latest" + description: > + Bookkeeper deployment on Kubernetes + keywords: + - "nautilus" + - "pravega" + - "bookkeeper" diff --git a/charts/app/crd.yaml b/charts/app/crd.yaml new file mode 100644 index 00000000..642f7e2a --- /dev/null +++ b/charts/app/crd.yaml @@ -0,0 +1,268 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + generation: 1 + labels: + controller-tools.k8s.io: "1.0" + name: applications.app.k8s.io + selfLink: /apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/applications.app.k8s.io +spec: + conversion: + strategy: None + group: app.k8s.io + names: + kind: Application + listKind: ApplicationList + plural: applications + singular: application + preserveUnknownFields: true + scope: Namespaced + validation: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + assemblyPhase: + type: string + componentKinds: + items: + type: object + type: array + descriptor: + properties: + description: + type: string + icons: + items: + properties: + size: + type: string + src: + type: string + type: + type: string + required: + - src + type: object + type: array + keywords: + items: + type: string + type: array + links: + items: + properties: + description: + type: string + url: + type: string + type: object + type: array + maintainers: + items: + properties: + email: + type: string + name: + type: string + url: + type: string + type: object + type: array + notes: + type: string + owners: + items: + properties: + email: + type: string + name: + type: string + url: + type: string + type: object + type: array + type: + type: string + version: + type: string + type: object + info: + items: + properties: + name: + type: string + type: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + key: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + resourceVersion: + type: string + uid: + type: string + type: object + ingressRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + host: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + path: + type: string + resourceVersion: + type: string + uid: + type: string + type: object + secretKeyRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + key: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + resourceVersion: + type: string + uid: + type: string + type: object + serviceRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + path: + type: string + port: + format: int32 + type: integer + resourceVersion: + type: string + uid: + type: string + type: object + type: + type: string + type: object + type: object + type: array + selector: + type: object + type: object + status: + properties: + components: + items: + properties: + group: + type: string + kind: + type: string + link: + type: string + name: + type: string + status: + type: string + type: object + type: array + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + lastUpdateTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - type + - status + type: object + type: array + observedGeneration: + format: int64 + type: integer + type: object + version: v1beta1 + versions: + - name: v1beta1 + served: true + storage: true +status: + acceptedNames: + kind: Application + listKind: ApplicationList + plural: applications + singular: application + conditions: + - lastTransitionTime: "2020-03-27T01:59:25Z" + message: no conflicts found + reason: NoConflicts + status: "True" + type: NamesAccepted + - lastTransitionTime: null + message: the initial names have been accepted + reason: InitialNamesAccepted + status: "True" + type: Established + - lastTransitionTime: "2020-03-27T01:59:25Z" + message: 'spec.validation.openAPIV3Schema.type: Required value: must not be empty + at the root' + reason: Violations + status: "True" + type: NonStructuralSchema + storedVersions: + - v1beta1 diff --git a/pkg/apis/bookkeeper/v1alpha1/status.go b/pkg/apis/bookkeeper/v1alpha1/status.go index 8ecb5783..87ff9fa7 100644 --- a/pkg/apis/bookkeeper/v1alpha1/status.go +++ b/pkg/apis/bookkeeper/v1alpha1/status.go @@ -26,11 +26,9 @@ const ( ClusterConditionError = "Error" // Reasons for cluster upgrading condition - UpdatingControllerReason = "Updating Controller" - UpdatingSegmentstoreReason = "Updating Segmentstore" - UpdatingBookkeeperReason = "Updating Bookkeeper" - UpgradeErrorReason = "Upgrade Error" - RollbackErrorReason = "Rollback Error" + UpdatingBookkeeperReason = "Updating Bookkeeper" + UpgradeErrorReason = "Upgrade Error" + RollbackErrorReason = "Rollback Error" ) // BookkeeperClusterStatus defines the observed state of BookkeeperCluster diff --git a/pkg/controller/bookkeepercluster/bookkeepercluster_controller.go b/pkg/controller/bookkeepercluster/bookkeepercluster_controller.go index d2c00cfe..6b85eb4c 100644 --- a/pkg/controller/bookkeepercluster/bookkeepercluster_controller.go +++ b/pkg/controller/bookkeepercluster/bookkeepercluster_controller.go @@ -265,7 +265,14 @@ func (r *ReconcileBookkeeperCluster) reconcileFinalizers(bk *bookkeeperv1alpha1. return fmt.Errorf("failed to update Bookkeeper object (%s): %v", bk.Name, err) } if err = r.cleanUpZookeeperMeta(bk, pravegaClusterName); err != nil { - return fmt.Errorf("failed to clean up metadata (%s): %v", bk.Name, err) + // emit an event for zk metadata cleanup failure + message := fmt.Sprintf("failed to cleanup %s metadata from zookeeper (znode path: /pravega/%s): %v", bk.Name, pravegaClusterName, err) + event := util.NewApplicationEvent("ZKMETA_CLEANUP_ERROR", bk, "ZK Metadata Cleanup Failed", message, "Error") + pubErr := r.client.Create(context.TODO(), event) + if pubErr != nil { + log.Printf("Error publishing zk metadata cleanup failure event to k8s. %v", pubErr) + } + return fmt.Errorf(message) } } } diff --git a/pkg/util/k8sutil.go b/pkg/util/k8sutil.go index 28c0e620..798439dc 100644 --- a/pkg/util/k8sutil.go +++ b/pkg/util/k8sutil.go @@ -127,11 +127,12 @@ func IsPodFaulty(pod *corev1.Pod) (bool, error) { func NewEvent(name string, p *v1alpha1.BookkeeperCluster, reason string, message string, eventType string) *corev1.Event { now := metav1.Now() operatorName, _ := k8s.GetOperatorName() + generateName := name + "-" event := corev1.Event{ ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: p.Namespace, - Labels: LabelsForBookkeeperCluster(p), + GenerateName: generateName, + Namespace: p.Namespace, + Labels: LabelsForBookkeeperCluster(p), }, InvolvedObject: corev1.ObjectReference{ APIVersion: "bookkeeper.pravega.io/v1alpha1", @@ -151,3 +152,30 @@ func NewEvent(name string, p *v1alpha1.BookkeeperCluster, reason string, message } return &event } + +func NewApplicationEvent(name string, p *v1alpha1.BookkeeperCluster, reason string, message string, eventType string) *corev1.Event { + now := metav1.Now() + operatorName, _ := k8s.GetOperatorName() + generateName := name + "-" + event := corev1.Event{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: generateName, + Namespace: p.Namespace, + Labels: LabelsForBookkeeperCluster(p), + }, + InvolvedObject: corev1.ObjectReference{ + APIVersion: "app.k8s.io/v1beta1", + Kind: "Application", + Name: "bookkeeper-cluster", + Namespace: p.GetNamespace(), + }, + Reason: reason, + Message: message, + FirstTimestamp: now, + LastTimestamp: now, + Type: eventType, + ReportingController: operatorName, + ReportingInstance: os.Getenv("POD_NAME"), + } + return &event +}