...

Source file src/github.com/chaos-mesh/chaos-mesh/controllers/action/delegate.go

Documentation: github.com/chaos-mesh/chaos-mesh/controllers/action

     1  // Copyright 2021 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 action
    17  
    18  import (
    19  	"context"
    20  	"reflect"
    21  	"strings"
    22  
    23  	"github.com/pkg/errors"
    24  
    25  	"github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
    26  	impltypes "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/types"
    27  )
    28  
    29  var _ impltypes.ChaosImpl = (*Delegate)(nil)
    30  
    31  type Delegate struct {
    32  	impl interface{}
    33  }
    34  
    35  func (i *Delegate) callAccordingToAction(action, methodName string, defaultPhase v1alpha1.Phase, args ...interface{}) (v1alpha1.Phase, error) {
    36  	implType := reflect.TypeOf(i.impl).Elem()
    37  	implVal := reflect.ValueOf(i.impl)
    38  
    39  	reflectArgs := []reflect.Value{}
    40  	for _, arg := range args {
    41  		reflectArgs = append(reflectArgs, reflect.ValueOf(arg))
    42  	}
    43  	for i := 0; i < implType.NumField(); i++ {
    44  		field := implType.Field(i)
    45  
    46  		actions := strings.Split(field.Tag.Get("action"), ",")
    47  		for i := range actions {
    48  			if actions[i] == action {
    49  				rets := implVal.Elem().FieldByIndex(field.Index).MethodByName(methodName).Call(reflectArgs)
    50  
    51  				// nil.(error) will panic :(
    52  				err := rets[1].Interface()
    53  				if err == nil {
    54  					return rets[0].Interface().(v1alpha1.Phase), nil
    55  				}
    56  
    57  				return rets[0].Interface().(v1alpha1.Phase), err.(error)
    58  			}
    59  		}
    60  	}
    61  
    62  	return defaultPhase, errors.Errorf("unknown action %s", action)
    63  }
    64  
    65  func (i *Delegate) getAction(obj v1alpha1.InnerObject) string {
    66  	return reflect.ValueOf(obj).Elem().FieldByName("Spec").FieldByName("Action").String()
    67  }
    68  
    69  func (i *Delegate) Apply(ctx context.Context, index int, records []*v1alpha1.Record, obj v1alpha1.InnerObject) (v1alpha1.Phase, error) {
    70  	return i.callAccordingToAction(i.getAction(obj), "Apply", v1alpha1.NotInjected, ctx, index, records, obj)
    71  }
    72  
    73  func (i *Delegate) Recover(ctx context.Context, index int, records []*v1alpha1.Record, obj v1alpha1.InnerObject) (v1alpha1.Phase, error) {
    74  	return i.callAccordingToAction(i.getAction(obj), "Recover", v1alpha1.Injected, ctx, index, records, obj)
    75  }
    76  
    77  func New(impl interface{}) Delegate {
    78  	return Delegate{
    79  		impl,
    80  	}
    81  }
    82