1
2
3
4
5
6
7
8
9
10
11
12
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