Skip to content

Commit

Permalink
Merge branch 'master' into external-option-client-service
Browse files Browse the repository at this point in the history
  • Loading branch information
idolaman authored Aug 7, 2024
2 parents 2ca1a87 + 644ebe3 commit 99c9463
Show file tree
Hide file tree
Showing 20 changed files with 948 additions and 1,109 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.20
- name: Set up Go 1.21
uses: actions/setup-go@v2
with:
go-version: "1.20"
go-version: "1.21"
id: go
- name: Set up Go for root
run: |
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ARG DOCKER_REGISTRY
ARG DISTROLESS_DOCKER_REGISTRY
ARG ALPINE_VERSION=3.18
FROM ${DOCKER_REGISTRY:+$DOCKER_REGISTRY/}golang:1.20-alpine${ALPINE_VERSION} as go-builder
FROM ${DOCKER_REGISTRY:+$DOCKER_REGISTRY/}golang:1.21-alpine${ALPINE_VERSION} as go-builder

ARG PROJECT_NAME=zookeeper-operator
ARG REPO_PATH=github.com/pravega/$PROJECT_NAME
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The project is currently alpha. While no breaking API changes are currently plan

### Overview

This operator runs a Zookeeper 3.7.1 cluster, and uses Zookeeper dynamic reconfiguration to handle node membership.
This operator runs a Zookeeper 3.7.2 cluster, and uses Zookeeper dynamic reconfiguration to handle node membership.

The operator itself is built with the [Operator framework](https://github.com/operator-framework/operator-sdk).

Expand Down
5 changes: 3 additions & 2 deletions charts/zookeeper-operator/templates/operator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@ spec:
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: 6000
- containerPort: {{ int .Values.metricsPort }}
name: metrics
command:
- zookeeper-operator
{{- if .Values.disableFinalizer }}
args:
- -metrics-bind-address={{ .Values.metricsBindAddress }}:{{ int .Values.metricsPort }}
{{- if .Values.disableFinalizer }}
- -disableFinalizer
{{- end }}
env:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ metadata:
"helm.sh/hook": post-install, post-upgrade
"helm.sh/hook-weight": "1"
"helm.sh/hook-delete-policy": hook-succeeded, before-hook-creation, hook-failed
{{- if or .Values.global.imagePullSecrets .Values.hooks.serviceAccount.imagePullSecrets }}
imagePullSecrets:
{{- range (default .Values.global.imagePullSecrets .Values.hooks.serviceAccount.imagePullSecrets) }}
- name: {{ . }}
{{- end }}
{{- end }}

---

Expand Down
6 changes: 6 additions & 0 deletions charts/zookeeper-operator/templates/pre-delete-hooks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ metadata:
"helm.sh/hook": pre-delete
"helm.sh/hook-weight": "1"
"helm.sh/hook-delete-policy": hook-succeeded, before-hook-creation, hook-failed
{{- if or .Values.global.imagePullSecrets .Values.hooks.serviceAccount.imagePullSecrets }}
imagePullSecrets:
{{- range (default .Values.global.imagePullSecrets .Values.hooks.serviceAccount.imagePullSecrets) }}
- name: {{ . }}
{{- end }}
{{- end }}

---

Expand Down

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions charts/zookeeper-operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ tolerations: []
annotations: {}

hooks:
## Optionally specify an array of imagePullSecrets. Will override the global parameter if set
serviceAccount:
imagePullSecrets: []

backoffLimit: 10
image:
repository: lachlanevenson/k8s-kubectl
Expand Down Expand Up @@ -86,3 +90,7 @@ additionalVolumes: {}
# emptyDir: {}

disableFinalizer: false

## In order to enable gathering metrics by Prometheus etc... bind to 0.0.0.0
metricsBindAddress: 127.0.0.1
metricsPort: "6000"
437 changes: 342 additions & 95 deletions config/crd/bases/zookeeper.pravega.io_zookeeperclusters.yaml

Large diffs are not rendered by default.

29 changes: 28 additions & 1 deletion controllers/zookeepercluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,33 @@ func compareResourceVersion(zk *zookeeperv1beta1.ZookeeperCluster, sts *appsv1.S
func (r *ZookeeperClusterReconciler) reconcileStatefulSet(instance *zookeeperv1beta1.ZookeeperCluster) (err error) {

// we cannot upgrade if cluster is in UpgradeFailed
if instance.Status.IsClusterInUpgradeFailedState() {
sts := zk.MakeStatefulSet(instance)
if err = controllerutil.SetControllerReference(instance, sts, r.Scheme); err != nil {
return err
}
foundSts := &appsv1.StatefulSet{}
err = r.Client.Get(context.TODO(), types.NamespacedName{
Name: sts.Name,
Namespace: sts.Namespace,
}, foundSts)
if err == nil {
err = r.Client.Update(context.TODO(), foundSts)
if err != nil {
return err
}
if foundSts.Status.Replicas == foundSts.Status.ReadyReplicas && foundSts.Status.CurrentRevision == foundSts.Status.UpdateRevision {
r.Log.Info("failed upgrade completed", "upgrade from:", instance.Status.CurrentVersion, "upgrade to:", instance.Status.TargetVersion)
instance.Status.CurrentVersion = instance.Status.TargetVersion
instance.Status.SetErrorConditionFalse()
return r.clearUpgradeStatus(instance)
} else {
r.Log.Info("Unable to recover failed upgrade, make sure all nodes are running the target version")
}

}
}

if instance.Status.IsClusterInUpgradeFailedState() {
return nil
}
Expand Down Expand Up @@ -594,7 +621,7 @@ func YAMLExporterReconciler(zookeepercluster *zookeeperv1beta1.ZookeeperCluster)
var scheme = scheme.Scheme
scheme.AddKnownTypes(zookeeperv1beta1.GroupVersion, zookeepercluster)
return &ZookeeperClusterReconciler{
Client: fake.NewFakeClient(zookeepercluster),
Client: fake.NewClientBuilder().WithRuntimeObjects(zookeepercluster).Build(),
Scheme: scheme,
ZkClient: new(zk.DefaultZookeeperClient),
}
Expand Down
82 changes: 64 additions & 18 deletions controllers/zookeepercluster_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {
)

BeforeEach(func() {
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(z).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(z).WithStatusSubresource(z).Build()
r = &ZookeeperClusterReconciler{Client: cl, Scheme: s, ZkClient: mockZkClient}
res, err = r.Reconcile(context.TODO(), req)
})
Expand Down Expand Up @@ -135,7 +135,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {

BeforeEach(func() {
z.WithDefaults()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(z).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(z).WithStatusSubresource(z).Build()
r = &ZookeeperClusterReconciler{Client: cl, Scheme: s, ZkClient: mockZkClient}
res, err = r.Reconcile(context.TODO(), req)
})
Expand Down Expand Up @@ -206,7 +206,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {
next := z.DeepCopy()
st := zk.MakeStatefulSet(z)
next.Spec.Replicas = 6
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, st).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, st).WithStatusSubresource(next).Build()
r = &ZookeeperClusterReconciler{Client: cl, Scheme: s, ZkClient: mockZkClient}
res, err = r.Reconcile(context.TODO(), req)
})
Expand Down Expand Up @@ -234,7 +234,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {
z.Status.Init()
next := z.DeepCopy()
st := zk.MakeStatefulSet(z)
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, st).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, st).WithStatusSubresource(next).Build()
r = &ZookeeperClusterReconciler{Client: cl, Scheme: s, ZkClient: mockZkClient}
res, err = r.Reconcile(context.TODO(), req)
})
Expand Down Expand Up @@ -265,7 +265,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {
z.Status.Init()
next = z.DeepCopy()
sa = zk.MakeServiceAccount(z)
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, sa).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, sa).WithStatusSubresource(next).Build()
r = &ZookeeperClusterReconciler{Client: cl, Scheme: s, ZkClient: mockZkClient}
res, err = r.Reconcile(context.TODO(), req)
})
Expand All @@ -282,7 +282,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {
})
It("should update the service account", func() {
next.Spec.Pod.ImagePullSecrets = []corev1.LocalObjectReference{{Name: "test-pull-secret"}}
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, sa).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, sa).WithStatusSubresource(next).Build()
r = &ZookeeperClusterReconciler{Client: cl, Scheme: s, ZkClient: mockZkClient}
_, err := r.Reconcile(context.TODO(), req)
Ω(err).To(BeNil())
Expand All @@ -307,7 +307,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {
next.Status.CurrentVersion = "0.2.6"
next.Status.SetPodsReadyConditionTrue()
st := zk.MakeStatefulSet(z)
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, st).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, st).WithStatusSubresource(next).Build()
st = &appsv1.StatefulSet{}
err = cl.Get(context.TODO(), req.NamespacedName, st)
// changing the Revision value to simulate the upgrade scenario
Expand Down Expand Up @@ -367,7 +367,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {
next.Status.TargetVersion = "0.2.7"
next.Status.SetUpgradingConditionTrue(" ", " ")
st := zk.MakeStatefulSet(z)
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, st).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, st).WithStatusSubresource(next).Build()
st = &appsv1.StatefulSet{}
err = cl.Get(context.TODO(), req.NamespacedName, st)
// changing the Revision value to simulate the upgrade scenario completion
Expand Down Expand Up @@ -414,7 +414,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {
next.Status.SetUpgradingConditionTrue(" ", "1")
next.Status.TargetVersion = "0.2.7"
st := zk.MakeStatefulSet(z)
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, st).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, st).WithStatusSubresource(next).Build()
st = &appsv1.StatefulSet{}
err = cl.Get(context.TODO(), req.NamespacedName, st)
// changing the Revision value to simulate the upgrade scenario
Expand Down Expand Up @@ -443,6 +443,52 @@ var _ = Describe("ZookeeperCluster Controller", func() {
})
})

Context("Checking for healing of upgrade failed for zookeepercluster", func() {
var (
cl client.Client
err error
)

BeforeEach(func() {
z.WithDefaults()
z.Status.Init()
next := z.DeepCopy()
next.Status.SetErrorConditionTrue("UpgradeFailed", " ")
next.Status.TargetVersion = "0.2.7"
next.Status.CurrentVersion = "0.2.6"
next.Status.ReadyReplicas = 3
next.Spec.Replicas = 3
next.Spec.Image.Tag = "0.2.7"
st := zk.MakeStatefulSet(z)
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, st).Build()
st = &appsv1.StatefulSet{}
err = cl.Get(context.TODO(), req.NamespacedName, st)
// changing the Revision value to simulate the upgrade scenario
st.Status.CurrentRevision = "updateRevision"
st.Status.UpdateRevision = "updateRevision"
st.Status.UpdatedReplicas = 2
cl.Status().Update(context.TODO(), st)
r = &ZookeeperClusterReconciler{Client: cl, Scheme: s, ZkClient: mockZkClient}
res, err = r.Reconcile(context.TODO(), req)
// sleeping for 3 seconds
time.Sleep(3 * time.Second)
// checking if more than 2 secs have passed from the last update time
err = checkSyncTimeout(next, " ", 1, 2*time.Second)

})

It("checking update replicas", func() {
foundZookeeper := &v1beta1.ZookeeperCluster{}
_ = cl.Get(context.TODO(), req.NamespacedName, foundZookeeper)
condition := foundZookeeper.Status.CurrentVersion
Ω(condition).To(Equal("0.2.7"))
})

It("should not raise an error", func() {
Ω(err).To(BeNil())
})
})

Context("Upgrading with Targetversion empty", func() {
var (
cl client.Client
Expand All @@ -458,7 +504,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {
next.Status.TargetVersion = ""
next.Status.IsClusterInUpgradingState()
st := zk.MakeStatefulSet(z)
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, st).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, st).WithStatusSubresource(next).Build()
r = &ZookeeperClusterReconciler{Client: cl, Scheme: s, ZkClient: mockZkClient}
res, err = r.Reconcile(context.TODO(), req)
})
Expand All @@ -482,7 +528,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {
BeforeEach(func() {
z.WithDefaults()
z.Status.Init()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(z).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(z).WithStatusSubresource(z).Build()
r = &ZookeeperClusterReconciler{Client: cl, Scheme: s, ZkClient: mockZkClient}
req.NamespacedName.Namespace = "temp"
res, err = r.Reconcile(context.TODO(), req)
Expand All @@ -503,7 +549,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {
BeforeEach(func() {
z.WithDefaults()
z.Status.Init()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(z).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(z).WithStatusSubresource(z).Build()
r = &ZookeeperClusterReconciler{Client: cl, Scheme: s, ZkClient: mockZkClient}
res, err = r.Reconcile(context.TODO(), req)
})
Expand Down Expand Up @@ -576,7 +622,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {
next := z.DeepCopy()
next.Spec.Ports[0].ContainerPort = 2182
svc := zk.MakeClientService(z)
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, svc).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, svc).WithStatusSubresource(next).Build()
r = &ZookeeperClusterReconciler{Client: cl, Scheme: s, ZkClient: mockZkClient}
res, err = r.Reconcile(context.TODO(), req)
})
Expand All @@ -594,7 +640,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {
BeforeEach(func() {
z.WithDefaults()
z.Spec.Persistence = nil
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(z).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(z).WithStatusSubresource(z).Build()
r = &ZookeeperClusterReconciler{Client: cl, Scheme: s, ZkClient: mockZkClient}
res, err = r.Reconcile(context.TODO(), req)
err = r.reconcileFinalizers(z)
Expand All @@ -618,7 +664,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {
BeforeEach(func() {
z.WithDefaults()
z.Spec.Persistence = nil
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(z).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(z).WithStatusSubresource(z).Build()
})
It("should have 1 finalizer, should not raise an error", func() {
config.DisableFinalizer = false
Expand Down Expand Up @@ -693,7 +739,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {
next = z.DeepCopy()
next.Spec.TriggerRollingRestart = true
svc = zk.MakeClientService(z)
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, svc).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, svc).WithStatusSubresource(next).Build()
r = &ZookeeperClusterReconciler{Client: cl, Scheme: s, ZkClient: mockZkClient}
res, err = r.Reconcile(context.TODO(), req)
err = cl.Get(context.TODO(), req.NamespacedName, foundZk)
Expand All @@ -713,7 +759,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {

next.Spec.TriggerRollingRestart = false
svc = zk.MakeClientService(z)
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, svc).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, svc).WithStatusSubresource(next).Build()
r = &ZookeeperClusterReconciler{Client: cl, Scheme: s, ZkClient: mockZkClient}
res, err = r.Reconcile(context.TODO(), req)

Expand Down Expand Up @@ -751,7 +797,7 @@ var _ = Describe("ZookeeperCluster Controller", func() {
// update the crd instance to trigger rolling restart
next.Spec.TriggerRollingRestart = true
svc = zk.MakeClientService(z)
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, svc).Build()
cl = fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(next, svc).WithStatusSubresource(next).Build()
r = &ZookeeperClusterReconciler{Client: cl, Scheme: s, ZkClient: mockZkClient}
res, err = r.Reconcile(context.TODO(), req)
err = cl.Get(context.TODO(), req.NamespacedName, foundZk)
Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ COPY zu /zu
WORKDIR /zu
RUN ./gradlew --console=verbose --info shadowJar

FROM ${DOCKER_REGISTRY:+$DOCKER_REGISTRY/}zookeeper:3.7.1
FROM ${DOCKER_REGISTRY:+$DOCKER_REGISTRY/}zookeeper:3.7.2
COPY bin /usr/local/bin
RUN chmod +x /usr/local/bin/*
COPY --from=0 /zu/build/libs/zu.jar /opt/libs/
Expand Down
2 changes: 1 addition & 1 deletion docker/zu/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ repositories {

dependencies {
implementation(kotlin("stdlib"))
implementation("org.apache.zookeeper:zookeeper:3.7.1")
implementation("org.apache.zookeeper:zookeeper:3.7.2")
}

tasks.withType<ShadowJar>() {
Expand Down
Loading

0 comments on commit 99c9463

Please sign in to comment.