forked from ydb-platform/ydb-kubernetes-operator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstorage_webhook.go
128 lines (104 loc) · 3.8 KB
/
storage_webhook.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package v1alpha1
import (
"fmt"
"gopkg.in/yaml.v2"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/strings/slices"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)
// log is for logging in this package.
var storagelog = logf.Log.WithName("storage-resource")
func (r *Storage) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
Complete()
}
//+kubebuilder:webhook:path=/mutate-ydb-tech-v1alpha1-storage,mutating=true,failurePolicy=fail,sideEffects=None,groups=ydb.tech,resources=storages,verbs=create;update,versions=v1alpha1,name=mutate-storage.ydb.tech,admissionReviewVersions=v1
var _ webhook.Defaulter = &Storage{}
// Default implements webhook.Defaulter so a webhook will be registered for the type
func (r *Storage) Default() {
storagelog.Info("default", "name", r.Name)
if r.Spec.Image.Name == "" {
if r.Spec.YDBVersion == "" {
r.Spec.Image.Name = fmt.Sprintf(ImagePathFormat, RegistryPath, DefaultTag)
} else {
r.Spec.Image.Name = fmt.Sprintf(ImagePathFormat, RegistryPath, r.Spec.YDBVersion)
}
}
if r.Spec.Image.PullPolicyName == nil {
policy := v1.PullIfNotPresent
r.Spec.Image.PullPolicyName = &policy
}
if r.Spec.Service.GRPC.TLSConfiguration == nil {
r.Spec.Service.GRPC.TLSConfiguration = &TLSConfiguration{Enabled: false}
}
if r.Spec.Service.Interconnect.TLSConfiguration == nil {
r.Spec.Service.Interconnect.TLSConfiguration = &TLSConfiguration{Enabled: false}
}
if r.Spec.Monitoring == nil {
r.Spec.Monitoring = &MonitoringOptions{
Enabled: false,
}
}
if r.Spec.Domain == "" {
r.Spec.Domain = "root" // FIXME
}
}
//+kubebuilder:webhook:path=/validate-ydb-tech-v1alpha1-storage,mutating=true,failurePolicy=fail,sideEffects=None,groups=ydb.tech,resources=storages,verbs=create;update,versions=v1alpha1,name=validate-storage.ydb.tech,admissionReviewVersions=v1
var _ webhook.Validator = &Storage{}
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *Storage) ValidateCreate() error {
storagelog.Info("validate create", "name", r.Name)
configuration := make(map[string]interface{})
err := yaml.Unmarshal([]byte(r.Spec.Configuration), &configuration)
if err != nil {
return fmt.Errorf("failed to parse Storage.spec.configuration, error: %w", err)
}
var nodesNumber int32
if configuration["hosts"] == nil {
nodesNumber = r.Spec.Nodes
} else {
hosts, ok := configuration["hosts"].([]interface{})
if !ok {
return fmt.Errorf("failed to parse Storage.spec.configuration, error: invalid hosts section")
}
nodesNumber = int32(len(hosts))
}
minNodesPerErasure := map[ErasureType]int32{
ErasureMirror3DC: 9,
ErasureBlock42: 8,
None: 1,
}
if nodesNumber < minNodesPerErasure[r.Spec.Erasure] {
return fmt.Errorf("erasure type %v requires at least %v storage nodes", r.Spec.Erasure, minNodesPerErasure[r.Spec.Erasure])
}
reservedSecretNames := []string{
"database_encryption",
"datastreams",
}
for _, secret := range r.Spec.Secrets {
if slices.Contains(reservedSecretNames, secret.Name) {
return fmt.Errorf("the secret name %s is reserved, use another one", secret.Name)
}
}
if r.Spec.Volumes != nil {
for _, volume := range r.Spec.Volumes {
if volume.HostPath == nil {
return fmt.Errorf("unsupported volume source, %v. Only hostPath is supported ", volume.VolumeSource)
}
}
}
return nil
}
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *Storage) ValidateUpdate(old runtime.Object) error {
storagelog.Info("validate update", "name", r.Name)
// TODO(user): fill in your validation logic upon object update.
return nil
}
func (r *Storage) ValidateDelete() error {
return nil
}