Skip to content

Commit

Permalink
#221 use local dogu fetcher to update deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
jelemux committed Dec 20, 2024
1 parent 0d6ab29 commit f55accb
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 84 deletions.
29 changes: 15 additions & 14 deletions controllers/doguSecurityContextManager.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,43 +19,44 @@ const (
)

type doguSecurityContextManager struct {
resourceDoguFetcher resourceDoguFetcher
resourceUpserter resource.ResourceUpserter
securityValidator securityValidator
recorder eventRecorder
localDoguFetcher localDoguFetcher
resourceUpserter resource.ResourceUpserter
securityValidator securityValidator
recorder eventRecorder
}

func NewDoguSecurityContextManager(mgrSet *util.ManagerSet, eventRecorder record.EventRecorder) *doguSecurityContextManager {
return &doguSecurityContextManager{
resourceDoguFetcher: mgrSet.ResourceDoguFetcher,
resourceUpserter: mgrSet.ResourceUpserter,
securityValidator: mgrSet.SecurityValidator,
recorder: eventRecorder,
localDoguFetcher: mgrSet.LocalDoguFetcher,
resourceUpserter: mgrSet.ResourceUpserter,
securityValidator: mgrSet.SecurityValidator,
recorder: eventRecorder,
}
}

func (d doguSecurityContextManager) UpdateDeploymentWithSecurityContext(ctx context.Context, doguResource *k8sv2.Dogu) error {
logger := log.FromContext(ctx)

logger.Info("Fetching dogu...")
d.recorder.Event(doguResource, corev1.EventTypeNormal, SecurityContextChangeEventReason, "Fetching dogu...")
dogu, _, err := d.resourceDoguFetcher.FetchWithResource(ctx, doguResource)
logger.Info("Getting local dogu descriptor...")
d.recorder.Event(doguResource, corev1.EventTypeNormal, SecurityContextChangeEventReason, "Getting local dogu descriptor...")
dogu, err := d.localDoguFetcher.FetchInstalled(ctx, doguResource.GetSimpleDoguName())
if err != nil {
return fmt.Errorf("failed to fetch dogu %s: %w", doguResource.Spec.Name, err)
return fmt.Errorf("failed to get local descriptor for dogu %q: %w", doguResource.Name, err)
}

logger.Info("Validating dogu security...")
d.recorder.Event(doguResource, corev1.EventTypeNormal, SecurityContextChangeEventReason, "Validating dogu security...")
err = d.securityValidator.ValidateSecurity(dogu, doguResource)
if err != nil {
return err
return fmt.Errorf("validation of security context failed for dogu %q: %w", doguResource.Name, err)
}

logger.Info("Upserting deployment...")
d.recorder.Event(doguResource, corev1.EventTypeNormal, SecurityContextChangeEventReason, "Upserting deployment...")
_, err = d.resourceUpserter.UpsertDoguDeployment(ctx, doguResource, dogu, nil)
if err != nil {
return fmt.Errorf("failed to upsert deployment with security context: %w", err)
return fmt.Errorf("failed to upsert deployment with security context for dogu %q: %w", doguResource.Name, err)
}

return nil
}
181 changes: 111 additions & 70 deletions controllers/doguSecurityContextManager_test.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package controllers

import (
"errors"
"fmt"
"testing"

cescommons "github.com/cloudogu/ces-commons-lib/dogu"
"github.com/cloudogu/cesapp-lib/core"
k8sv2 "github.com/cloudogu/k8s-dogu-operator/v3/api/v2"
"github.com/cloudogu/k8s-dogu-operator/v3/controllers/resource"
"github.com/cloudogu/k8s-dogu-operator/v3/controllers/util"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/apps/v1"
"testing"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestNewDoguSecurityContextManager(t *testing.T) {
Expand All @@ -29,98 +32,136 @@ func TestNewDoguSecurityContextManager(t *testing.T) {

func Test_doguSecurityContextManager_UpdateDeploymentWithSecurityContext(t *testing.T) {
// TODO all test cases have to be completed
doguResource := &k8sv2.Dogu{
ObjectMeta: metav1.ObjectMeta{Name: "ldap"},
Spec: k8sv2.DoguSpec{Name: "official/ldap"},
}
doguDescriptor := &core.Dogu{Name: "official/ldap"}
tests := []struct {
name string
resourceDoguFetcherFn func(t *testing.T) resourceDoguFetcher
resourceUpserterFn func(t *testing.T) resource.ResourceUpserter
doguResource *k8sv2.Dogu
wantErr assert.ErrorAssertionFunc
name string
localDoguFetcherFn func(t *testing.T) localDoguFetcher
resourceUpserterFn func(t *testing.T) resourceUpserter
recorderFn func(t *testing.T) eventRecorder
securityValidatorFn func(t *testing.T) securityValidator
wantErr assert.ErrorAssertionFunc
}{
{
name: "failed to fetch dogu",
resourceDoguFetcherFn: func(t *testing.T) resourceDoguFetcher {
doguResource := &k8sv2.Dogu{
Spec: k8sv2.DoguSpec{
Name: "ldap",
},
}
mockDoguFetcher := newMockResourceDoguFetcher(t)
mockDoguFetcher.EXPECT().FetchWithResource(testCtx, doguResource).Return(nil, nil, errors.New("failed to get development dogu map:"))
name: "should fail to get local dogu descriptor",
localDoguFetcherFn: func(t *testing.T) localDoguFetcher {
mockDoguFetcher := newMockLocalDoguFetcher(t)
mockDoguFetcher.EXPECT().FetchInstalled(testCtx, cescommons.SimpleName("ldap")).Return(nil, assert.AnError)
return mockDoguFetcher
},
resourceUpserterFn: func(t *testing.T) resource.ResourceUpserter {
recorderFn: func(t *testing.T) eventRecorder {
mockEventRecorder := newMockEventRecorder(t)
mockEventRecorder.EXPECT().Event(doguResource, "Normal", "SecurityContextChange", "Getting local dogu descriptor...")
return mockEventRecorder
},
securityValidatorFn: func(t *testing.T) securityValidator {
mockSecurityValidator := newMockSecurityValidator(t)
return mockSecurityValidator
},
resourceUpserterFn: func(t *testing.T) resourceUpserter {
mockResourceUpserter := newMockResourceUpserter(t)
return mockResourceUpserter
},
doguResource: &k8sv2.Dogu{
Spec: k8sv2.DoguSpec{
Name: "ldap",
},
},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
return assert.ErrorContains(t, err, "failed to fetch dogu ldap", i)
return assert.ErrorIs(t, err, assert.AnError) &&
assert.ErrorContains(t, err, "failed to get local descriptor for dogu \"ldap\"", i)
},
},

{
name: "failed to upsert dogu deployment",
resourceDoguFetcherFn: func(t *testing.T) resourceDoguFetcher {
doguResource := &k8sv2.Dogu{
Spec: k8sv2.DoguSpec{
Name: "ldap",
},
}
dogu := &core.Dogu{
Name: "ldap",
}
mockDoguFetcher := newMockResourceDoguFetcher(t)
mockDoguFetcher.EXPECT().FetchWithResource(testCtx, doguResource).Return(dogu, nil, nil)
name: "should fail when validating security",
localDoguFetcherFn: func(t *testing.T) localDoguFetcher {
mockDoguFetcher := newMockLocalDoguFetcher(t)
mockDoguFetcher.EXPECT().FetchInstalled(testCtx, cescommons.SimpleName("ldap")).Return(doguDescriptor, nil)
return mockDoguFetcher
},
resourceUpserterFn: func(t *testing.T) resource.ResourceUpserter {
/*
TODO
doguResource := &k8sv2.Dogu{
Spec: k8sv2.DoguSpec{
Name: "ldap",
},
}
dogu := &core.Dogu{
Name: "ldap",
}
mockResourceUpserter.EXPECT().UpsertDoguDeployment(testCtx, doguResource, dogu, mock.AnythingOfType("func(*v1.Deployment)")).Return(nil, errors.New("failed to upsert deployment with security context"))
*/
doguResource := &k8sv2.Dogu{
Spec: k8sv2.DoguSpec{
Name: "ldap",
},
}
dogu := &core.Dogu{
Name: "ldap",
}
recorderFn: func(t *testing.T) eventRecorder {
mockEventRecorder := newMockEventRecorder(t)
mockEventRecorder.EXPECT().Event(doguResource, "Normal", "SecurityContextChange", "Getting local dogu descriptor...")
mockEventRecorder.EXPECT().Event(doguResource, "Normal", "SecurityContextChange", "Validating dogu security...")
return mockEventRecorder
},
securityValidatorFn: func(t *testing.T) securityValidator {
mockSecurityValidator := newMockSecurityValidator(t)
mockSecurityValidator.EXPECT().ValidateSecurity(doguDescriptor, doguResource).Return(assert.AnError)
return mockSecurityValidator
},
resourceUpserterFn: func(t *testing.T) resourceUpserter {
mockResourceUpserter := newMockResourceUpserter(t)

fn := (func(*v1.Deployment))(nil)
mockResourceUpserter.On("UpsertDoguDeployment", testCtx, doguResource, dogu, fn).Return(nil, errors.New("failed to upsert deployment with security context"))
return mockResourceUpserter
},
doguResource: &k8sv2.Dogu{
Spec: k8sv2.DoguSpec{
Name: "ldap",
},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
return assert.ErrorIs(t, err, assert.AnError) &&
assert.ErrorContains(t, err, "validation of security context failed for dogu \"ldap\"", i)
},
},
{
name: "should fail to upsert deployment",
localDoguFetcherFn: func(t *testing.T) localDoguFetcher {
mockDoguFetcher := newMockLocalDoguFetcher(t)
mockDoguFetcher.EXPECT().FetchInstalled(testCtx, cescommons.SimpleName("ldap")).Return(doguDescriptor, nil)
return mockDoguFetcher
},
recorderFn: func(t *testing.T) eventRecorder {
mockEventRecorder := newMockEventRecorder(t)
mockEventRecorder.EXPECT().Event(doguResource, "Normal", "SecurityContextChange", "Getting local dogu descriptor...")
mockEventRecorder.EXPECT().Event(doguResource, "Normal", "SecurityContextChange", "Validating dogu security...")
mockEventRecorder.EXPECT().Event(doguResource, "Normal", "SecurityContextChange", "Upserting deployment...")
return mockEventRecorder
},
securityValidatorFn: func(t *testing.T) securityValidator {
mockSecurityValidator := newMockSecurityValidator(t)
mockSecurityValidator.EXPECT().ValidateSecurity(doguDescriptor, doguResource).Return(nil)
return mockSecurityValidator
},
resourceUpserterFn: func(t *testing.T) resourceUpserter {
mockResourceUpserter := newMockResourceUpserter(t)
mockResourceUpserter.EXPECT().UpsertDoguDeployment(testCtx, doguResource, doguDescriptor, mock.AnythingOfType("func(*v1.Deployment)")).Return(nil, assert.AnError)
return mockResourceUpserter
},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
return assert.ErrorContains(t, err, "failed to fetch dogu ldap", i)
return assert.ErrorIs(t, err, assert.AnError) &&
assert.ErrorContains(t, err, "failed to upsert deployment with security context for dogu \"ldap\"", i)
},
},
{
name: "should succeed",
localDoguFetcherFn: func(t *testing.T) localDoguFetcher {
mockDoguFetcher := newMockLocalDoguFetcher(t)
mockDoguFetcher.EXPECT().FetchInstalled(testCtx, cescommons.SimpleName("ldap")).Return(doguDescriptor, nil)
return mockDoguFetcher
},
recorderFn: func(t *testing.T) eventRecorder {
mockEventRecorder := newMockEventRecorder(t)
mockEventRecorder.EXPECT().Event(doguResource, "Normal", "SecurityContextChange", "Getting local dogu descriptor...")
mockEventRecorder.EXPECT().Event(doguResource, "Normal", "SecurityContextChange", "Validating dogu security...")
mockEventRecorder.EXPECT().Event(doguResource, "Normal", "SecurityContextChange", "Upserting deployment...")
return mockEventRecorder
},
securityValidatorFn: func(t *testing.T) securityValidator {
mockSecurityValidator := newMockSecurityValidator(t)
mockSecurityValidator.EXPECT().ValidateSecurity(doguDescriptor, doguResource).Return(nil)
return mockSecurityValidator
},
resourceUpserterFn: func(t *testing.T) resourceUpserter {
mockResourceUpserter := newMockResourceUpserter(t)
mockResourceUpserter.EXPECT().UpsertDoguDeployment(testCtx, doguResource, doguDescriptor, mock.AnythingOfType("func(*v1.Deployment)")).Return(nil, nil)
return mockResourceUpserter
},
wantErr: assert.NoError,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
d := doguSecurityContextManager{
resourceDoguFetcher: tt.resourceDoguFetcherFn(t),
resourceUpserter: tt.resourceUpserterFn(t),
localDoguFetcher: tt.localDoguFetcherFn(t),
resourceUpserter: tt.resourceUpserterFn(t),
securityValidator: tt.securityValidatorFn(t),
recorder: tt.recorderFn(t),
}
tt.wantErr(t, d.UpdateDeploymentWithSecurityContext(testCtx, tt.doguResource), fmt.Sprintf("UpdateDeploymentWithSecurityContext(%v, %v)", testCtx, tt.doguResource))
tt.wantErr(t, d.UpdateDeploymentWithSecurityContext(testCtx, doguResource), fmt.Sprintf("UpdateDeploymentWithSecurityContext(%v, %v)", testCtx, doguResource))
})
}
}

0 comments on commit f55accb

Please sign in to comment.