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