...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package v1alpha1
17
18 import (
19 "fmt"
20 "net/url"
21 "reflect"
22 "strconv"
23 "strings"
24
25 "github.com/pkg/errors"
26 "k8s.io/apimachinery/pkg/util/validation/field"
27
28 "github.com/chaos-mesh/chaos-mesh/api/genericwebhook"
29 )
30
31 func (in *StatusCheckSpec) Default(root interface{}, field *reflect.StructField) {
32 if in.Mode == "" {
33 in.Mode = StatusCheckSynchronous
34 }
35 }
36
37 func (in *StatusCheckSpec) Validate(root interface{}, path *field.Path) field.ErrorList {
38 allErrs := field.ErrorList{}
39
40 if in.Type == TypeHTTP {
41 if in.EmbedStatusCheck == nil || in.EmbedStatusCheck.HTTPStatusCheck == nil {
42 allErrs = append(allErrs, field.Invalid(path.Child("http"), nil, "the detail of http status check is required"))
43 }
44 } else {
45 allErrs = append(allErrs, field.Invalid(path.Child("type"), in.Type, fmt.Sprintf("unrecognized type: %s", in.Type)))
46 }
47
48 return allErrs
49 }
50
51 func (in *HTTPStatusCheck) Validate(root interface{}, path *field.Path) field.ErrorList {
52 allErrs := field.ErrorList{}
53 if in.RequestUrl == "" {
54 allErrs = append(allErrs, field.Invalid(path.Child("url"), in.RequestUrl, "request url is required"))
55 return allErrs
56 }
57
58 if _, err := url.ParseRequestURI(in.RequestUrl); err != nil {
59 allErrs = append(allErrs, field.Invalid(path.Child("url"), in.RequestUrl, "invalid http request url"))
60 }
61 return allErrs
62 }
63
64 type StatusCode string
65
66 func (in *StatusCode) Validate(root interface{}, path *field.Path) field.ErrorList {
67 packError := func(err error) field.ErrorList {
68 return field.ErrorList{
69 field.Invalid(path, in, fmt.Sprintf("incorrect status code format: %s", err.Error())),
70 }
71 }
72
73 codeStr := string(*in)
74 if codeStr == "" {
75 return field.ErrorList{
76 field.Invalid(path, in, "status code is required"),
77 }
78 }
79
80 if code, err := strconv.Atoi(codeStr); err == nil {
81 if !validateHTTPStatusCode(code) {
82 return packError(errors.New("invalid status code"))
83 }
84 } else {
85 index := strings.Index(codeStr, "-")
86 if index == -1 {
87 return packError(errors.New("not a single number or a range"))
88 }
89
90 validateRange := func(codeStr string) error {
91 code, err := strconv.Atoi(codeStr)
92 if err != nil {
93 return err
94 }
95 if !validateHTTPStatusCode(code) {
96 return errors.Errorf("invalid status code range, code: %d", code)
97 }
98 return nil
99 }
100 start := codeStr[:index]
101 end := codeStr[index+1:]
102 if err := validateRange(start); err != nil {
103 return packError(err)
104 }
105 if err := validateRange(end); err != nil {
106 return packError(err)
107 }
108 }
109 return nil
110 }
111
112 func validateHTTPStatusCode(code int) bool {
113 return code > 0 && code < 1000
114 }
115
116 func init() {
117 genericwebhook.Register("StatusCode", reflect.PtrTo(reflect.TypeOf(StatusCode(""))))
118 }
119