Skip to content

Commit

Permalink
Implement wait for Gardener shoot be ready after configuring Audit Log
Browse files Browse the repository at this point in the history
  • Loading branch information
mvshao committed Sep 4, 2024
1 parent 2cdd73a commit f750a36
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 22 deletions.
2 changes: 1 addition & 1 deletion internal/auditlogging/auditlogging.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func (al *AuditLog) Enable(ctx context.Context, shoot *gardener.Shoot) (bool, er
}
}

return true, nil
return annotated, nil
}

func ApplyAuditLogConfig(shoot *gardener.Shoot, auditConfigFromFile map[string]map[string]AuditLogData, providerType string) (bool, error) {
Expand Down
29 changes: 20 additions & 9 deletions internal/controller/runtime/fsm/runtime_fsm_configure_auditlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,32 @@ func sFnConfigureAuditLog(ctx context.Context, m *fsm, s *systemState) (stateFn,

if wasAuditLogEnabled {
m.log.Info("Audit Log configured for shoot: " + s.shoot.Name)
s.instance.UpdateStateReady(
s.instance.UpdateStatePending(
imv1.ConditionTypeAuditLogConfigured,
imv1.ConditionReasonAuditLogConfigured,
"Audit Log configured",
"Unknown",
"Waiting for Gardener shoot to be Ready state after configuration of the Audit Logs",
)

return updateStatusAndStop()
return updateStatusAndRequeueAfter(gardenerRequeueDuration)
}

m.log.Error(err, "Failed to configure Audit Log")
s.instance.UpdateStatePending(
if err != nil {
m.log.Error(err, "Failed to configure Audit Log")
s.instance.UpdateStatePending(
imv1.ConditionTypeAuditLogConfigured,
imv1.ConditionReasonAuditLogError,
"False",
err.Error(),
)
return updateStatusAndRequeueAfter(gardenerRequeueDuration)
}

s.instance.UpdateStateReady(
imv1.ConditionTypeAuditLogConfigured,
imv1.ConditionReasonAuditLogError,
"False",
err.Error(),
imv1.ConditionReasonAuditLogConfigured,
"Audit Log configured successfully",
)
return updateStatusAndRequeueAfter(gardenerRequeueDuration)

return updateStatusAndStop()
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
)

func TestAuditLogState(t *testing.T) {
t.Run("Should set status on Runtime CR when Audit Log was successfully configured", func(t *testing.T) {
t.Run("Should set status on Runtime CR when Audit Log configuration was changed and Shoot enters into reconciliation", func(t *testing.T) {
// given
ctx := context.Background()
auditLog := &mocks.AuditLogging{}
Expand All @@ -27,9 +27,9 @@ func TestAuditLogState(t *testing.T) {
expectedRuntimeConditions := []metav1.Condition{
{
Type: string(v1.ConditionTypeAuditLogConfigured),
Status: "True",
Status: "Unknown",
Reason: string(v1.ConditionReasonAuditLogConfigured),
Message: "Audit Log configured",
Message: "Waiting for Gardener shoot to be Ready state after configuration of the Audit Logs",
},
}

Expand All @@ -42,6 +42,41 @@ func TestAuditLogState(t *testing.T) {
// set the time to its zero value for comparison purposes
systemState.instance.Status.Conditions[0].LastTransitionTime = metav1.Time{}

// then
auditLog.AssertExpectations(t)
require.Contains(t, stateFn.name(), "sFnUpdateStatus")
assert.Equal(t, v1.RuntimeStatePending, string(systemState.instance.Status.State))
assert.Equal(t, expectedRuntimeConditions, systemState.instance.Status.Conditions)
})

t.Run("Should set status on Runtime CR when Shoot is in Succeeded state after configuring Audit Log", func(t *testing.T) {
// given
ctx := context.Background()
auditLog := &mocks.AuditLogging{}
shoot := shootForTest()
instance := runtimeForTest()
systemState := &systemState{
instance: instance,
shoot: shoot,
}
expectedRuntimeConditions := []metav1.Condition{
{
Type: string(v1.ConditionTypeAuditLogConfigured),
Status: "True",
Reason: string(v1.ConditionReasonAuditLogConfigured),
Message: "Audit Log configured successfully",
},
}

auditLog.On("Enable", ctx, shoot).Return(false, nil).Once()

// when
fsm := &fsm{AuditLogging: auditLog}
stateFn, _, _ := sFnConfigureAuditLog(ctx, fsm, systemState)

// set the time to its zero value for comparison purposes
systemState.instance.Status.Conditions[0].LastTransitionTime = metav1.Time{}

// then
auditLog.AssertExpectations(t)
require.Contains(t, stateFn.name(), "sFnUpdateStatus")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ func sFnWaitForShootReconcile(_ context.Context, m *fsm, s *systemState) (stateF
return ensureStatusConditionIsSetAndContinue(
&s.instance,
imv1.ConditionTypeRuntimeProvisioned,
imv1.ConditionReasonConfigurationCompleted,
imv1.ConditionReasonAuditLogConfigured,
"Runtime processing completed successfully",
sFnApplyClusterRoleBindings)
sFnConfigureAuditLog)
}

m.log.Info("Update did not processed, exiting with no retry")
Expand Down
2 changes: 1 addition & 1 deletion internal/controller/runtime/runtime_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ var _ = Describe("Runtime Controller", func() {
return false
}

if !runtime.IsConditionSet(imv1.ConditionTypeRuntimeProvisioned, imv1.ConditionReasonConfigurationCompleted) {
if !runtime.IsConditionSet(imv1.ConditionTypeRuntimeProvisioned, imv1.ConditionReasonAuditLogConfigured) {
return false
}

Expand Down
82 changes: 77 additions & 5 deletions internal/controller/runtime/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ package runtime

import (
"context"
"encoding/json"
"github.com/kyma-project/infrastructure-manager/internal/auditlogging"
v1 "k8s.io/api/autoscaling/v1"
v12 "k8s.io/api/core/v1"
"path/filepath"
"testing"
"time"
Expand Down Expand Up @@ -140,14 +144,14 @@ var _ = AfterSuite(func() {
func setupGardenerTestClientForProvisioning() {
baseShoot := getBaseShootForTestingSequence()
shoots := fixShootsSequenceForProvisioning(&baseShoot)
seeds := fixSeedsSequence()
seeds := fixSeedsSequenceForProvisioning()
setupGardenerClientWithSequence(shoots, seeds)
}

func setupGardenerTestClientForUpdate() {
baseShoot := getBaseShootForTestingSequence()
shoots := fixShootsSequenceForUpdate(&baseShoot)
seeds := fixSeedsSequence()
seeds := fixSeedsSequenceForUpdate()
setupGardenerClientWithSequence(shoots, seeds)
}

Expand Down Expand Up @@ -205,14 +209,24 @@ func fixShootsSequenceForProvisioning(shoot *gardener_api.Shoot) []*gardener_api

readyShoot.Status.LastOperation.State = gardener_api.LastOperationStateSucceeded

processingShootAfterAuditLogs := readyShoot.DeepCopy()
addAuditLogConfigToShoot(processingShootAfterAuditLogs)
processingShootAfterAuditLogs.Status.LastOperation.Type = gardener_api.LastOperationTypeReconcile
processingShootAfterAuditLogs.Status.LastOperation.State = gardener_api.LastOperationStateProcessing

readyShootAfterAuditLogs := processingShootAfterAuditLogs.DeepCopy()
readyShootAfterAuditLogs.Status.LastOperation.State = gardener_api.LastOperationStateSucceeded

// processedShoot := processingShoot.DeepCopy() // will add specific data later

return []*gardener_api.Shoot{missingShoot, missingShoot, missingShoot, initialisedShoot, dnsShoot, pendingShoot, processingShoot, readyShoot, readyShoot, readyShoot, readyShoot, readyShoot}
return []*gardener_api.Shoot{missingShoot, missingShoot, missingShoot, initialisedShoot, dnsShoot, pendingShoot, processingShoot, readyShoot, readyShoot, readyShoot, readyShoot, readyShoot, processingShootAfterAuditLogs, readyShootAfterAuditLogs, readyShootAfterAuditLogs}
}

func fixShootsSequenceForUpdate(shoot *gardener_api.Shoot) []*gardener_api.Shoot {
pendingShoot := shoot.DeepCopy()

addAuditLogConfigToShoot(pendingShoot)

pendingShoot.Spec.DNS = &gardener_api.DNS{
Domain: ptr.To("test.domain"),
}
Expand All @@ -236,7 +250,7 @@ func fixShootsSequenceForUpdate(shoot *gardener_api.Shoot) []*gardener_api.Shoot

// processedShoot := processingShoot.DeepCopy() // will add specific data later

return []*gardener_api.Shoot{pendingShoot, processingShoot, readyShoot, readyShoot, readyShoot}
return []*gardener_api.Shoot{pendingShoot, processingShoot, readyShoot, readyShoot}
}

func fixShootsSequenceForDelete(shoot *gardener_api.Shoot) []*gardener_api.Shoot {
Expand Down Expand Up @@ -270,7 +284,22 @@ func fixShootsSequenceForDelete(shoot *gardener_api.Shoot) []*gardener_api.Shoot
return []*gardener_api.Shoot{currentShoot, currentShoot, currentShoot, currentShoot, pendingDeleteShoot, nil}
}

func fixSeedsSequence() []*gardener_api.Seed {
func fixSeedsSequenceForProvisioning() []*gardener_api.Seed {
seed := &gardener_api.Seed{
ObjectMeta: metav1.ObjectMeta{
Name: "test-seed",
},
Spec: gardener_api.SeedSpec{
Provider: gardener_api.SeedProvider{
Type: "aws",
},
},
}

return []*gardener_api.Seed{seed, seed}
}

func fixSeedsSequenceForUpdate() []*gardener_api.Seed {
seed := &gardener_api.Seed{
ObjectMeta: metav1.ObjectMeta{
Name: "test-seed",
Expand Down Expand Up @@ -325,3 +354,46 @@ func fixConverterConfigForTests() gardener_shoot.ConverterConfig {
},
}
}

func addAuditLogConfigToShoot(shoot *gardener_api.Shoot) {
shoot.Spec.Kubernetes.KubeAPIServer.AuditConfig = &gardener_api.AuditConfig{
AuditPolicy: &gardener_api.AuditPolicy{
ConfigMapRef: &v12.ObjectReference{Name: "policy-config-map"},
},
}

shoot.Spec.Resources = append(shoot.Spec.Resources, gardener_api.NamedResourceReference{
Name: "auditlog-credentials",
ResourceRef: v1.CrossVersionObjectReference{
Kind: "Secret",
Name: "auditlog-secret",
APIVersion: "v1",
},
})

const (
extensionKind = "AuditlogConfig"
extensionVersion = "service.auditlog.extensions.gardener.cloud/v1alpha1"
extensionType = "standard"
)

shoot.Spec.Extensions = append(shoot.Spec.Extensions, gardener_api.Extension{
Type: "shoot-auditlog-service",
})

ext := &shoot.Spec.Extensions[len(shoot.Spec.Extensions)-1]

cfg := auditlogging.AuditlogExtensionConfig{
TypeMeta: metav1.TypeMeta{
Kind: extensionKind,
APIVersion: extensionVersion,
},
Type: extensionType,
TenantID: "79c64792-9c1e-4c1b-9941-ef7560dd3eae",
ServiceURL: "https://auditlog.example.com:3001",
SecretReferenceName: "auditlog-credentials",
}

ext.ProviderConfig = &runtime.RawExtension{}
ext.ProviderConfig.Raw, _ = json.Marshal(cfg)
}
2 changes: 1 addition & 1 deletion internal/controller/runtime/testdata/auditConfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"eu-central-1": {
"tenantID": "79c64792-9c1e-4c1b-9941-ef7560dd3eae",
"serviceURL": "https://auditlog.example.com:3001",
"secretName": "auditlog-secret2"
"secretName": "auditlog-secret"
}
}
}

0 comments on commit f750a36

Please sign in to comment.