From d23466082d9f0265715c48c52782d003440fd0a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ravier?= Date: Fri, 9 Feb 2024 11:44:53 +0100 Subject: [PATCH] RHEL-24950: Backport fix for unexpected Azure IMDS status codes Resolves: https://issues.redhat.com/browse/RHEL-24950 See: https://issues.redhat.com/browse/OCPBUGS-29252 --- ...TP-requests-on-codes-404-410-and-429.patch | 97 +++++++++++++++++++ ignition.spec | 7 +- 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 0001-azure-retry-HTTP-requests-on-codes-404-410-and-429.patch diff --git a/0001-azure-retry-HTTP-requests-on-codes-404-410-and-429.patch b/0001-azure-retry-HTTP-requests-on-codes-404-410-and-429.patch new file mode 100644 index 0000000..a49a0a4 --- /dev/null +++ b/0001-azure-retry-HTTP-requests-on-codes-404-410-and-429.patch @@ -0,0 +1,97 @@ +From 3babc7a5b767fb60ca877213d9201568205e983f Mon Sep 17 00:00:00 2001 +From: Jonathan Lebon +Date: Thu, 8 Feb 2024 11:02:27 -0500 +Subject: [PATCH] azure: retry HTTP requests on codes 404, 410, and 429 + +For some reason, the Azure IMDS server expects clients to retry their +HTTP requests even on codes that usually would be considered final. +The documented one is 410[[1]], but let's just match the set from +cloud-init, which also includes 404 and 429[[2]]. + +Closes: #1806 + +[1]: https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service?tabs=linux#errors-and-debugging +[2]: https://github.com/canonical/cloud-init/commit/c1a2047cf291 + +travier: Edited to cleanly backport on top of 2.17.0 +--- + internal/providers/azure/azure.go | 11 ++++++++++- + internal/resource/http.go | 17 ++++++++++++++++- + internal/resource/url.go | 4 ++++ + 3 files changed, 30 insertions(+), 2 deletions(-) + +diff --git a/internal/providers/azure/azure.go b/internal/providers/azure/azure.go +index d3115f2b..caddcff5 100644 +--- a/internal/providers/azure/azure.go ++++ b/internal/providers/azure/azure.go +@@ -112,7 +112,16 @@ func fetchFromIMDS(f *resource.Fetcher) ([]byte, error) { + headers := make(http.Header) + headers.Set("Metadata", "true") + +- data, err := f.FetchToBuffer(imdsUserdataURL, resource.FetchOptions{Headers: headers}) ++ // Azure IMDS expects some codes <500 to still be retried... ++ // Here, we match the cloud-init set. ++ // https://github.com/canonical/cloud-init/commit/c1a2047cf291 ++ // https://github.com/coreos/ignition/issues/1806 ++ retryCodes := []int{ ++ 404, // not found ++ 410, // gone ++ 429, // rate-limited ++ } ++ data, err := f.FetchToBuffer(imdsUserdataURL, resource.FetchOptions{Headers: headers, RetryCodes: retryCodes}) + if err != nil { + return nil, fmt.Errorf("fetching to buffer: %w", err) + } +diff --git a/internal/resource/http.go b/internal/resource/http.go +index 0d8edace..872ce253 100644 +--- a/internal/resource/http.go ++++ b/internal/resource/http.go +@@ -263,6 +263,21 @@ func (f *Fetcher) newHttpClient() error { + return nil + } + ++func shouldRetryHttp(statusCode int, opts FetchOptions) bool { ++ // we always retry 500+ ++ if statusCode >= 500 { ++ return true ++ } ++ ++ for _, retryCode := range opts.RetryCodes { ++ if statusCode == retryCode { ++ return true ++ } ++ } ++ ++ return false ++} ++ + // httpReaderWithHeader performs an HTTP request on the provided URL with the + // provided request header & method and returns the response body Reader, HTTP + // status code, a cancel function for the result's context, and error (if any). +@@ -298,7 +313,7 @@ func (c HttpClient) httpReaderWithHeader(opts FetchOptions, url string) (io.Read + + if err == nil { + c.logger.Info("%s result: %s", opts.HTTPVerb, http.StatusText(resp.StatusCode)) +- if resp.StatusCode < 500 { ++ if !shouldRetryHttp(resp.StatusCode, opts) { + return resp.Body, resp.StatusCode, cancelFn, nil + } + resp.Body.Close() +diff --git a/internal/resource/url.go b/internal/resource/url.go +index 58e0b9fc..3d16cc59 100644 +--- a/internal/resource/url.go ++++ b/internal/resource/url.go +@@ -125,6 +125,10 @@ type FetchOptions struct { + // HTTPVerb is an HTTP request method to indicate the desired action to + // be performed for a given resource. + HTTPVerb string ++ ++ // List of HTTP codes to retry that usually would be considered as complete. ++ // Status codes >= 500 are always retried. ++ RetryCodes []int + } + + // FetchToBuffer will fetch the given url into a temporary file, and then read +-- +2.43.0 + diff --git a/ignition.spec b/ignition.spec index 105b491..241ed20 100644 --- a/ignition.spec +++ b/ignition.spec @@ -22,7 +22,7 @@ Version: 2.17.0 %global dracutlibdir %{_prefix}/lib/dracut Name: ignition -Release: 1%{?dist} +Release: 2%{?dist} Summary: First boot installer and configuration tool (RHEL CoreOS only) # Upstream license specification: Apache-2.0 @@ -31,6 +31,8 @@ URL: %{gourl} Source0: %{gosource} Source1: https://github.com/fedora-iot/ignition-edge/archive/%{ignedgecommit}/ignition-edge-%{ignedgeshortcommit}.tar.gz +Patch0: 0001-azure-retry-HTTP-requests-on-codes-404-410-and-429.patch + BuildRequires: libblkid-devel BuildRequires: systemd-rpm-macros @@ -352,6 +354,9 @@ install -p -m 0755 ./ignition %{buildroot}/%{dracutlibdir}/modules.d/30ignition %endif %changelog +* Fri Feb 09 2024 Timothée Ravier - 2.17.0-2 +- Backport fix for unexpected Azure IMDS status codes + * Mon Dec 18 2023 Yasmin Valim - 2.17.0-1 - New release