Skip to content

Commit

Permalink
Merge branch 'release/v1.2.0' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
jelemux authored and cesmarvin committed Jun 12, 2024
2 parents 0e36354 + 4bdb834 commit 9b07dba
Show file tree
Hide file tree
Showing 24 changed files with 734 additions and 113 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [v1.2.0] - 2024-06-12
### Added
- [#181] Handle dogu health states with a config map and provide dogus the volume mounts

### Changed
- [#182] Update dogu upgrade docs not to use doguctl state for handling upgrades

## [v1.1.0] - 2024-05-29
### Fixed
- [#171] Fix unnecessary creation of dogu PVCs.
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ RUN make compile-generic
FROM gcr.io/distroless/static:nonroot
LABEL maintainer="hello@cloudogu.com" \
NAME="k8s-dogu-operator" \
VERSION="1.1.0"
VERSION="1.2.0"

WORKDIR /
COPY --from=builder /workspace/target/k8s-dogu-operator .
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Set these to the desired values
ARTIFACT_ID=k8s-dogu-operator
VERSION=1.1.0
VERSION=1.2.0

IMAGE=cloudogu/${ARTIFACT_ID}:${VERSION}
GOTAG=1.22
Expand Down
21 changes: 16 additions & 5 deletions controllers/deploymentController.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ package controllers
import (
"context"
"fmt"
doguv1 "github.com/cloudogu/k8s-dogu-operator/api/v1"
"github.com/cloudogu/k8s-dogu-operator/controllers/health"
"github.com/cloudogu/k8s-dogu-operator/internal/cloudogu"
"github.com/cloudogu/k8s-dogu-operator/internal/thirdParty"
"github.com/cloudogu/k8s-registry-lib/dogu/local"
"github.com/go-logr/logr"
appsv1 "k8s.io/api/apps/v1"
metav1api "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"

doguv1 "github.com/cloudogu/k8s-dogu-operator/api/v1"
"github.com/cloudogu/k8s-dogu-operator/controllers/health"
"github.com/cloudogu/k8s-dogu-operator/internal/cloudogu"
)

const legacyDoguLabel = "dogu"
Expand All @@ -24,14 +24,16 @@ type DeploymentReconciler struct {
k8sClientSet thirdParty.ClientSet
availabilityChecker cloudogu.DeploymentAvailabilityChecker
doguHealthStatusUpdater cloudogu.DoguHealthStatusUpdater
localDoguRegistry local.LocalDoguRegistry
}

func NewDeploymentReconciler(k8sClientSet thirdParty.ClientSet, availabilityChecker *health.AvailabilityChecker,
doguHealthStatusUpdater cloudogu.DoguHealthStatusUpdater) *DeploymentReconciler {
doguHealthStatusUpdater cloudogu.DoguHealthStatusUpdater, localDoguRegistry *local.CombinedLocalDoguRegistry) *DeploymentReconciler {
return &DeploymentReconciler{
k8sClientSet: k8sClientSet,
availabilityChecker: availabilityChecker,
doguHealthStatusUpdater: doguHealthStatusUpdater,
localDoguRegistry: localDoguRegistry,
}
}

Expand Down Expand Up @@ -85,6 +87,15 @@ func hasDoguLabel(deployment client.Object) bool {

func (dr *DeploymentReconciler) updateDoguHealth(ctx context.Context, doguDeployment *appsv1.Deployment) error {
doguAvailable := dr.availabilityChecker.IsAvailable(doguDeployment)
doguJson, err := dr.localDoguRegistry.GetCurrent(ctx, doguDeployment.Name)
if err != nil {
return fmt.Errorf("failed to get current dogu json to update health state configMap: %w", err)
}
err = dr.doguHealthStatusUpdater.UpdateHealthConfigMap(ctx, doguDeployment, doguJson)
if err != nil {
return fmt.Errorf("failed to update health state configMap: %w", err)
}

log.FromContext(ctx).Info(fmt.Sprintf("dogu deployment %q is %s", doguDeployment.Name, (map[bool]string{true: "available", false: "unavailable"})[doguAvailable]))
return dr.doguHealthStatusUpdater.UpdateStatus(ctx,
types.NamespacedName{Name: doguDeployment.Name, Namespace: doguDeployment.Namespace},
Expand Down
107 changes: 105 additions & 2 deletions controllers/deploymentController_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package controllers

import (
cesmocks "github.com/cloudogu/cesapp-lib/registry/mocks"
"github.com/cloudogu/k8s-dogu-operator/controllers/health"
"github.com/cloudogu/k8s-dogu-operator/internal/cloudogu/mocks"
extMocks "github.com/cloudogu/k8s-dogu-operator/internal/thirdParty/mocks"
"github.com/cloudogu/k8s-registry-lib/dogu/local"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
Expand All @@ -22,12 +24,20 @@ import (
func TestNewDeploymentReconciler(t *testing.T) {
t.Run("should not be empty", func(t *testing.T) {
// given
cmClientMock := extMocks.NewConfigMapInterface(t)
coreV1Client := extMocks.NewCoreV1Interface(t)
coreV1Client.EXPECT().ConfigMaps(testNamespace).Return(cmClientMock)
clientSetMock := extMocks.NewClientSet(t)
clientSetMock.EXPECT().CoreV1().Return(coreV1Client)
availabilityCheckerMock := &health.AvailabilityChecker{}
healthStatusUpdaterMock := mocks.NewDoguHealthStatusUpdater(t)

CesRegistryMock := &cesmocks.Registry{}
CesRegistryMock.On("DoguRegistry").Return(extMocks.NewDoguRegistry(t))
localDoguRegistry := local.NewCombinedLocalDoguRegistry(clientSetMock.CoreV1().ConfigMaps(testNamespace), CesRegistryMock)

// when
actual := NewDeploymentReconciler(clientSetMock, availabilityCheckerMock, healthStatusUpdaterMock)
actual := NewDeploymentReconciler(clientSetMock, availabilityCheckerMock, healthStatusUpdaterMock, localDoguRegistry)

// then
assert.NotEmpty(t, actual)
Expand Down Expand Up @@ -158,7 +168,7 @@ func TestDeploymentReconciler_Reconcile(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, ctrl.Result{}, actual)
})
t.Run("should fail to update dogu health", func(t *testing.T) {
t.Run("should throw error if fails to get current dogu json", func(t *testing.T) {
// given
request := ctrl.Request{NamespacedName: types.NamespacedName{Name: "my-dogu", Namespace: testNamespace}}

Expand All @@ -179,13 +189,101 @@ func TestDeploymentReconciler_Reconcile(t *testing.T) {
deployAvailCheckMock := mocks.NewDeploymentAvailabilityChecker(t)
deployAvailCheckMock.EXPECT().IsAvailable(deployment).Return(true)

localDoguRegistry := extMocks.NewLocalDoguRegistry(t)
localDoguRegistry.EXPECT().GetCurrent(testCtx, "my-dogu").Return(nil, assert.AnError)

sut := &DeploymentReconciler{
k8sClientSet: clientSetMock,
availabilityChecker: deployAvailCheckMock,
localDoguRegistry: localDoguRegistry,
}

// when
actual, err := sut.Reconcile(testCtx, request)

// then
require.Error(t, err)
assert.ErrorIs(t, err, assert.AnError)
assert.ErrorContains(t, err, "failed to get current dogu json to update health state configMap")
assert.Equal(t, ctrl.Result{}, actual)
})
t.Run("should fail to update dogu health configmap", func(t *testing.T) {
// given
request := ctrl.Request{NamespacedName: types.NamespacedName{Name: "my-dogu", Namespace: testNamespace}}

deployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "my-dogu",
Labels: map[string]string{"dogu.name": "my-dogu", "dogu.version": "1.2.3"},
},
}

deployClientMock := extMocks.NewDeploymentInterface(t)
deployClientMock.EXPECT().Get(testCtx, "my-dogu", metav1.GetOptions{}).Return(deployment, nil)
appsV1Client := extMocks.NewAppsV1Interface(t)
appsV1Client.EXPECT().Deployments(testNamespace).Return(deployClientMock)
clientSetMock := extMocks.NewClientSet(t)
clientSetMock.EXPECT().AppsV1().Return(appsV1Client)

deployAvailCheckMock := mocks.NewDeploymentAvailabilityChecker(t)
deployAvailCheckMock.EXPECT().IsAvailable(deployment).Return(true)

localDoguRegistry := extMocks.NewLocalDoguRegistry(t)
localDoguRegistry.EXPECT().GetCurrent(testCtx, "my-dogu").Return(readDoguDescriptor(t, ldapDoguDescriptorBytes), nil)

doguHealthUpdaterMock := mocks.NewDoguHealthStatusUpdater(t)
doguHealthUpdaterMock.EXPECT().UpdateHealthConfigMap(testCtx, deployment, readDoguDescriptor(t, ldapDoguDescriptorBytes)).Return(assert.AnError)

sut := &DeploymentReconciler{
k8sClientSet: clientSetMock,
availabilityChecker: deployAvailCheckMock,
doguHealthStatusUpdater: doguHealthUpdaterMock,
localDoguRegistry: localDoguRegistry,
}

// when
actual, err := sut.Reconcile(testCtx, request)

// then
require.Error(t, err)
assert.ErrorIs(t, err, assert.AnError)
assert.ErrorContains(t, err, "failed to update health state configMap")
assert.ErrorContains(t, err, "failed to update dogu health for deployment \"test-namespace/my-dogu\"")
assert.Equal(t, ctrl.Result{}, actual)
})
t.Run("should fail to update dogu health status", func(t *testing.T) {
// given
request := ctrl.Request{NamespacedName: types.NamespacedName{Name: "my-dogu", Namespace: testNamespace}}

deployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "my-dogu",
Labels: map[string]string{"dogu.name": "my-dogu", "dogu.version": "1.2.3"},
},
}

deployClientMock := extMocks.NewDeploymentInterface(t)
deployClientMock.EXPECT().Get(testCtx, "my-dogu", metav1.GetOptions{}).Return(deployment, nil)
appsV1Client := extMocks.NewAppsV1Interface(t)
appsV1Client.EXPECT().Deployments(testNamespace).Return(deployClientMock)
clientSetMock := extMocks.NewClientSet(t)
clientSetMock.EXPECT().AppsV1().Return(appsV1Client)

deployAvailCheckMock := mocks.NewDeploymentAvailabilityChecker(t)
deployAvailCheckMock.EXPECT().IsAvailable(deployment).Return(true)

localDoguRegistry := extMocks.NewLocalDoguRegistry(t)
localDoguRegistry.EXPECT().GetCurrent(testCtx, "my-dogu").Return(readDoguDescriptor(t, ldapDoguDescriptorBytes), nil)

doguHealthUpdaterMock := mocks.NewDoguHealthStatusUpdater(t)
doguHealthUpdaterMock.EXPECT().UpdateHealthConfigMap(testCtx, deployment, readDoguDescriptor(t, ldapDoguDescriptorBytes)).Return(nil)
doguHealthUpdaterMock.EXPECT().UpdateStatus(testCtx, types.NamespacedName{Namespace: "", Name: "my-dogu"}, true).Return(assert.AnError)

sut := &DeploymentReconciler{
k8sClientSet: clientSetMock,
availabilityChecker: deployAvailCheckMock,
doguHealthStatusUpdater: doguHealthUpdaterMock,
localDoguRegistry: localDoguRegistry,
}

// when
Expand Down Expand Up @@ -218,13 +316,18 @@ func TestDeploymentReconciler_Reconcile(t *testing.T) {
deployAvailCheckMock := mocks.NewDeploymentAvailabilityChecker(t)
deployAvailCheckMock.EXPECT().IsAvailable(deployment).Return(false)

localDoguRegistry := extMocks.NewLocalDoguRegistry(t)
localDoguRegistry.EXPECT().GetCurrent(testCtx, "my-dogu").Return(readDoguDescriptor(t, ldapDoguDescriptorBytes), nil)

doguHealthUpdaterMock := mocks.NewDoguHealthStatusUpdater(t)
doguHealthUpdaterMock.EXPECT().UpdateHealthConfigMap(testCtx, deployment, readDoguDescriptor(t, ldapDoguDescriptorBytes)).Return(nil)
doguHealthUpdaterMock.EXPECT().UpdateStatus(testCtx, types.NamespacedName{Namespace: "", Name: "my-dogu"}, false).Return(nil)

sut := &DeploymentReconciler{
k8sClientSet: clientSetMock,
availabilityChecker: deployAvailCheckMock,
doguHealthStatusUpdater: doguHealthUpdaterMock,
localDoguRegistry: localDoguRegistry,
}

// when
Expand Down
36 changes: 35 additions & 1 deletion controllers/doguDeleteManager.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"
"fmt"
"github.com/cloudogu/k8s-dogu-operator/controllers/util"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
Expand Down Expand Up @@ -31,7 +33,13 @@ type doguDeleteManager struct {
}

// NewDoguDeleteManager creates a new instance of doguDeleteManager.
func NewDoguDeleteManager(client client.Client, operatorConfig *config.OperatorConfig, cesRegistry cesregistry.Registry, mgrSet *util.ManagerSet, recorder record.EventRecorder) *doguDeleteManager {
func NewDoguDeleteManager(
client client.Client,
operatorConfig *config.OperatorConfig,
cesRegistry cesregistry.Registry,
mgrSet *util.ManagerSet,
recorder record.EventRecorder,
) *doguDeleteManager {
return &doguDeleteManager{
client: client,
localDoguFetcher: mgrSet.LocalDoguFetcher,
Expand Down Expand Up @@ -74,6 +82,12 @@ func (m *doguDeleteManager) Delete(ctx context.Context, doguResource *k8sv1.Dogu
if err != nil {
logger.Error(err, "failed to remove exposed ports")
}

logger.Info("Remove health state out of ConfigMap")
err := m.DeleteDoguOutOfHealthConfigMap(ctx, doguResource)
if err != nil {
logger.Error(err, "failed to remove health state out of configMap")
}
}

logger.Info("Remove finalizer...")
Expand All @@ -86,3 +100,23 @@ func (m *doguDeleteManager) Delete(ctx context.Context, doguResource *k8sv1.Dogu

return nil
}

func (m *doguDeleteManager) DeleteDoguOutOfHealthConfigMap(ctx context.Context, dogu *k8sv1.Dogu) error {
namespace := dogu.Namespace
stateConfigMap := &corev1.ConfigMap{}
cmKey := types.NamespacedName{Namespace: namespace, Name: "k8s-dogu-operator-dogu-health"}
err := m.client.Get(ctx, cmKey, stateConfigMap, &client.GetOptions{})

newData := stateConfigMap.Data
if err != nil || newData == nil {
newData = make(map[string]string)
}
delete(newData, dogu.Name)

stateConfigMap.Data = newData

// Update the ConfigMap
//_, err = m.k8sClientSet.CoreV1().ConfigMaps(namespace).Update(ctx, stateConfigMap, metav1api.UpdateOptions{})
err = m.client.Update(ctx, stateConfigMap, &client.UpdateOptions{})
return err
}
12 changes: 12 additions & 0 deletions controllers/dogu_controller_int_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,18 @@ var _ = Describe("Dogu Upgrade Tests", func() {
err := k8sClient.Create(ctx, namespace)
Expect(err).NotTo(HaveOccurred())

By("Create dogu health state config map")
healthCM := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "k8s-dogu-operator-dogu-health",
Namespace: testNamespace,
},
}
_, err = k8sClientSet.CoreV1().ConfigMaps(testNamespace).Create(ctx, healthCM, metav1.CreateOptions{})
if err != nil {
panic(err)
}

By("Creating dogu resource")
installDoguCr(ctx, ldapCr)

Expand Down
Loading

0 comments on commit 9b07dba

Please sign in to comment.