...

Source file src/github.com/chaos-mesh/chaos-mesh/api/v1alpha1/statuscheck_webhook.go

Documentation: github.com/chaos-mesh/chaos-mesh/api/v1alpha1

     1  // Copyright Chaos Mesh Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    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