...
1
2
3
4
5
6
7
8
9
10
11
12
13
14 package v1alpha1
15
16 import (
17 "fmt"
18 "reflect"
19
20 "k8s.io/apimachinery/pkg/runtime"
21 "k8s.io/apimachinery/pkg/util/validation/field"
22 logf "sigs.k8s.io/controller-runtime/pkg/log"
23 "sigs.k8s.io/controller-runtime/pkg/webhook"
24 )
25
26
27 var awschaoslog = logf.Log.WithName("awschaos-resource")
28
29
30 var ErrCanNotUpdateChaos = fmt.Errorf("Cannot update chaos spec")
31
32
33
34 var _ webhook.Defaulter = &AWSChaos{}
35
36
37 func (in *AWSChaos) Default() {
38 awschaoslog.Info("default", "name", in.Name)
39 in.Spec.Default()
40 }
41
42 func (in *AWSChaosSpec) Default() {}
43
44
45
46 var _ webhook.Validator = &AWSChaos{}
47
48
49 func (in *AWSChaos) ValidateCreate() error {
50 awschaoslog.Info("validate create", "name", in.Name)
51 return in.Validate()
52 }
53
54
55 func (in *AWSChaos) ValidateUpdate(old runtime.Object) error {
56 awschaoslog.Info("validate update", "name", in.Name)
57 if !reflect.DeepEqual(in.Spec, old.(*AWSChaos).Spec) {
58 return ErrCanNotUpdateChaos
59 }
60 return in.Validate()
61 }
62
63
64 func (in *AWSChaos) ValidateDelete() error {
65 awschaoslog.Info("validate delete", "name", in.Name)
66
67
68 return nil
69 }
70
71
72 func (in *AWSChaos) Validate() error {
73 allErrs := in.Spec.Validate()
74
75 if len(allErrs) > 0 {
76 return fmt.Errorf(allErrs.ToAggregate().Error())
77 }
78 return nil
79 }
80
81 func (in *AWSChaosSpec) Validate() field.ErrorList {
82 specField := field.NewPath("spec")
83 allErrs := in.validateEbsVolume(specField.Child("volumeID"))
84 allErrs = append(allErrs, in.validateAction(specField)...)
85 allErrs = append(allErrs, validateDuration(in, specField)...)
86 allErrs = append(allErrs, in.validateDeviceName(specField.Child("deviceName"))...)
87 return allErrs
88 }
89
90
91 func (in *AWSChaosSpec) validateEbsVolume(containerField *field.Path) field.ErrorList {
92 allErrs := field.ErrorList{}
93 if in.Action == DetachVolume {
94 if in.EbsVolume == nil {
95 err := fmt.Errorf("the ID of EBS volume should not be empty on %s action", in.Action)
96 allErrs = append(allErrs, field.Invalid(containerField, in.EbsVolume, err.Error()))
97 }
98 }
99 return allErrs
100 }
101
102
103 func (in *AWSChaosSpec) validateDeviceName(containerField *field.Path) field.ErrorList {
104 allErrs := field.ErrorList{}
105 if in.Action == DetachVolume {
106 if in.DeviceName == nil {
107 err := fmt.Errorf("the name of device should not be empty on %s action", in.Action)
108 allErrs = append(allErrs, field.Invalid(containerField, in.DeviceName, err.Error()))
109 }
110 }
111 return allErrs
112 }
113
114
115 func (in *AWSChaosSpec) validateAction(spec *field.Path) field.ErrorList {
116 allErrs := field.ErrorList{}
117
118 switch in.Action {
119 case Ec2Stop, DetachVolume:
120 case Ec2Restart:
121 default:
122 err := fmt.Errorf("awschaos have unknown action type")
123 log.Error(err, "Wrong AWSChaos Action type")
124
125 actionField := spec.Child("action")
126 allErrs = append(allErrs, field.Invalid(actionField, in.Action, err.Error()))
127 }
128 return allErrs
129 }
130