Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade Go and Packages #1

Merged
merged 24 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
077e2b7
go get go@1.22 && go mod tidy
abicky Aug 4, 2024
730dd9b
Resolve deprecated warnings
abicky Aug 4, 2024
d0d386d
Use go.uber.org/mock/gomock instead of github.com/golang/mock/gomock
abicky Aug 4, 2024
db2b939
Use dario.cat/mergo instead of github.com/imdario/mergo
abicky Aug 4, 2024
be28f56
Use generics in sliceutil
abicky Aug 10, 2024
7e60020
Migrate to aws-sdk-go-v2
abicky Aug 4, 2024
cb6dda9
Upgrade GitHub Actions versions
abicky Aug 11, 2024
3ce0302
Upgrade cobra and use new feature
abicky Aug 11, 2024
b59c37d
Use any instead of interface{}
abicky Aug 11, 2024
b382a94
Upgrade Go
abicky Oct 28, 2024
7fe75f2
Refactoring: Use new range syntax introduced in Go 1.22
abicky Oct 28, 2024
d65fb39
Refactoring: Use math/rand/v2 instead of math/rand
abicky Oct 28, 2024
c5fb1bc
Refactoring: Use slices package
abicky Oct 28, 2024
f04c95d
Apply suggestions from code review
abicky Oct 28, 2024
ea447b8
Refactoring: Use constants
abicky Oct 28, 2024
a7e3020
Fix .gorelease.yml
abicky Oct 28, 2024
94ed157
Refactoring: Use Int32.Add and Int32.Load
abicky Oct 28, 2024
9a92aaf
Upgrade golang.org/x/xerrors
abicky Oct 28, 2024
b3779e8
Fix test error messages
abicky Oct 28, 2024
17b5800
Refactoring: Introduce testutil.AnyContext()
abicky Oct 29, 2024
e6583b3
Support new ECS service configurations
abicky Oct 29, 2024
84d7ae2
Set trimpath option
abicky Oct 30, 2024
26e00d0
Fix bugs caused by aws-sdk-go-v2 migration
abicky Oct 30, 2024
cdccb4e
Set language information to code blocks
abicky Oct 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 11 additions & 15 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,15 @@ jobs:
- macos-latest
- windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v1
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 1.15
- uses: actions/cache@v1
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
go-version-file: go.mod

abicky marked this conversation as resolved.
Show resolved Hide resolved
- run: go install go.uber.org/mock/mockgen@latest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider pinning mockgen to a specific version.

Using @latest could lead to unexpected behavior if breaking changes are released. Consider pinning to a specific version for reproducible builds.

-      - run: go install go.uber.org/mock/mockgen@latest
+      - run: go install go.uber.org/mock/mockgen@v0.5.0
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- run: go install go.uber.org/mock/mockgen@latest
- run: go install go.uber.org/mock/mockgen@v0.5.0


# `go test` uses only a high-confidence subset of go vet, so execute also `go vet`
- run: go vet ./...
- run: make vet

- run: go fmt ./... && git diff --exit-code -- ':!go.sum'

Expand All @@ -38,19 +34,19 @@ jobs:
needs: test
if: contains(github.ref, 'tags/v')
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Check the version
run: grep -qr "version = \"$(git tag --points-at HEAD | sed 's/^v//')\"" cmd

- run: git fetch --prune --unshallow
- uses: actions/setup-go@v1
- uses: actions/setup-go@v5
with:
go-version: 1.15
- uses: goreleaser/goreleaser-action@v1
go-version-file: go.mod
- uses: goreleaser/goreleaser-action@v6
with:
version: latest
args: release --rm-dist
args: release --clean
env:
# Use a custom token instead of GITHUB_TOKEN for the homebrew tap
GITHUB_TOKEN: ${{ secrets.GORELEASER_GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/CREDITS
/bin
/dist
mocks.go
17 changes: 9 additions & 8 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
version: 2

before:
hooks:
- go mod download
- env GO111MODULE=off GOBIN=/tmp/bin go get github.com/Songmu/gocredits/cmd/gocredits
- /tmp/bin/gocredits -w .
- go install github.com/Songmu/gocredits/cmd/gocredits@latest
- gocredits -w .
builds:
- env:
- CGO_ENABLED=0
Expand All @@ -13,8 +14,8 @@ builds:
ldflags:
- -s -w -X github.com/abicky/ecsmec/cmd.revision={{.ShortCommit}}
archives:
- # Exclude the version to download the latest version via https://github.com/abicky/ecsmec/releases/latest/download/$archive_name
name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
- # Exclude the version from the default name_template to download the latest version via https://github.com/abicky/ecsmec/releases/latest/download/$archive_name
name_template: '{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
files:
- LICENSE
- README.md
Expand All @@ -24,18 +25,18 @@ archives:
format: zip
wrap_in_directory: true
brews:
- tap:
- repository:
owner: abicky
name: homebrew-tools
homepage: "https://github.com/abicky/ecsmec"
description: "A CLI tool for Amazon ECS that provides some commands to execute bothersome operations"
folder: Formula
directory: Formula
test: |
system "#{bin}/ecsmec --version"
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "{{ .Tag }}-next"
version_template: "{{ .Tag }}-next"
changelog:
sort: asc
filters:
Expand Down
16 changes: 13 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
NAME := ecsmec
SRCS := $(shell find . -type f -name '*.go' -not -name '*_test.go')
SRCS := $(shell find . -type f -name '*.go' -not -name '*_test.go' -not -path './internal/testing/*')
MOCKS := internal/testing/capacitymock/mocks.go internal/testing/servicemock/mocks.go
abicky marked this conversation as resolved.
Show resolved Hide resolved

all: bin/$(NAME)

Expand All @@ -8,12 +9,21 @@ bin/$(NAME): $(SRCS)

.PHONY: clean
clean:
rm -rf bin/$(NAME)
rm -rf bin/$(NAME) $(MOCKS)

.PHONY: install
install:
go install -ldflags "-s -w -X github.com/abicky/ecsmec/cmd.revision=$(shell git rev-parse --short HEAD)"

.PHONY: test
test:
test: $(MOCKS)
go test -v ./...

.PHONY: vet
vet: $(MOCKS)
go vet ./...

$(MOCKS): $(SRCS)
go generate ./...
# mockgen doesn't update timestamps if the generated code doesn't change
touch $(MOCKS)
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ This tool enables you to do such operations easily.

Download the binary archive from the [releases page](https://github.com/abicky/ecsmec/releases), unpack it, and move the executable "ecsmec" to a directory in your path (e.g. `/usr/local/bin`).

For example, you can install the latest binary on macOS by the following commands:
For example, you can install the latest binary on a Mac with Apple silicon by the following commands:

```
curl -LO https://github.com/abicky/ecsmec/releases/latest/download/ecsmec_darwin_amd64.tar.gz
tar xvf ecsmec_darwin_amd64.tar.gz
mv ecsmec_darwin_amd64/ecsmec /usr/local/bin/
curl -LO https://github.com/abicky/ecsmec/releases/latest/download/ecsmec_darwin_arm64.tar.gz
tar xvf ecsmec_darwin_arm64.tar.gz
mv ecsmec_darwin_arm64/ecsmec /usr/local/bin/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Installation instructions should include both Intel and Apple Silicon options

The README currently only shows installation instructions for Apple Silicon (arm64) Macs, while the repository also supports Intel-based Macs through Homebrew and source installation. For clarity and completeness:

  • The binary installation section should include both architectures:
    # For Apple Silicon (M1/M2) Macs:
    curl -LO https://github.com/abicky/ecsmec/releases/latest/download/ecsmec_darwin_arm64.tar.gz
    
    # For Intel Macs:
    curl -LO https://github.com/abicky/ecsmec/releases/latest/download/ecsmec_darwin_amd64.tar.gz
    

Since Homebrew support is already documented as an alternative installation method (which handles architecture selection automatically), users have a reliable fallback option.

🔗 Analysis chain

Verify binary availability for all architectures

While updating the instructions for Apple Silicon is great, we should ensure that Intel Mac users can still find appropriate installation instructions.

Consider adding a note about architecture-specific binaries and how Intel Mac users should download the darwin_amd64 version instead.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if both ARM64 and AMD64 binaries are available in the latest release
gh release download --repo abicky/ecsmec latest --pattern "*darwin_*" --dry-run

Length of output: 679


Script:

#!/bin/bash
# Let's try a different approach to check the release assets
gh release view --repo abicky/ecsmec latest --json assets -q '.assets[].name'

Length of output: 97


Script:

#!/bin/bash
# Let's check the repository's README.md for any other architecture-related information
cat README.md

Length of output: 14917

🧰 Tools
🪛 LanguageTool

[grammar] ~15-~15: Did you mean the proper noun “Apple Silicon”?
Context: ...install the latest binary on a Mac with Apple silicon by the following commands: ``` curl -L...

(APPLE_PRODUCTS)

🪛 Markdownlint

17-17: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

```

If you download the archive via a browser on macOS Catalina or later, you may receive the message "“ecsmec” cannot be opened because the developer cannot be verified."
Expand Down
8 changes: 4 additions & 4 deletions cmd/recreateservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"encoding/json"
"strings"

"github.com/aws/aws-sdk-go/service/ecs"
"github.com/aws/aws-sdk-go-v2/service/ecs"
"github.com/spf13/cobra"

"github.com/abicky/ecsmec/internal/service"
Expand Down Expand Up @@ -64,12 +64,12 @@ func recreateService(cmd *cobra.Command, args []string) error {
return newRuntimeError("failed to parse \"overrides\": %w", err)
}

sess, err := newSession()
cfg, err := newConfig(cmd.Context())
if err != nil {
return newRuntimeError("failed to initialize a session: %w", err)
return newRuntimeError("failed to initialize configuration: %w", err)
}

if err := service.NewService(ecs.New(sess)).Recreate(cluster, serviceName, overrideDef); err != nil {
if err := service.NewService(ecs.NewFromConfig(cfg)).Recreate(cmd.Context(), cluster, serviceName, overrideDef); err != nil {
return newRuntimeError("failed to recreate the service: %w", err)
}
return nil
Expand Down
90 changes: 46 additions & 44 deletions cmd/reduceclustercapacity.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package cmd

import (
"context"
"errors"
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/aws/aws-sdk-go/service/eventbridge"
"github.com/aws/aws-sdk-go/service/sqs"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/autoscaling"
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go-v2/service/ecs"
"github.com/aws/aws-sdk-go-v2/service/eventbridge"
eventbridgetypes "github.com/aws/aws-sdk-go-v2/service/eventbridge/types"
"github.com/aws/aws-sdk-go-v2/service/sqs"
sqstypes "github.com/aws/aws-sdk-go-v2/service/sqs/types"
"github.com/spf13/cobra"
"golang.org/x/xerrors"

Expand All @@ -36,10 +39,12 @@ that belong to the auto scaling group or spot fleet request.`,

cmd.Flags().String("auto-scaling-group-name", "", "The name of the target `GROUP`")
cmd.Flags().String("spot-fleet-request-id", "", "The ID of the target `REQUEST`")
cmd.MarkFlagsOneRequired("auto-scaling-group-name", "spot-fleet-request-id")
abicky marked this conversation as resolved.
Show resolved Hide resolved
cmd.MarkFlagsMutuallyExclusive("auto-scaling-group-name", "spot-fleet-request-id")

cmd.Flags().String("cluster", "default", "The name of the target `CLUSTER`")

cmd.Flags().Int64("amount", 0, "The amount of the capacity to reduce (required)")
cmd.Flags().Int32("amount", 0, "The amount of the capacity to reduce (required)")
cmd.MarkFlagRequired("amount")

reduceClusterCapacityCmd = cmd
Expand All @@ -49,107 +54,104 @@ func reduceClusterCapacity(cmd *cobra.Command, args []string) error {
id, _ := reduceClusterCapacityCmd.Flags().GetString("spot-fleet-request-id")
name, _ := reduceClusterCapacityCmd.Flags().GetString("auto-scaling-group-name")
cluster, _ := reduceClusterCapacityCmd.Flags().GetString("cluster")
amount, _ := reduceClusterCapacityCmd.Flags().GetInt64("amount")
amount, _ := reduceClusterCapacityCmd.Flags().GetInt32("amount")

if len(id) == 0 && len(name) == 0 {
return errors.New("\"spot-fleet-request-id\" or \"auto-scaling-group-name\" is required")
}
if amount <= 0 {
return errors.New("\"amount\" must be greater than 0")
}

sess, err := newSession()
cfg, err := newConfig(cmd.Context())
if err != nil {
return newRuntimeError("failed to initialize a session: %w", err)
}

drainer, err := capacity.NewDrainer(cluster, ecsconst.MaxListableContainerInstances, ecs.New(sess))
drainer, err := capacity.NewDrainer(cluster, ecsconst.MaxListableContainerInstances, ecs.NewFromConfig(cfg))
if err != nil {
return newRuntimeError("failed to initialize a Drainer: %w", err)
}

if len(id) == 0 {
asg, err := capacity.NewAutoScalingGroup(name, autoscaling.New(sess), ec2.New(sess))
asg, err := capacity.NewAutoScalingGroup(name, autoscaling.NewFromConfig(cfg), ec2.NewFromConfig(cfg))
if err != nil {
return newRuntimeError("failed to initialize a AutoScalingGroup: %w", err)
}

if err := asg.ReduceCapacity(amount, drainer); err != nil {
if err := asg.ReduceCapacity(cmd.Context(), amount, drainer); err != nil {
return newRuntimeError("failed to reduce the cluster capacity: %w", err)
}
} else {
sfr, err := capacity.NewSpotFleetRequest(id, ec2.New(sess))
sfr, err := capacity.NewSpotFleetRequest(id, ec2.NewFromConfig(cfg))
if err != nil {
return newRuntimeError("failed to initialize a SpotFleetRequest: %w", err)
}

sqsSvc := sqs.New(sess)
queueURL, queueArn, err := putSQSQueue(sqsSvc, queueNameForInterruptionWarnings)
sqsSvc := sqs.NewFromConfig(cfg)
queueURL, queueArn, err := putSQSQueue(cmd.Context(), sqsSvc, queueNameForInterruptionWarnings)
if err != nil {
return newRuntimeError("failed to create a queue for interruption warnings: %w", err)
}

eventsSvc := eventbridge.New(sess)
eventsSvc := eventbridge.NewFromConfig(cfg)
targetID := "sqs"
if err := putEventRule(eventsSvc, sqsSvc, ruleNameForInterruptionWarnings, targetID, queueURL, queueArn); err != nil {
if err := putEventRule(cmd.Context(), eventsSvc, sqsSvc, ruleNameForInterruptionWarnings, targetID, queueURL, queueArn); err != nil {
return newRuntimeError("failed to create an event rule for interruption warnings: %w", err)
}

if err := sfr.ReduceCapacity(amount, drainer, capacity.NewSQSQueuePoller(queueURL, sqsSvc)); err != nil {
if err := sfr.ReduceCapacity(cmd.Context(), amount, drainer, capacity.NewSQSQueuePoller(queueURL, sqsSvc)); err != nil {
return newRuntimeError("failed to reduce the cluster capacity: %w", err)
}

if err := deleteEventRule(eventsSvc, ruleNameForInterruptionWarnings, targetID); err != nil {
if err := deleteEventRule(cmd.Context(), eventsSvc, ruleNameForInterruptionWarnings, targetID); err != nil {
return newRuntimeError("failed to delete the event rule \"%s\": %w", ruleNameForInterruptionWarnings, err)
}
if err := deleteSQSQueue(sqsSvc, queueURL); err != nil {
if err := deleteSQSQueue(cmd.Context(), sqsSvc, queueURL); err != nil {
return newRuntimeError("failed to delete the SQS queue \"%s\": %w", queueNameForInterruptionWarnings, err)
}
Comment on lines +104 to 109
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider wrapping cleanup errors

The cleanup operations (deleteEventRule and deleteSQSQueue) should continue even if one fails. Consider collecting and wrapping all cleanup errors.

-		if err := deleteEventRule(cmd.Context(), eventsSvc, ruleNameForInterruptionWarnings, targetID); err != nil {
-			return newRuntimeError("failed to delete the event rule \"%s\": %w", ruleNameForInterruptionWarnings, err)
-		}
-		if err := deleteSQSQueue(cmd.Context(), sqsSvc, queueURL); err != nil {
-			return newRuntimeError("failed to delete the SQS queue \"%s\": %w", queueNameForInterruptionWarnings, err)
-		}
+		var errs []error
+		if err := deleteEventRule(cmd.Context(), eventsSvc, ruleNameForInterruptionWarnings, targetID); err != nil {
+			errs = append(errs, fmt.Errorf("failed to delete the event rule \"%s\": %w", ruleNameForInterruptionWarnings, err))
+		}
+		if err := deleteSQSQueue(cmd.Context(), sqsSvc, queueURL); err != nil {
+			errs = append(errs, fmt.Errorf("failed to delete the SQS queue \"%s\": %w", queueNameForInterruptionWarnings, err))
+		}
+		if len(errs) > 0 {
+			return newRuntimeError("cleanup errors: %v", errs)
+		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if err := deleteEventRule(cmd.Context(), eventsSvc, ruleNameForInterruptionWarnings, targetID); err != nil {
return newRuntimeError("failed to delete the event rule \"%s\": %w", ruleNameForInterruptionWarnings, err)
}
if err := deleteSQSQueue(sqsSvc, queueURL); err != nil {
if err := deleteSQSQueue(cmd.Context(), sqsSvc, queueURL); err != nil {
return newRuntimeError("failed to delete the SQS queue \"%s\": %w", queueNameForInterruptionWarnings, err)
}
var errs []error
if err := deleteEventRule(cmd.Context(), eventsSvc, ruleNameForInterruptionWarnings, targetID); err != nil {
errs = append(errs, fmt.Errorf("failed to delete the event rule \"%s\": %w", ruleNameForInterruptionWarnings, err))
}
if err := deleteSQSQueue(cmd.Context(), sqsSvc, queueURL); err != nil {
errs = append(errs, fmt.Errorf("failed to delete the SQS queue \"%s\": %w", queueNameForInterruptionWarnings, err))
}
if len(errs) > 0 {
return newRuntimeError("cleanup errors: %v", errs)
}

}

return nil
}

func putSQSQueue(svc *sqs.SQS, name string) (string, string, error) {
queue, err := svc.CreateQueue(&sqs.CreateQueueInput{
func putSQSQueue(ctx context.Context, svc *sqs.Client, name string) (string, string, error) {
queue, err := svc.CreateQueue(ctx, &sqs.CreateQueueInput{
QueueName: aws.String(name),
})
if err != nil {
return "", "", xerrors.Errorf("failed to create the SQS queue \"%s\": %w", name, err)
}

attrs, err := svc.GetQueueAttributes(&sqs.GetQueueAttributesInput{
AttributeNames: []*string{
aws.String("QueueArn"),
attrs, err := svc.GetQueueAttributes(ctx, &sqs.GetQueueAttributesInput{
AttributeNames: []sqstypes.QueueAttributeName{
"QueueArn",
},
QueueUrl: queue.QueueUrl,
})
if err != nil {
return "", "", xerrors.Errorf("failed to get queue attributes of the queue \"%s\": %w", name, err)
}

return *queue.QueueUrl, *attrs.Attributes["QueueArn"], nil
return *queue.QueueUrl, attrs.Attributes["QueueArn"], nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Ensure non-nil values before dereferencing AWS SDK responses

When returning *queue.QueueUrl and attrs.Attributes["QueueArn"], ensure that these values are not nil to prevent potential nil pointer dereference errors.

Consider adding checks before dereferencing, for example:

if queue.QueueUrl == nil {
    return "", "", xerrors.Errorf("QueueUrl is nil")
}
queueUrl := *queue.QueueUrl

queueArn, ok := attrs.Attributes["QueueArn"]
if !ok {
    return "", "", xerrors.Errorf("QueueArn attribute not found")
}

return queueUrl, queueArn, nil

}

func deleteSQSQueue(svc *sqs.SQS, queueURL string) error {
_, err := svc.DeleteQueue(&sqs.DeleteQueueInput{
func deleteSQSQueue(ctx context.Context, svc *sqs.Client, queueURL string) error {
_, err := svc.DeleteQueue(ctx, &sqs.DeleteQueueInput{
QueueUrl: aws.String(queueURL),
})
return err
}

func putEventRule(eventsSvc *eventbridge.EventBridge, sqsSvc *sqs.SQS, ruleName, targetID, queueURL, queueArn string) error {
rule, err := eventsSvc.PutRule(&eventbridge.PutRuleInput{
func putEventRule(ctx context.Context, eventsSvc *eventbridge.Client, sqsSvc *sqs.Client, ruleName, targetID, queueURL, queueArn string) error {
rule, err := eventsSvc.PutRule(ctx, &eventbridge.PutRuleInput{
EventPattern: aws.String("{\"detail-type\":[\"EC2 Spot Instance Interruption Warning\"],\"source\":[\"aws.ec2\"]}"),
Name: aws.String(ruleName),
})
if err != nil {
return xerrors.Errorf("failed to create a rule for interruption warnings: %w", err)
}

_, err = sqsSvc.SetQueueAttributes(&sqs.SetQueueAttributesInput{
Attributes: map[string]*string{
"Policy": aws.String(fmt.Sprintf(`{
_, err = sqsSvc.SetQueueAttributes(ctx, &sqs.SetQueueAttributesInput{
Attributes: map[string]string{
"Policy": fmt.Sprintf(`{
"Version": "2012-10-17",
"Statement": [
{
Expand All @@ -166,17 +168,17 @@ func putEventRule(eventsSvc *eventbridge.EventBridge, sqsSvc *sqs.SQS, ruleName,
}
}
]
}`, queueArn, *rule.RuleArn)),
}`, queueArn, *rule.RuleArn),
},
QueueUrl: aws.String(queueURL),
})
if err != nil {
return xerrors.Errorf("failed to update the queue access policy for interruption warnings: %w", err)
}

_, err = eventsSvc.PutTargets(&eventbridge.PutTargetsInput{
_, err = eventsSvc.PutTargets(ctx, &eventbridge.PutTargetsInput{
Rule: aws.String(ruleName),
Targets: []*eventbridge.Target{
Targets: []eventbridgetypes.Target{
{
Id: aws.String(targetID),
Arn: aws.String(queueArn),
Expand All @@ -190,17 +192,17 @@ func putEventRule(eventsSvc *eventbridge.EventBridge, sqsSvc *sqs.SQS, ruleName,
return nil
}

func deleteEventRule(svc *eventbridge.EventBridge, ruleName, targetID string) error {
_, err := svc.RemoveTargets(&eventbridge.RemoveTargetsInput{
Ids: []*string{aws.String(targetID)},
func deleteEventRule(ctx context.Context, svc *eventbridge.Client, ruleName, targetID string) error {
_, err := svc.RemoveTargets(ctx, &eventbridge.RemoveTargetsInput{
Ids: []string{targetID},
Rule: aws.String(ruleName),
})
if err != nil {
return xerrors.Errorf("failed to remove targets of the rule \"%s\": %w", ruleName, err)
}

_, err = svc.DeleteRule(&eventbridge.DeleteRuleInput{
Force: aws.Bool(true),
_, err = svc.DeleteRule(ctx, &eventbridge.DeleteRuleInput{
Force: true,
Name: aws.String(ruleName),
})
return err
Expand Down
Loading