From 5aabd0e961a8fc5db631937bdcdb648ce5fad93a Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 27 Oct 2026 11:18:55 +0100 Subject: [PATCH 1/2] provider OpenStack: add 404 retryCode --- internal/providers/openstack/openstack.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/internal/providers/openstack/openstack.go b/internal/providers/openstack/openstack.go index 803c6f396..c6fc0eac6 100644 --- a/internal/providers/openstack/openstack.go +++ b/internal/providers/openstack/openstack.go @@ -182,11 +182,14 @@ func fetchConfigFromDevice(logger *log.Logger, ctx context.Context, path string) } func fetchConfigFromMetadataService(f *resource.Fetcher) ([]byte, error) { + retryCodes := []int{ + 404, // not found + } ipv6Interfaces, err := findInterfacesWithIPv6() if err != nil { f.Logger.Info("No active IPv6 network interface found: %v", err) // Fall back to IPv4 only - return fetchConfigFromMetadataServiceIPv4Only(f) + return fetchConfigFromMetadataServiceIPv4Only(f, retryCodes) } urls := []url.URL{userdataURLs[resource.IPv4]} @@ -198,7 +201,7 @@ func fetchConfigFromMetadataService(f *resource.Fetcher) ([]byte, error) { } // Use parallel fetching for all interfaces - data, err := fetchConfigParallel(f, urls) + data, err := fetchConfigParallel(f, urls, retryCodes) if err != nil { // the metadata server exists but doesn't contain any actual metadata, // assume that there is no config specified @@ -211,10 +214,10 @@ func fetchConfigFromMetadataService(f *resource.Fetcher) ([]byte, error) { return data, nil } -func fetchConfigFromMetadataServiceIPv4Only(f *resource.Fetcher) ([]byte, error) { +func fetchConfigFromMetadataServiceIPv4Only(f *resource.Fetcher, retryCodes []int) ([]byte, error) { ipv4Url := userdataURLs[resource.IPv4] - data, err := f.FetchToBuffer(ipv4Url, resource.FetchOptions{}) + data, err := f.FetchToBuffer(ipv4Url, resource.FetchOptions{RetryCodes: retryCodes}) if err != nil { if err == resource.ErrNotFound { return nil, nil @@ -225,7 +228,7 @@ func fetchConfigFromMetadataServiceIPv4Only(f *resource.Fetcher) ([]byte, error) return data, nil } -func fetchConfigParallel(f *resource.Fetcher, urls []url.URL) ([]byte, error) { +func fetchConfigParallel(f *resource.Fetcher, urls []url.URL, retryCodes []int) ([]byte, error) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -244,7 +247,7 @@ func fetchConfigParallel(f *resource.Fetcher, urls []url.URL) ([]byte, error) { fetch := func(_ context.Context, u url.URL) { defer wg.Done() - d, e := f.FetchToBuffer(u, resource.FetchOptions{}) + d, e := f.FetchToBuffer(u, resource.FetchOptions{RetryCodes: retryCodes}) if e != nil { f.Logger.Err("fetching configuration for %s: %v", u.String(), e) err = e From 5cfd399facc9e6c1f79e330b11b43b33ad5d1c93 Mon Sep 17 00:00:00 2001 From: Robin Schneider Date: Tue, 27 Oct 2026 11:19:47 +0100 Subject: [PATCH 2/2] provider OpenStack: improve code quality --- internal/providers/openstack/openstack.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/providers/openstack/openstack.go b/internal/providers/openstack/openstack.go index c6fc0eac6..52a2b2a07 100644 --- a/internal/providers/openstack/openstack.go +++ b/internal/providers/openstack/openstack.go @@ -13,14 +13,14 @@ // limitations under the License. // The OpenStack provider fetches configurations from the userdata available in -// both the config-drive as well as the network metadata service. Whichever +// both the config-drive and the network metadata service. Whichever // responds first is the config that is used. -// NOTE: This provider is still EXPERIMENTAL. package openstack import ( "context" + "errors" "fmt" "net" "net/url" @@ -92,8 +92,8 @@ func fetchConfig(f *resource.Fetcher) (types.Config, report.Report, error) { go func() { raw, err := fn() if err != nil { - switch err { - case context.Canceled: + switch { + case errors.Is(err, context.Canceled): default: f.Logger.Err("failed to fetch config from %s: %v", name, err) } @@ -137,7 +137,7 @@ Loop: func fileExists(path string) bool { _, err := os.Stat(path) - return (err == nil) + return err == nil } func fetchConfigFromDevice(logger *log.Logger, ctx context.Context, path string) ([]byte, error) { @@ -205,7 +205,7 @@ func fetchConfigFromMetadataService(f *resource.Fetcher) ([]byte, error) { if err != nil { // the metadata server exists but doesn't contain any actual metadata, // assume that there is no config specified - if err == resource.ErrNotFound { + if errors.Is(err, resource.ErrNotFound) { return nil, nil } return nil, err @@ -219,7 +219,7 @@ func fetchConfigFromMetadataServiceIPv4Only(f *resource.Fetcher, retryCodes []in data, err := f.FetchToBuffer(ipv4Url, resource.FetchOptions{RetryCodes: retryCodes}) if err != nil { - if err == resource.ErrNotFound { + if errors.Is(err, resource.ErrNotFound) { return nil, nil } return nil, err @@ -240,7 +240,7 @@ func fetchConfigParallel(f *resource.Fetcher, urls []url.URL, retryCodes []int) cfg := make(map[url.URL][]byte) success := make(chan url.URL, 1) - errors := make(chan error, len(urls)) + errs := make(chan error, len(urls)) // Use waitgroup to wait for all goroutines to complete var wg sync.WaitGroup @@ -251,7 +251,7 @@ func fetchConfigParallel(f *resource.Fetcher, urls []url.URL, retryCodes []int) if e != nil { f.Logger.Err("fetching configuration for %s: %v", u.String(), e) err = e - errors <- e + errs <- e } else { cfg[u] = d select { @@ -278,7 +278,7 @@ func fetchConfigParallel(f *resource.Fetcher, urls []url.URL, retryCodes []int) case u := <-success: f.Logger.Debug("got configuration from: %s", u.String()) return cfg[u], nil - case <-errors: + case <-errs: nbErrors++ if nbErrors == len(urls) { f.Logger.Debug("all routines have failed to fetch configuration, returning last known error: %v", err)