From 27a8158c8fd60935efef38d43b223e779581def2 Mon Sep 17 00:00:00 2001 From: Tom Wieczorek Date: Tue, 16 Jul 2024 18:01:44 +0200 Subject: [PATCH 1/7] Rename nodehostname*.go to nodename*.go This reflects the public function name declared in these files. Signed-off-by: Tom Wieczorek --- pkg/node/{nodehostname.go => nodename.go} | 0 pkg/node/{nodehostname_test.go => nodename_test.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename pkg/node/{nodehostname.go => nodename.go} (100%) rename pkg/node/{nodehostname_test.go => nodename_test.go} (100%) diff --git a/pkg/node/nodehostname.go b/pkg/node/nodename.go similarity index 100% rename from pkg/node/nodehostname.go rename to pkg/node/nodename.go diff --git a/pkg/node/nodehostname_test.go b/pkg/node/nodename_test.go similarity index 100% rename from pkg/node/nodehostname_test.go rename to pkg/node/nodename_test.go From 2aada4652c5696ca52b3c2ca276e3acee18e315c Mon Sep 17 00:00:00 2001 From: Tom Wieczorek Date: Tue, 16 Jul 2024 18:06:30 +0200 Subject: [PATCH 2/7] Add a context to the internal GetNodename implementation So that there's proper context propagation internally. External context propagation may be done in the future. Signed-off-by: Tom Wieczorek --- pkg/node/nodename.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pkg/node/nodename.go b/pkg/node/nodename.go index 6e133cde30e5..9ab7ceba7eac 100644 --- a/pkg/node/nodename.go +++ b/pkg/node/nodename.go @@ -28,8 +28,12 @@ import ( // GetNodename returns the node name for the node taking OS, cloud provider and override into account func GetNodename(override string) (string, error) { + return getNodename(context.TODO(), override) +} + +func getNodename(ctx context.Context, override string) (string, error) { if runtime.GOOS == "windows" { - return getNodeNameWindows(override, awsMetaInformationHostnameURL) + return getNodeNameWindows(ctx, override, awsMetaInformationHostnameURL) } nodeName, err := nodeutil.GetHostname(override) if err != nil { @@ -40,8 +44,8 @@ func GetNodename(override string) (string, error) { const awsMetaInformationHostnameURL = "http://169.254.169.254/latest/meta-data/local-hostname" -func getHostnameFromAwsMeta(url string) string { - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) +func getHostnameFromAwsMeta(ctx context.Context, url string) string { + ctx, cancel := context.WithTimeout(ctx, 1*time.Second) defer cancel() var s string @@ -56,14 +60,14 @@ func getHostnameFromAwsMeta(url string) string { return s } -func getNodeNameWindows(override string, metadataURL string) (string, error) { +func getNodeNameWindows(ctx context.Context, override string, metadataURL string) (string, error) { // if we have explicit hostnameOverride, we use it as is even on windows if override != "" { return nodeutil.GetHostname(override) } // we need to check if we have EC2 dns name available - if h := getHostnameFromAwsMeta(metadataURL); h != "" { + if h := getHostnameFromAwsMeta(ctx, metadataURL); h != "" { return h, nil } // otherwise we use the k8s hostname helper From a55712c79d1d4745c6aab35be41f72a4d7624f1b Mon Sep 17 00:00:00 2001 From: Tom Wieczorek Date: Tue, 16 Jul 2024 18:16:06 +0200 Subject: [PATCH 3/7] Use context to override metadata URL in tests This allows the URL parameter, which was used for testing only, to be removed from the function signature. This is a preparation for unifying the Windows and non-windows code paths, so that the function signatures are identical. Signed-off-by: Tom Wieczorek --- pkg/node/nodename.go | 17 +++++++++++------ pkg/node/nodename_test.go | 7 +++++-- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/pkg/node/nodename.go b/pkg/node/nodename.go index 9ab7ceba7eac..4a54b458e7dc 100644 --- a/pkg/node/nodename.go +++ b/pkg/node/nodename.go @@ -23,6 +23,7 @@ import ( "time" "github.com/carlmjohnson/requests" + "github.com/k0sproject/k0s/pkg/k0scontext" nodeutil "k8s.io/component-helpers/node/util" ) @@ -31,9 +32,12 @@ func GetNodename(override string) (string, error) { return getNodename(context.TODO(), override) } +// A URL that may be retrieved to determine the nodename. +type nodenameURL string + func getNodename(ctx context.Context, override string) (string, error) { if runtime.GOOS == "windows" { - return getNodeNameWindows(ctx, override, awsMetaInformationHostnameURL) + return getNodeNameWindows(ctx, override) } nodeName, err := nodeutil.GetHostname(override) if err != nil { @@ -42,15 +46,16 @@ func getNodename(ctx context.Context, override string) (string, error) { return nodeName, nil } -const awsMetaInformationHostnameURL = "http://169.254.169.254/latest/meta-data/local-hostname" +func getHostnameFromAwsMeta(ctx context.Context) string { + const awsMetaInformationHostnameURL nodenameURL = "http://169.254.169.254/latest/meta-data/local-hostname" + url := k0scontext.ValueOr(ctx, awsMetaInformationHostnameURL) -func getHostnameFromAwsMeta(ctx context.Context, url string) string { ctx, cancel := context.WithTimeout(ctx, 1*time.Second) defer cancel() var s string err := requests. - URL(url). + URL(string(url)). ToString(&s). Fetch(ctx) // if status code is 2XX and no transport error, we assume we are running on ec2 @@ -60,14 +65,14 @@ func getHostnameFromAwsMeta(ctx context.Context, url string) string { return s } -func getNodeNameWindows(ctx context.Context, override string, metadataURL string) (string, error) { +func getNodeNameWindows(ctx context.Context, override string) (string, error) { // if we have explicit hostnameOverride, we use it as is even on windows if override != "" { return nodeutil.GetHostname(override) } // we need to check if we have EC2 dns name available - if h := getHostnameFromAwsMeta(ctx, metadataURL); h != "" { + if h := getHostnameFromAwsMeta(ctx); h != "" { return h, nil } // otherwise we use the k8s hostname helper diff --git a/pkg/node/nodename_test.go b/pkg/node/nodename_test.go index 73d416ec634f..461e01fb4c0c 100644 --- a/pkg/node/nodename_test.go +++ b/pkg/node/nodename_test.go @@ -23,6 +23,7 @@ import ( "net/url" "testing" + "github.com/k0sproject/k0s/pkg/k0scontext" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" nodeutil "k8s.io/component-helpers/node/util" @@ -46,7 +47,8 @@ func TestGetNodename(t *testing.T) { }) t.Run("windows_no_metadata_service_available", func(t *testing.T) { - name, err := getNodeNameWindows("", baseURL) + ctx := k0scontext.WithValue(context.TODO(), nodenameURL(baseURL)) + name, err := getNodeNameWindows(ctx, "") nodename, err2 := nodeutil.GetHostname("") require.NoError(t, err) require.NoError(t, err2) @@ -54,7 +56,8 @@ func TestGetNodename(t *testing.T) { }) t.Run("windows_metadata_service_is_available", func(t *testing.T) { - name, err := getNodeNameWindows("", baseURL+"/latest/meta-data/local-hostname") + ctx := k0scontext.WithValue(context.TODO(), nodenameURL(baseURL+"/latest/meta-data/local-hostname")) + name, err := getNodeNameWindows(ctx, "") nodename, err2 := nodeutil.GetHostname("") require.NoError(t, err) require.NoError(t, err2) From 9babe009faf698ad7cb2dfd25f5815df6ba8c627 Mon Sep 17 00:00:00 2001 From: Tom Wieczorek Date: Tue, 16 Jul 2024 18:22:14 +0200 Subject: [PATCH 4/7] More accurate test assertions Retrieve the Kubernetes hostname once and reuse it in the assertions. Assert the concrete Windows hostname that's returned by the fake server. Signed-off-by: Tom Wieczorek --- pkg/node/nodename_test.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pkg/node/nodename_test.go b/pkg/node/nodename_test.go index 461e01fb4c0c..003cfba09630 100644 --- a/pkg/node/nodename_test.go +++ b/pkg/node/nodename_test.go @@ -30,38 +30,38 @@ import ( ) func TestGetNodename(t *testing.T) { + kubeHostname, err := nodeutil.GetHostname("") + require.NoError(t, err) baseURL := startFakeMetadataServer(t) t.Run("should_always_return_override_if_given", func(t *testing.T) { name, err := GetNodename("override") - require.Equal(t, "override", name) - require.NoError(t, err) + if assert.NoError(t, err) { + assert.Equal(t, "override", name) + } }) t.Run("should_call_kubernetes_hostname_helper_on_linux", func(t *testing.T) { name, err := GetNodename("") - name2, err2 := nodeutil.GetHostname("") - require.Equal(t, name, name2) - require.NoError(t, err) - require.NoError(t, err2) + if assert.NoError(t, err) { + assert.Equal(t, kubeHostname, name) + } }) t.Run("windows_no_metadata_service_available", func(t *testing.T) { ctx := k0scontext.WithValue(context.TODO(), nodenameURL(baseURL)) name, err := getNodeNameWindows(ctx, "") - nodename, err2 := nodeutil.GetHostname("") - require.NoError(t, err) - require.NoError(t, err2) - require.Equal(t, nodename, name) + if assert.NoError(t, err) { + assert.Equal(t, kubeHostname, name) + } }) t.Run("windows_metadata_service_is_available", func(t *testing.T) { ctx := k0scontext.WithValue(context.TODO(), nodenameURL(baseURL+"/latest/meta-data/local-hostname")) name, err := getNodeNameWindows(ctx, "") - nodename, err2 := nodeutil.GetHostname("") - require.NoError(t, err) - require.NoError(t, err2) - require.NotEqual(t, nodename, name) + if assert.NoError(t, err) { + assert.Equal(t, "some-hostname-from-metadata", name) + } }) } From d668710dd195f94d7a9d66a3885fd55c6cc22dc8 Mon Sep 17 00:00:00 2001 From: Tom Wieczorek Date: Wed, 17 Jul 2024 08:00:37 +0200 Subject: [PATCH 5/7] Use EC2 hostname as an override This way, the normalization also applies to EC2 hostnames, and it saves one intermediary function. The tests are now OS dependent, since the Windows specific functionality can now only be targeted on Windows, but that's not a problem since the CI takes care of running the Windows tests. Signed-off-by: Tom Wieczorek --- pkg/node/nodename.go | 19 +++----------- pkg/node/nodename_test.go | 52 +++++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 40 deletions(-) diff --git a/pkg/node/nodename.go b/pkg/node/nodename.go index 4a54b458e7dc..52d8ae2163a3 100644 --- a/pkg/node/nodename.go +++ b/pkg/node/nodename.go @@ -36,8 +36,9 @@ func GetNodename(override string) (string, error) { type nodenameURL string func getNodename(ctx context.Context, override string) (string, error) { - if runtime.GOOS == "windows" { - return getNodeNameWindows(ctx, override) + if override == "" && runtime.GOOS == "windows" { + // we need to check if we have EC2 dns name available + override = getHostnameFromAwsMeta(ctx) } nodeName, err := nodeutil.GetHostname(override) if err != nil { @@ -64,17 +65,3 @@ func getHostnameFromAwsMeta(ctx context.Context) string { } return s } - -func getNodeNameWindows(ctx context.Context, override string) (string, error) { - // if we have explicit hostnameOverride, we use it as is even on windows - if override != "" { - return nodeutil.GetHostname(override) - } - - // we need to check if we have EC2 dns name available - if h := getHostnameFromAwsMeta(ctx); h != "" { - return h, nil - } - // otherwise we use the k8s hostname helper - return nodeutil.GetHostname(override) -} diff --git a/pkg/node/nodename_test.go b/pkg/node/nodename_test.go index 003cfba09630..8b3738fb655b 100644 --- a/pkg/node/nodename_test.go +++ b/pkg/node/nodename_test.go @@ -21,6 +21,7 @@ import ( "net" "net/http" "net/url" + "runtime" "testing" "github.com/k0sproject/k0s/pkg/k0scontext" @@ -33,7 +34,6 @@ func TestGetNodename(t *testing.T) { kubeHostname, err := nodeutil.GetHostname("") require.NoError(t, err) - baseURL := startFakeMetadataServer(t) t.Run("should_always_return_override_if_given", func(t *testing.T) { name, err := GetNodename("override") if assert.NoError(t, err) { @@ -41,34 +41,38 @@ func TestGetNodename(t *testing.T) { } }) - t.Run("should_call_kubernetes_hostname_helper_on_linux", func(t *testing.T) { - name, err := GetNodename("") - if assert.NoError(t, err) { - assert.Equal(t, kubeHostname, name) - } - }) - - t.Run("windows_no_metadata_service_available", func(t *testing.T) { - ctx := k0scontext.WithValue(context.TODO(), nodenameURL(baseURL)) - name, err := getNodeNameWindows(ctx, "") - if assert.NoError(t, err) { - assert.Equal(t, kubeHostname, name) - } - }) - - t.Run("windows_metadata_service_is_available", func(t *testing.T) { - ctx := k0scontext.WithValue(context.TODO(), nodenameURL(baseURL+"/latest/meta-data/local-hostname")) - name, err := getNodeNameWindows(ctx, "") - if assert.NoError(t, err) { - assert.Equal(t, "some-hostname-from-metadata", name) - } - }) + if runtime.GOOS != "windows" { + t.Run("should_call_kubernetes_hostname_helper_on_linux", func(t *testing.T) { + name, err := GetNodename("") + if assert.NoError(t, err) { + assert.Equal(t, kubeHostname, name) + } + }) + } else { + baseURL := startFakeMetadataServer(t) + + t.Run("windows_no_metadata_service_available", func(t *testing.T) { + ctx := k0scontext.WithValue(context.TODO(), nodenameURL(baseURL)) + name, err := getNodename(ctx, "") + if assert.NoError(t, err) { + assert.Equal(t, kubeHostname, name) + } + }) + + t.Run("windows_metadata_service_is_available", func(t *testing.T) { + ctx := k0scontext.WithValue(context.TODO(), nodenameURL(baseURL+"/latest/meta-data/local-hostname")) + name, err := getNodename(ctx, "") + if assert.NoError(t, err) { + assert.Equal(t, "some-hostname from aws_metadata", name) + } + }) + } } func startFakeMetadataServer(t *testing.T) string { mux := http.NewServeMux() mux.HandleFunc("/latest/meta-data/local-hostname", func(w http.ResponseWriter, r *http.Request) { - _, err := w.Write([]byte("some-hostname-from-metadata")) + _, err := w.Write([]byte("Some-hostname from AWS_metadata\n")) assert.NoError(t, err) }) server := &http.Server{Addr: "localhost:0", Handler: mux} From e77e442693302fb21123b4a2f12f277b648774b8 Mon Sep 17 00:00:00 2001 From: Tom Wieczorek Date: Tue, 26 Nov 2024 12:49:43 +0100 Subject: [PATCH 6/7] Move Windows-specific things into their own files So that they are only compiled on Windows. Signed-off-by: Tom Wieczorek --- pkg/node/nodename.go | 31 +----------- pkg/node/nodename_other.go | 27 ++++++++++ pkg/node/nodename_test.go | 59 ++-------------------- pkg/node/nodename_windows.go | 48 ++++++++++++++++++ pkg/node/nodename_windows_test.go | 82 +++++++++++++++++++++++++++++++ 5 files changed, 162 insertions(+), 85 deletions(-) create mode 100644 pkg/node/nodename_other.go create mode 100644 pkg/node/nodename_windows.go create mode 100644 pkg/node/nodename_windows_test.go diff --git a/pkg/node/nodename.go b/pkg/node/nodename.go index 52d8ae2163a3..e58cb37fbb1f 100644 --- a/pkg/node/nodename.go +++ b/pkg/node/nodename.go @@ -19,11 +19,7 @@ package node import ( "context" "fmt" - "runtime" - "time" - "github.com/carlmjohnson/requests" - "github.com/k0sproject/k0s/pkg/k0scontext" nodeutil "k8s.io/component-helpers/node/util" ) @@ -32,13 +28,9 @@ func GetNodename(override string) (string, error) { return getNodename(context.TODO(), override) } -// A URL that may be retrieved to determine the nodename. -type nodenameURL string - func getNodename(ctx context.Context, override string) (string, error) { - if override == "" && runtime.GOOS == "windows" { - // we need to check if we have EC2 dns name available - override = getHostnameFromAwsMeta(ctx) + if override == "" { + override = defaultNodenameOverride(ctx) } nodeName, err := nodeutil.GetHostname(override) if err != nil { @@ -46,22 +38,3 @@ func getNodename(ctx context.Context, override string) (string, error) { } return nodeName, nil } - -func getHostnameFromAwsMeta(ctx context.Context) string { - const awsMetaInformationHostnameURL nodenameURL = "http://169.254.169.254/latest/meta-data/local-hostname" - url := k0scontext.ValueOr(ctx, awsMetaInformationHostnameURL) - - ctx, cancel := context.WithTimeout(ctx, 1*time.Second) - defer cancel() - - var s string - err := requests. - URL(string(url)). - ToString(&s). - Fetch(ctx) - // if status code is 2XX and no transport error, we assume we are running on ec2 - if err != nil { - return "" - } - return s -} diff --git a/pkg/node/nodename_other.go b/pkg/node/nodename_other.go new file mode 100644 index 000000000000..6a9911e0c047 --- /dev/null +++ b/pkg/node/nodename_other.go @@ -0,0 +1,27 @@ +//go:build !windows + +/* +Copyright 2024 k0s authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package node + +import ( + "context" +) + +func defaultNodenameOverride(context.Context) string { + return "" // no default override +} diff --git a/pkg/node/nodename_test.go b/pkg/node/nodename_test.go index 8b3738fb655b..a6e5ee99945c 100644 --- a/pkg/node/nodename_test.go +++ b/pkg/node/nodename_test.go @@ -17,23 +17,15 @@ limitations under the License. package node import ( - "context" - "net" - "net/http" - "net/url" "runtime" "testing" - "github.com/k0sproject/k0s/pkg/k0scontext" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" nodeutil "k8s.io/component-helpers/node/util" ) func TestGetNodename(t *testing.T) { - kubeHostname, err := nodeutil.GetHostname("") - require.NoError(t, err) - t.Run("should_always_return_override_if_given", func(t *testing.T) { name, err := GetNodename("override") if assert.NoError(t, err) { @@ -42,59 +34,14 @@ func TestGetNodename(t *testing.T) { }) if runtime.GOOS != "windows" { + kubeHostname, err := nodeutil.GetHostname("") + require.NoError(t, err) + t.Run("should_call_kubernetes_hostname_helper_on_linux", func(t *testing.T) { name, err := GetNodename("") if assert.NoError(t, err) { assert.Equal(t, kubeHostname, name) } }) - } else { - baseURL := startFakeMetadataServer(t) - - t.Run("windows_no_metadata_service_available", func(t *testing.T) { - ctx := k0scontext.WithValue(context.TODO(), nodenameURL(baseURL)) - name, err := getNodename(ctx, "") - if assert.NoError(t, err) { - assert.Equal(t, kubeHostname, name) - } - }) - - t.Run("windows_metadata_service_is_available", func(t *testing.T) { - ctx := k0scontext.WithValue(context.TODO(), nodenameURL(baseURL+"/latest/meta-data/local-hostname")) - name, err := getNodename(ctx, "") - if assert.NoError(t, err) { - assert.Equal(t, "some-hostname from aws_metadata", name) - } - }) } } - -func startFakeMetadataServer(t *testing.T) string { - mux := http.NewServeMux() - mux.HandleFunc("/latest/meta-data/local-hostname", func(w http.ResponseWriter, r *http.Request) { - _, err := w.Write([]byte("Some-hostname from AWS_metadata\n")) - assert.NoError(t, err) - }) - server := &http.Server{Addr: "localhost:0", Handler: mux} - listener, err := net.Listen("tcp", server.Addr) - if err != nil { - require.NoError(t, err) - } - - serverError := make(chan error) - go func() { - defer close(serverError) - serverError <- server.Serve(listener) - }() - - t.Cleanup(func() { - err := server.Shutdown(context.Background()) - if !assert.NoError(t, err, "Couldn't shutdown HTTP server") { - return - } - - assert.ErrorIs(t, <-serverError, http.ErrServerClosed, "HTTP server terminated unexpectedly") - }) - - return (&url.URL{Scheme: "http", Host: listener.Addr().String()}).String() -} diff --git a/pkg/node/nodename_windows.go b/pkg/node/nodename_windows.go new file mode 100644 index 000000000000..6ae3390037c9 --- /dev/null +++ b/pkg/node/nodename_windows.go @@ -0,0 +1,48 @@ +/* +Copyright 2024 k0s authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package node + +import ( + "context" + "time" + + "github.com/k0sproject/k0s/pkg/k0scontext" + + "github.com/carlmjohnson/requests" +) + +// A URL that may be retrieved to determine the nodename. +type nodenameURL string + +func defaultNodenameOverride(ctx context.Context) string { + // we need to check if we have EC2 dns name available + url := k0scontext.ValueOr[nodenameURL](ctx, "http://169.254.169.254/latest/meta-data/local-hostname") + + ctx, cancel := context.WithTimeout(ctx, 1*time.Second) + defer cancel() + + var s string + err := requests. + URL(string(url)). + ToString(&s). + Fetch(ctx) + // if status code is 2XX and no transport error, we assume we are running on ec2 + if err != nil { + return "" + } + return s +} diff --git a/pkg/node/nodename_windows_test.go b/pkg/node/nodename_windows_test.go new file mode 100644 index 000000000000..58d611bca585 --- /dev/null +++ b/pkg/node/nodename_windows_test.go @@ -0,0 +1,82 @@ +/* +Copyright 2024 k0s authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package node + +import ( + "context" + "net" + "net/http" + "net/url" + "testing" + + "github.com/k0sproject/k0s/pkg/k0scontext" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + nodeutil "k8s.io/component-helpers/node/util" +) + +func TestGetNodenameWindows(t *testing.T) { + kubeHostname, err := nodeutil.GetHostname("") + require.NoError(t, err) + baseURL := startFakeMetadataServer(t) + + t.Run("no_metadata_service_available", func(t *testing.T) { + ctx := k0scontext.WithValue(context.TODO(), nodenameURL(baseURL)) + name, err := getNodename(ctx, "") + if assert.NoError(t, err) { + assert.Equal(t, kubeHostname, name) + } + }) + + t.Run("metadata_service_is_available", func(t *testing.T) { + ctx := k0scontext.WithValue(context.TODO(), nodenameURL(baseURL+"/latest/meta-data/local-hostname")) + name, err := getNodename(ctx, "") + if assert.NoError(t, err) { + assert.Equal(t, "some-hostname from aws_metadata", name) + } + }) +} + +func startFakeMetadataServer(t *testing.T) string { + mux := http.NewServeMux() + mux.HandleFunc("/latest/meta-data/local-hostname", func(w http.ResponseWriter, r *http.Request) { + _, err := w.Write([]byte("Some-hostname from AWS_metadata\n")) + assert.NoError(t, err) + }) + server := &http.Server{Addr: "localhost:0", Handler: mux} + listener, err := net.Listen("tcp", server.Addr) + if err != nil { + require.NoError(t, err) + } + + serverError := make(chan error) + go func() { + defer close(serverError) + serverError <- server.Serve(listener) + }() + + t.Cleanup(func() { + err := server.Shutdown(context.Background()) + if !assert.NoError(t, err, "Couldn't shutdown HTTP server") { + return + } + + assert.ErrorIs(t, <-serverError, http.ErrServerClosed, "HTTP server terminated unexpectedly") + }) + + return (&url.URL{Scheme: "http", Host: listener.Addr().String()}).String() +} From 3fa3c6831b9cbe26a2e897994071d7d62d0c0dd6 Mon Sep 17 00:00:00 2001 From: Tom Wieczorek Date: Tue, 26 Nov 2024 13:05:02 +0100 Subject: [PATCH 7/7] Replace requests module with standard library http There's no need to pull in an extra dependency for such a simple use case. Signed-off-by: Tom Wieczorek --- go.mod | 1 - go.sum | 2 -- pkg/node/nodename.go | 6 +++++- pkg/node/nodename_other.go | 4 ++-- pkg/node/nodename_windows.go | 34 +++++++++++++++++++++------------- 5 files changed, 28 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index c8c3bc0d66c7..29a2beeebf68 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,6 @@ require ( github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 github.com/avast/retry-go v3.0.0+incompatible github.com/bombsimon/logrusr/v4 v4.1.0 - github.com/carlmjohnson/requests v0.24.2 github.com/cilium/ebpf v0.16.0 github.com/cloudflare/cfssl v1.6.4 github.com/containerd/cgroups/v3 v3.0.4 diff --git a/go.sum b/go.sum index 9fdd59b5745f..843db22b909f 100644 --- a/go.sum +++ b/go.sum @@ -66,8 +66,6 @@ github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembj github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/carlmjohnson/requests v0.24.2 h1:JDakhAmTIKL/qL/1P7Kkc2INGBJIkIFP6xUeUmPzLso= -github.com/carlmjohnson/requests v0.24.2/go.mod h1:duYA/jDnyZ6f3xbcF5PpZ9N8clgopubP2nK5i6MVMhU= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= diff --git a/pkg/node/nodename.go b/pkg/node/nodename.go index e58cb37fbb1f..e8f0b710aa9d 100644 --- a/pkg/node/nodename.go +++ b/pkg/node/nodename.go @@ -30,7 +30,11 @@ func GetNodename(override string) (string, error) { func getNodename(ctx context.Context, override string) (string, error) { if override == "" { - override = defaultNodenameOverride(ctx) + var err error + override, err = defaultNodenameOverride(ctx) + if err != nil { + return "", err + } } nodeName, err := nodeutil.GetHostname(override) if err != nil { diff --git a/pkg/node/nodename_other.go b/pkg/node/nodename_other.go index 6a9911e0c047..57fcb36b2aa0 100644 --- a/pkg/node/nodename_other.go +++ b/pkg/node/nodename_other.go @@ -22,6 +22,6 @@ import ( "context" ) -func defaultNodenameOverride(context.Context) string { - return "" // no default override +func defaultNodenameOverride(context.Context) (string, error) { + return "", nil // no default override } diff --git a/pkg/node/nodename_windows.go b/pkg/node/nodename_windows.go index 6ae3390037c9..f70367aef95f 100644 --- a/pkg/node/nodename_windows.go +++ b/pkg/node/nodename_windows.go @@ -18,31 +18,39 @@ package node import ( "context" + "io" + "net/http" "time" "github.com/k0sproject/k0s/pkg/k0scontext" - - "github.com/carlmjohnson/requests" ) // A URL that may be retrieved to determine the nodename. type nodenameURL string -func defaultNodenameOverride(ctx context.Context) string { +func defaultNodenameOverride(ctx context.Context) (string, error) { // we need to check if we have EC2 dns name available url := k0scontext.ValueOr[nodenameURL](ctx, "http://169.254.169.254/latest/meta-data/local-hostname") - ctx, cancel := context.WithTimeout(ctx, 1*time.Second) - defer cancel() + client := http.Client{ + Transport: &http.Transport{DisableKeepAlives: true}, + Timeout: 1 * time.Second, + } - var s string - err := requests. - URL(string(url)). - ToString(&s). - Fetch(ctx) - // if status code is 2XX and no transport error, we assume we are running on ec2 + req, err := http.NewRequestWithContext(ctx, http.MethodGet, string(url), nil) if err != nil { - return "" + return "", err } - return s + + // if status code is 2XX we assume we are running on ec2 + if resp, err := client.Do(req); err == nil { + defer resp.Body.Close() + if resp.StatusCode >= 200 && resp.StatusCode <= 299 { + if bytes, err := io.ReadAll(resp.Body); err == nil { + return string(bytes), nil + } + } + } + + return "", nil }