...

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

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

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