...

Source file src/github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/awschaos/detachvolume/impl.go

Documentation: github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/awschaos/detachvolume

     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 detachvolume
    17  
    18  import (
    19  	"context"
    20  	"encoding/json"
    21  
    22  	awscfg "github.com/aws/aws-sdk-go-v2/config"
    23  	"github.com/aws/aws-sdk-go-v2/credentials"
    24  	"github.com/aws/aws-sdk-go-v2/service/ec2"
    25  	"github.com/go-logr/logr"
    26  	v1 "k8s.io/api/core/v1"
    27  	"k8s.io/apimachinery/pkg/types"
    28  	"sigs.k8s.io/controller-runtime/pkg/client"
    29  
    30  	"github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
    31  	impltypes "github.com/chaos-mesh/chaos-mesh/controllers/chaosimpl/types"
    32  )
    33  
    34  var _ impltypes.ChaosImpl = (*Impl)(nil)
    35  
    36  type Impl struct {
    37  	client.Client
    38  
    39  	Log logr.Logger
    40  }
    41  
    42  func (impl *Impl) Apply(ctx context.Context, index int, records []*v1alpha1.Record, obj v1alpha1.InnerObject) (v1alpha1.Phase, error) {
    43  	awschaos := obj.(*v1alpha1.AWSChaos)
    44  
    45  	opts := []func(*awscfg.LoadOptions) error{
    46  		awscfg.WithRegion(awschaos.Spec.AWSRegion),
    47  	}
    48  	if awschaos.Spec.SecretName != nil {
    49  		secret := &v1.Secret{}
    50  		err := impl.Client.Get(ctx, types.NamespacedName{
    51  			Name:      *awschaos.Spec.SecretName,
    52  			Namespace: awschaos.Namespace,
    53  		}, secret)
    54  		if err != nil {
    55  			impl.Log.Error(err, "fail to get cloud secret")
    56  			return v1alpha1.NotInjected, err
    57  		}
    58  		opts = append(opts, awscfg.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(
    59  			string(secret.Data["aws_access_key_id"]),
    60  			string(secret.Data["aws_secret_access_key"]),
    61  			"",
    62  		)))
    63  	}
    64  	cfg, err := awscfg.LoadDefaultConfig(ctx, opts...)
    65  	if err != nil {
    66  		impl.Log.Error(err, "unable to load aws SDK config")
    67  		return v1alpha1.NotInjected, err
    68  	}
    69  	ec2client := ec2.NewFromConfig(cfg)
    70  
    71  	var selected v1alpha1.AWSSelector
    72  	json.Unmarshal([]byte(records[index].Id), &selected)
    73  	_, err = ec2client.DetachVolume(context.TODO(), &ec2.DetachVolumeInput{
    74  		VolumeId:   selected.EbsVolume,
    75  		Device:     selected.DeviceName,
    76  		Force:      true,
    77  		InstanceId: &selected.Ec2Instance,
    78  	})
    79  
    80  	if err != nil {
    81  		impl.Log.Error(err, "fail to detach the volume")
    82  		return v1alpha1.NotInjected, err
    83  	}
    84  
    85  	return v1alpha1.Injected, nil
    86  }
    87  
    88  func (impl *Impl) Recover(ctx context.Context, index int, records []*v1alpha1.Record, obj v1alpha1.InnerObject) (v1alpha1.Phase, error) {
    89  	awschaos := obj.(*v1alpha1.AWSChaos)
    90  
    91  	opts := []func(*awscfg.LoadOptions) error{
    92  		awscfg.WithRegion(awschaos.Spec.AWSRegion),
    93  	}
    94  	if awschaos.Spec.SecretName != nil {
    95  		secret := &v1.Secret{}
    96  		err := impl.Client.Get(ctx, types.NamespacedName{
    97  			Name:      *awschaos.Spec.SecretName,
    98  			Namespace: awschaos.Namespace,
    99  		}, secret)
   100  		if err != nil {
   101  			impl.Log.Error(err, "fail to get cloud secret")
   102  			return v1alpha1.Injected, err
   103  		}
   104  		opts = append(opts, awscfg.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(
   105  			string(secret.Data["aws_access_key_id"]),
   106  			string(secret.Data["aws_secret_access_key"]),
   107  			"",
   108  		)))
   109  	}
   110  	cfg, err := awscfg.LoadDefaultConfig(ctx, opts...)
   111  	if err != nil {
   112  		impl.Log.Error(err, "unable to load aws SDK config")
   113  		return v1alpha1.Injected, err
   114  	}
   115  	ec2client := ec2.NewFromConfig(cfg)
   116  
   117  	var selected v1alpha1.AWSSelector
   118  	json.Unmarshal([]byte(records[index].Id), &selected)
   119  
   120  	_, err = ec2client.AttachVolume(context.TODO(), &ec2.AttachVolumeInput{
   121  		Device:     selected.DeviceName,
   122  		InstanceId: &selected.Ec2Instance,
   123  		VolumeId:   selected.EbsVolume,
   124  	})
   125  
   126  	if err != nil {
   127  		impl.Log.Error(err, "fail to attach the volume")
   128  		return v1alpha1.Injected, err
   129  	}
   130  
   131  	return v1alpha1.NotInjected, nil
   132  }
   133  
   134  func NewImpl(c client.Client, log logr.Logger) *Impl {
   135  	return &Impl{
   136  		Client: c,
   137  		Log:    log.WithName("detachvolume"),
   138  	}
   139  }
   140