...

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

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

     1  // Copyright 2020 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  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package v1alpha1
    15  
    16  import (
    17  	"fmt"
    18  	"reflect"
    19  	"strconv"
    20  
    21  	"k8s.io/apimachinery/pkg/runtime"
    22  	"k8s.io/apimachinery/pkg/util/validation/field"
    23  	logf "sigs.k8s.io/controller-runtime/pkg/log"
    24  	"sigs.k8s.io/controller-runtime/pkg/webhook"
    25  )
    26  
    27  // log is for logging in this package.
    28  var jvmchaoslog = logf.Log.WithName("jvmchaos-resource")
    29  
    30  // +kubebuilder:webhook:path=/mutate-chaos-mesh-org-v1alpha1-jvmchaos,mutating=true,failurePolicy=fail,groups=chaos-mesh.org,resources=jvmchaos,verbs=create;update,versions=v1alpha1,name=mjvmchaos.kb.io
    31  
    32  var _ webhook.Defaulter = &JVMChaos{}
    33  
    34  // Default implements webhook.Defaulter so a webhook will be registered for the type
    35  func (in *JVMChaos) Default() {
    36  	jvmchaoslog.Info("default", "name", in.Name)
    37  
    38  	in.Spec.Selector.DefaultNamespace(in.GetNamespace())
    39  	in.Spec.Default()
    40  }
    41  
    42  func (in *JVMChaosSpec) Default() {
    43  
    44  }
    45  
    46  // +kubebuilder:webhook:verbs=create;update,path=/validate-chaos-mesh-org-v1alpha1-jvmchaos,mutating=false,failurePolicy=fail,groups=chaos-mesh.org,resources=jvmchaos,versions=v1alpha1,name=vjvmchaos.kb.io
    47  
    48  var _ webhook.Validator = &JVMChaos{}
    49  
    50  // ValidateCreate implements webhook.Validator so a webhook will be registered for the type
    51  func (in *JVMChaos) ValidateCreate() error {
    52  	jvmchaoslog.Info("validate create", "name", in.Name)
    53  
    54  	return in.Validate()
    55  }
    56  
    57  // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
    58  func (in *JVMChaos) ValidateUpdate(old runtime.Object) error {
    59  	jvmchaoslog.Info("validate update", "name", in.Name)
    60  	if !reflect.DeepEqual(in.Spec, old.(*JVMChaos).Spec) {
    61  		return ErrCanNotUpdateChaos
    62  	}
    63  	return in.Validate()
    64  }
    65  
    66  // ValidateDelete implements webhook.Validator so a webhook will be registered for the type
    67  func (in *JVMChaos) ValidateDelete() error {
    68  	jvmchaoslog.Info("validate delete", "name", in.Name)
    69  
    70  	// Nothing to do?
    71  	return nil
    72  }
    73  
    74  // Validate validates chaos object
    75  func (in *JVMChaos) Validate() error {
    76  	allErrs := in.Spec.Validate()
    77  	if len(allErrs) > 0 {
    78  		return fmt.Errorf(allErrs.ToAggregate().Error())
    79  	}
    80  
    81  	return nil
    82  }
    83  
    84  func (in *JVMChaosSpec) Validate() field.ErrorList {
    85  	specField := field.NewPath("spec")
    86  	allErrs := in.validateJvmChaos(specField)
    87  	allErrs = append(allErrs, validateDuration(in, specField)...)
    88  	return allErrs
    89  }
    90  
    91  func (in *JVMChaosSpec) validateJvmChaos(spec *field.Path) field.ErrorList {
    92  	allErrs := field.ErrorList{}
    93  	targetField := spec.Child("target")
    94  	actionField := spec.Child("action")
    95  	flagsField := spec.Child("flags")
    96  	matcherField := spec.Child("matcher")
    97  	if actions, ok := JvmSpec[in.Target]; ok {
    98  		if actionPR, actionOK := actions[in.Action]; actionOK {
    99  			if actionPR.Flags != nil {
   100  				allErrs = append(allErrs, in.validateParameterRules(in.Flags, actionPR.Flags, flagsField, targetField, actionField)...)
   101  			}
   102  
   103  			if actionPR.Matchers != nil {
   104  				allErrs = append(allErrs, in.validateParameterRules(in.Matchers, actionPR.Matchers, matcherField, targetField, actionField)...)
   105  			}
   106  
   107  		} else {
   108  			supportActions := make([]JVMChaosAction, 0)
   109  			for k := range actions {
   110  				supportActions = append(supportActions, k)
   111  			}
   112  
   113  			notSupportedError := field.NotSupported(actionField, in.Action, toString(supportActions))
   114  			errorMsg := fmt.Sprintf("target: %s does not match action: %s, action detail error: %s",
   115  				in.Target, in.Action, notSupportedError)
   116  			allErrs = append(allErrs, field.Invalid(targetField, in.Target, errorMsg))
   117  		}
   118  	} else {
   119  		allErrs = append(allErrs, field.Invalid(targetField, in.Target, "unknown JVM chaos target"))
   120  	}
   121  
   122  	return allErrs
   123  }
   124  
   125  func toString(actions []JVMChaosAction) []string {
   126  	ret := make([]string, 0)
   127  	for _, act := range actions {
   128  		ret = append(ret, string(act))
   129  	}
   130  	return ret
   131  }
   132  
   133  func (in *JVMChaosSpec) validateParameterRules(parameters map[string]string, rules []ParameterRules, parent *field.Path, target *field.Path, action *field.Path) field.ErrorList {
   134  	allErrs := field.ErrorList{}
   135  	for _, rule := range rules {
   136  		innerField := parent.Child(rule.Name)
   137  
   138  		var value = ""
   139  		var exist = false
   140  		if parameters != nil {
   141  			value, exist = parameters[rule.Name]
   142  		}
   143  		if rule.Required && !exist {
   144  			errorMsg := fmt.Sprintf("with %s: %s, %s: %s", target, in.Target, action, in.Action)
   145  			allErrs = append(allErrs, field.Required(innerField, errorMsg))
   146  		}
   147  
   148  		if exist && rule.Required && rule.ParameterType == StringType {
   149  			if len(value) == 0 {
   150  				errorMsg := fmt.Sprintf("%s:%s cannot be empty", innerField, value)
   151  				allErrs = append(allErrs, field.Invalid(innerField, value, errorMsg))
   152  			}
   153  		}
   154  
   155  		if exist && rule.ParameterType == IntType {
   156  			_, err := strconv.Atoi(value)
   157  			if err != nil {
   158  				errorMsg := fmt.Sprintf("%s:%s cannot parse as Int", innerField, value)
   159  				allErrs = append(allErrs, field.Invalid(innerField, value, errorMsg))
   160  			}
   161  		}
   162  
   163  		if exist && rule.ParameterType == BoolType {
   164  			_, err := strconv.ParseBool(value)
   165  			if err != nil {
   166  				errorMsg := fmt.Sprintf("%s:%s cannot parse as boolean", innerField, value)
   167  				allErrs = append(allErrs, field.Invalid(innerField, value, errorMsg))
   168  			}
   169  		}
   170  	}
   171  	return allErrs
   172  }
   173  
   174  // +kubebuilder:object:generate=false
   175  
   176  // JvmSpec from chaosblade-jvm-spec.yaml
   177  // chaosblade-jvm-spec.yaml file generated by
   178  // https://github.com/chaosblade-io/chaosblade-exec-jvm/blob/master/chaosblade-exec-service/src/main/java/com/alibaba/chaosblade/exec/service/build/SpecMain.java
   179  var JvmSpec = map[JVMChaosTarget]map[JVMChaosAction]ActionParameterRules{
   180  	SERVLET: {
   181  		JVMDelayAction: ActionParameterRules{
   182  			Flags: []ParameterRules{
   183  				{Name: "time", ParameterType: IntType, Required: true},
   184  				{Name: "offset", ParameterType: IntType},
   185  			},
   186  			Matchers: []ParameterRules{
   187  				{Name: "effect-count", ParameterType: IntType},
   188  				{Name: "effect-percent", ParameterType: IntType},
   189  				{Name: "method"},
   190  				{Name: "querystring"},
   191  				{Name: "requestpath"},
   192  			},
   193  		},
   194  		JVMExceptionAction: ActionParameterRules{
   195  			Flags: []ParameterRules{
   196  				{Name: "exception", Required: true},
   197  				{Name: "exception-message"},
   198  			},
   199  			Matchers: []ParameterRules{
   200  				{Name: "effect-count", ParameterType: IntType},
   201  				{Name: "effect-percent", ParameterType: IntType},
   202  				{Name: "method"},
   203  				{Name: "querystring"},
   204  				{Name: "requestpath"},
   205  			},
   206  		},
   207  	},
   208  	PSQL: {
   209  		JVMDelayAction: ActionParameterRules{
   210  			Flags: []ParameterRules{
   211  				{Name: "time", ParameterType: IntType, Required: true},
   212  				{Name: "offset", ParameterType: IntType},
   213  			},
   214  			Matchers: []ParameterRules{
   215  				{Name: "effect-count", ParameterType: IntType},
   216  				{Name: "effect-percent", ParameterType: IntType},
   217  				{Name: "sqltype"},
   218  				{Name: "database"},
   219  				{Name: "port", ParameterType: IntType},
   220  				{Name: "host"},
   221  				{Name: "table"},
   222  			},
   223  		},
   224  		JVMExceptionAction: ActionParameterRules{
   225  			Flags: []ParameterRules{
   226  				{Name: "exception", Required: true},
   227  				{Name: "exception-message"},
   228  			},
   229  			Matchers: []ParameterRules{
   230  				{Name: "effect-count", ParameterType: IntType},
   231  				{Name: "effect-percent", ParameterType: IntType},
   232  				{Name: "sqltype"},
   233  				{Name: "database"},
   234  				{Name: "port", ParameterType: IntType},
   235  				{Name: "host"},
   236  				{Name: "table"},
   237  			},
   238  		},
   239  	},
   240  	MYSQL: {
   241  		JVMDelayAction: ActionParameterRules{
   242  			Flags: []ParameterRules{
   243  				{Name: "time", ParameterType: IntType, Required: true},
   244  				{Name: "offset", ParameterType: IntType},
   245  			},
   246  			Matchers: []ParameterRules{
   247  				{Name: "effect-count", ParameterType: IntType},
   248  				{Name: "effect-percent", ParameterType: IntType},
   249  				{Name: "sqltype"},
   250  				{Name: "database"},
   251  				{Name: "port", ParameterType: IntType},
   252  				{Name: "host"},
   253  				{Name: "table"},
   254  			},
   255  		},
   256  		JVMExceptionAction: ActionParameterRules{
   257  			Flags: []ParameterRules{
   258  				{Name: "exception", Required: true},
   259  				{Name: "exception-message"},
   260  			},
   261  			Matchers: []ParameterRules{
   262  				{Name: "effect-count", ParameterType: IntType},
   263  				{Name: "effect-percent", ParameterType: IntType},
   264  				{Name: "sqltype"},
   265  				{Name: "database"},
   266  				{Name: "port", ParameterType: IntType},
   267  				{Name: "host"},
   268  				{Name: "table"},
   269  			},
   270  		},
   271  	},
   272  	JEDIS: {
   273  		JVMDelayAction: ActionParameterRules{
   274  			Flags: []ParameterRules{
   275  				{Name: "time", ParameterType: IntType, Required: true},
   276  				{Name: "offset", ParameterType: IntType},
   277  			},
   278  			Matchers: []ParameterRules{
   279  				{Name: "effect-count", ParameterType: IntType},
   280  				{Name: "effect-percent", ParameterType: IntType},
   281  				{Name: "cmd"},
   282  				{Name: "key"},
   283  			},
   284  		},
   285  		JVMExceptionAction: ActionParameterRules{
   286  			Flags: []ParameterRules{
   287  				{Name: "exception", Required: true},
   288  				{Name: "exception-message"},
   289  			},
   290  			Matchers: []ParameterRules{
   291  				{Name: "effect-count", ParameterType: IntType},
   292  				{Name: "effect-percent", ParameterType: IntType},
   293  				{Name: "cmd"},
   294  				{Name: "key"},
   295  			},
   296  		},
   297  	},
   298  	HTTP: {
   299  		JVMDelayAction: ActionParameterRules{
   300  			Flags: []ParameterRules{
   301  				{Name: "time", ParameterType: IntType, Required: true},
   302  				{Name: "offset", ParameterType: IntType},
   303  			},
   304  			Matchers: []ParameterRules{
   305  				{Name: "effect-count", ParameterType: IntType},
   306  				{Name: "effect-percent", ParameterType: IntType},
   307  				{Name: "httpclient4", ParameterType: BoolType},
   308  				{Name: "rest", ParameterType: BoolType},
   309  				{Name: "httpclient3", ParameterType: BoolType},
   310  				{Name: "okhttp3", ParameterType: BoolType},
   311  				{Name: "uri", Required: true},
   312  			},
   313  		},
   314  		JVMExceptionAction: ActionParameterRules{
   315  			Flags: []ParameterRules{
   316  				{Name: "exception", Required: true},
   317  				{Name: "exception-message"},
   318  			},
   319  			Matchers: []ParameterRules{
   320  				{Name: "effect-count", ParameterType: IntType},
   321  				{Name: "effect-percent", ParameterType: IntType},
   322  				{Name: "httpclient4", ParameterType: BoolType},
   323  				{Name: "rest", ParameterType: BoolType},
   324  				{Name: "httpclient3", ParameterType: BoolType},
   325  				{Name: "okhttp3", ParameterType: BoolType},
   326  				{Name: "uri", Required: true},
   327  			},
   328  		},
   329  	},
   330  	RABBITMQ: {
   331  		JVMDelayAction: ActionParameterRules{
   332  			Flags: []ParameterRules{
   333  				{Name: "time", ParameterType: IntType, Required: true},
   334  				{Name: "offset", ParameterType: IntType},
   335  			},
   336  			Matchers: []ParameterRules{
   337  				{Name: "effect-count", ParameterType: IntType},
   338  				{Name: "effect-percent", ParameterType: IntType},
   339  				{Name: "routingkey"},
   340  				{Name: "producer", ParameterType: BoolType},
   341  				{Name: "topic"},
   342  				{Name: "exchange"},
   343  				{Name: "consumer", ParameterType: BoolType},
   344  			},
   345  		},
   346  		JVMExceptionAction: ActionParameterRules{
   347  			Flags: []ParameterRules{
   348  				{Name: "exception", Required: true},
   349  				{Name: "exception-message"},
   350  			},
   351  			Matchers: []ParameterRules{
   352  				{Name: "effect-count", ParameterType: IntType},
   353  				{Name: "effect-percent", ParameterType: IntType},
   354  				{Name: "routingkey"},
   355  				{Name: "producer", ParameterType: BoolType},
   356  				{Name: "topic"},
   357  				{Name: "exchange"},
   358  				{Name: "consumer", ParameterType: BoolType},
   359  			},
   360  		},
   361  	},
   362  	TARS: {
   363  		JVMDelayAction: ActionParameterRules{
   364  			Flags: []ParameterRules{
   365  				{Name: "time", ParameterType: IntType, Required: true},
   366  				{Name: "offset", ParameterType: IntType},
   367  			},
   368  			Matchers: []ParameterRules{
   369  				{Name: "effect-count", ParameterType: IntType},
   370  				{Name: "effect-percent", ParameterType: IntType},
   371  				{Name: "servant", ParameterType: BoolType},
   372  				{Name: "functionname"},
   373  				{Name: "client", ParameterType: BoolType},
   374  				{Name: "servantname", Required: true},
   375  			},
   376  		},
   377  		JVMExceptionAction: ActionParameterRules{
   378  			Flags: []ParameterRules{
   379  				{Name: "exception", Required: true},
   380  				{Name: "exception-message"},
   381  			},
   382  			Matchers: []ParameterRules{
   383  				{Name: "effect-count", ParameterType: IntType},
   384  				{Name: "effect-percent", ParameterType: IntType},
   385  				{Name: "servant", ParameterType: BoolType},
   386  				{Name: "functionname"},
   387  				{Name: "client", ParameterType: BoolType},
   388  				{Name: "servantname", Required: true},
   389  			},
   390  		},
   391  	},
   392  	DUBBO: {
   393  		JVMDelayAction: ActionParameterRules{
   394  			Flags: []ParameterRules{
   395  				{Name: "time", ParameterType: IntType, Required: true},
   396  				{Name: "offset", ParameterType: IntType},
   397  			},
   398  			Matchers: []ParameterRules{
   399  				{Name: "effect-count", ParameterType: IntType},
   400  				{Name: "effect-percent", ParameterType: IntType},
   401  				{Name: "appname"},
   402  				{Name: "provider", ParameterType: BoolType},
   403  				{Name: "service"},
   404  				{Name: "version"},
   405  				{Name: "consumer", ParameterType: BoolType},
   406  				{Name: "methodname"},
   407  				{Name: "group"},
   408  			},
   409  		},
   410  		JVMExceptionAction: ActionParameterRules{
   411  			Flags: []ParameterRules{
   412  				{Name: "exception", Required: true},
   413  				{Name: "exception-message"},
   414  			},
   415  			Matchers: []ParameterRules{
   416  				{Name: "effect-count", ParameterType: IntType},
   417  				{Name: "effect-percent", ParameterType: IntType},
   418  				{Name: "appname"},
   419  				{Name: "provider", ParameterType: BoolType},
   420  				{Name: "service"},
   421  				{Name: "version"},
   422  				{Name: "consumer", ParameterType: BoolType},
   423  				{Name: "methodname"},
   424  				{Name: "group"},
   425  			},
   426  		},
   427  		JVMThreadPoolFullAction: ActionParameterRules{
   428  			Matchers: []ParameterRules{
   429  				{Name: "effect-count", ParameterType: IntType},
   430  				{Name: "effect-percent", ParameterType: IntType},
   431  				{Name: "provider", ParameterType: BoolType},
   432  			},
   433  		},
   434  	},
   435  	JVM: {
   436  		JVMDelayAction: ActionParameterRules{
   437  			Flags: []ParameterRules{
   438  				{Name: "time", ParameterType: IntType, Required: true},
   439  				{Name: "offset", ParameterType: IntType},
   440  			},
   441  			Matchers: []ParameterRules{
   442  				{Name: "effect-count", ParameterType: IntType},
   443  				{Name: "effect-percent", ParameterType: IntType},
   444  				{Name: "classname", Required: true},
   445  				{Name: "after", ParameterType: BoolType},
   446  				{Name: "methodname", Required: true},
   447  			},
   448  		},
   449  		JVMExceptionAction: ActionParameterRules{
   450  			Flags: []ParameterRules{
   451  				{Name: "exception", Required: true},
   452  				{Name: "exception-message"},
   453  			},
   454  			Matchers: []ParameterRules{
   455  				{Name: "effect-count", ParameterType: IntType},
   456  				{Name: "effect-percent", ParameterType: IntType},
   457  				{Name: "classname", Required: true},
   458  				{Name: "after", ParameterType: BoolType},
   459  				{Name: "methodname", Required: true},
   460  			},
   461  		},
   462  		JVMCodeCacheFillingAction: ActionParameterRules{},
   463  		JVMCpuFullloadAction: ActionParameterRules{
   464  			Flags: []ParameterRules{
   465  				{Name: "cpu-count", ParameterType: IntType},
   466  			},
   467  		},
   468  		JVMThrowDeclaredExceptionAction: ActionParameterRules{
   469  			Matchers: []ParameterRules{
   470  				{Name: "effect-count", ParameterType: IntType},
   471  				{Name: "effect-percent", ParameterType: IntType},
   472  				{Name: "classname", Required: true},
   473  				{Name: "after", ParameterType: BoolType},
   474  				{Name: "methodname", Required: true},
   475  			},
   476  		},
   477  		JVMReturnAction: ActionParameterRules{
   478  			Flags: []ParameterRules{
   479  				{Name: "value", Required: true},
   480  			},
   481  			Matchers: []ParameterRules{
   482  				{Name: "effect-count", ParameterType: IntType},
   483  				{Name: "effect-percent", ParameterType: IntType},
   484  				{Name: "classname", Required: true},
   485  				{Name: "after", ParameterType: BoolType},
   486  				{Name: "methodname", Required: true},
   487  			},
   488  		},
   489  		JVMScriptAction: ActionParameterRules{
   490  			Flags: []ParameterRules{
   491  				{Name: "script-file"},
   492  				{Name: "script-type"},
   493  				{Name: "script-content"},
   494  				{Name: "script-name"},
   495  				{Name: "external-jar"},
   496  				{Name: "external-jar-path"},
   497  			},
   498  			Matchers: []ParameterRules{
   499  				{Name: "effect-count", ParameterType: IntType},
   500  				{Name: "effect-percent", ParameterType: IntType},
   501  				{Name: "classname", Required: true},
   502  				{Name: "after", ParameterType: BoolType},
   503  				{Name: "methodname", Required: true},
   504  			},
   505  		},
   506  		JVMOOMAction: ActionParameterRules{
   507  			Flags: []ParameterRules{
   508  				{Name: "area", Required: true},
   509  				{Name: "wild-mode", ParameterType: BoolType},
   510  				{Name: "interval", ParameterType: IntType},
   511  				{Name: "block", ParameterType: IntType},
   512  			},
   513  		},
   514  	},
   515  	DRUID: {
   516  		JVMConnectionPoolFullAction: ActionParameterRules{
   517  			Matchers: []ParameterRules{
   518  				{Name: "effect-count", ParameterType: IntType},
   519  				{Name: "effect-percent", ParameterType: IntType},
   520  			},
   521  		},
   522  	},
   523  	REDISSON: {
   524  		JVMDelayAction: ActionParameterRules{
   525  			Flags: []ParameterRules{
   526  				{Name: "time", ParameterType: IntType, Required: true},
   527  				{Name: "offset", ParameterType: IntType},
   528  			},
   529  			Matchers: []ParameterRules{
   530  				{Name: "effect-count", ParameterType: IntType},
   531  				{Name: "effect-percent", ParameterType: IntType},
   532  				{Name: "cmd"},
   533  				{Name: "key"},
   534  			},
   535  		},
   536  		JVMExceptionAction: ActionParameterRules{
   537  			Flags: []ParameterRules{
   538  				{Name: "exception", Required: true},
   539  				{Name: "exception-message"},
   540  			},
   541  			Matchers: []ParameterRules{
   542  				{Name: "effect-count", ParameterType: IntType},
   543  				{Name: "effect-percent", ParameterType: IntType},
   544  				{Name: "cmd"},
   545  				{Name: "key"},
   546  			},
   547  		},
   548  	},
   549  	ROCKETMQ: {
   550  		JVMDelayAction: ActionParameterRules{
   551  			Flags: []ParameterRules{
   552  				{Name: "time", ParameterType: IntType, Required: true},
   553  				{Name: "offset", ParameterType: IntType},
   554  			},
   555  			Matchers: []ParameterRules{
   556  				{Name: "effect-count", ParameterType: IntType},
   557  				{Name: "effect-percent", ParameterType: IntType},
   558  				{Name: "producerGroup"},
   559  				{Name: "producer"},
   560  				{Name: "topic", Required: true},
   561  				{Name: "consumerGroup"},
   562  			},
   563  		},
   564  		JVMExceptionAction: ActionParameterRules{
   565  			Flags: []ParameterRules{
   566  				{Name: "exception", Required: true},
   567  				{Name: "exception-message"},
   568  			},
   569  			Matchers: []ParameterRules{
   570  				{Name: "effect-count", ParameterType: IntType},
   571  				{Name: "effect-percent", ParameterType: IntType},
   572  				{Name: "producerGroup"},
   573  				{Name: "producer"},
   574  				{Name: "topic", Required: true},
   575  				{Name: "consumerGroup"},
   576  			},
   577  		},
   578  	},
   579  	MONGODB: {
   580  		JVMDelayAction: ActionParameterRules{
   581  			Flags: []ParameterRules{
   582  				{Name: "time", ParameterType: IntType, Required: true},
   583  				{Name: "offset", ParameterType: IntType},
   584  			},
   585  			Matchers: []ParameterRules{
   586  				{Name: "effect-count", ParameterType: IntType},
   587  				{Name: "effect-percent", ParameterType: IntType},
   588  				{Name: "sqltype"},
   589  				{Name: "database"},
   590  				{Name: "false"},
   591  			},
   592  		},
   593  		JVMExceptionAction: ActionParameterRules{
   594  			Flags: []ParameterRules{
   595  				{Name: "exception", Required: true},
   596  				{Name: "exception-message"},
   597  			},
   598  			Matchers: []ParameterRules{
   599  				{Name: "effect-count", ParameterType: IntType},
   600  				{Name: "effect-percent", ParameterType: IntType},
   601  				{Name: "sqltype"},
   602  				{Name: "database"},
   603  				{Name: "false"},
   604  			},
   605  		},
   606  	},
   607  }
   608  
   609  // ActionParameterRules defines the parameter validation rules for action
   610  type ActionParameterRules struct {
   611  	// Flags represents the parameter validation rules for flags
   612  	Flags []ParameterRules
   613  
   614  	// Matchers represents the parameter validation rules for Matcher
   615  	Matchers []ParameterRules
   616  }
   617  
   618  // ParameterType defines the parameter type
   619  type ParameterType string
   620  
   621  const (
   622  	// IntType a int type parameter
   623  	IntType ParameterType = "int"
   624  
   625  	// BoolType a boolean type parameter
   626  	BoolType ParameterType = "bool"
   627  
   628  	// StringType a string type parameter
   629  	StringType ParameterType = "string"
   630  )
   631  
   632  // ParameterRules defines the parameter validation rules
   633  type ParameterRules struct {
   634  	// Name represents the name of parameter
   635  	Name string
   636  
   637  	// ParameterType represents the parameter type
   638  	ParameterType ParameterType
   639  
   640  	// Required defines whether it is a required parameter
   641  	Required bool
   642  }
   643