Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions .github/workflows/build-and-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ on:
- cron: '0 19 * * 1-5'

env:
DEFAULT_GO_VERSION: ^1.22.0
DEFAULT_GO_VERSION: ^1.25.0
GITHUB_USERNAME: ${{ secrets.EC2_BOT_GITHUB_USERNAME }}
GITHUB_TOKEN: ${{ secrets.EC2_BOT_GITHUB_TOKEN }}
WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }}
Expand Down Expand Up @@ -71,7 +71,7 @@ jobs:
cache: false

- name: Set up golangci-lint
uses: golangci/golangci-lint-action@v3
uses: golangci/golangci-lint-action@v7
with:
version: latest
args: --timeout=5m
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ permissions:
id-token: write

env:
DEFAULT_GO_VERSION: ^1.22.0
DEFAULT_GO_VERSION: ^1.25.0
GITHUB_USERNAME: ${{ secrets.EC2_BOT_GITHUB_USERNAME }}
GITHUB_TOKEN: ${{ secrets.EC2_BOT_GITHUB_TOKEN }}
WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }}
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM --platform=$BUILDPLATFORM golang:1.22 as builder
FROM --platform=$BUILDPLATFORM golang:1.25 as builder

## GOLANG env
ARG GOPROXY="https://proxy.golang.org|direct"
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.windows
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ARG WINDOWS_VERSION=1809

# Build the manager binary
FROM --platform=windows/amd64 golang:1.22 as builder
FROM --platform=windows/amd64 golang:1.25 as builder

## GOLANG env
ENV GO111MODULE="on" CGO_ENABLED="0" GOOS="windows" GOARCH="amd64"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<a href="https://github.com/kubernetes/kubernetes/releases">
<img src="https://img.shields.io/badge/Kubernetes-%3E%3D%201.23-brightgreen" alt="kubernetes">
</a>
<a href="https://golang.org/doc/go1.22">
<a href="https://golang.org/doc/go1.25">
<img src="https://img.shields.io/github/go-mod/go-version/aws/aws-node-termination-handler?color=blueviolet" alt="go-version">
</a>
<a href="https://opensource.org/licenses/Apache-2.0">
Expand Down
5 changes: 3 additions & 2 deletions cmd/node-termination-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,11 +279,12 @@ func main() {
asgLaunchHandler := launch.New(interruptionEventStore, *node, nthConfig, metrics, recorder, clientset)
drainCordonHander := draincordon.New(interruptionEventStore, *node, nthConfig, nodeMetadata, metrics, recorder)

InterruptionLoop:
for range time.NewTicker(1 * time.Second).C {
select {
case <-signalChan:
// Exit interruption loop if a SIGTERM is received or the channel is closed
break
break InterruptionLoop
default:
EventLoop:
for event, ok := interruptionEventStore.GetActiveEvent(); ok; event, ok = interruptionEventStore.GetActiveEvent() {
Expand Down Expand Up @@ -320,7 +321,7 @@ func handleRebootUncordon(nodeName string, interruptionEventStore *interruptione
}
err = node.UncordonIfRebooted(nodeName)
if err != nil {
return fmt.Errorf("Unable to complete node label actions: %w", err)
return fmt.Errorf("unable to complete node label actions: %w", err)
}
interruptionEventStore.IgnoreEvent(eventID)
return nil
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
module github.com/aws/aws-node-termination-handler

go 1.22.0
go 1.25

toolchain go1.22.2
toolchain go1.25.5

require (
github.com/Masterminds/sprig/v3 v3.2.3
Expand Down
8 changes: 6 additions & 2 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,12 @@ func ParseCliArgs() (config Config, err error) {
}

// client-go expects these to be set in env vars
os.Setenv(kubernetesServiceHostConfigKey, config.KubernetesServiceHost)
os.Setenv(kubernetesServicePortConfigKey, config.KubernetesServicePort)
if err := os.Setenv(kubernetesServiceHostConfigKey, config.KubernetesServiceHost); err != nil {
return config, fmt.Errorf("failed to set %s environment variable: %w", kubernetesServiceHostConfigKey, err)
}
if err := os.Setenv(kubernetesServicePortConfigKey, config.KubernetesServicePort); err != nil {
return config, fmt.Errorf("failed to set %s environment variable: %w", kubernetesServicePortConfigKey, err)
}

return config, err
}
Expand Down
54 changes: 27 additions & 27 deletions pkg/ec2metadata/ec2metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,16 +139,16 @@ func New(metadataURL string, tries int) *Service {
func (e *Service) GetScheduledMaintenanceEvents() ([]ScheduledEventDetail, error) {
resp, err := e.Request(ScheduledEventPath)
if resp != nil && (resp.StatusCode < 200 || resp.StatusCode >= 300) {
return nil, fmt.Errorf("Metadata request received http status code: %d", resp.StatusCode)
return nil, fmt.Errorf("metadata request received http status code: %d", resp.StatusCode)
}
if err != nil {
return nil, fmt.Errorf("Unable to parse metadata response: %w", err)
return nil, fmt.Errorf("unable to parse metadata response: %w", err)
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()
var scheduledEvents []ScheduledEventDetail
err = json.NewDecoder(resp.Body).Decode(&scheduledEvents)
if err != nil {
return nil, fmt.Errorf("Could not decode json retrieved from imds: %w", err)
return nil, fmt.Errorf("could not decode json retrieved from imds: %w", err)
}
return scheduledEvents, nil
}
Expand All @@ -160,16 +160,16 @@ func (e *Service) GetSpotITNEvent() (instanceAction *InstanceAction, err error)
if resp != nil && resp.StatusCode == 404 {
return nil, nil
} else if resp != nil && (resp.StatusCode < 200 || resp.StatusCode >= 300) {
return nil, fmt.Errorf("Metadata request received http status code: %d", resp.StatusCode)
return nil, fmt.Errorf("metadata request received http status code: %d", resp.StatusCode)
}
if err != nil {
return nil, fmt.Errorf("Unable to parse metadata response: %w", err)
return nil, fmt.Errorf("unable to parse metadata response: %w", err)
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()

err = json.NewDecoder(resp.Body).Decode(&instanceAction)
if err != nil {
return nil, fmt.Errorf("Could not decode instance action response: %w", err)
return nil, fmt.Errorf("could not decode instance action response: %w", err)
}
return instanceAction, nil
}
Expand All @@ -181,16 +181,16 @@ func (e *Service) GetRebalanceRecommendationEvent() (rebalanceRec *RebalanceReco
if resp != nil && resp.StatusCode == 404 {
return nil, nil
} else if resp != nil && (resp.StatusCode < 200 || resp.StatusCode >= 300) {
return nil, fmt.Errorf("Metadata request received http status code: %d", resp.StatusCode)
return nil, fmt.Errorf("metadata request received http status code: %d", resp.StatusCode)
}
if err != nil {
return nil, fmt.Errorf("Unable to parse metadata response: %w", err)
return nil, fmt.Errorf("unable to parse metadata response: %w", err)
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()

err = json.NewDecoder(resp.Body).Decode(&rebalanceRec)
if err != nil {
return nil, fmt.Errorf("Could not decode rebalance recommendation response: %w", err)
return nil, fmt.Errorf("could not decode rebalance recommendation response: %w", err)
}
return rebalanceRec, nil
}
Expand All @@ -203,16 +203,16 @@ func (e *Service) GetASGTargetLifecycleState() (state string, err error) {
if resp != nil && resp.StatusCode == 404 {
return "", nil
} else if resp != nil && (resp.StatusCode < 200 || resp.StatusCode >= 300) {
return "", fmt.Errorf("Metadata request received http status code: %d", resp.StatusCode)
return "", fmt.Errorf("metadata request received http status code: %d", resp.StatusCode)
}
if err != nil {
return "", fmt.Errorf("Unable to parse metadata response: %w", err)
return "", fmt.Errorf("unable to parse metadata response: %w", err)
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()

body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("Unable to parse http response. Status code: %d. %w", resp.StatusCode, err)
return "", fmt.Errorf("unable to parse http response. Status code: %d. %w", resp.StatusCode, err)
}
return string(body), nil
}
Expand All @@ -222,19 +222,19 @@ func (e *Service) GetMetadataInfo(path string, allowMissing bool) (info string,
metadataInfo := ""
resp, err := e.Request(path)
if err != nil {
return "", fmt.Errorf("Unable to parse metadata response: %w", err)
return "", fmt.Errorf("unable to parse metadata response: %w", err)
}
if resp != nil {
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("Unable to parse http response. Status code: %d. %w", resp.StatusCode, err)
return "", fmt.Errorf("unable to parse http response. Status code: %d. %w", resp.StatusCode, err)
}
metadataInfo = string(body)
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
if resp.StatusCode != 404 || !allowMissing {
log.Info().Msgf("Metadata response status code: %d. Body: %s", resp.StatusCode, metadataInfo)
return "", fmt.Errorf("Metadata request received http status code: %d", resp.StatusCode)
return "", fmt.Errorf("metadata request received http status code: %d", resp.StatusCode)
} else {
return "", nil
}
Expand All @@ -249,7 +249,7 @@ func (e *Service) GetMetadataInfo(path string, allowMissing bool) (info string,
func (e *Service) Request(contextPath string) (*http.Response, error) {
req, err := http.NewRequest(http.MethodGet, e.metadataURL+contextPath, nil)
if err != nil {
return nil, fmt.Errorf("Unable to construct an http get request to IDMS for %s: %w", e.metadataURL+contextPath, err)
return nil, fmt.Errorf("unable to construct an http get request to IDMS for %s: %w", e.metadataURL+contextPath, err)
}
var resp *http.Response
for i := 0; i < tokenRetryAttempts; i++ {
Expand All @@ -274,7 +274,7 @@ func (e *Service) Request(contextPath string) (*http.Response, error) {
}
resp, err = retry(e.tries, 2*time.Second, httpReq)
if err != nil {
return nil, fmt.Errorf("Unable to get a response from IMDS: %w", err)
return nil, fmt.Errorf("unable to get a response from IMDS: %w", err)
}
if resp != nil && resp.StatusCode == 401 {
e.Lock()
Expand All @@ -297,7 +297,7 @@ func (e *Service) Request(contextPath string) (*http.Response, error) {
func (e *Service) getV2Token() (string, int, error) {
req, err := http.NewRequest(http.MethodPut, e.metadataURL+tokenRefreshPath, nil)
if err != nil {
return "", -1, fmt.Errorf("Unable to construct http put request to retrieve imdsv2 token: %w", err)
return "", -1, fmt.Errorf("unable to construct http put request to retrieve imdsv2 token: %w", err)
}
req.Header.Add(tokenTTLHeader, strconv.Itoa(tokenTTL))
httpReq := func() (*http.Response, error) {
Expand All @@ -308,13 +308,13 @@ func (e *Service) getV2Token() (string, int, error) {
if err != nil {
return "", -1, err
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return "", -1, fmt.Errorf("Received an http status code %d", resp.StatusCode)
return "", -1, fmt.Errorf("received an http status code %d", resp.StatusCode)
}
token, err := io.ReadAll(resp.Body)
if err != nil {
return "", -1, fmt.Errorf("Unable to read token response from IMDSv2: %w", err)
return "", -1, fmt.Errorf("unable to read token response from IMDSv2: %w", err)
}
ttl, err := ttlHeaderToInt(resp)
if err != nil {
Expand All @@ -327,7 +327,7 @@ func (e *Service) getV2Token() (string, int, error) {
func ttlHeaderToInt(resp *http.Response) (int, error) {
ttl := resp.Header.Get(tokenTTLHeader)
if ttl == "" {
return -1, fmt.Errorf("No token TTL header found")
return -1, fmt.Errorf("no token TTL header found")
}
ttlInt, err := strconv.Atoi(ttl)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions pkg/ec2metadata/ec2metadata_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
)

func TestRetry(t *testing.T) {
var numRetries int = 3
var errorMsg string = "Request failed"
var numRetries = 3
var errorMsg = "Request failed"
var requestCount int

request := func() (*http.Response, error) {
Expand All @@ -42,7 +42,7 @@

resp, err := retry(numRetries, time.Microsecond, request)
h.Assert(t, err != nil, "Should have gotten a \"Request failed\" error")
defer resp.Body.Close()

Check failure on line 45 in pkg/ec2metadata/ec2metadata_internal_test.go

View workflow job for this annotation

GitHub Actions / Lint Eastwood

Error return value of `resp.Body.Close` is not checked (errcheck)

h.Equals(t, errorMsg, err.Error())
h.Equals(t, numRetries, requestCount)
Expand Down
Loading
Loading