Skip to content

Commit 39f0c69

Browse files
authored
CHAOSPLT-68: Replace ddmark with go-validator (#944)
1 parent eada948 commit 39f0c69

File tree

157 files changed

+31073
-34
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

157 files changed

+31073
-34
lines changed

CONTRIBUTING.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,15 @@ export DATADOG_API_KEY=$(security find-generic-password -a ${USER} -s datadog_ap
219219

220220
- Go to Datadog you [test-services](https://app.datadoghq.com/ci/test-services?env=local&view=branches&paused=false)
221221

222+
## Adding new spec validation
223+
224+
We use [go-validator](https://github.com/go-playground/validator) to supplement the kubebuilder validation annotations on our resource Specs.
225+
Structs are tagged with `"chaos_validate:..."` to specify constraints on valid fields, such as `lte`, `gte`, `required`, etc.
226+
Error messages are customized in the translation functions in [validations.go](./api/v1beta1/validations.go). Most are self-explanatory
227+
but the go-validator docs will have more information. We want to especially call out the "dive" tag here. This is used on slice or map
228+
fields to tell go-validator that validation needs to be run on every element in the slice or map. Other nested structs will be validated
229+
by default. When using the "dive" tag, on a field, it _must_ be the final tag, or the others will be skipped.
230+
222231
## 3rd-party licenses
223232

224233
3rd-party references and licenses are kept in the [LICENSE-3rdparty.csv](LICENSE-3rdparty.csv) file. This file has been generated by the [tasks/thirdparty.py](tasks/thirdparty.py) script. If any vendor is updated, added or removed, this file must be updated as well.

LICENSE-3rdparty.csv

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ github.com/evanphx/json-patch/v5,github.com/evanphx/json-patch/v5,BSD-3-Clause
213213
github.com/evanphx/json-patch/v5,github.com/evanphx/json-patch/v5/internal/json,BSD-3-Clause
214214
github.com/felixge/httpsnoop,github.com/felixge/httpsnoop,MIT
215215
github.com/fsnotify/fsnotify,github.com/fsnotify/fsnotify,BSD-3-Clause
216+
github.com/gabriel-vasile/mimetype,github.com/gabriel-vasile/mimetype,MIT
217+
github.com/gabriel-vasile/mimetype,github.com/gabriel-vasile/mimetype/internal/charset,MIT
218+
github.com/gabriel-vasile/mimetype,github.com/gabriel-vasile/mimetype/internal/json,MIT
219+
github.com/gabriel-vasile/mimetype,github.com/gabriel-vasile/mimetype/internal/magic,MIT
216220
github.com/go-logr/logr,github.com/go-logr/logr,Apache-2.0
217221
github.com/go-logr/logr,github.com/go-logr/logr/funcr,Apache-2.0
218222
github.com/go-logr/logr,github.com/go-logr/logr/slogr,Apache-2.0
@@ -224,6 +228,11 @@ github.com/go-openapi/jsonpointer,github.com/go-openapi/jsonpointer,Apache-2.0
224228
github.com/go-openapi/jsonreference,github.com/go-openapi/jsonreference,Apache-2.0
225229
github.com/go-openapi/jsonreference,github.com/go-openapi/jsonreference/internal,Apache-2.0
226230
github.com/go-openapi/swag,github.com/go-openapi/swag,Apache-2.0
231+
github.com/go-playground/locales,github.com/go-playground/locales,MIT
232+
github.com/go-playground/locales,github.com/go-playground/locales/currency,MIT
233+
github.com/go-playground/locales,github.com/go-playground/locales/en,MIT
234+
github.com/go-playground/universal-translator,github.com/go-playground/universal-translator,MIT
235+
github.com/go-playground/validator/v10,github.com/go-playground/validator/v10,MIT
227236
github.com/go-task/slim-sprig,github.com/go-task/slim-sprig,MIT
228237
github.com/godbus/dbus/v5,github.com/godbus/dbus/v5,BSD-2-Clause
229238
github.com/gogo/googleapis,github.com/gogo/googleapis/google/rpc,Apache-2.0
@@ -281,6 +290,8 @@ github.com/klauspost/compress,github.com/klauspost/compress/internal/cpuinfo,Apa
281290
github.com/klauspost/compress,github.com/klauspost/compress/internal/snapref,Apache-2.0
282291
github.com/klauspost/compress,github.com/klauspost/compress/zstd,Apache-2.0
283292
github.com/klauspost/compress,github.com/klauspost/compress/zstd/internal/xxhash,Apache-2.0
293+
github.com/leodido/go-urn,github.com/leodido/go-urn,MIT
294+
github.com/leodido/go-urn,github.com/leodido/go-urn/scim/schema,MIT
284295
github.com/liggitt/tabwriter,github.com/liggitt/tabwriter,BSD-3-Clause
285296
github.com/lufia/plan9stats,github.com/lufia/plan9stats,BSD-3-Clause
286297
github.com/magiconair/properties,github.com/magiconair/properties,BSD-2-Clause
@@ -486,6 +497,7 @@ go.uber.org/zap,go.uber.org/zap/internal/ztest,MIT
486497
go.uber.org/zap,go.uber.org/zap/zapcore,MIT
487498
go.uber.org/zap,go.uber.org/zap/zaptest,MIT
488499
go.uber.org/zap,go.uber.org/zap/zaptest/observer,MIT
500+
golang.org/x/crypto,golang.org/x/crypto/sha3,BSD-3-Clause
489501
golang.org/x/exp,golang.org/x/exp/maps,BSD-3-Clause
490502
golang.org/x/mod,golang.org/x/mod/semver,BSD-3-Clause
491503
golang.org/x/net,golang.org/x/net/bpf,BSD-3-Clause
@@ -510,6 +522,7 @@ golang.org/x/oauth2,golang.org/x/oauth2,BSD-3-Clause
510522
golang.org/x/oauth2,golang.org/x/oauth2/internal,BSD-3-Clause
511523
golang.org/x/sync,golang.org/x/sync/errgroup,BSD-3-Clause
512524
golang.org/x/sync,golang.org/x/sync/semaphore,BSD-3-Clause
525+
golang.org/x/sys,golang.org/x/sys/cpu,BSD-3-Clause
513526
golang.org/x/sys,golang.org/x/sys/execabs,BSD-3-Clause
514527
golang.org/x/sys,golang.org/x/sys/plan9,BSD-3-Clause
515528
golang.org/x/sys,golang.org/x/sys/unix,BSD-3-Clause

api/v1beta1/disk_failure.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ import (
1717
type OpenatSyscallSpec struct {
1818
// Refer to this documentation: https://linux.die.net/man/2/open
1919
// +kubebuilder:validation:Enum=EACCES;EDQUOT;EEXIST;EFAULT;EFBIG;EINTR;EISDIR;ELOOP;EMFILE;ENAMETOOLONG;ENFILE;ENODEV;ENOENT;ENOMEM;ENOSPC;ENOTDIR;ENXIO;EOVERFLOW;EPERM;EROFS;ETXTBSY;EWOULDBLOCK
20-
ExitCode string `json:"exitCode"`
20+
ExitCode string `json:"exitCode" chaos_validate:"oneofci=EACCES EDQUOT EEXIST EFAULT EFBIG EINTR EISDIR ELOOP EMFILE ENAMETOOLONG ENFILE ENODEV ENOENT ENOMEM ENOSPC ENOTDIR ENXIO EOVERFLOW EPERM EROFS ETXTBSY EWOULDBLOCK"`
2121
}
2222

2323
// DiskFailureSpec represents a disk failure disruption
2424
type DiskFailureSpec struct {
2525
// +kubebuilder:validation:Required
26-
Paths []string `json:"paths"`
26+
Paths []string `json:"paths" chaos_validate:"required"`
2727
// +nullable
2828
OpenatSyscall *OpenatSyscallSpec `json:"openat,omitempty"`
2929
Probability string `json:"probability,omitempty"`

api/v1beta1/disk_pressure.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
type DiskPressureSpec struct {
1414
Path string `json:"path"`
1515
// +kubebuilder:validation:Required
16-
Throttling DiskPressureThrottlingSpec `json:"throttling"`
16+
Throttling DiskPressureThrottlingSpec `json:"throttling" chaos_validate:"required"`
1717
}
1818

1919
// DiskPressureThrottlingSpec represents a throttle on read and write disk operations

api/v1beta1/disruption_types.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import (
3737
// DisruptionSpec defines the desired state of Disruption
3838
type DisruptionSpec struct {
3939
// +kubebuilder:validation:Required
40-
Count *intstr.IntOrString `json:"count"` // number of pods to target in either integer form or percent form appended with a %
40+
Count *intstr.IntOrString `json:"count" chaos_validate:"required"` // number of pods to target in either integer form or percent form appended with a %
4141
// AllowDisruptedTargets allow pods with one or several other active disruptions, with disruption kinds that does not intersect
4242
// with this disruption kinds, to be returned as part of eligible targets for this disruption
4343
// - e.g. apply a CPU pressure and later, apply a container failure for a short duration
@@ -61,7 +61,7 @@ type DisruptionSpec struct {
6161
// Level defines what the disruption will target, either a pod or a node
6262
// +kubebuilder:default=pod
6363
// +kubebuilder:validation:Enum=pod;node
64-
Level chaostypes.DisruptionLevel `json:"level,omitempty"`
64+
Level chaostypes.DisruptionLevel `json:"level,omitempty" chaos_validate:"omitempty,oneofci=pod node"`
6565
Containers []string `json:"containers,omitempty"`
6666
// +nullable
6767
Network *NetworkDisruptionSpec `json:"network,omitempty"`
@@ -125,7 +125,7 @@ type Reporting struct {
125125
// +kubebuilder:validation:MaxLength=80
126126
// +kubebuilder:validation:Pattern=(^[a-z0-9-_]+$)|(^C[A-Z0-9]+$)
127127
// +kubebuilder:validation:Required
128-
SlackChannel string `json:"slackChannel,omitempty"`
128+
SlackChannel string `json:"slackChannel,omitempty" chaos_validate:"required"`
129129
// Purpose determines contextual informations about the disruption
130130
// a brief context to determines disruption goal
131131
// +kubebuilder:validation:MinLength=10
@@ -586,6 +586,10 @@ func (s DisruptionSpec) ValidateSelectorsOptional(requireSelectors bool) (retErr
586586
}
587587
}
588588

589+
if err := validateStructTags(s); err != nil {
590+
retErr = multierror.Append(retErr, err)
591+
}
592+
589593
return multierror.Prefix(retErr, "Spec:")
590594
}
591595

@@ -747,7 +751,7 @@ func (s DisruptionSpec) validateGlobalDisruptionScope(requireSelectors bool) (re
747751
}
748752
}
749753

750-
if s.GRPC != nil && s.Level != chaostypes.DisruptionLevelPod {
754+
if s.GRPC != nil && s.Level == chaostypes.DisruptionLevelNode {
751755
retErr = multierror.Append(retErr, errors.New("GRPC disruptions can only be applied at the pod level"))
752756
}
753757

api/v1beta1/grpc_disruption.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,22 @@ var ErrorMap = map[string]codes.Code{
4545
type GRPCDisruptionSpec struct {
4646
// +kubebuilder:validation:Minimum=1
4747
// +kubebuilder:validation:Maximum=65535
48-
Port int `json:"port"`
49-
Endpoints []EndpointAlteration `json:"endpoints"`
48+
Port int `json:"port" chaos_validate:"gte=1,lte=65535"`
49+
// +kubebuilder:validation:Required
50+
Endpoints []EndpointAlteration `json:"endpoints" chaos_validate:"required,dive"`
5051
}
5152

5253
// EndpointAlteration represents an endpoint to disrupt and the corresponding error to return
5354
type EndpointAlteration struct {
54-
TargetEndpoint string `json:"endpoint"`
55+
// +kubebuilder:validation:Required
56+
TargetEndpoint string `json:"endpoint" chaos_validate:"required"`
5557
// +kubebuilder:validation:Enum=OK;CANCELED;UNKNOWN;INVALID_ARGUMENT;DEADLINE_EXCEEDED;NOT_FOUND;ALREADY_EXISTS;PERMISSION_DENIED;RESOURCE_EXHAUSTED;FAILED_PRECONDITION;ABORTED;OUT_OF_RANGE;UNIMPLEMENTED;INTERNAL;UNAVAILABLE;DATA_LOSS;UNAUTHENTICATED
56-
ErrorToReturn string `json:"error,omitempty"`
58+
ErrorToReturn string `json:"error,omitempty" chaos_validate:"omitempty,oneofci=OK CANCELED UNKNOWN INVALID_ARGUMENT DEADLINE_EXCEEDED NOT_FOUND ALREADY_EXISTS PERMISSION_DENIED RESOURCE_EXHAUSTED FAILED_PRECONDITION ABORTED OUT_OF_RANGE UNIMPLEMENTED INTERNAL UNAVAILABLE DATA_LOSS UNAUTHENTICATED"`
5759
// +kubebuilder:validation:Enum={}
5860
OverrideToReturn string `json:"override,omitempty"`
5961
// +kubebuilder:validation:Minimum=0
6062
// +kubebuilder:validation:Maximum=100
61-
QueryPercent int `json:"queryPercent,omitempty"`
63+
QueryPercent int `json:"queryPercent,omitempty" chaos_validate:"omitempty,gte=0,lte=100"`
6264
}
6365

6466
// Validate validates that all alterations have either an error or override to return and at least 1% chance of occurring,

api/v1beta1/network_disruption.go

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -58,31 +58,31 @@ type HTTPPath string
5858
// NetworkDisruptionSpec represents a network disruption injection
5959
type NetworkDisruptionSpec struct {
6060
// +nullable
61-
Hosts []NetworkDisruptionHostSpec `json:"hosts,omitempty"`
61+
Hosts []NetworkDisruptionHostSpec `json:"hosts,omitempty" chaos_validate:"omitempty,dive"`
6262
// +nullable
63-
AllowedHosts []NetworkDisruptionHostSpec `json:"allowedHosts,omitempty"`
63+
AllowedHosts []NetworkDisruptionHostSpec `json:"allowedHosts,omitempty" chaos_validate:"omitempty,dive"`
6464
DisableDefaultAllowedHosts bool `json:"disableDefaultAllowedHosts,omitempty"`
6565
// +nullable
66-
Services []NetworkDisruptionServiceSpec `json:"services,omitempty"`
66+
Services []NetworkDisruptionServiceSpec `json:"services,omitempty" chaos_validate:"omitempty,dive"`
6767
// +nullable
6868
Cloud *NetworkDisruptionCloudSpec `json:"cloud,omitempty"`
6969
// +kubebuilder:validation:Minimum=0
7070
// +kubebuilder:validation:Maximum=100
71-
Drop int `json:"drop,omitempty"`
71+
Drop int `json:"drop,omitempty" chaos_validate:"omitempty,gte=0,lte=100"`
7272
// +kubebuilder:validation:Minimum=0
7373
// +kubebuilder:validation:Maximum=100
74-
Duplicate int `json:"duplicate,omitempty"`
74+
Duplicate int `json:"duplicate,omitempty" chaos_validate:"omitempty,gte=0,lte=100"`
7575
// +kubebuilder:validation:Minimum=0
7676
// +kubebuilder:validation:Maximum=100
77-
Corrupt int `json:"corrupt,omitempty"`
77+
Corrupt int `json:"corrupt,omitempty" chaos_validate:"omitempty,gte=0,lte=100"`
7878
// +kubebuilder:validation:Minimum=0
7979
// +kubebuilder:validation:Maximum=60000
80-
Delay uint `json:"delay,omitempty"`
80+
Delay uint `json:"delay,omitempty" chaos_validate:"omitempty,gte=0,lte=60000"`
8181
// +kubebuilder:validation:Minimum=0
8282
// +kubebuilder:validation:Maximum=100
83-
DelayJitter uint `json:"delayJitter,omitempty"`
83+
DelayJitter uint `json:"delayJitter,omitempty" chaos_validate:"omitempty,gte=0,lte=100"`
8484
// +kubebuilder:validation:Minimum=0
85-
BandwidthLimit int `json:"bandwidthLimit,omitempty"`
85+
BandwidthLimit int `json:"bandwidthLimit,omitempty" chaos_validate:"omitempty,gte=0"`
8686
// +nullable
8787
HTTP *NetworkHTTPFilters `json:"http,omitempty"`
8888
}
@@ -97,44 +97,44 @@ type NetworkDisruptionHostSpec struct {
9797
Host string `json:"host,omitempty"`
9898
// +kubebuilder:validation:Minimum=0
9999
// +kubebuilder:validation:Maximum=65535
100-
Port int `json:"port,omitempty"`
100+
Port int `json:"port,omitempty" chaos_validate:"omitempty,gte=0,lte=65535"`
101101
// +kubebuilder:validation:Enum=tcp;udp;""
102-
Protocol string `json:"protocol,omitempty"`
102+
Protocol string `json:"protocol,omitempty" chaos_validate:"omitempty,oneofci=udp tcp"`
103103
// +kubebuilder:validation:Enum=ingress;egress;""
104-
Flow string `json:"flow,omitempty"`
104+
Flow string `json:"flow,omitempty" chaos_validate:"omitempty,oneofci=ingress egress"`
105105
// +kubebuilder:validation:Enum=new;est;""
106-
ConnState string `json:"connState,omitempty"`
106+
ConnState string `json:"connState,omitempty" chaos_validate:"omitempty,oneofci=new est"`
107107
}
108108

109109
type NetworkDisruptionServiceSpec struct {
110110
Name string `json:"name"`
111111
Namespace string `json:"namespace"`
112112
// +optional
113-
Ports []NetworkDisruptionServicePortSpec `json:"ports,omitempty"`
113+
Ports []NetworkDisruptionServicePortSpec `json:"ports,omitempty" chaos_validate:"omitempty,dive"`
114114
}
115115

116116
type NetworkDisruptionServicePortSpec struct {
117117
Name string `json:"name,omitempty"`
118118
// +kubebuilder:validation:Minimum=0
119119
// +kubebuilder:validation:Maximum=65535
120-
Port int `json:"port,omitempty"`
120+
Port int `json:"port,omitempty" chaos_validate:"omitempty,gte=0,lte=65535"`
121121
}
122122

123123
type NetworkDisruptionCloudSpec struct {
124-
AWSServiceList *[]NetworkDisruptionCloudServiceSpec `json:"aws,omitempty"`
125-
GCPServiceList *[]NetworkDisruptionCloudServiceSpec `json:"gcp,omitempty"`
126-
DatadogServiceList *[]NetworkDisruptionCloudServiceSpec `json:"datadog,omitempty"`
124+
AWSServiceList *[]NetworkDisruptionCloudServiceSpec `json:"aws,omitempty" chaos_validate:"omitempty,dive"`
125+
GCPServiceList *[]NetworkDisruptionCloudServiceSpec `json:"gcp,omitempty" chaos_validate:"omitempty,dive"`
126+
DatadogServiceList *[]NetworkDisruptionCloudServiceSpec `json:"datadog,omitempty" chaos_validate:"omitempty,dive"`
127127
}
128128

129129
type NetworkDisruptionCloudServiceSpec struct {
130130
// +kubebuilder:validation:Required
131-
ServiceName string `json:"service"`
131+
ServiceName string `json:"service" chaos_validate:"required"`
132132
// +kubebuilder:validation:Enum=tcp;udp;""
133-
Protocol string `json:"protocol,omitempty"`
133+
Protocol string `json:"protocol,omitempty" chaos_validate:"omitempty,oneofci=tcp udp"`
134134
// +kubebuilder:validation:Enum=ingress;egress;""
135-
Flow string `json:"flow,omitempty"`
135+
Flow string `json:"flow,omitempty" chaos_validate:"omitempty,oneofci=ingress egress"`
136136
// +kubebuilder:validation:Enum=new;est;""
137-
ConnState string `json:"connState,omitempty"`
137+
ConnState string `json:"connState,omitempty" chaos_validate:"omitempty,oneofci=new est"`
138138
}
139139

140140
func (p HTTPPath) validate() error {

0 commit comments

Comments
 (0)