From 46d6ecdae9a5460db6d13523622d43363920cc09 Mon Sep 17 00:00:00 2001 From: lufreita Date: Thu, 2 Jul 2026 15:35:07 -0300 Subject: [PATCH 1/2] ROSAENG-61053 | chore: bump Go to 1.26 Update the ROSA CLI toolchain from Go 1.25.8 to Go 1.26.4 across go.mod, Dockerfiles, and Renovate configuration. Remove the k8s.io/apimachinery < 0.36.0 version pin that was only necessary while the repo was on Go 1.25. Run go fix as part of the Go 1.26 upgrade and keep the verified subset of mechanical updates that passes the repo's format, lint, changed-lines coverage, and unit/integration test gates. Paired with: openshift/release#81358 --- Dockerfile | 2 +- cmd/create/iamserviceaccount/cmd.go | 31 ++++++++--- cmd/create/idp/cmd.go | 10 ++-- cmd/create/idp/htpasswd.go | 6 +-- cmd/edit/ingress/flags.go | 20 +++---- cmd/list/accessrequests/cmd.go | 8 +-- cmd/list/imagemirrors/cmd.go | 11 ++-- cmd/list/imagemirrors/cmd_test.go | 2 +- go.mod | 2 +- images/Dockerfile.e2e | 6 +-- images/Dockerfile.konflux | 2 +- pkg/fedramp/config.go | 83 +++++++++++++++-------------- pkg/helper/url/helpers.go | 6 +-- pkg/iamserviceaccount/helpers.go | 32 ++++++----- pkg/input/helper.go | 4 +- pkg/kubeletconfig/output.go | 17 +++--- pkg/logforwarding/helpers.go | 9 ++-- pkg/logforwarding/output.go | 25 ++++----- pkg/logging/aws_logger.go | 2 +- pkg/logging/round_tripper.go | 5 +- pkg/network/helper.go | 16 +++--- pkg/output/reporter.go | 8 +-- pkg/reporter/reporter.go | 16 +++--- renovate.json | 12 +---- 24 files changed, 179 insertions(+), 156 deletions(-) diff --git a/Dockerfile b/Dockerfile index 03cbc28671..8167315cef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM registry.access.redhat.com/ubi9/go-toolset:1.25.8 AS builder +FROM registry.access.redhat.com/ubi9/go-toolset:1.26.4-1782852234 AS builder COPY --chown=1001:0 . . ENV GOFLAGS=-buildvcs=false diff --git a/cmd/create/iamserviceaccount/cmd.go b/cmd/create/iamserviceaccount/cmd.go index 365c043cef..14f5800584 100644 --- a/cmd/create/iamserviceaccount/cmd.go +++ b/cmd/create/iamserviceaccount/cmd.go @@ -37,7 +37,9 @@ func NewCreateIamServiceAccountCommand() *cobra.Command { var Cmd = NewCreateIamServiceAccountCommand() -func CreateIamServiceAccountRunner(userOptions *iamServiceAccountOpts.CreateIamServiceAccountUserOptions) rosa.CommandRunner { +func CreateIamServiceAccountRunner( + userOptions *iamServiceAccountOpts.CreateIamServiceAccountUserOptions, +) rosa.CommandRunner { return func(ctx context.Context, r *rosa.Runtime, cmd *cobra.Command, argv []string) error { cluster := r.FetchCluster() @@ -75,7 +77,11 @@ func CreateIamServiceAccountRunner(userOptions *iamServiceAccountOpts.CreateIamS if len(userOptions.ServiceAccountNames) > 1 { return fmt.Errorf("role name is required when specifying multiple service accounts") } - roleName = iamserviceaccount.GenerateRoleName(cluster.Name(), userOptions.Namespace, userOptions.ServiceAccountNames[0]) + roleName = iamserviceaccount.GenerateRoleName( + cluster.Name(), + userOptions.Namespace, + userOptions.ServiceAccountNames[0], + ) } serviceAccounts := make([]iamserviceaccount.ServiceAccountIdentifier, len(userOptions.ServiceAccountNames)) @@ -92,10 +98,23 @@ func CreateIamServiceAccountRunner(userOptions *iamServiceAccountOpts.CreateIamS } trustPolicy := iamserviceaccount.GenerateTrustPolicyMultiple(oidcProviderARN, serviceAccounts) - tags := iamserviceaccount.GenerateDefaultTags(cluster.Name(), userOptions.Namespace, userOptions.ServiceAccountNames[0]) + tags := iamserviceaccount.GenerateDefaultTags( + cluster.Name(), + userOptions.Namespace, + userOptions.ServiceAccountNames[0], + ) managedPolicies := false - roleARN, err := r.AWSClient.EnsureRole(r.Reporter, roleName, trustPolicy, userOptions.PermissionsBoundary, "", tags, userOptions.Path, managedPolicies) + roleARN, err := r.AWSClient.EnsureRole( + r.Reporter, + roleName, + trustPolicy, + userOptions.PermissionsBoundary, + "", + tags, + userOptions.Path, + managedPolicies, + ) if err != nil { return fmt.Errorf("failed to create role: %s", err) } @@ -120,8 +139,8 @@ func CreateIamServiceAccountRunner(userOptions *iamServiceAccountOpts.CreateIamS inlinePolicy := userOptions.InlinePolicy // Process inline policy if it's a file reference - if strings.HasPrefix(inlinePolicy, "file://") { - policyPath := strings.TrimPrefix(inlinePolicy, "file://") + if after, ok := strings.CutPrefix(inlinePolicy, "file://"); ok { + policyPath := after policyBytes, err := os.ReadFile(policyPath) if err != nil { return fmt.Errorf("failed to read policy file '%s': %s", policyPath, err) diff --git a/cmd/create/idp/cmd.go b/cmd/create/idp/cmd.go index 33241b183e..cc5aa84ac6 100644 --- a/cmd/create/idp/cmd.go +++ b/cmd/create/idp/cmd.go @@ -444,20 +444,20 @@ func getIDPName(cmd *cobra.Command, idpName string, r *rosa.Runtime) string { return strings.Trim(idpName, " \t") } -func ValidateIdpName(idpName interface{}) error { +func ValidateIdpName(idpName any) error { name, ok := idpName.(string) if !ok { - return fmt.Errorf("Invalid type for identity provider name. Expected a string, got %T", idpName) + return fmt.Errorf("invalid type for identity provider name: expected a string, got %T", idpName) } if !idRE.MatchString(name) { - return fmt.Errorf("Invalid identifier '%s' for 'name'", idpName) + return fmt.Errorf("invalid identifier '%s' for 'name'", idpName) } if strings.EqualFold(name, "cluster-admin") { - return fmt.Errorf("The name \"cluster-admin\" is reserved for admin user IDP") + return fmt.Errorf("the name \"cluster-admin\" is reserved for admin user IDP") } return nil } @@ -550,7 +550,7 @@ func getMappingMethod(cmd *cobra.Command, mappingMethod string) (string, error) } } if !isValidMappingMethod { - err = fmt.Errorf("Expected a valid mapping method. Options are %s", validMappingMethods) + err = fmt.Errorf("expected a valid mapping method; options are %s", validMappingMethods) } return mappingMethod, err } diff --git a/cmd/create/idp/htpasswd.go b/cmd/create/idp/htpasswd.go index a5f660320d..c6fa007e1c 100644 --- a/cmd/create/idp/htpasswd.go +++ b/cmd/create/idp/htpasswd.go @@ -256,7 +256,7 @@ func exitHTPasswdCreate(format, clusterKey string, err error, r *rosa.Runtime) { os.Exit(1) } -func UsernameValidator(val interface{}) error { +func UsernameValidator(val any) error { if username, ok := val.(string); ok { if strings.ContainsAny(username, "/:%") { return fmt.Errorf("invalid username '%s': "+ @@ -267,7 +267,7 @@ func UsernameValidator(val interface{}) error { return fmt.Errorf("can only validate strings, got '%v'", val) } -func clusterAdminValidator(val interface{}) error { +func clusterAdminValidator(val any) error { if username, ok := val.(string); ok { if username == ClusterAdminUsername { return fmt.Errorf("username '%s' is not allowed. It is preserved for cluster admin creation. "+ @@ -302,7 +302,7 @@ func parseHtpasswordFile(usersList *map[string]string, filePath string) error { // split "user:password" at colon username, password, found := strings.Cut(line, ":") if !found || username == "" || password == "" { - return fmt.Errorf("Malformed line, Expected: validUsername:validPassword, Got: %s", line) + return fmt.Errorf("malformed line, expected validUsername:validPassword, got: %s", line) } (*usersList)[username] = password diff --git a/cmd/edit/ingress/flags.go b/cmd/edit/ingress/flags.go index 6a819bc9c2..436162346c 100644 --- a/cmd/edit/ingress/flags.go +++ b/cmd/edit/ingress/flags.go @@ -2,13 +2,14 @@ package ingress import ( "fmt" + "slices" "strings" cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" "github.com/spf13/pflag" "github.com/openshift/rosa/pkg/helper" - . "github.com/openshift/rosa/pkg/ingress" + pkgingress "github.com/openshift/rosa/pkg/ingress" ) type stringTransformation func(source string) string @@ -47,13 +48,7 @@ var expectedParameters = []string{ } func IsIngressV2SetViaCLI(flags *pflag.FlagSet) bool { - for _, parameter := range exclusivelyIngressV2Flags { - if flags.Changed(parameter) { - return true - } - } - - return false + return slices.ContainsFunc(exclusivelyIngressV2Flags, flags.Changed) } func addIngressV2Flags(flags *pflag.FlagSet) { @@ -70,7 +65,7 @@ func addIngressV2Flags(flags *pflag.FlagSet) { wildcardPolicyFlag, "", fmt.Sprintf("Wildcard Policy for ingress. Options are %s. Default is '%s'.", - strings.Join(ValidWildcardPolicies, ","), DefaultWildcardPolicy), + strings.Join(pkgingress.ValidWildcardPolicies, ","), pkgingress.DefaultWildcardPolicy), ) flags.StringVar( @@ -78,7 +73,7 @@ func addIngressV2Flags(flags *pflag.FlagSet) { namespaceOwnershipPolicyFlag, "", fmt.Sprintf("Namespace Ownership Policy for ingress. Options are %s. Default is '%s'.", - strings.Join(ValidNamespaceOwnershipPolicies, ","), DefaultNamespaceOwnershipPolicy), + strings.Join(pkgingress.ValidNamespaceOwnershipPolicies, ","), pkgingress.DefaultNamespaceOwnershipPolicy), ) flags.StringVar( @@ -158,9 +153,10 @@ func parseComponentRoutes(input string) (map[string]*cmv1.ComponentRouteBuilder, parameterValue = t(parameterValue) } // TODO: use reflection, couldn't get it to work - if parameterName == hostnameParameter { + switch parameterName { + case hostnameParameter: componentRouteBuilder.Hostname(parameterValue) - } else if parameterName == tlsSecretRefParameter { + case tlsSecretRefParameter: componentRouteBuilder.TlsSecretRef(parameterValue) } } diff --git a/cmd/list/accessrequests/cmd.go b/cmd/list/accessrequests/cmd.go index 7d40f027ff..e24c7814a4 100644 --- a/cmd/list/accessrequests/cmd.go +++ b/cmd/list/accessrequests/cmd.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "strings" "text/tabwriter" "time" @@ -85,7 +86,8 @@ func ListAccessRequestsRunner() rosa.CommandRunner { } func getAccessRequestsOutput(clusterId string, accessRequests []*v1.AccessRequest) (string, bool, string) { - output := "STATE\tID\tCLUSTER ID\tUPDATED AT\n" + var output strings.Builder + output.WriteString("STATE\tID\tCLUSTER ID\tUPDATED AT\n") hasPending := false id := "" for _, accessRequest := range accessRequests { @@ -95,12 +97,12 @@ func getAccessRequestsOutput(clusterId string, accessRequests []*v1.AccessReques id = accessRequest.ID() } } - output += fmt.Sprintf("%s\t%s\t%s\t%s\n", + fmt.Fprintf(&output, "%s\t%s\t%s\t%s\n", accessRequest.Status().State(), accessRequest.ID(), accessRequest.ClusterId(), accessRequest.UpdatedAt().Format(time.UnixDate)) } - return output, hasPending, id + return output.String(), hasPending, id } diff --git a/cmd/list/imagemirrors/cmd.go b/cmd/list/imagemirrors/cmd.go index d0f29220cb..17c4c12267 100644 --- a/cmd/list/imagemirrors/cmd.go +++ b/cmd/list/imagemirrors/cmd.go @@ -20,6 +20,7 @@ import ( "context" "fmt" "os" + "strings" "text/tabwriter" "github.com/spf13/cobra" @@ -71,7 +72,7 @@ func ListImageMirrorsRunner(options *ListImageMirrorsOptions) rosa.CommandRunner } imageMirrors, err := runtime.OCMClient.ListImageMirrors(cluster.ID()) if err != nil { - return fmt.Errorf("Failed to list image mirrors: %v", err) + return fmt.Errorf("failed to list image mirrors: %v", err) } if output.HasFlag() { @@ -88,13 +89,13 @@ func ListImageMirrorsRunner(options *ListImageMirrorsOptions) rosa.CommandRunner fmt.Fprintf(writer, "ID\tTYPE\tSOURCE\tMIRRORS\n") for _, mirror := range imageMirrors { - mirrors := "" + var mirrors strings.Builder if len(mirror.Mirrors()) > 0 { for i, m := range mirror.Mirrors() { if i > 0 { - mirrors += ", " + mirrors.WriteString(", ") } - mirrors += m + mirrors.WriteString(m) } } @@ -102,7 +103,7 @@ func ListImageMirrorsRunner(options *ListImageMirrorsOptions) rosa.CommandRunner mirror.ID(), mirror.Type(), mirror.Source(), - mirrors, + mirrors.String(), ) } diff --git a/cmd/list/imagemirrors/cmd_test.go b/cmd/list/imagemirrors/cmd_test.go index 71fed7b22c..ab014a3be0 100644 --- a/cmd/list/imagemirrors/cmd_test.go +++ b/cmd/list/imagemirrors/cmd_test.go @@ -147,7 +147,7 @@ var _ = Describe("List image mirrors", func() { Expect(err).ToNot(HaveOccurred()) err = runner(context.Background(), t.RosaRuntime, cmd, []string{}) Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("Failed to list image mirrors")) + Expect(err.Error()).To(ContainSubstring("failed to list image mirrors")) }) }) diff --git a/go.mod b/go.mod index 388e567219..66e843b3d9 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/openshift/rosa -go 1.25.8 +go 1.26.4 require ( github.com/AlecAivazis/survey/v2 v2.3.7 diff --git a/images/Dockerfile.e2e b/images/Dockerfile.e2e index a57bdbfffc..228c4825b4 100644 --- a/images/Dockerfile.e2e +++ b/images/Dockerfile.e2e @@ -1,5 +1,5 @@ # The image is for Prow CI steps to manage the ROSA cluster lifecycle and testing -FROM registry.access.redhat.com/ubi9/go-toolset:1.25.8 as builder +FROM registry.access.redhat.com/ubi9/go-toolset:1.26.4-1782852234 as builder WORKDIR /rosa USER root ENV GOBIN=/go/bin @@ -13,13 +13,13 @@ RUN go test -c -o /go/bin/rosatest ./tests/e2e RUN rosa verify openshift-client RUN rosatest --ginkgo.no-color --ginkgo.label-filter "e2e-commit" -FROM registry.access.redhat.com/ubi9/go-toolset:1.25.8 AS rosa-support +FROM registry.access.redhat.com/ubi9/go-toolset:1.26.4-1782852234 AS rosa-support WORKDIR /opt/app-root/src/rosa-support RUN go install github.com/openshift-online/rosa-support@latest FROM registry.ci.openshift.org/ci/cli-ocm:latest as ocmcli -FROM registry.access.redhat.com/ubi9/go-toolset:1.25.8 +FROM registry.access.redhat.com/ubi9/go-toolset:1.26.4-1782852234 USER root COPY --from=builder /go/bin/rosa* /usr/bin COPY --from=builder /rosa/tests/ci/data /rosa/tests/ci/data diff --git a/images/Dockerfile.konflux b/images/Dockerfile.konflux index 3a31fee397..e56c19d267 100644 --- a/images/Dockerfile.konflux +++ b/images/Dockerfile.konflux @@ -1,4 +1,4 @@ -FROM registry.access.redhat.com/ubi9/go-toolset:1.25.8 AS builder +FROM registry.access.redhat.com/ubi9/go-toolset:1.26.4-1782852234 AS builder WORKDIR /rosa USER root COPY . . diff --git a/pkg/fedramp/config.go b/pkg/fedramp/config.go index dc4fdaec12..ce6405105d 100644 --- a/pkg/fedramp/config.go +++ b/pkg/fedramp/config.go @@ -19,17 +19,15 @@ limitations under the License. package fedramp -import "fmt" +import ( + "fmt" + "slices" +) var regions = []string{"us-gov-west-1", "us-gov-east-1"} func IsGovRegion(region string) bool { - for _, r := range regions { - if r == region { - return true - } - } - return false + return slices.Contains(regions, region) } func IsValidEnv(env string) bool { @@ -43,61 +41,68 @@ func IsValidEnv(env string) bool { // JumpAccounts are the various of AWS accounts used for the installer jump role in the various OCM environments var JumpAccounts = map[string]string{ - "production": "448648337690", - "staging": "448870092490", - "staging01": "448870092490", - "integration": "449053620653", + envProduction: "448648337690", + envStaging: "448870092490", + envStaging01: "448870092490", + envIntegration: "449053620653", } // LoginURLs allows the value of the `--env` option to map to the various login URLs. var LoginURLs = map[string]string{ - "production": "https://api.openshiftusgov.com/auth", - "staging": "https://api.stage.openshiftusgov.com/auth", - "staging01": "https://api01.stage.openshiftusgov.com/auth", - "integration": "https://api.int.openshiftusgov.com/auth", + envProduction: "https://api.openshiftusgov.com/auth", + envStaging: "https://api.stage.openshiftusgov.com/auth", + envStaging01: "https://api01.stage.openshiftusgov.com/auth", + envIntegration: "https://api.int.openshiftusgov.com/auth", } // AdminLoginURLs allows the value of the `--env` option to map to the various Admin login URLs. var AdminLoginURLs = map[string]string{ - "production": "https://api-admin.openshiftusgov.com/auth", - "staging": "https://api-admin.stage.openshiftusgov.com/auth", - "staging01": "https://api.stage.openshiftusgov.com/auth", - "integration": "https://api-admin.int.openshiftusgov.com/auth", + envProduction: "https://api-admin.openshiftusgov.com/auth", + envStaging: "https://api-admin.stage.openshiftusgov.com/auth", + envStaging01: "https://api.stage.openshiftusgov.com/auth", + envIntegration: "https://api-admin.int.openshiftusgov.com/auth", } // URLAliases allows the value of the `--env` option to map to the various API URLs. var URLAliases = map[string]string{ - "production": "https://api.openshiftusgov.com", - "staging": "https://api.stage.openshiftusgov.com", - "staging01": "https://api01.stage.openshiftusgov.com", - "integration": "https://api.int.openshiftusgov.com", + envProduction: "https://api.openshiftusgov.com", + envStaging: "https://api.stage.openshiftusgov.com", + envStaging01: "https://api01.stage.openshiftusgov.com", + envIntegration: "https://api.int.openshiftusgov.com", } // AdminURLAliases allows the value of the `--env` option to map to the various Admin API URLs. var AdminURLAliases = map[string]string{ - "production": "https://api-admin.openshiftusgov.com", - "staging": "https://api-admin.stage.openshiftusgov.com", - "staging01": "https://api01.stage.openshiftusgov.com", - "integration": "https://api-admin.int.openshiftusgov.com", + envProduction: "https://api-admin.openshiftusgov.com", + envStaging: "https://api-admin.stage.openshiftusgov.com", + envStaging01: "https://api01.stage.openshiftusgov.com", + envIntegration: "https://api-admin.int.openshiftusgov.com", } const cognitoURL = "auth-fips.us-gov-west-1.amazoncognito.com/oauth2/token" const keycloakURL = "realms/redhat-external/protocol/openid-connect/token" +const ( + envProduction = "production" + envStaging = "staging" + envStaging01 = "staging01" + envIntegration = "integration" +) + // TokenURLs allows the value of the `--env` option to map to the various AWS Cognito token URLs. var TokenURLs = map[string]string{ - "production": fmt.Sprintf("https://sso.openshiftusgov.com/%s", keycloakURL), - "staging": fmt.Sprintf("https://sso.stage.openshiftusgov.com/%s", keycloakURL), - "staging01": fmt.Sprintf("https://sso01.stage.openshiftusgov.com/%s", keycloakURL), - "integration": fmt.Sprintf("https://sso.int.openshiftusgov.com/%s", keycloakURL), + envProduction: fmt.Sprintf("https://sso.openshiftusgov.com/%s", keycloakURL), + envStaging: fmt.Sprintf("https://sso.stage.openshiftusgov.com/%s", keycloakURL), + envStaging01: fmt.Sprintf("https://sso01.stage.openshiftusgov.com/%s", keycloakURL), + envIntegration: fmt.Sprintf("https://sso.int.openshiftusgov.com/%s", keycloakURL), } // AdminTokenURLs allows the value of the `--env` option to map to the various Admin AWS Cognito token URLs. var AdminTokenURLs = map[string]string{ - "production": fmt.Sprintf("https://ocm-ra-production-domain.%s", cognitoURL), - "staging": fmt.Sprintf("https://ocm-ra-stage-domain.%s", cognitoURL), - "staging01": fmt.Sprintf("https://ocm-ra-stage-domain.%s", cognitoURL), - "integration": fmt.Sprintf("https://rh-ocm-appsre-integration.%s", cognitoURL), + envProduction: fmt.Sprintf("https://ocm-ra-production-domain.%s", cognitoURL), + envStaging: fmt.Sprintf("https://ocm-ra-stage-domain.%s", cognitoURL), + envStaging01: fmt.Sprintf("https://ocm-ra-stage-domain.%s", cognitoURL), + envIntegration: fmt.Sprintf("https://rh-ocm-appsre-integration.%s", cognitoURL), } // ClientID stores the client id for use with all `--env` options for Keycloak authentication flow. @@ -106,8 +111,8 @@ var ClientID = "console-dot" // AdminClientIDs allows the value of the `--env` option to map to the various Admin AWS Cognito user pool clients. var AdminClientIDs = map[string]string{ - "production": "72ekjh5laouap6qcfis521jlgi", - "staging": "1lb687dlpsmsfuj53r3je06vpp", - "staging01": "1lb687dlpsmsfuj53r3je06vpp", - "integration": "20fbrpgl28f8oehp6709mk3nnr", + envProduction: "72ekjh5laouap6qcfis521jlgi", + envStaging: "1lb687dlpsmsfuj53r3je06vpp", + envStaging01: "1lb687dlpsmsfuj53r3je06vpp", + envIntegration: "20fbrpgl28f8oehp6709mk3nnr", } diff --git a/pkg/helper/url/helpers.go b/pkg/helper/url/helpers.go index 0794f3ec05..e277114a4f 100644 --- a/pkg/helper/url/helpers.go +++ b/pkg/helper/url/helpers.go @@ -99,12 +99,12 @@ func validateIPv6LiteralHost(rawURL string) error { } func getAuthority(rawURL string) (string, bool) { - schemeIdx := strings.Index(rawURL, "://") - if schemeIdx == -1 { + _, after, ok := strings.Cut(rawURL, "://") + if !ok { return "", false } - authority := rawURL[schemeIdx+len("://"):] + authority := after if endIdx := strings.IndexAny(authority, "/?#"); endIdx != -1 { authority = authority[:endIdx] } diff --git a/pkg/iamserviceaccount/helpers.go b/pkg/iamserviceaccount/helpers.go index f165eab5a2..370b26290f 100644 --- a/pkg/iamserviceaccount/helpers.go +++ b/pkg/iamserviceaccount/helpers.go @@ -17,6 +17,7 @@ package iamserviceaccount import ( "fmt" "regexp" + "slices" "strings" ) @@ -140,14 +141,15 @@ func GenerateTrustPolicyMultiple(oidcProviderARN string, serviceAccounts []Servi }`, oidcProviderARN, oidcProviderURL, subjects[0]) } else { // Multiple subjects - use array format - subjectsJSON := `[` + var subjectsJSON strings.Builder + subjectsJSON.WriteString(`[`) for i, subject := range subjects { if i > 0 { - subjectsJSON += ", " + subjectsJSON.WriteString(", ") } - subjectsJSON += fmt.Sprintf(`"%s"`, subject) + fmt.Fprintf(&subjectsJSON, `"%s"`, subject) } - subjectsJSON += `]` + subjectsJSON.WriteString(`]`) trustPolicy = fmt.Sprintf(`{ "Version": "2012-10-17", @@ -165,7 +167,7 @@ func GenerateTrustPolicyMultiple(oidcProviderARN string, serviceAccounts []Servi } } ] -}`, oidcProviderARN, oidcProviderURL, subjectsJSON) +}`, oidcProviderARN, oidcProviderURL, subjectsJSON.String()) } return trustPolicy @@ -182,7 +184,10 @@ func ValidateServiceAccountName(name string) error { } if !ServiceAccountNameRE.MatchString(name) { - return fmt.Errorf("service account name must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character") + return fmt.Errorf( + "service account name must consist of lower case alphanumeric characters, '-' or '.', " + + "and must start and end with an alphanumeric character", + ) } return nil @@ -199,15 +204,16 @@ func ValidateNamespaceName(name string) error { } if !NamespaceNameRE.MatchString(name) { - return fmt.Errorf("namespace name must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character") + return fmt.Errorf( + "namespace name must consist of lower case alphanumeric characters or '-', " + + "and must start and end with an alphanumeric character", + ) } // Reserved namespaces (only system namespaces) reserved := []string{"kube-system", "kube-public", "kube-node-lease"} - for _, r := range reserved { - if name == r { - return fmt.Errorf("namespace '%s' is reserved and cannot be used", name) - } + if slices.Contains(reserved, name) { + return fmt.Errorf("namespace '%s' is reserved and cannot be used", name) } return nil @@ -233,11 +239,11 @@ func GetRoleARN(accountID, roleName, path, partition string) string { } // ServiceAccountNameValidator is an interactive validator for service account names -func ServiceAccountNameValidator(val interface{}) error { +func ServiceAccountNameValidator(val any) error { return ValidateServiceAccountName(val.(string)) } // NamespaceNameValidator is an interactive validator for namespace names -func NamespaceNameValidator(val interface{}) error { +func NamespaceNameValidator(val any) error { return ValidateNamespaceName(val.(string)) } diff --git a/pkg/input/helper.go b/pkg/input/helper.go index 93add86996..516f6f3d0a 100644 --- a/pkg/input/helper.go +++ b/pkg/input/helper.go @@ -8,8 +8,8 @@ import ( ) // UnmarshalInputFile is a generic unmarshaller from an input path -func UnmarshalInputFile(specPath string) (map[string]interface{}, error) { - var result map[string]interface{} +func UnmarshalInputFile(specPath string) (map[string]any, error) { + var result map[string]any specFile, err := os.Open(specPath) if err != nil { return result, err diff --git a/pkg/kubeletconfig/output.go b/pkg/kubeletconfig/output.go index e9a5d30dc5..6d5d745369 100644 --- a/pkg/kubeletconfig/output.go +++ b/pkg/kubeletconfig/output.go @@ -2,6 +2,7 @@ package kubeletconfig import ( "fmt" + "strings" cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" ) @@ -9,12 +10,13 @@ import ( const emptyName = "-" func PrintKubeletConfigsForTabularOutput(configs []*cmv1.KubeletConfig) string { - output := "ID\tNAME\tPOD PIDS LIMIT\n" + var output strings.Builder + output.WriteString("ID\tNAME\tPOD PIDS LIMIT\n") for _, config := range configs { - output += fmt.Sprintf("%s\t%s\t%d\n", config.ID(), getName(config), config.PodPidsLimit()) + fmt.Fprintf(&output, "%s\t%s\t%d\n", config.ID(), getName(config), config.PodPidsLimit()) } - return output + return output.String() } func getName(config *cmv1.KubeletConfig) string { @@ -25,15 +27,16 @@ func getName(config *cmv1.KubeletConfig) string { } func PrintKubeletConfigForHcp(config *cmv1.KubeletConfig, nodePools []*cmv1.NodePool) string { - output := PrintKubeletConfigForClassic(config) + var output strings.Builder + output.WriteString(PrintKubeletConfigForClassic(config)) if len(nodePools) != 0 { - output += "MachinePools Using This KubeletConfig:\n" + output.WriteString("MachinePools Using This KubeletConfig:\n") for _, n := range nodePools { - output += fmt.Sprintf(" - %s\n", n.ID()) + fmt.Fprintf(&output, " - %s\n", n.ID()) } } - return output + return output.String() } func PrintKubeletConfigForClassic(config *cmv1.KubeletConfig) string { diff --git a/pkg/logforwarding/helpers.go b/pkg/logforwarding/helpers.go index 8452809683..013fa8cccb 100644 --- a/pkg/logforwarding/helpers.go +++ b/pkg/logforwarding/helpers.go @@ -2,6 +2,7 @@ package logforwarding import ( "os" + "strings" "gopkg.in/yaml.v3" @@ -48,14 +49,14 @@ type LogForwarderYaml struct { func ConstructPodGroupsHelpMessage(options []*cmv1.LogForwarderGroupVersions) (s string) { s = "" for _, option := range options { - apps := "" + var apps strings.Builder for i, application := range option.Versions()[len(option.Versions())-1].Applications() { if i != 0 { - apps += "," + apps.WriteString(",") } - apps += application + apps.WriteString(application) } - s = s + option.Name() + ": " + apps + "\n" + s = s + option.Name() + ": " + apps.String() + "\n" } return } diff --git a/pkg/logforwarding/output.go b/pkg/logforwarding/output.go index 0aca9341a4..34a5b5c7e7 100644 --- a/pkg/logforwarding/output.go +++ b/pkg/logforwarding/output.go @@ -2,6 +2,7 @@ package logforwarding import ( "fmt" + "strings" cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" ) @@ -20,25 +21,25 @@ func LogForwarderObjectAsString(logForwarder *cmv1.LogForwarder) string { } if logForwarder.Applications() != nil && len(logForwarder.Applications()) > 0 { - applicationsStr := "" + var applicationsStr strings.Builder for i, app := range logForwarder.Applications() { if i > 0 { - applicationsStr += " " + applicationsStr.WriteString(" ") } - applicationsStr += app + applicationsStr.WriteString(app) } - out += fmt.Sprintf("Applications: %s\n", applicationsStr) + out += fmt.Sprintf("Applications: %s\n", applicationsStr.String()) } if logForwarder.Groups() != nil && len(logForwarder.Groups()) > 0 { - groupsStr := "" + var groupsStr strings.Builder for i, group := range logForwarder.Groups() { if i > 0 { - groupsStr += " " + groupsStr.WriteString(" ") } - groupsStr += fmt.Sprintf("(%s,v%s)", group.ID(), group.Version()) + fmt.Fprintf(&groupsStr, "(%s,v%s)", group.ID(), group.Version()) } - out += fmt.Sprintf("Groups: %s\n", groupsStr) + out += fmt.Sprintf("Groups: %s\n", groupsStr.String()) } if logForwarder.Status() != nil { @@ -47,14 +48,14 @@ func LogForwarderObjectAsString(logForwarder *cmv1.LogForwarder) string { } if logForwarder.Status().ResolvedApplications() != nil && len(logForwarder.Status().ResolvedApplications()) > 0 { - resolvedAppsStr := "" + var resolvedAppsStr strings.Builder for i, app := range logForwarder.Status().ResolvedApplications() { if i > 0 { - resolvedAppsStr += " " + resolvedAppsStr.WriteString(" ") } - resolvedAppsStr += app + resolvedAppsStr.WriteString(app) } - out += fmt.Sprintf("Resolved Applications: %s\n", resolvedAppsStr) + out += fmt.Sprintf("Resolved Applications: %s\n", resolvedAppsStr.String()) } } diff --git a/pkg/logging/aws_logger.go b/pkg/logging/aws_logger.go index b28a59cd9b..78eca06089 100644 --- a/pkg/logging/aws_logger.go +++ b/pkg/logging/aws_logger.go @@ -61,6 +61,6 @@ func (b *AWSLoggerBuilder) Build() (result *AWSLogger, err error) { return } -func (l *AWSLogger) Log(args ...interface{}) { +func (l *AWSLogger) Log(args ...any) { l.logger.Info(args...) } diff --git a/pkg/logging/round_tripper.go b/pkg/logging/round_tripper.go index 382d21047e..ee93c22e22 100644 --- a/pkg/logging/round_tripper.go +++ b/pkg/logging/round_tripper.go @@ -24,6 +24,7 @@ import ( "encoding/json" "fmt" "io" + "maps" "mime" "net/http" "net/url" @@ -99,9 +100,7 @@ func (b *RoundTripperBuilder) Build() (result *RoundTripper, err error) { // Copy the set of redactedReplacement fields: redact := make(map[string]bool) - for key, value := range b.redact { - redact[key] = value - } + maps.Copy(redact, b.redact) // Create and populate the object: result = &RoundTripper{ diff --git a/pkg/network/helper.go b/pkg/network/helper.go index 54c94bd305..f85a02f16c 100644 --- a/pkg/network/helper.go +++ b/pkg/network/helper.go @@ -82,8 +82,8 @@ func ParseParams(params []string) (map[string]string, map[string]string, error) return nil, nil, errors.New("invalid parameter format") } if parts[0] == "Tags" { - tagEntries := strings.Split(parts[1], ",") - for _, entry := range tagEntries { + tagEntries := strings.SplitSeq(parts[1], ",") + for entry := range tagEntries { tagParts := strings.SplitN(strings.TrimSpace(entry), "=", 2) if len(tagParts) != 2 { return nil, nil, errors.New("invalid tag format") @@ -110,29 +110,29 @@ func SelectTemplate(templateDir, command string) string { } func formatParams(params map[string]string) string { - var paramStr string + var paramStr strings.Builder keys := make([]string, 0, len(params)) for k := range params { keys = append(keys, k) } sort.Strings(keys) for _, k := range keys { - paramStr += fmt.Sprintf("ParameterKey=%s,ParameterValue=%s ", k, params[k]) + fmt.Fprintf(¶mStr, "ParameterKey=%s,ParameterValue=%s ", k, params[k]) } - return paramStr + return paramStr.String() } func formatTags(tags map[string]string) string { - var tagStr string + var tagStr strings.Builder keys := make([]string, 0, len(tags)) for k := range tags { keys = append(keys, k) } sort.Strings(keys) for _, k := range keys { - tagStr += fmt.Sprintf("Key=%s,Value=%s ", k, tags[k]) + fmt.Fprintf(&tagStr, "Key=%s,Value=%s ", k, tags[k]) } - return tagStr + return tagStr.String() } func deleteHelperMessage(logger *logrus.Logger, params map[string]string, err error) { diff --git a/pkg/output/reporter.go b/pkg/output/reporter.go index 50fa564cf6..70be75ff0c 100644 --- a/pkg/output/reporter.go +++ b/pkg/output/reporter.go @@ -36,7 +36,7 @@ func NewStructuredReporter(r reporter.Logger) reporter.Logger { return &StructuredReporter{inner: r} } -func (r *StructuredReporter) Errorf(format string, args ...interface{}) error { +func (r *StructuredReporter) Errorf(format string, args ...any) error { err := fmt.Errorf(format, args...) if !PrintError(err) { return r.inner.Errorf(format, args...) @@ -44,17 +44,17 @@ func (r *StructuredReporter) Errorf(format string, args ...interface{}) error { return err } -func (r *StructuredReporter) Warnf(format string, args ...interface{}) { +func (r *StructuredReporter) Warnf(format string, args ...any) { if !PrintWarn(fmt.Errorf(format, args...)) { r.inner.Warnf(format, args...) } } -func (r *StructuredReporter) Debugf(format string, args ...interface{}) { +func (r *StructuredReporter) Debugf(format string, args ...any) { r.inner.Debugf(format, args...) } -func (r *StructuredReporter) Infof(format string, args ...interface{}) { +func (r *StructuredReporter) Infof(format string, args ...any) { r.inner.Infof(format, args...) } diff --git a/pkg/reporter/reporter.go b/pkg/reporter/reporter.go index f8af5e763f..94f46d30f0 100644 --- a/pkg/reporter/reporter.go +++ b/pkg/reporter/reporter.go @@ -27,19 +27,19 @@ import ( type Logger interface { // Debugf logs a debug message with formatted arguments. - Debugf(format string, args ...interface{}) + Debugf(format string, args ...any) // Errorf logs an error message with formatted arguments and returns an error. - Errorf(format string, args ...interface{}) error + Errorf(format string, args ...any) error // Infof logs an info message with formatted arguments. - Infof(format string, args ...interface{}) + Infof(format string, args ...any) // IsTerminal checks if the output is a terminal. IsTerminal() bool // Warnf logs a warning message with formatted arguments. - Warnf(format string, args ...interface{}) + Warnf(format string, args ...any) } // Object is the reported object used by the tool. It prints the messages to the standard output or @@ -48,7 +48,7 @@ type Object struct { } // Debugf prints a debug message with the given format and arguments. -func (r *Object) Debugf(format string, args ...interface{}) { +func (r *Object) Debugf(format string, args ...any) { if !debug.Enabled() { return } @@ -56,7 +56,7 @@ func (r *Object) Debugf(format string, args ...interface{}) { } // Infof prints an informative message with the given format and arguments. -func (r *Object) Infof(format string, args ...interface{}) { +func (r *Object) Infof(format string, args ...any) { message := fmt.Sprintf(format, args...) if color.UseColor() { _, _ = fmt.Fprintf(os.Stdout, "%s%s\n", infoColorPrefix, message) @@ -66,7 +66,7 @@ func (r *Object) Infof(format string, args ...interface{}) { } // Warnf prints an warning message with the given format and arguments. -func (r *Object) Warnf(format string, args ...interface{}) { +func (r *Object) Warnf(format string, args ...any) { message := fmt.Sprintf(format, args...) if color.UseColor() { _, _ = fmt.Fprintf(os.Stderr, "%s%s\n", warnColorPrefix, message) @@ -80,7 +80,7 @@ func (r *Object) Warnf(format string, args ...interface{}) { // report the error and also return it. // //nolint:errcheck -func (r *Object) Errorf(format string, args ...interface{}) error { +func (r *Object) Errorf(format string, args ...any) error { message := fmt.Sprintf(format, args...) if color.UseColor() { _, _ = fmt.Fprintf(os.Stderr, "%s%s\n", errorColorPrefix, message) diff --git a/renovate.json b/renovate.json index 4e179e63d0..5b1613ff2c 100644 --- a/renovate.json +++ b/renovate.json @@ -27,7 +27,7 @@ }, "gomod": { "constraints": { - "go": "1.25.8" + "go": "1.26.4" }, "managerFilePatterns": [ "/(^|/)\\.bingo/[^/]+\\.mod$/" @@ -128,16 +128,6 @@ "sigs.k8s.io/{/,}**" ] }, - { - "description": "Pin k8s.io/apimachinery below the Go 1.26-only line", - "matchManagers": [ - "gomod" - ], - "matchPackageNames": [ - "k8s.io/apimachinery" - ], - "allowedVersions": "< 0.36.0" - }, { "description": "Test and generator stack", "groupName": "testing", From 23ac5e93958e734378d9d738bab3f88ed689ac87 Mon Sep 17 00:00:00 2001 From: lufreita Date: Fri, 3 Jul 2026 15:06:38 -0300 Subject: [PATCH 2/2] ROSAENG-61053 | fix: retarget Go toolchain to 1.26.3 Follow the 1.26.3 rollout pattern used in terraform-provider-rhcs and move the ROSA repo off 1.26.4, which is not available in all required images yet. Align go.mod, Dockerfiles, Renovate, and the committed bingo tool modules to the 1.26.3 baseline. --- .bingo/bingo.mod | 2 +- .bingo/gci.mod | 2 +- .bingo/go-bindata.mod | 2 +- .bingo/golangci-lint.mod | 2 +- .bingo/goreleaser.mod | 2 +- .bingo/mockgen.mod | 4 +++- Dockerfile | 2 +- go.mod | 2 +- images/Dockerfile.e2e | 6 +++--- images/Dockerfile.konflux | 2 +- renovate.json | 2 +- 11 files changed, 15 insertions(+), 13 deletions(-) diff --git a/.bingo/bingo.mod b/.bingo/bingo.mod index 2b2b5467e8..271199eabe 100644 --- a/.bingo/bingo.mod +++ b/.bingo/bingo.mod @@ -1,5 +1,5 @@ module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT -go 1.25.8 +go 1.26.3 require github.com/bwplotka/bingo v0.10.0 diff --git a/.bingo/gci.mod b/.bingo/gci.mod index c1a38bbaea..8057ec6aa3 100644 --- a/.bingo/gci.mod +++ b/.bingo/gci.mod @@ -1,5 +1,5 @@ module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT -go 1.25.8 +go 1.26.3 require github.com/daixiang0/gci v0.14.0 diff --git a/.bingo/go-bindata.mod b/.bingo/go-bindata.mod index 6ec3c50faf..e911d0144f 100644 --- a/.bingo/go-bindata.mod +++ b/.bingo/go-bindata.mod @@ -1,5 +1,5 @@ module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT -go 1.25.8 +go 1.26.3 require github.com/go-bindata/go-bindata v3.1.2+incompatible // go-bindata diff --git a/.bingo/golangci-lint.mod b/.bingo/golangci-lint.mod index 52b5c8bb78..033d71f80b 100644 --- a/.bingo/golangci-lint.mod +++ b/.bingo/golangci-lint.mod @@ -1,5 +1,5 @@ module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT -go 1.25.8 +go 1.26.3 require github.com/golangci/golangci-lint/v2 v2.12.2 // cmd/golangci-lint diff --git a/.bingo/goreleaser.mod b/.bingo/goreleaser.mod index 06401f9044..94a0e6be87 100644 --- a/.bingo/goreleaser.mod +++ b/.bingo/goreleaser.mod @@ -1,6 +1,6 @@ module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT -go 1.25.8 +go 1.26.3 require ( al.essio.dev/pkg/shellescape v1.6.0 // indirect diff --git a/.bingo/mockgen.mod b/.bingo/mockgen.mod index 177c08515b..5a47ec5cf8 100644 --- a/.bingo/mockgen.mod +++ b/.bingo/mockgen.mod @@ -1,3 +1,5 @@ module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT -go 1.25.8 +go 1.26.3 + +require go.uber.org/mock v0.4.0 // mockgen diff --git a/Dockerfile b/Dockerfile index 8167315cef..6d2d02a73e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM registry.access.redhat.com/ubi9/go-toolset:1.26.4-1782852234 AS builder +FROM registry.access.redhat.com/ubi9/go-toolset:1.26.3 AS builder COPY --chown=1001:0 . . ENV GOFLAGS=-buildvcs=false diff --git a/go.mod b/go.mod index 66e843b3d9..392576826a 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/openshift/rosa -go 1.26.4 +go 1.26.3 require ( github.com/AlecAivazis/survey/v2 v2.3.7 diff --git a/images/Dockerfile.e2e b/images/Dockerfile.e2e index 228c4825b4..6add3c8dc8 100644 --- a/images/Dockerfile.e2e +++ b/images/Dockerfile.e2e @@ -1,5 +1,5 @@ # The image is for Prow CI steps to manage the ROSA cluster lifecycle and testing -FROM registry.access.redhat.com/ubi9/go-toolset:1.26.4-1782852234 as builder +FROM registry.access.redhat.com/ubi9/go-toolset:1.26.3 as builder WORKDIR /rosa USER root ENV GOBIN=/go/bin @@ -13,13 +13,13 @@ RUN go test -c -o /go/bin/rosatest ./tests/e2e RUN rosa verify openshift-client RUN rosatest --ginkgo.no-color --ginkgo.label-filter "e2e-commit" -FROM registry.access.redhat.com/ubi9/go-toolset:1.26.4-1782852234 AS rosa-support +FROM registry.access.redhat.com/ubi9/go-toolset:1.26.3 AS rosa-support WORKDIR /opt/app-root/src/rosa-support RUN go install github.com/openshift-online/rosa-support@latest FROM registry.ci.openshift.org/ci/cli-ocm:latest as ocmcli -FROM registry.access.redhat.com/ubi9/go-toolset:1.26.4-1782852234 +FROM registry.access.redhat.com/ubi9/go-toolset:1.26.3 USER root COPY --from=builder /go/bin/rosa* /usr/bin COPY --from=builder /rosa/tests/ci/data /rosa/tests/ci/data diff --git a/images/Dockerfile.konflux b/images/Dockerfile.konflux index e56c19d267..604b55a530 100644 --- a/images/Dockerfile.konflux +++ b/images/Dockerfile.konflux @@ -1,4 +1,4 @@ -FROM registry.access.redhat.com/ubi9/go-toolset:1.26.4-1782852234 AS builder +FROM registry.access.redhat.com/ubi9/go-toolset:1.26.3 AS builder WORKDIR /rosa USER root COPY . . diff --git a/renovate.json b/renovate.json index 5b1613ff2c..00c898d787 100644 --- a/renovate.json +++ b/renovate.json @@ -27,7 +27,7 @@ }, "gomod": { "constraints": { - "go": "1.26.4" + "go": "1.26.3" }, "managerFilePatterns": [ "/(^|/)\\.bingo/[^/]+\\.mod$/"