/
validate_config.go
98 lines (85 loc) · 3.42 KB
/
validate_config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package controller
import (
"context"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/record"
"github.com/authzed/controller-idioms/handler"
"github.com/authzed/controller-idioms/hash"
"github.com/authzed/spicedb-operator/pkg/apis/authzed/v1alpha1"
"github.com/authzed/spicedb-operator/pkg/config"
)
const EventInvalidSpiceDBConfig = "InvalidSpiceDBConfig"
type ValidateConfigHandler struct {
recorder record.EventRecorder
patchStatus func(ctx context.Context, patch *v1alpha1.SpiceDBCluster) error
next handler.ContextHandler
}
func (c *ValidateConfigHandler) Handle(ctx context.Context) {
cluster := CtxCluster.MustValue(ctx)
secret := CtxSecret.Value(ctx)
operatorConfig := CtxOperatorConfig.MustValue(ctx)
validatedConfig, warning, err := config.NewConfig(cluster, operatorConfig, secret)
if err != nil {
failedCondition := v1alpha1.NewInvalidConfigCondition(CtxSecretHash.Value(ctx), err)
if existing := cluster.FindStatusCondition(v1alpha1.ConditionValidatingFailed); existing != nil && existing.Message == failedCondition.Message {
QueueOps.Done(ctx)
return
}
cluster.Status.ObservedGeneration = cluster.GetGeneration()
cluster.RemoveStatusCondition(v1alpha1.ConditionTypeValidating)
cluster.SetStatusCondition(failedCondition)
if err := c.patchStatus(ctx, cluster); err != nil {
QueueOps.RequeueAPIErr(ctx, err)
return
}
c.recorder.Eventf(cluster, corev1.EventTypeWarning, EventInvalidSpiceDBConfig, "invalid config: %v", err)
// if the config is invalid, there's no work to do until it has changed
QueueOps.Done(ctx)
return
}
var warningCondition *metav1.Condition
if warning != nil {
cond := v1alpha1.NewConfigWarningCondition(warning)
warningCondition = &cond
}
migrationHash := hash.SecureObject(validatedConfig.MigrationConfig)
ctx = CtxMigrationHash.WithValue(ctx, migrationHash)
computedStatus := v1alpha1.ClusterStatus{
ObservedGeneration: cluster.GetGeneration(),
TargetMigrationHash: migrationHash,
CurrentMigrationHash: cluster.Status.CurrentMigrationHash,
SecretHash: cluster.Status.SecretHash,
Image: validatedConfig.TargetSpiceDBImage,
Migration: validatedConfig.TargetMigration,
Phase: validatedConfig.TargetPhase,
CurrentVersion: validatedConfig.SpiceDBVersion,
Conditions: *cluster.GetStatusConditions(),
}
if version := validatedConfig.SpiceDBVersion; version != nil {
computedStatus.AvailableVersions, err = operatorConfig.UpdateGraph.AvailableVersions(validatedConfig.DatastoreEngine, *version)
if err != nil {
QueueOps.RequeueErr(ctx, err)
return
}
}
meta.RemoveStatusCondition(&computedStatus.Conditions, v1alpha1.ConditionValidatingFailed)
meta.RemoveStatusCondition(&computedStatus.Conditions, v1alpha1.ConditionTypeValidating)
if warningCondition != nil {
meta.SetStatusCondition(&computedStatus.Conditions, *warningCondition)
} else {
meta.RemoveStatusCondition(&computedStatus.Conditions, v1alpha1.ConditionTypeConfigWarnings)
}
// Remove invalid config status and set image and hash
if !cluster.Status.Equals(computedStatus) {
cluster.Status = computedStatus
if err := c.patchStatus(ctx, cluster); err != nil {
QueueOps.RequeueAPIErr(ctx, err)
return
}
}
ctx = CtxConfig.WithValue(ctx, validatedConfig)
ctx = CtxCluster.WithValue(ctx, cluster)
c.next.Handle(ctx)
}