...

Source file src/github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/podchaos/podfailure/impl.go

Documentation: github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/podchaos/podfailure

     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 podfailure
    17  
    18  import (
    19  	"context"
    20  
    21  	v1 "k8s.io/api/core/v1"
    22  	k8sError "k8s.io/apimachinery/pkg/api/errors"
    23  	"sigs.k8s.io/controller-runtime/pkg/client"
    24  
    25  	"github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
    26  	impltypes "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/types"
    27  	"github.com/chaos-mesh/chaos-mesh/controllers/config"
    28  	"github.com/chaos-mesh/chaos-mesh/controllers/utils/controller"
    29  	"github.com/chaos-mesh/chaos-mesh/pkg/annotation"
    30  )
    31  
    32  var _ impltypes.ChaosImpl = (*Impl)(nil)
    33  
    34  type Impl struct {
    35  	client.Client
    36  }
    37  
    38  func (impl *Impl) Apply(ctx context.Context, index int, records []*v1alpha1.Record, obj v1alpha1.InnerObject) (v1alpha1.Phase, error) {
    39  	podchaos := obj.(*v1alpha1.PodChaos)
    40  
    41  	var origin v1.Pod
    42  	namespacedName, err := controller.ParseNamespacedName(records[index].Id)
    43  	if err != nil {
    44  		return v1alpha1.NotInjected, err
    45  	}
    46  	err = impl.Get(ctx, namespacedName, &origin)
    47  	if err != nil {
    48  		// TODO: handle this error
    49  		return v1alpha1.NotInjected, err
    50  	}
    51  	pod := origin.DeepCopy()
    52  	for index := range pod.Spec.Containers {
    53  		originImage := pod.Spec.Containers[index].Image
    54  		name := pod.Spec.Containers[index].Name
    55  
    56  		key := annotation.GenKeyForImage(podchaos, name, false)
    57  		if pod.Annotations == nil {
    58  			pod.Annotations = make(map[string]string)
    59  		}
    60  
    61  		// If the annotation is already existed, we could skip the reconcile for this container
    62  		if _, ok := pod.Annotations[key]; ok {
    63  			continue
    64  		}
    65  		pod.Annotations[key] = originImage
    66  		pod.Spec.Containers[index].Image = config.ControllerCfg.PodFailurePauseImage
    67  	}
    68  
    69  	for index := range pod.Spec.InitContainers {
    70  		originImage := pod.Spec.InitContainers[index].Image
    71  		name := pod.Spec.InitContainers[index].Name
    72  
    73  		key := annotation.GenKeyForImage(podchaos, name, true)
    74  		if pod.Annotations == nil {
    75  			pod.Annotations = make(map[string]string)
    76  		}
    77  
    78  		// If the annotation is already existed, we could skip the reconcile for this container
    79  		if _, ok := pod.Annotations[key]; ok {
    80  			continue
    81  		}
    82  		pod.Annotations[key] = originImage
    83  		pod.Spec.InitContainers[index].Image = config.ControllerCfg.PodFailurePauseImage
    84  	}
    85  
    86  	err = impl.Patch(ctx, pod, client.MergeFrom(&origin))
    87  	if err != nil {
    88  		// TODO: handle this error
    89  		return v1alpha1.NotInjected, err
    90  	}
    91  
    92  	return v1alpha1.Injected, nil
    93  }
    94  
    95  func (impl *Impl) Recover(ctx context.Context, index int, records []*v1alpha1.Record, obj v1alpha1.InnerObject) (v1alpha1.Phase, error) {
    96  	podchaos := obj.(*v1alpha1.PodChaos)
    97  
    98  	var origin v1.Pod
    99  	namespacedName, err := controller.ParseNamespacedName(records[index].Id)
   100  	if err != nil {
   101  		// This error is not expected to exist
   102  		return v1alpha1.NotInjected, err
   103  	}
   104  	err = impl.Get(ctx, namespacedName, &origin)
   105  	if err != nil {
   106  		// TODO: handle this error
   107  		if k8sError.IsNotFound(err) {
   108  			return v1alpha1.NotInjected, nil
   109  		}
   110  		return v1alpha1.Injected, err
   111  	}
   112  	pod := origin.DeepCopy()
   113  	for index := range pod.Spec.Containers {
   114  		name := pod.Spec.Containers[index].Name
   115  		key := annotation.GenKeyForImage(podchaos, name, false)
   116  
   117  		if pod.Annotations == nil {
   118  			pod.Annotations = make(map[string]string)
   119  		}
   120  		// check annotation
   121  		if image, ok := pod.Annotations[key]; ok {
   122  			pod.Spec.Containers[index].Image = image
   123  			delete(pod.Annotations, key)
   124  		}
   125  	}
   126  
   127  	for index := range pod.Spec.InitContainers {
   128  		name := pod.Spec.InitContainers[index].Name
   129  		key := annotation.GenKeyForImage(podchaos, name, true)
   130  
   131  		if pod.Annotations == nil {
   132  			pod.Annotations = make(map[string]string)
   133  		}
   134  		// check annotation
   135  		if image, ok := pod.Annotations[key]; ok {
   136  			pod.Spec.InitContainers[index].Image = image
   137  			delete(pod.Annotations, key)
   138  		}
   139  	}
   140  
   141  	err = impl.Patch(ctx, pod, client.MergeFrom(&origin))
   142  	if err != nil {
   143  		// TODO: handle this error
   144  		return v1alpha1.Injected, err
   145  	}
   146  
   147  	return v1alpha1.NotInjected, nil
   148  }
   149  
   150  func NewImpl(c client.Client) *Impl {
   151  	return &Impl{
   152  		Client: c,
   153  	}
   154  }
   155