From bbc8bd4bcebd43faeb2ad009babe307590e06dcf Mon Sep 17 00:00:00 2001 From: lou-lan Date: Tue, 14 Feb 2023 17:37:30 +0800 Subject: [PATCH 01/69] Fix incorrect annotation name in upstream hashing configuration (#9617) --- docs/user-guide/nginx-configuration/annotations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/nginx-configuration/annotations.md b/docs/user-guide/nginx-configuration/annotations.md index 8cc6f4c16..9c79d9d9c 100755 --- a/docs/user-guide/nginx-configuration/annotations.md +++ b/docs/user-guide/nginx-configuration/annotations.md @@ -239,7 +239,7 @@ To enable consistent hashing for a backend: `nginx.ingress.kubernetes.io/upstream-hash-by`: the nginx variable, text value or any combination thereof to use for consistent hashing. For example: `nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri"` or `nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri$host"` or `nginx.ingress.kubernetes.io/upstream-hash-by: "${request_uri}-text-value"` to consistently hash upstream requests by the current request URI. -"subset" hashing can be enabled setting `nginx.ingress.kubernetes.io/upstream-hash-by-subset`: "true". This maps requests to subset of nodes instead of a single one. `upstream-hash-by-subset-size` determines the size of each subset (default 3). +"subset" hashing can be enabled setting `nginx.ingress.kubernetes.io/upstream-hash-by-subset`: "true". This maps requests to subset of nodes instead of a single one. `nginx.ingress.kubernetes.io/upstream-hash-by-subset-size` determines the size of each subset (default 3). Please check the [chashsubset](../../examples/chashsubset/deployment.yaml) example. From 5e85747db71578d3ac828923b72d38f7d7f7027b Mon Sep 17 00:00:00 2001 From: James Strong Date: Tue, 14 Feb 2023 21:33:52 +0100 Subject: [PATCH 02/69] remove tests and regex path checks (#9626) Signed-off-by: James Strong --- go.mod | 1 - go.sum | 2 - internal/ingress/controller/store/store.go | 5 - pkg/util/ingress/ingress.go | 25 ---- pkg/util/ingress/ingress_test.go | 85 ------------- test/e2e/security/invalid_paths.go | 134 --------------------- 6 files changed, 252 deletions(-) delete mode 100644 test/e2e/security/invalid_paths.go diff --git a/go.mod b/go.mod index 1aad274fb..10b9e2fda 100644 --- a/go.mod +++ b/go.mod @@ -77,7 +77,6 @@ require ( github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect - github.com/magefile/mage v1.14.0 // indirect github.com/mailru/easyjson v0.7.6 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect diff --git a/go.sum b/go.sum index 1d99238cb..6e370c655 100644 --- a/go.sum +++ b/go.sum @@ -235,8 +235,6 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo= -github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= diff --git a/internal/ingress/controller/store/store.go b/internal/ingress/controller/store/store.go index 13af28137..b5731c4bf 100644 --- a/internal/ingress/controller/store/store.go +++ b/internal/ingress/controller/store/store.go @@ -59,7 +59,6 @@ import ( "k8s.io/ingress-nginx/internal/ingress/resolver" "k8s.io/ingress-nginx/internal/k8s" "k8s.io/ingress-nginx/pkg/apis/ingress" - ingressutils "k8s.io/ingress-nginx/pkg/util/ingress" ) // IngressFilterFunc decides if an Ingress should be omitted or not @@ -865,10 +864,6 @@ func (s *k8sStore) syncIngress(ing *networkingv1.Ingress) { if path.Path == "" { copyIng.Spec.Rules[ri].HTTP.Paths[pi].Path = "/" } - if !ingressutils.IsSafePath(copyIng, path.Path) { - klog.Warningf("ingress %s contains invalid path %s", key, path.Path) - return - } } } diff --git a/pkg/util/ingress/ingress.go b/pkg/util/ingress/ingress.go index 5fb3ee7b9..7df2cc114 100644 --- a/pkg/util/ingress/ingress.go +++ b/pkg/util/ingress/ingress.go @@ -18,30 +18,15 @@ package ingress import ( "fmt" - "regexp" "strings" - networkingv1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/ingress-nginx/internal/ingress/annotations/parser" "k8s.io/ingress-nginx/internal/k8s" "k8s.io/ingress-nginx/internal/net/ssl" "k8s.io/ingress-nginx/pkg/apis/ingress" "k8s.io/klog/v2" ) -const ( - alphaNumericChars = `\-\.\_\~a-zA-Z0-9/` - regexEnabledChars = `\^\$\[\]\(\)\{\}\*\+` -) - -var ( - // pathAlphaNumeric is a regex validation of something like "^/[a-zA-Z]+$" on path - pathAlphaNumeric = regexp.MustCompile("^/[" + alphaNumericChars + "]*$").MatchString - // pathRegexEnabled is a regex validation of paths that may contain regex. - pathRegexEnabled = regexp.MustCompile("^/[" + alphaNumericChars + regexEnabledChars + "]*$").MatchString -) - func GetRemovedHosts(rucfg, newcfg *ingress.Configuration) []string { oldSet := sets.NewString() newSet := sets.NewString() @@ -246,13 +231,3 @@ func BuildRedirects(servers []*ingress.Server) []*redirect { return redirectServers } - -// IsSafePath verifies if the path used in ingress object contains only valid characters. -// It will behave differently if regex is enabled or not -func IsSafePath(copyIng *networkingv1.Ingress, path string) bool { - isRegex, _ := parser.GetBoolAnnotation("use-regex", copyIng) - if isRegex { - return pathRegexEnabled(path) - } - return pathAlphaNumeric(path) -} diff --git a/pkg/util/ingress/ingress_test.go b/pkg/util/ingress/ingress_test.go index d829a57f1..24597fb6e 100644 --- a/pkg/util/ingress/ingress_test.go +++ b/pkg/util/ingress/ingress_test.go @@ -17,13 +17,8 @@ limitations under the License. package ingress import ( - "fmt" "testing" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - networkingv1 "k8s.io/api/networking/v1" - "k8s.io/ingress-nginx/internal/ingress/annotations/parser" "k8s.io/ingress-nginx/pkg/apis/ingress" ) @@ -135,83 +130,3 @@ func TestIsDynamicConfigurationEnough(t *testing.T) { t.Errorf("Expected new config to not change") } } - -func generateDumbIngressforPathTest(regexEnabled bool) *networkingv1.Ingress { - var annotations = make(map[string]string) - regexAnnotation := fmt.Sprintf("%s/use-regex", parser.AnnotationsPrefix) - if regexEnabled { - annotations[regexAnnotation] = "true" - } - return &networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{ - Name: "dumb", - Namespace: "default", - Annotations: annotations, - }, - } -} - -func TestIsSafePath(t *testing.T) { - tests := []struct { - name string - copyIng *networkingv1.Ingress - path string - want bool - }{ - { - name: "should accept valid path with regex disabled", - want: true, - copyIng: generateDumbIngressforPathTest(false), - path: "/xpto/~user/t-e_st.exe", - }, - { - name: "should accept valid path / with regex disabled", - want: true, - copyIng: generateDumbIngressforPathTest(false), - path: "/", - }, - { - name: "should reject invalid path with invalid chars", - want: false, - copyIng: generateDumbIngressforPathTest(false), - path: "/foo/bar/;xpto", - }, - { - name: "should reject regex path when regex is disabled", - want: false, - copyIng: generateDumbIngressforPathTest(false), - path: "/foo/bar/(.+)", - }, - { - name: "should accept valid path / with regex enabled", - want: true, - copyIng: generateDumbIngressforPathTest(true), - path: "/", - }, - { - name: "should accept regex path when regex is enabled", - want: true, - copyIng: generateDumbIngressforPathTest(true), - path: "/foo/bar/(.+)", - }, - { - name: "should reject regex path when regex is enabled but the path is invalid", - want: false, - copyIng: generateDumbIngressforPathTest(true), - path: "/foo/bar/;xpto", - }, - { - name: "should reject regex path when regex is enabled but the path is invalid", - want: false, - copyIng: generateDumbIngressforPathTest(true), - path: ";xpto", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := IsSafePath(tt.copyIng, tt.path); got != tt.want { - t.Errorf("IsSafePath() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/test/e2e/security/invalid_paths.go b/test/e2e/security/invalid_paths.go deleted file mode 100644 index d75aefc2c..000000000 --- a/test/e2e/security/invalid_paths.go +++ /dev/null @@ -1,134 +0,0 @@ -/* -Copyright 2022 The Kubernetes 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 security - -import ( - "fmt" - "net/http" - "strings" - - "github.com/onsi/ginkgo/v2" - - "k8s.io/ingress-nginx/test/e2e/framework" -) - -const ( - validPath = "/xpto/~user/t-e_st.exe" - invalidPath = "/foo/bar/;xpto" - regexPath = "/foo/bar/(.+)" - host = "securitytest.com" -) - -var ( - annotationRegex = map[string]string{ - "nginx.ingress.kubernetes.io/use-regex": "true", - } -) - -var _ = framework.IngressNginxDescribe("[Security] validate path fields", func() { - f := framework.NewDefaultFramework("validate-path") - - ginkgo.BeforeEach(func() { - f.NewEchoDeployment() - }) - - ginkgo.It("should accept an ingress with valid path", func() { - - ing := framework.NewSingleIngress(host, validPath, host, f.Namespace, framework.EchoService, 80, nil) - - f.EnsureIngress(ing) - - f.WaitForNginxServer(host, - func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) - }) - - f.HTTPTestClient(). - GET(validPath). - WithHeader("Host", host). - Expect(). - Status(http.StatusOK) - }) - - ginkgo.It("should drop an ingress with invalid path", func() { - - ing := framework.NewSingleIngress(host, invalidPath, host, f.Namespace, framework.EchoService, 80, nil) - f.EnsureIngress(ing) - - f.WaitForNginxServer(host, - func(server string) bool { - return !strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) - }) - - f.HTTPTestClient(). - GET(invalidPath). - WithHeader("Host", host). - Expect(). - Status(http.StatusNotFound) - }) - - ginkgo.It("should drop an ingress with regex path and regex disabled", func() { - - ing := framework.NewSingleIngress(host, regexPath, host, f.Namespace, framework.EchoService, 80, nil) - f.EnsureIngress(ing) - - f.WaitForNginxServer(host, - func(server string) bool { - return !strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) - }) - - f.HTTPTestClient(). - GET("/foo/bar/lalala"). - WithHeader("Host", host). - Expect(). - Status(http.StatusNotFound) - }) - - ginkgo.It("should accept an ingress with regex path and regex enabled", func() { - - ing := framework.NewSingleIngress(host, regexPath, host, f.Namespace, framework.EchoService, 80, annotationRegex) - f.EnsureIngress(ing) - - f.WaitForNginxServer(host, - func(server string) bool { - return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) - }) - - f.HTTPTestClient(). - GET("/foo/bar/lalala"). - WithHeader("Host", host). - Expect(). - Status(http.StatusOK) - }) - - ginkgo.It("should reject an ingress with invalid path and regex enabled", func() { - - ing := framework.NewSingleIngress(host, invalidPath, host, f.Namespace, framework.EchoService, 80, annotationRegex) - f.EnsureIngress(ing) - - f.WaitForNginxServer(host, - func(server string) bool { - return !strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) - }) - - f.HTTPTestClient(). - GET(invalidPath). - WithHeader("Host", host). - Expect(). - Status(http.StatusNotFound) - }) -}) From 8afba516e7b14019327dd62da89fcc0c6d094659 Mon Sep 17 00:00:00 2001 From: James Strong Date: Tue, 14 Feb 2023 15:55:09 -0500 Subject: [PATCH 03/69] start 1.6.4 build Signed-off-by: James Strong --- TAG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TAG b/TAG index e37df95ee..9dc820555 100644 --- a/TAG +++ b/TAG @@ -1,2 +1,2 @@ -v1.6.3 +v1.6.4 From 8045cd29fbaaf720dea7586e5b559005250f03c9 Mon Sep 17 00:00:00 2001 From: James Strong Date: Tue, 14 Feb 2023 19:12:18 -0500 Subject: [PATCH 04/69] Release Notes Controller 1.6.4 Helm 4.5.1 Signed-off-by: James Strong --- README.md | 2 +- ...{Changelog-1.6.3.md => Changelog-1.6.4.md} | 14 +- charts/ingress-nginx/Chart.yaml | 6 +- charts/ingress-nginx/README.md | 8 +- ...{Changelog-4.5.0.md => Changelog-4.5.1.md} | 6 +- charts/ingress-nginx/values.yaml | 6 +- deploy/static/provider/aws/deploy.yaml | 42 ++--- .../aws/nlb-with-tls-termination/deploy.yaml | 42 ++--- deploy/static/provider/baremetal/deploy.yaml | 42 ++--- deploy/static/provider/cloud/deploy.yaml | 42 ++--- deploy/static/provider/do/deploy.yaml | 42 ++--- deploy/static/provider/exoscale/deploy.yaml | 42 ++--- deploy/static/provider/kind/deploy.yaml | 42 ++--- deploy/static/provider/scw/deploy.yaml | 42 ++--- docs/e2e-tests.md | 148 +++++++++--------- 15 files changed, 259 insertions(+), 267 deletions(-) rename changelog/{Changelog-1.6.3.md => Changelog-1.6.4.md} (93%) rename charts/ingress-nginx/changelog/{Changelog-4.5.0.md => Changelog-4.5.1.md} (82%) diff --git a/README.md b/README.md index 6d3fb7873..855c47418 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ the versions listed. Ingress-Nginx versions may work on older versions but the p | Ingress-NGINX version | k8s supported version | Alpine Version | Nginx Version | |-----------------------|------------------------------|----------------|---------------| -| v1.6.3 | 1.26, 1.25, 1.24, 1.23 | 3.17.0 | 1.21.6 | +| v1.6.4 | 1.26, 1.25, 1.24, 1.23 | 3.17.0 | 1.21.6 | | v1.5.1 | 1.25, 1.24, 1.23 | 3.16.2 | 1.21.6 | | v1.4.0 | 1.25, 1.24, 1.23, 1.22 | 3.16.2 | 1.19.10† | | v1.3.1 | 1.24, 1.23, 1.22, 1.21, 1.20 | 3.16.2 | 1.19.10† | diff --git a/changelog/Changelog-1.6.3.md b/changelog/Changelog-1.6.4.md similarity index 93% rename from changelog/Changelog-1.6.3.md rename to changelog/Changelog-1.6.4.md index 39fa5bb24..5f940d1c4 100644 --- a/changelog/Changelog-1.6.3.md +++ b/changelog/Changelog-1.6.4.md @@ -1,13 +1,16 @@ # Changelog -### 1.6.3 +### 1.6.4 Images: - * registry.k8s.io/controller:controller-v1.6.3@sha256:b92667e0afde1103b736e6a3f00dd75ae66eec4e71827d19f19f471699e909d2 - * registry.k8s.io/controller-chroot:controller-v1.6.3@sha256:4b4a249c9a35ac16a8ec0e22f6c522b8707f7e59e656e64a4ad9ace8fea830a4 + * registry.k8s.io/controller:controller-v1.6.4@sha256:15be4666c53052484dd2992efacf2f50ea77a78ae8aa21ccd91af6baaa7ea22f + * registry.k8s.io/controller-chroot:controller-v1.6.4@sha256:0de01e2c316c3ca7847ca13b32d077af7910d07f21a4a82f81061839764f8f81 ### All Changes: +* remove tests and regex path checks (#9626) +* Fix incorrect annotation name in upstream hashing configuration (#9617) +* Release docs for Controller v1.6.3 and Helm v4.5.0 (#9614) * Revert Implement pathType validation (#9511) (#9607) * update history and allow to pass a target test (#9605) * Allow to pass a target test (#9542) @@ -19,7 +22,6 @@ Images: * Add CORS template check inside location for externalAuth.SignURL (#8814) * fix(grafana-dashboard): remove hardcoded namespace references (#9523) * Replace deprecated command with environment file (#9581) -* add path validation to implementation specific as well (#9573) * add lint on chart before release (#9570) * Switch logic on path type validation and setting it to false (#9543) * tcpproxy: increase buffer size to 16K (#9548) @@ -27,7 +29,6 @@ Images: * Add CORS template check inside location for externalAuth.SignURL (#8814) * fix(grafana-dashboard): remove hardcoded namespace references (#9523) * Align default value for keepalive_request with NGINX default (#9518) -* Implement pathType validation (#9511) * feat(configmap): expose gzip-disable (#9505) * Values: Add missing `controller.metrics.service.labels`. (#9501) * Add docs about orphan_ingress metric (#9514) @@ -89,7 +90,6 @@ Images: * remove the configmap related permissions (#9310) * remove hardcoded datasource from grafana dashboard (#9284) * update gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b to 3.0.0 (#9277) -* Validate ingress path fields (#9309) * added SAN to cert create command (#9295) * Missing controller.ingressClass (#9304) * OpenTelemetry static linking (#9286) @@ -133,4 +133,4 @@ Images: * Bump actions/dependency-review-action from 2.5.1 to 3.0.0 (#9301) * Bump k8s.io/component-base from 0.25.3 to 0.25.4 (#9300) -**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/controller-controller-v1.5.1...controller-controller-v1.6.3 +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/controller-controller-v1.5.1...controller-controller-v1.6.4 diff --git a/charts/ingress-nginx/Chart.yaml b/charts/ingress-nginx/Chart.yaml index c11859326..89e679d49 100644 --- a/charts/ingress-nginx/Chart.yaml +++ b/charts/ingress-nginx/Chart.yaml @@ -4,10 +4,10 @@ annotations: - "ci: remove setup-helm step (#9404)" - "feat(helm): Optionally use cert-manager instead admission patch (#9279)" - "run helm release on main only and when the chart/value changes only (#9290)" - - "Update Ingress-Nginx version controller-v1.6.3" + - "Update Ingress-Nginx version controller-v1.6.4" artifacthub.io/prerelease: "false" apiVersion: v2 -appVersion: 1.6.3 +appVersion: 1.6.4 description: Ingress controller for Kubernetes using NGINX as a reverse proxy and load balancer engine: gotpl @@ -24,4 +24,4 @@ maintainers: name: ingress-nginx sources: - https://github.com/kubernetes/ingress-nginx -version: 4.5.0 +version: 4.5.1 diff --git a/charts/ingress-nginx/README.md b/charts/ingress-nginx/README.md index cb454b535..6c5437a26 100644 --- a/charts/ingress-nginx/README.md +++ b/charts/ingress-nginx/README.md @@ -2,7 +2,7 @@ [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Ingress controller for Kubernetes using NGINX as a reverse proxy and load balancer -![Version: 4.5.0](https://img.shields.io/badge/Version-4.5.0-informational?style=flat-square) ![AppVersion: 1.6.3](https://img.shields.io/badge/AppVersion-1.6.3-informational?style=flat-square) +![Version: 4.5.1](https://img.shields.io/badge/Version-4.5.1-informational?style=flat-square) ![AppVersion: 1.6.4](https://img.shields.io/badge/AppVersion-1.6.4-informational?style=flat-square) To use, add `ingressClassName: nginx` spec field or the `kubernetes.io/ingress.class: nginx` annotation to your Ingress resources. @@ -333,13 +333,13 @@ Kubernetes: `>=1.20.0-0` | controller.hostname | object | `{}` | Optionally customize the pod hostname. | | controller.image.allowPrivilegeEscalation | bool | `true` | | | controller.image.chroot | bool | `false` | | -| controller.image.digest | string | `"sha256:b92667e0afde1103b736e6a3f00dd75ae66eec4e71827d19f19f471699e909d2"` | | -| controller.image.digestChroot | string | `"sha256:4b4a249c9a35ac16a8ec0e22f6c522b8707f7e59e656e64a4ad9ace8fea830a4"` | | +| controller.image.digest | string | `"sha256:15be4666c53052484dd2992efacf2f50ea77a78ae8aa21ccd91af6baaa7ea22f"` | | +| controller.image.digestChroot | string | `"sha256:0de01e2c316c3ca7847ca13b32d077af7910d07f21a4a82f81061839764f8f81"` | | | controller.image.image | string | `"ingress-nginx/controller"` | | | controller.image.pullPolicy | string | `"IfNotPresent"` | | | controller.image.registry | string | `"registry.k8s.io"` | | | controller.image.runAsUser | int | `101` | | -| controller.image.tag | string | `"v1.6.3"` | | +| controller.image.tag | string | `"v1.6.4"` | | | controller.ingressClass | string | `"nginx"` | For backwards compatibility with ingress.class annotation, use ingressClass. Algorithm is as follows, first ingressClassName is considered, if not present, controller looks for ingress.class annotation | | controller.ingressClassByName | bool | `false` | Process IngressClass per name (additionally as per spec.controller). | | controller.ingressClassResource.controllerValue | string | `"k8s.io/ingress-nginx"` | Controller-value of the controller that is processing this ingressClass | diff --git a/charts/ingress-nginx/changelog/Changelog-4.5.0.md b/charts/ingress-nginx/changelog/Changelog-4.5.1.md similarity index 82% rename from charts/ingress-nginx/changelog/Changelog-4.5.0.md rename to charts/ingress-nginx/changelog/Changelog-4.5.1.md index ba4b52cbc..ebe78f49c 100644 --- a/charts/ingress-nginx/changelog/Changelog-4.5.0.md +++ b/charts/ingress-nginx/changelog/Changelog-4.5.1.md @@ -2,12 +2,12 @@ This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). -### 4.5.0 +### 4.5.1 * add lint on chart before release (#9570) * ci: remove setup-helm step (#9404) * feat(helm): Optionally use cert-manager instead admission patch (#9279) * run helm release on main only and when the chart/value changes only (#9290) -* Update Ingress-Nginx version controller-v1.6.3 +* Update Ingress-Nginx version controller-v1.6.4 -**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.4.3...helm-chart-4.5.0 +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.4.3...helm-chart-4.5.1 diff --git a/charts/ingress-nginx/values.yaml b/charts/ingress-nginx/values.yaml index 34e1cf6ef..202cd4a23 100644 --- a/charts/ingress-nginx/values.yaml +++ b/charts/ingress-nginx/values.yaml @@ -23,9 +23,9 @@ controller: ## for backwards compatibility consider setting the full image url via the repository value below ## use *either* current default registry/image or repository format or installing chart by providing the values.yaml will fail ## repository: - tag: "v1.6.3" - digest: sha256:b92667e0afde1103b736e6a3f00dd75ae66eec4e71827d19f19f471699e909d2 - digestChroot: sha256:4b4a249c9a35ac16a8ec0e22f6c522b8707f7e59e656e64a4ad9ace8fea830a4 + tag: "v1.6.4" + digest: sha256:15be4666c53052484dd2992efacf2f50ea77a78ae8aa21ccd91af6baaa7ea22f + digestChroot: sha256:0de01e2c316c3ca7847ca13b32d077af7910d07f21a4a82f81061839764f8f81 pullPolicy: IfNotPresent # www-data -> uid 101 runAsUser: 101 diff --git a/deploy/static/provider/aws/deploy.yaml b/deploy/static/provider/aws/deploy.yaml index c79412536..487340a73 100644 --- a/deploy/static/provider/aws/deploy.yaml +++ b/deploy/static/provider/aws/deploy.yaml @@ -15,7 +15,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx --- @@ -27,7 +27,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx --- @@ -39,7 +39,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx rules: @@ -129,7 +129,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx rules: @@ -148,7 +148,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx rules: - apiGroups: @@ -230,7 +230,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission rules: - apiGroups: @@ -249,7 +249,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx roleRef: @@ -269,7 +269,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx roleRef: @@ -288,7 +288,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io @@ -307,7 +307,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission roleRef: apiGroup: rbac.authorization.k8s.io @@ -328,7 +328,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx --- @@ -344,7 +344,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx spec: @@ -377,7 +377,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller-admission namespace: ingress-nginx spec: @@ -400,7 +400,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx spec: @@ -440,7 +440,7 @@ spec: fieldPath: metadata.namespace - name: LD_PRELOAD value: /usr/local/lib/libmimalloc.so - image: registry.k8s.io/ingress-nginx/controller:v1.6.3@sha256:b92667e0afde1103b736e6a3f00dd75ae66eec4e71827d19f19f471699e909d2 + image: registry.k8s.io/ingress-nginx/controller:v1.6.4@sha256:15be4666c53052484dd2992efacf2f50ea77a78ae8aa21ccd91af6baaa7ea22f imagePullPolicy: IfNotPresent lifecycle: preStop: @@ -512,7 +512,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-create namespace: ingress-nginx spec: @@ -523,7 +523,7 @@ spec: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-create spec: containers: @@ -559,7 +559,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-patch namespace: ingress-nginx spec: @@ -570,7 +570,7 @@ spec: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-patch spec: containers: @@ -608,7 +608,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: nginx spec: controller: k8s.io/ingress-nginx @@ -621,7 +621,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission webhooks: - admissionReviewVersions: diff --git a/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml b/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml index fae1c5d61..4763623c8 100644 --- a/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml +++ b/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml @@ -15,7 +15,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx --- @@ -27,7 +27,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx --- @@ -39,7 +39,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx rules: @@ -129,7 +129,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx rules: @@ -148,7 +148,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx rules: - apiGroups: @@ -230,7 +230,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission rules: - apiGroups: @@ -249,7 +249,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx roleRef: @@ -269,7 +269,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx roleRef: @@ -288,7 +288,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io @@ -307,7 +307,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission roleRef: apiGroup: rbac.authorization.k8s.io @@ -335,7 +335,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx --- @@ -353,7 +353,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx spec: @@ -386,7 +386,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller-admission namespace: ingress-nginx spec: @@ -409,7 +409,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx spec: @@ -449,7 +449,7 @@ spec: fieldPath: metadata.namespace - name: LD_PRELOAD value: /usr/local/lib/libmimalloc.so - image: registry.k8s.io/ingress-nginx/controller:v1.6.3@sha256:b92667e0afde1103b736e6a3f00dd75ae66eec4e71827d19f19f471699e909d2 + image: registry.k8s.io/ingress-nginx/controller:v1.6.4@sha256:15be4666c53052484dd2992efacf2f50ea77a78ae8aa21ccd91af6baaa7ea22f imagePullPolicy: IfNotPresent lifecycle: preStop: @@ -524,7 +524,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-create namespace: ingress-nginx spec: @@ -535,7 +535,7 @@ spec: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-create spec: containers: @@ -571,7 +571,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-patch namespace: ingress-nginx spec: @@ -582,7 +582,7 @@ spec: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-patch spec: containers: @@ -620,7 +620,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: nginx spec: controller: k8s.io/ingress-nginx @@ -633,7 +633,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission webhooks: - admissionReviewVersions: diff --git a/deploy/static/provider/baremetal/deploy.yaml b/deploy/static/provider/baremetal/deploy.yaml index 245978140..a642d67da 100644 --- a/deploy/static/provider/baremetal/deploy.yaml +++ b/deploy/static/provider/baremetal/deploy.yaml @@ -15,7 +15,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx --- @@ -27,7 +27,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx --- @@ -39,7 +39,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx rules: @@ -129,7 +129,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx rules: @@ -148,7 +148,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx rules: - apiGroups: @@ -230,7 +230,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission rules: - apiGroups: @@ -249,7 +249,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx roleRef: @@ -269,7 +269,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx roleRef: @@ -288,7 +288,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io @@ -307,7 +307,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission roleRef: apiGroup: rbac.authorization.k8s.io @@ -328,7 +328,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx --- @@ -340,7 +340,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx spec: @@ -372,7 +372,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller-admission namespace: ingress-nginx spec: @@ -395,7 +395,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx spec: @@ -434,7 +434,7 @@ spec: fieldPath: metadata.namespace - name: LD_PRELOAD value: /usr/local/lib/libmimalloc.so - image: registry.k8s.io/ingress-nginx/controller:v1.6.3@sha256:b92667e0afde1103b736e6a3f00dd75ae66eec4e71827d19f19f471699e909d2 + image: registry.k8s.io/ingress-nginx/controller:v1.6.4@sha256:15be4666c53052484dd2992efacf2f50ea77a78ae8aa21ccd91af6baaa7ea22f imagePullPolicy: IfNotPresent lifecycle: preStop: @@ -506,7 +506,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-create namespace: ingress-nginx spec: @@ -517,7 +517,7 @@ spec: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-create spec: containers: @@ -553,7 +553,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-patch namespace: ingress-nginx spec: @@ -564,7 +564,7 @@ spec: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-patch spec: containers: @@ -602,7 +602,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: nginx spec: controller: k8s.io/ingress-nginx @@ -615,7 +615,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission webhooks: - admissionReviewVersions: diff --git a/deploy/static/provider/cloud/deploy.yaml b/deploy/static/provider/cloud/deploy.yaml index 9bc28ec80..8b09efac1 100644 --- a/deploy/static/provider/cloud/deploy.yaml +++ b/deploy/static/provider/cloud/deploy.yaml @@ -15,7 +15,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx --- @@ -27,7 +27,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx --- @@ -39,7 +39,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx rules: @@ -129,7 +129,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx rules: @@ -148,7 +148,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx rules: - apiGroups: @@ -230,7 +230,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission rules: - apiGroups: @@ -249,7 +249,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx roleRef: @@ -269,7 +269,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx roleRef: @@ -288,7 +288,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io @@ -307,7 +307,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission roleRef: apiGroup: rbac.authorization.k8s.io @@ -328,7 +328,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx --- @@ -340,7 +340,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx spec: @@ -373,7 +373,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller-admission namespace: ingress-nginx spec: @@ -396,7 +396,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx spec: @@ -436,7 +436,7 @@ spec: fieldPath: metadata.namespace - name: LD_PRELOAD value: /usr/local/lib/libmimalloc.so - image: registry.k8s.io/ingress-nginx/controller:v1.6.3@sha256:b92667e0afde1103b736e6a3f00dd75ae66eec4e71827d19f19f471699e909d2 + image: registry.k8s.io/ingress-nginx/controller:v1.6.4@sha256:15be4666c53052484dd2992efacf2f50ea77a78ae8aa21ccd91af6baaa7ea22f imagePullPolicy: IfNotPresent lifecycle: preStop: @@ -508,7 +508,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-create namespace: ingress-nginx spec: @@ -519,7 +519,7 @@ spec: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-create spec: containers: @@ -555,7 +555,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-patch namespace: ingress-nginx spec: @@ -566,7 +566,7 @@ spec: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-patch spec: containers: @@ -604,7 +604,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: nginx spec: controller: k8s.io/ingress-nginx @@ -617,7 +617,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission webhooks: - admissionReviewVersions: diff --git a/deploy/static/provider/do/deploy.yaml b/deploy/static/provider/do/deploy.yaml index b17da8a07..7461d9794 100644 --- a/deploy/static/provider/do/deploy.yaml +++ b/deploy/static/provider/do/deploy.yaml @@ -15,7 +15,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx --- @@ -27,7 +27,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx --- @@ -39,7 +39,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx rules: @@ -129,7 +129,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx rules: @@ -148,7 +148,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx rules: - apiGroups: @@ -230,7 +230,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission rules: - apiGroups: @@ -249,7 +249,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx roleRef: @@ -269,7 +269,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx roleRef: @@ -288,7 +288,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io @@ -307,7 +307,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission roleRef: apiGroup: rbac.authorization.k8s.io @@ -329,7 +329,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx --- @@ -343,7 +343,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx spec: @@ -376,7 +376,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller-admission namespace: ingress-nginx spec: @@ -399,7 +399,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx spec: @@ -439,7 +439,7 @@ spec: fieldPath: metadata.namespace - name: LD_PRELOAD value: /usr/local/lib/libmimalloc.so - image: registry.k8s.io/ingress-nginx/controller:v1.6.3@sha256:b92667e0afde1103b736e6a3f00dd75ae66eec4e71827d19f19f471699e909d2 + image: registry.k8s.io/ingress-nginx/controller:v1.6.4@sha256:15be4666c53052484dd2992efacf2f50ea77a78ae8aa21ccd91af6baaa7ea22f imagePullPolicy: IfNotPresent lifecycle: preStop: @@ -511,7 +511,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-create namespace: ingress-nginx spec: @@ -522,7 +522,7 @@ spec: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-create spec: containers: @@ -558,7 +558,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-patch namespace: ingress-nginx spec: @@ -569,7 +569,7 @@ spec: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-patch spec: containers: @@ -607,7 +607,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: nginx spec: controller: k8s.io/ingress-nginx @@ -620,7 +620,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission webhooks: - admissionReviewVersions: diff --git a/deploy/static/provider/exoscale/deploy.yaml b/deploy/static/provider/exoscale/deploy.yaml index d93497323..be0e2f587 100644 --- a/deploy/static/provider/exoscale/deploy.yaml +++ b/deploy/static/provider/exoscale/deploy.yaml @@ -15,7 +15,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx --- @@ -27,7 +27,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx --- @@ -39,7 +39,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx rules: @@ -129,7 +129,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx rules: @@ -148,7 +148,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx rules: - apiGroups: @@ -230,7 +230,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission rules: - apiGroups: @@ -249,7 +249,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx roleRef: @@ -269,7 +269,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx roleRef: @@ -288,7 +288,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io @@ -307,7 +307,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission roleRef: apiGroup: rbac.authorization.k8s.io @@ -328,7 +328,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx --- @@ -349,7 +349,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx spec: @@ -382,7 +382,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller-admission namespace: ingress-nginx spec: @@ -405,7 +405,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx spec: @@ -445,7 +445,7 @@ spec: fieldPath: metadata.namespace - name: LD_PRELOAD value: /usr/local/lib/libmimalloc.so - image: registry.k8s.io/ingress-nginx/controller:v1.6.3@sha256:b92667e0afde1103b736e6a3f00dd75ae66eec4e71827d19f19f471699e909d2 + image: registry.k8s.io/ingress-nginx/controller:v1.6.4@sha256:15be4666c53052484dd2992efacf2f50ea77a78ae8aa21ccd91af6baaa7ea22f imagePullPolicy: IfNotPresent lifecycle: preStop: @@ -517,7 +517,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-create namespace: ingress-nginx spec: @@ -528,7 +528,7 @@ spec: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-create spec: containers: @@ -564,7 +564,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-patch namespace: ingress-nginx spec: @@ -575,7 +575,7 @@ spec: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-patch spec: containers: @@ -613,7 +613,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: nginx spec: controller: k8s.io/ingress-nginx @@ -626,7 +626,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission webhooks: - admissionReviewVersions: diff --git a/deploy/static/provider/kind/deploy.yaml b/deploy/static/provider/kind/deploy.yaml index 8c9e96891..abb310999 100644 --- a/deploy/static/provider/kind/deploy.yaml +++ b/deploy/static/provider/kind/deploy.yaml @@ -15,7 +15,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx --- @@ -27,7 +27,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx --- @@ -39,7 +39,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx rules: @@ -129,7 +129,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx rules: @@ -148,7 +148,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx rules: - apiGroups: @@ -230,7 +230,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission rules: - apiGroups: @@ -249,7 +249,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx roleRef: @@ -269,7 +269,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx roleRef: @@ -288,7 +288,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io @@ -307,7 +307,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission roleRef: apiGroup: rbac.authorization.k8s.io @@ -328,7 +328,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx --- @@ -340,7 +340,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx spec: @@ -372,7 +372,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller-admission namespace: ingress-nginx spec: @@ -395,7 +395,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx spec: @@ -440,7 +440,7 @@ spec: fieldPath: metadata.namespace - name: LD_PRELOAD value: /usr/local/lib/libmimalloc.so - image: registry.k8s.io/ingress-nginx/controller:v1.6.3@sha256:b92667e0afde1103b736e6a3f00dd75ae66eec4e71827d19f19f471699e909d2 + image: registry.k8s.io/ingress-nginx/controller:v1.6.4@sha256:15be4666c53052484dd2992efacf2f50ea77a78ae8aa21ccd91af6baaa7ea22f imagePullPolicy: IfNotPresent lifecycle: preStop: @@ -522,7 +522,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-create namespace: ingress-nginx spec: @@ -533,7 +533,7 @@ spec: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-create spec: containers: @@ -569,7 +569,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-patch namespace: ingress-nginx spec: @@ -580,7 +580,7 @@ spec: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-patch spec: containers: @@ -618,7 +618,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: nginx spec: controller: k8s.io/ingress-nginx @@ -631,7 +631,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission webhooks: - admissionReviewVersions: diff --git a/deploy/static/provider/scw/deploy.yaml b/deploy/static/provider/scw/deploy.yaml index edd00a98d..fdc3c6cde 100644 --- a/deploy/static/provider/scw/deploy.yaml +++ b/deploy/static/provider/scw/deploy.yaml @@ -15,7 +15,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx --- @@ -27,7 +27,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx --- @@ -39,7 +39,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx rules: @@ -129,7 +129,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx rules: @@ -148,7 +148,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx rules: - apiGroups: @@ -230,7 +230,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission rules: - apiGroups: @@ -249,7 +249,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx namespace: ingress-nginx roleRef: @@ -269,7 +269,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission namespace: ingress-nginx roleRef: @@ -288,7 +288,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io @@ -307,7 +307,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission roleRef: apiGroup: rbac.authorization.k8s.io @@ -329,7 +329,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx --- @@ -343,7 +343,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx spec: @@ -376,7 +376,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller-admission namespace: ingress-nginx spec: @@ -399,7 +399,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-controller namespace: ingress-nginx spec: @@ -439,7 +439,7 @@ spec: fieldPath: metadata.namespace - name: LD_PRELOAD value: /usr/local/lib/libmimalloc.so - image: registry.k8s.io/ingress-nginx/controller:v1.6.3@sha256:b92667e0afde1103b736e6a3f00dd75ae66eec4e71827d19f19f471699e909d2 + image: registry.k8s.io/ingress-nginx/controller:v1.6.4@sha256:15be4666c53052484dd2992efacf2f50ea77a78ae8aa21ccd91af6baaa7ea22f imagePullPolicy: IfNotPresent lifecycle: preStop: @@ -511,7 +511,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-create namespace: ingress-nginx spec: @@ -522,7 +522,7 @@ spec: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-create spec: containers: @@ -558,7 +558,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-patch namespace: ingress-nginx spec: @@ -569,7 +569,7 @@ spec: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission-patch spec: containers: @@ -607,7 +607,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: nginx spec: controller: k8s.io/ingress-nginx @@ -620,7 +620,7 @@ metadata: app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - app.kubernetes.io/version: 1.6.3 + app.kubernetes.io/version: 1.6.4 name: ingress-nginx-admission webhooks: - admissionReviewVersions: diff --git a/docs/e2e-tests.md b/docs/e2e-tests.md index 5c67b47aa..9f66e3991 100644 --- a/docs/e2e-tests.md +++ b/docs/e2e-tests.md @@ -21,6 +21,21 @@ Do not try to edit it manually. - [should return an error if the Ingress V1 definition contains invalid annotations](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/admission/admission.go#L201) - [should not return an error for an invalid Ingress when it has unknown class](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/admission/admission.go#L212) +### [modsecurity owasp](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L28) + +- [should enable modsecurity](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L35) +- [should enable modsecurity with transaction ID and OWASP rules](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L53) +- [should disable modsecurity](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L74) +- [should enable modsecurity with snippet](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L91) +- [should enable modsecurity without using 'modsecurity on;'](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L110) +- [should disable modsecurity using 'modsecurity off;'](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L132) +- [should enable modsecurity with snippet and block requests](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L153) +- [should enable modsecurity globally and with modsecurity-snippet block requests](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L189) +- [should enable modsecurity when enable-owasp-modsecurity-crs is set to true](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L225) +- [should enable modsecurity through the config map](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L264) +- [should enable modsecurity through the config map but ignore snippet as disabled by admin](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L305) +- [should disable default modsecurity conf setting when modsecurity-snippet is specified](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L347) + ### [affinitymode](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinitymode.go#L31) - [Balanced affinity mode should balance](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinitymode.go#L34) @@ -194,21 +209,6 @@ Do not try to edit it manually. - [should set mirror-target to https://test.env.com/$request_uri](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/mirror.go#L51) - [should disable mirror-request-body](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/mirror.go#L67) -### [modsecurity owasp](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L28) - -- [should enable modsecurity](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L35) -- [should enable modsecurity with transaction ID and OWASP rules](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L53) -- [should disable modsecurity](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L74) -- [should enable modsecurity with snippet](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L91) -- [should enable modsecurity without using 'modsecurity on;'](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L110) -- [should disable modsecurity using 'modsecurity off;'](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L132) -- [should enable modsecurity with snippet and block requests](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L153) -- [should enable modsecurity globally and with modsecurity-snippet block requests](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L189) -- [should enable modsecurity when enable-owasp-modsecurity-crs is set to true](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L225) -- [should enable modsecurity through the config map](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L264) -- [should enable modsecurity through the config map but ignore snippet as disabled by admin](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L305) -- [should disable default modsecurity conf setting when modsecurity-snippet is specified](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/modsecurity/modsecurity.go#L347) - ### [preserve-trailing-slash](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/preservetrailingslash.go#L27) - [should allow preservation of trailing slashes](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/preservetrailingslash.go#L34) @@ -285,11 +285,6 @@ Do not try to edit it manually. - [should set the X-Forwarded-Prefix to the annotation value](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/xforwardedprefix.go#L35) - [should not add X-Forwarded-Prefix if the annotation value is empty](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/xforwardedprefix.go#L57) -### [denylist-source-range](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/ipdenylist.go#L28) - -- [only deny explicitly denied IPs, allow all others](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/ipdenylist.go#L35) -- [only allow explicitly allowed IPs, deny all others](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/ipdenylist.go#L86) - ### [affinity session-cookie-name](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L35) - [should set sticky cookie SERVERID](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L42) @@ -308,6 +303,14 @@ Do not try to edit it manually. - [should not set secure in cookie with provided false annotation on http](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L435) - [should set secure in cookie with provided false annotation on https](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/affinity.go#L458) +### [rewrite-target use-regex enable-rewrite-log](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L30) + +- [should write rewrite logs](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L37) +- [should use correct longest path match](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L66) +- [should use ~* location modifier if regex annotation is present](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L111) +- [should fail to use longest match for documented warning](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L158) +- [should allow for custom rewrite parameters](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L190) + ### [auth-*](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L39) - [should return status code 200 when no authentication is configured](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L46) @@ -344,13 +347,10 @@ Do not try to edit it manually. - [should return 503 (location was denied)](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L879) - [should add error to the config](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/auth.go#L887) -### [rewrite-target use-regex enable-rewrite-log](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L30) +### [denylist-source-range](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/ipdenylist.go#L28) -- [should write rewrite logs](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L37) -- [should use correct longest path match](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L66) -- [should use ~* location modifier if regex annotation is present](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L111) -- [should fail to use longest match for documented warning](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L158) -- [should allow for custom rewrite parameters](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/rewrite.go#L190) +- [only deny explicitly denied IPs, allow all others](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/ipdenylist.go#L35) +- [only allow explicitly allowed IPs, deny all others](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/annotations/ipdenylist.go#L86) ### [Debug CLI](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/dbg/main.go#L29) @@ -376,26 +376,22 @@ Do not try to edit it manually. - [should apply the annotation to the default backend](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/defaultbackend/with_hosts.go#L38) -### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/e2e.go#L) - -- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/e2e.go#L) - ### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/e2e_test.go#L) - [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/e2e_test.go#L) -### [[Endpointslices] long service name](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/endpointslices/longname.go#L29) - -- [should return 200 when service name has max allowed number of characters 63](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/endpointslices/longname.go#L38) - -### [[TopologyHints] topology aware routing](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/endpointslices/topology.go#L36) - -- [should return 200 when service has topology hints](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/endpointslices/topology.go#L50) - ### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/exec.go#L) - [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/exec.go#L) +### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/healthz.go#L) + +- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/healthz.go#L) + +### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/metrics.go#L) + +- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/metrics.go#L) + ### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/fastcgi_helloserver.go#L) - [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/fastcgi_helloserver.go#L) @@ -409,10 +405,6 @@ Do not try to edit it manually. - [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/grpc_fortune_teller.go#L) -### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/healthz.go#L) - -- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/healthz.go#L) - ### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/httpexpect/array.go#L) - [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/httpexpect/array.go#L) @@ -465,10 +457,6 @@ Do not try to edit it manually. - [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/logs.go#L) -### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/metrics.go#L) - -- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/metrics.go#L) - ### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/ssl.go#L) - [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/ssl.go#L) @@ -477,14 +465,14 @@ Do not try to edit it manually. - [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/test_context.go#L) -### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/util.go#L) - -- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/util.go#L) - ### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/deployment.go#L) - [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/deployment.go#L) +### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/util.go#L) + +- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/framework/util.go#L) + ### [[Shutdown] Grace period shutdown](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/gracefulshutdown/grace_period.go#L32) - [/healthz should return status code 500 during shutdown grace period](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/gracefulshutdown/grace_period.go#L35) @@ -558,24 +546,10 @@ Do not try to edit it manually. - [handles endpoints only changes consistently (down scaling of replicas vs. empty service)](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/lua/dynamic_configuration.go#L125) - [handles an annotation change](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/lua/dynamic_configuration.go#L171) -### [nginx-configuration](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/nginx/nginx.go#L99) - -- [start nginx with default configuration](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/nginx/nginx.go#L102) -- [fails when using alias directive](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/nginx/nginx.go#L115) -- [fails when using root directive](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/nginx/nginx.go#L124) - ### [[Security] request smuggling](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/security/request_smuggling.go#L32) - [should not return body content from error_page](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/security/request_smuggling.go#L39) -### [[Security] validate path fields](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/security/invalid_paths.go#L42) - -- [should accept an ingress with valid path](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/security/invalid_paths.go#L49) -- [should drop an ingress with invalid path](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/security/invalid_paths.go#L67) -- [should drop an ingress with regex path and regex disabled](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/security/invalid_paths.go#L84) -- [should accept an ingress with regex path and regex enabled](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/security/invalid_paths.go#L101) -- [should reject an ingress with invalid path and regex enabled](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/security/invalid_paths.go#L118) - ### [[Service] backend status code 503](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/servicebackend/service_backend.go#L33) - [should return 503 when backend service does not exist](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/servicebackend/service_backend.go#L36) @@ -596,6 +570,14 @@ Do not try to edit it manually. - [should return 404 when backend service is nil](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/servicebackend/service_nil_backend.go#L38) +### [[Security] modsecurity-snippet](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/modsecurity/modsecurity_snippet.go#L27) + +- [should add value of modsecurity-snippet setting to nginx config](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/modsecurity/modsecurity_snippet.go#L30) + +### [OCSP](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/ocsp/ocsp.go#L42) + +- [should enable OCSP and contain stapling information in the connection](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/ocsp/ocsp.go#L49) + ### [access-log](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/access_log.go#L27) - [use the default configuration](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/access_log.go#L32) @@ -748,10 +730,6 @@ Do not try to edit it manually. - [should add value of main-snippet setting to nginx config](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/main_snippet.go#L31) -### [[Security] modsecurity-snippet](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/modsecurity/modsecurity_snippet.go#L27) - -- [should add value of modsecurity-snippet setting to nginx config](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/modsecurity/modsecurity_snippet.go#L30) - ### [enable-multi-accept](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/multi_accept.go#L27) - [should be enabled by default](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/multi_accept.go#L31) @@ -772,10 +750,6 @@ Do not try to edit it manually. - [Check no tls redirect locations config](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/no_tls_redirect_locations.go#L31) -### [OCSP](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/ocsp/ocsp.go#L42) - -- [should enable OCSP and contain stapling information in the connection](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/ocsp/ocsp.go#L49) - ### [Configure OpenTracing](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/opentracing.go#L48) - [should not exists opentracing directive](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/opentracing.go#L58) @@ -869,11 +843,6 @@ Do not try to edit it manually. - [should not use ports during the HTTP to HTTPS redirection](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/tls.go#L187) - [should not use ports or X-Forwarded-Host during the HTTP to HTTPS redirection](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/tls.go#L205) -### [With enable-ssl-passthrough enabled](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/ssl_passthrough.go#L36) - -- [should enable ssl-passthrough-proxy-port on a different port](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/ssl_passthrough.go#L56) -- [should pass unknown traffic to default backend and handle known traffic](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/ssl_passthrough.go#L79) - ### [[Flag] disable-sync-events](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/disable_sync_events.go#L32) - [should create sync events (default)](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/disable_sync_events.go#L35) @@ -889,6 +858,11 @@ Do not try to edit it manually. - [should set gzip_min_length to 100](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/gzip.go#L78) - [should set gzip_types to application/javascript](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/gzip.go#L89) +### [With enable-ssl-passthrough enabled](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/ssl_passthrough.go#L36) + +- [should enable ssl-passthrough-proxy-port on a different port](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/ssl_passthrough.go#L56) +- [should pass unknown traffic to default backend and handle known traffic](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/settings/ssl_passthrough.go#L79) + ### [[SSL] redirect to HTTPS](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/ssl/http_redirect.go#L29) - [should redirect from HTTP to HTTPS when secret is missing](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/ssl/http_redirect.go#L36) @@ -905,4 +879,22 @@ Do not try to edit it manually. ### [[TCP] tcp-services](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/tcpudp/tcp.go#L37) - [should expose a TCP service](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/tcpudp/tcp.go#L40) -- [should expose an ExternalName TCP service](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/tcpudp/tcp.go#L98) \ No newline at end of file +- [should expose an ExternalName TCP service](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/tcpudp/tcp.go#L98) + +### [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/e2e.go#L) + +- [](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/e2e.go#L) + +### [[Endpointslices] long service name](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/endpointslices/longname.go#L29) + +- [should return 200 when service name has max allowed number of characters 63](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/endpointslices/longname.go#L38) + +### [[TopologyHints] topology aware routing](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/endpointslices/topology.go#L36) + +- [should return 200 when service has topology hints](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/endpointslices/topology.go#L50) + +### [nginx-configuration](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/nginx/nginx.go#L99) + +- [start nginx with default configuration](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/nginx/nginx.go#L102) +- [fails when using alias directive](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/nginx/nginx.go#L115) +- [fails when using root directive](https://github.com/kubernetes/ingress-nginx/tree/main/test/e2e/nginx/nginx.go#L124) \ No newline at end of file From 864316955fce19b7c5397680d91da313b097fc9b Mon Sep 17 00:00:00 2001 From: James Strong Date: Tue, 14 Feb 2023 20:22:36 -0500 Subject: [PATCH 05/69] Release new Helm Chart Signed-off-by: James Strong --- charts/ingress-nginx/Chart.yaml | 2 +- charts/ingress-nginx/README.md | 2 +- .../changelog/{Changelog-4.5.1.md => Changelog-4.5.2.md} | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename charts/ingress-nginx/changelog/{Changelog-4.5.1.md => Changelog-4.5.2.md} (91%) diff --git a/charts/ingress-nginx/Chart.yaml b/charts/ingress-nginx/Chart.yaml index 89e679d49..21779e195 100644 --- a/charts/ingress-nginx/Chart.yaml +++ b/charts/ingress-nginx/Chart.yaml @@ -24,4 +24,4 @@ maintainers: name: ingress-nginx sources: - https://github.com/kubernetes/ingress-nginx -version: 4.5.1 +version: 4.5.2 diff --git a/charts/ingress-nginx/README.md b/charts/ingress-nginx/README.md index 6c5437a26..49bb38273 100644 --- a/charts/ingress-nginx/README.md +++ b/charts/ingress-nginx/README.md @@ -2,7 +2,7 @@ [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Ingress controller for Kubernetes using NGINX as a reverse proxy and load balancer -![Version: 4.5.1](https://img.shields.io/badge/Version-4.5.1-informational?style=flat-square) ![AppVersion: 1.6.4](https://img.shields.io/badge/AppVersion-1.6.4-informational?style=flat-square) +![Version: 4.5.2](https://img.shields.io/badge/Version-4.5.2-informational?style=flat-square) ![AppVersion: 1.6.4](https://img.shields.io/badge/AppVersion-1.6.4-informational?style=flat-square) To use, add `ingressClassName: nginx` spec field or the `kubernetes.io/ingress.class: nginx` annotation to your Ingress resources. diff --git a/charts/ingress-nginx/changelog/Changelog-4.5.1.md b/charts/ingress-nginx/changelog/Changelog-4.5.2.md similarity index 91% rename from charts/ingress-nginx/changelog/Changelog-4.5.1.md rename to charts/ingress-nginx/changelog/Changelog-4.5.2.md index ebe78f49c..b6d8a3b0c 100644 --- a/charts/ingress-nginx/changelog/Changelog-4.5.1.md +++ b/charts/ingress-nginx/changelog/Changelog-4.5.2.md @@ -2,7 +2,7 @@ This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org). -### 4.5.1 +### 4.5.2 * add lint on chart before release (#9570) * ci: remove setup-helm step (#9404) @@ -10,4 +10,4 @@ This file documents all notable changes to [ingress-nginx](https://github.com/ku * run helm release on main only and when the chart/value changes only (#9290) * Update Ingress-Nginx version controller-v1.6.4 -**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.4.3...helm-chart-4.5.1 +**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.4.3...helm-chart-4.5.2 From de793dfeea03bd2db064b1f4c9b63e768a961172 Mon Sep 17 00:00:00 2001 From: Igor Milavec Date: Wed, 15 Feb 2023 14:50:24 +0100 Subject: [PATCH 06/69] Fix rewrite example (#9633) --- docs/examples/rewrite/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/examples/rewrite/README.md b/docs/examples/rewrite/README.md index c529c34ef..5b42e1fc7 100644 --- a/docs/examples/rewrite/README.md +++ b/docs/examples/rewrite/README.md @@ -38,6 +38,7 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: + nginx.ingress.kubernetes.io/use-regex: "true" nginx.ingress.kubernetes.io/rewrite-target: /$2 name: rewrite namespace: default From 9a79b059ca99380ff463f7ff589e8b4f01b19d75 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Feb 2023 05:52:25 -0800 Subject: [PATCH 07/69] Bump golang.org/x/crypto from 0.5.0 to 0.6.0 (#9609) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.5.0 to 0.6.0. - [Release notes](https://github.com/golang/crypto/releases) - [Commits](https://github.com/golang/crypto/compare/v0.5.0...v0.6.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 10b9e2fda..0aa7e6880 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/stretchr/testify v1.8.1 github.com/yudai/gojsondiff v1.0.0 github.com/zakjan/cert-chain-resolver v0.0.0-20211122211144-c6b0b792af9a - golang.org/x/crypto v0.5.0 + golang.org/x/crypto v0.6.0 google.golang.org/grpc v1.52.3 google.golang.org/grpc/examples v0.0.0-20221220003428-4f16fbe410f7 gopkg.in/go-playground/pool.v3 v3.1.1 @@ -99,11 +99,11 @@ require ( github.com/yudai/pp v2.0.1+incompatible // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect golang.org/x/mod v0.7.0 // indirect - golang.org/x/net v0.5.0 // indirect + golang.org/x/net v0.6.0 // indirect golang.org/x/oauth2 v0.3.0 // indirect - golang.org/x/sys v0.4.0 // indirect - golang.org/x/term v0.4.0 // indirect - golang.org/x/text v0.6.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/term v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/go.sum b/go.sum index 6e370c655..47777a30d 100644 --- a/go.sum +++ b/go.sum @@ -403,8 +403,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -471,8 +471,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -542,19 +542,19 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 15ecd2531fdcb722c8c477f0b51b86ab9213723f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Feb 2023 05:54:24 -0800 Subject: [PATCH 08/69] Bump github.com/prometheus/client_golang (#9630) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.11.0 to 1.11.1. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.11.0...v1.11.1) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- images/custom-error-pages/rootfs/go.mod | 2 +- images/custom-error-pages/rootfs/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/images/custom-error-pages/rootfs/go.mod b/images/custom-error-pages/rootfs/go.mod index b39db8b20..515b72c09 100644 --- a/images/custom-error-pages/rootfs/go.mod +++ b/images/custom-error-pages/rootfs/go.mod @@ -2,7 +2,7 @@ module k8s.io/ingress-nginx/custom-error-pages go 1.19 -require github.com/prometheus/client_golang v1.11.0 +require github.com/prometheus/client_golang v1.11.1 require ( github.com/beorn7/perks v1.0.1 // indirect diff --git a/images/custom-error-pages/rootfs/go.sum b/images/custom-error-pages/rootfs/go.sum index 87cd96b26..d071619b7 100644 --- a/images/custom-error-pages/rootfs/go.sum +++ b/images/custom-error-pages/rootfs/go.sum @@ -66,8 +66,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= From 00086ab429d99e3888bc2adf70178d2da66d2f57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Feb 2023 07:06:25 -0800 Subject: [PATCH 09/69] Bump google.golang.org/grpc from 1.52.3 to 1.53.0 (#9610) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.52.3 to 1.53.0. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.52.3...v1.53.0) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 0aa7e6880..d942c1637 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/yudai/gojsondiff v1.0.0 github.com/zakjan/cert-chain-resolver v0.0.0-20211122211144-c6b0b792af9a golang.org/x/crypto v0.6.0 - google.golang.org/grpc v1.52.3 + google.golang.org/grpc v1.53.0 google.golang.org/grpc/examples v0.0.0-20221220003428-4f16fbe410f7 gopkg.in/go-playground/pool.v3 v3.1.1 gopkg.in/mcuadros/go-syslog.v2 v2.3.0 @@ -48,7 +48,7 @@ require ( github.com/BurntSushi/toml v1.0.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/cyphar/filepath-securejoin v0.2.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -100,14 +100,14 @@ require ( go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect golang.org/x/mod v0.7.0 // indirect golang.org/x/net v0.6.0 // indirect - golang.org/x/oauth2 v0.3.0 // indirect + golang.org/x/oauth2 v0.4.0 // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/term v0.5.0 // indirect golang.org/x/text v0.7.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 // indirect + google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index 47777a30d..b1f6269a6 100644 --- a/go.sum +++ b/go.sum @@ -50,8 +50,8 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -479,8 +479,8 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8= -golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk= +golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= +golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -665,8 +665,8 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -679,8 +679,8 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.52.3 h1:pf7sOysg4LdgBqduXveGKrcEwbStiK2rtfghdzlUYDQ= -google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/grpc/examples v0.0.0-20221220003428-4f16fbe410f7 h1:pPsdyuBif+uoyUoL19yuj/TCfUPsmpJHJZhWQ98JGLU= google.golang.org/grpc/examples v0.0.0-20221220003428-4f16fbe410f7/go.mod h1:8pQa1yxxkh+EsxUK8/455D5MSbv3vgmEJqKCH3y17mI= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= From fbdbc24a423a1afa195d5770529fbd873ef68e66 Mon Sep 17 00:00:00 2001 From: Fish-pro Date: Thu, 16 Feb 2023 21:59:39 +0800 Subject: [PATCH 10/69] Optimize the judgment mode to remove redundant transformations (#9588) Signed-off-by: Fish-pro --- internal/ingress/inspector/inspector.go | 6 +++--- internal/nginx/maxmind.go | 2 +- pkg/apis/ingress/types_equals.go | 6 +----- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/internal/ingress/inspector/inspector.go b/internal/ingress/inspector/inspector.go index 98f257997..e7b6c2f10 100644 --- a/internal/ingress/inspector/inspector.go +++ b/internal/ingress/inspector/inspector.go @@ -26,11 +26,11 @@ import ( // if an object contains invalid configurations that may represent a security risk, // and returning an error in this case func DeepInspect(obj interface{}) error { - switch obj.(type) { + switch obj := obj.(type) { case *networking.Ingress: - return InspectIngress(obj.(*networking.Ingress)) + return InspectIngress(obj) case *corev1.Service: - return InspectService(obj.(*corev1.Service)) + return InspectService(obj) default: klog.Warningf("received invalid object to inspect: %T", obj) return nil diff --git a/internal/nginx/maxmind.go b/internal/nginx/maxmind.go index df9fd2231..5aee414cd 100644 --- a/internal/nginx/maxmind.go +++ b/internal/nginx/maxmind.go @@ -165,7 +165,7 @@ func downloadDatabase(dbName string) error { mmdbFile := dbName + dbExtension tarReader := tar.NewReader(archive) - for true { + for { header, err := tarReader.Next() if err == io.EOF { break diff --git a/pkg/apis/ingress/types_equals.go b/pkg/apis/ingress/types_equals.go index 0941e0956..2485f8a7b 100644 --- a/pkg/apis/ingress/types_equals.go +++ b/pkg/apis/ingress/types_equals.go @@ -76,11 +76,7 @@ func (c1 *Configuration) Equal(c2 *Configuration) bool { } } - if c1.BackendConfigChecksum != c2.BackendConfigChecksum { - return false - } - - return true + return c1.BackendConfigChecksum == c2.BackendConfigChecksum } // Equal tests for equality between two Backend types From 1cdd61fb9496b39dc7892ca3f3670784cb58ec58 Mon Sep 17 00:00:00 2001 From: Fish-pro Date: Thu, 16 Feb 2023 22:05:40 +0800 Subject: [PATCH 11/69] Adjust the import package order and use http library variables (#9587) Signed-off-by: Fish-pro --- internal/ingress/controller/checker_test.go | 2 +- internal/ingress/controller/nginx_test.go | 4 ++-- internal/ingress/status/status.go | 2 +- test/e2e/framework/healthz.go | 2 +- test/e2e/framework/metrics.go | 2 +- test/e2e/status/update.go | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/ingress/controller/checker_test.go b/internal/ingress/controller/checker_test.go index 5d9fb1baf..a0d2baafa 100644 --- a/internal/ingress/controller/checker_test.go +++ b/internal/ingress/controller/checker_test.go @@ -122,7 +122,7 @@ func TestNginxCheck(t *testing.T) { } func callHealthz(expErr bool, healthzPath string, mux *http.ServeMux) error { - req, err := http.NewRequest("GET", healthzPath, nil) + req, err := http.NewRequest(http.MethodGet, healthzPath, nil) if err != nil { return fmt.Errorf("healthz error: %v", err) } diff --git a/internal/ingress/controller/nginx_test.go b/internal/ingress/controller/nginx_test.go index 4d3155194..56eb0f324 100644 --- a/internal/ingress/controller/nginx_test.go +++ b/internal/ingress/controller/nginx_test.go @@ -62,7 +62,7 @@ func TestConfigureDynamically(t *testing.T) { Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusCreated) - if r.Method != "POST" { + if r.Method != http.MethodPost { t.Errorf("expected a 'POST' request, got '%s'", r.Method) } @@ -222,7 +222,7 @@ func TestConfigureCertificates(t *testing.T) { Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusCreated) - if r.Method != "POST" { + if r.Method != http.MethodPost { t.Errorf("expected a 'POST' request, got '%s'", r.Method) } diff --git a/internal/ingress/status/status.go b/internal/ingress/status/status.go index eac1f6cb0..a7506705c 100644 --- a/internal/ingress/status/status.go +++ b/internal/ingress/status/status.go @@ -19,7 +19,6 @@ package status import ( "context" "fmt" - v1 "k8s.io/api/networking/v1" "net" "regexp" "sort" @@ -30,6 +29,7 @@ import ( pool "gopkg.in/go-playground/pool.v3" apiv1 "k8s.io/api/core/v1" + v1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/wait" diff --git a/test/e2e/framework/healthz.go b/test/e2e/framework/healthz.go index bef093355..b52c3ffde 100644 --- a/test/e2e/framework/healthz.go +++ b/test/e2e/framework/healthz.go @@ -26,7 +26,7 @@ func (f *Framework) VerifyHealthz(ip string, statusCode int) error { url := fmt.Sprintf("http://%v:10254/healthz", ip) client := &http.Client{} - req, err := http.NewRequest("GET", url, nil) + req, err := http.NewRequest(http.MethodGet, url, nil) if err != nil { return fmt.Errorf("creating GET request for URL %q failed: %v", url, err) } diff --git a/test/e2e/framework/metrics.go b/test/e2e/framework/metrics.go index 349eb4dc3..830237540 100644 --- a/test/e2e/framework/metrics.go +++ b/test/e2e/framework/metrics.go @@ -29,7 +29,7 @@ func (f *Framework) GetMetric(metricName, ip string) (*dto.MetricFamily, error) url := fmt.Sprintf("http://%v:10254/metrics", ip) client := &http.Client{} - req, err := http.NewRequest("GET", url, nil) + req, err := http.NewRequest(http.MethodGet, url, nil) if err != nil { return nil, fmt.Errorf("creating GET request for URL %q failed: %v", url, err) } diff --git a/test/e2e/status/update.go b/test/e2e/status/update.go index 8bedc4d4e..5c6ea4977 100644 --- a/test/e2e/status/update.go +++ b/test/e2e/status/update.go @@ -19,7 +19,6 @@ package settings import ( "context" "fmt" - v1 "k8s.io/api/networking/v1" "log" "net" "strings" @@ -29,6 +28,7 @@ import ( "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/v1" + v1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" From ac8dd3dd53344b948b291530a71bcbffef9ca5d4 Mon Sep 17 00:00:00 2001 From: Fish-pro Date: Thu, 16 Feb 2023 22:05:48 +0800 Subject: [PATCH 12/69] sets.String is deprecated: use generic Set instead. new ways: s1 := Set[string]{} s2 := New[string]() (#9589) Signed-off-by: Fish-pro --- internal/ingress/controller/controller.go | 4 ++-- internal/ingress/controller/store/objectref.go | 8 ++++---- internal/ingress/controller/template/template.go | 10 +++++----- internal/ingress/metric/collectors/socket.go | 4 ++-- internal/ingress/metric/collectors/socket_test.go | 2 +- internal/ingress/metric/dummy.go | 2 +- internal/ingress/metric/main.go | 4 ++-- pkg/util/ingress/ingress.go | 2 +- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/internal/ingress/controller/controller.go b/internal/ingress/controller/controller.go index dab507cdf..a77d2ff37 100644 --- a/internal/ingress/controller/controller.go +++ b/internal/ingress/controller/controller.go @@ -541,11 +541,11 @@ func (n *NGINXController) getDefaultUpstream() *ingress.Backend { } // getConfiguration returns the configuration matching the standard kubernetes ingress -func (n *NGINXController) getConfiguration(ingresses []*ingress.Ingress) (sets.String, []*ingress.Server, *ingress.Configuration) { +func (n *NGINXController) getConfiguration(ingresses []*ingress.Ingress) (sets.Set[string], []*ingress.Server, *ingress.Configuration) { upstreams, servers := n.getBackendServers(ingresses) var passUpstreams []*ingress.SSLPassthroughBackend - hosts := sets.NewString() + hosts := sets.New[string]() for _, server := range servers { // If a location is defined by a prefix string that ends with the slash character, and requests are processed by one of diff --git a/internal/ingress/controller/store/objectref.go b/internal/ingress/controller/store/objectref.go index 9ef13bf07..89ea47251 100644 --- a/internal/ingress/controller/store/objectref.go +++ b/internal/ingress/controller/store/objectref.go @@ -37,13 +37,13 @@ type ObjectRefMap interface { type objectRefMap struct { sync.Mutex - v map[string]sets.String + v map[string]sets.Set[string] } // NewObjectRefMap returns a new ObjectRefMap. func NewObjectRefMap() ObjectRefMap { return &objectRefMap{ - v: make(map[string]sets.String), + v: make(map[string]sets.Set[string]), } } @@ -54,7 +54,7 @@ func (o *objectRefMap) Insert(consumer string, ref ...string) { for _, r := range ref { if _, ok := o.v[r]; !ok { - o.v[r] = sets.NewString(consumer) + o.v[r] = sets.New[string](consumer) continue } o.v[r].Insert(consumer) @@ -112,7 +112,7 @@ func (o *objectRefMap) Reference(ref string) []string { if !ok { return make([]string, 0) } - return consumers.List() + return consumers.UnsortedList() } // ReferencedBy returns all objects referenced by the given object. diff --git a/internal/ingress/controller/template/template.go b/internal/ingress/controller/template/template.go index 315262150..ea9807bd0 100644 --- a/internal/ingress/controller/template/template.go +++ b/internal/ingress/controller/template/template.go @@ -792,7 +792,7 @@ rewrite "(?i)%s" %s break; func filterRateLimits(input interface{}) []ratelimit.Config { ratelimits := []ratelimit.Config{} - found := sets.String{} + found := sets.Set[string]{} servers, ok := input.([]*ingress.Server) if !ok { @@ -815,12 +815,12 @@ func filterRateLimits(input interface{}) []ratelimit.Config { // for connection limit by IP address, one for limiting requests per minute, and // one for limiting requests per second. func buildRateLimitZones(input interface{}) []string { - zones := sets.String{} + zones := sets.Set[string]{} servers, ok := input.([]*ingress.Server) if !ok { klog.Errorf("expected a '[]*ingress.Server' type but %T was returned", input) - return zones.List() + return zones.UnsortedList() } for _, server := range servers { @@ -859,7 +859,7 @@ func buildRateLimitZones(input interface{}) []string { } } - return zones.List() + return zones.UnsortedList() } // buildRateLimit produces an array of limit_req to be used inside the Path of @@ -1654,7 +1654,7 @@ func buildModSecurityForLocation(cfg config.Configuration, location *ingress.Loc func buildMirrorLocations(locs []*ingress.Location) string { var buffer bytes.Buffer - mapped := sets.String{} + mapped := sets.Set[string]{} for _, loc := range locs { if loc.Mirror.Source == "" || loc.Mirror.Target == "" { diff --git a/internal/ingress/metric/collectors/socket.go b/internal/ingress/metric/collectors/socket.go index 9c0376cd3..23048d5d6 100644 --- a/internal/ingress/metric/collectors/socket.go +++ b/internal/ingress/metric/collectors/socket.go @@ -80,7 +80,7 @@ type SocketCollector struct { metricMapping map[string]interface{} - hosts sets.String + hosts sets.Set[string] metricsPerHost bool reportStatusClasses bool @@ -505,7 +505,7 @@ func (sc SocketCollector) Collect(ch chan<- prometheus.Metric) { // SetHosts sets the hostnames that are being served by the ingress controller // This set of hostnames is used to filter the metrics to be exposed -func (sc *SocketCollector) SetHosts(hosts sets.String) { +func (sc *SocketCollector) SetHosts(hosts sets.Set[string]) { sc.hosts = hosts } diff --git a/internal/ingress/metric/collectors/socket_test.go b/internal/ingress/metric/collectors/socket_test.go index f175828cc..4bebc7600 100644 --- a/internal/ingress/metric/collectors/socket_test.go +++ b/internal/ingress/metric/collectors/socket_test.go @@ -485,7 +485,7 @@ func TestCollector(t *testing.T) { t.Errorf("registering collector failed: %s", err) } - sc.SetHosts(sets.NewString("testshop.com")) + sc.SetHosts(sets.New[string]("testshop.com")) for _, d := range c.data { sc.handleMessage([]byte(d)) diff --git a/internal/ingress/metric/dummy.go b/internal/ingress/metric/dummy.go index e34b5ecbd..d8ae0155a 100644 --- a/internal/ingress/metric/dummy.go +++ b/internal/ingress/metric/dummy.go @@ -69,7 +69,7 @@ func (dc DummyCollector) SetSSLInfo([]*ingress.Server) {} func (dc DummyCollector) SetSSLExpireTime([]*ingress.Server) {} // SetHosts ... -func (dc DummyCollector) SetHosts(hosts sets.String) {} +func (dc DummyCollector) SetHosts(hosts sets.Set[string]) {} // OnStartedLeading indicates the pod is not the current leader func (dc DummyCollector) OnStartedLeading(electionID string) {} diff --git a/internal/ingress/metric/main.go b/internal/ingress/metric/main.go index 892c8e8db..cac86e889 100644 --- a/internal/ingress/metric/main.go +++ b/internal/ingress/metric/main.go @@ -52,7 +52,7 @@ type Collector interface { SetSSLInfo(servers []*ingress.Server) // SetHosts sets the hostnames that are being served by the ingress controller - SetHosts(sets.String) + SetHosts(set sets.Set[string]) Start(string) Stop(string) @@ -191,7 +191,7 @@ func (c *collector) DecOrphanIngress(namespace string, name string, orphanityTyp c.ingressController.DecOrphanIngress(namespace, name, orphanityType) } -func (c *collector) SetHosts(hosts sets.String) { +func (c *collector) SetHosts(hosts sets.Set[string]) { c.socket.SetHosts(hosts) } diff --git a/pkg/util/ingress/ingress.go b/pkg/util/ingress/ingress.go index 7df2cc114..39ca3f883 100644 --- a/pkg/util/ingress/ingress.go +++ b/pkg/util/ingress/ingress.go @@ -177,7 +177,7 @@ type redirect struct { // BuildRedirects build the redirects of servers based on configurations and certificates func BuildRedirects(servers []*ingress.Server) []*redirect { - names := sets.String{} + names := sets.Set[string]{} redirectServers := make([]*redirect, 0) for _, srv := range servers { From 57398dee16808fb5f7acc378bc7f84a9761348a9 Mon Sep 17 00:00:00 2001 From: Fish-pro Date: Thu, 16 Feb 2023 22:07:39 +0800 Subject: [PATCH 13/69] Optimize the document for readability (#9551) Signed-off-by: Fish-pro --- docs/how-it-works.md | 2 +- docs/user-guide/k8s-122-migration.md | 6 +++--- docs/user-guide/miscellaneous.md | 2 +- docs/user-guide/monitoring.md | 6 +++--- docs/user-guide/multiple-ingress.md | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/how-it-works.md b/docs/how-it-works.md index 4ad824dc8..894a504dc 100644 --- a/docs/how-it-works.md +++ b/docs/how-it-works.md @@ -10,7 +10,7 @@ The goal of this Ingress controller is the assembly of a configuration file (ngi Usually, a Kubernetes Controller utilizes the [synchronization loop pattern][1] to check if the desired state in the controller is updated or a change is required. To this purpose, we need to build a model using different objects from the cluster, in particular (in no special order) Ingresses, Services, Endpoints, Secrets, and Configmaps to generate a point in time configuration file that reflects the state of the cluster. -To get this object from the cluster, we use [Kubernetes Informers][2], in particular, `FilteredSharedInformer`. This informers allows reacting to changes in using [callbacks][3] to individual changes when a new object is added, modified or removed. Unfortunately, there is no way to know if a particular change is going to affect the final configuration file. Therefore on every change, we have to rebuild a new model from scratch based on the state of cluster and compare it to the current model. If the new model equals to the current one, then we avoid generating a new NGINX configuration and triggering a reload. Otherwise, we check if the difference is only about Endpoints. If so we then send the new list of Endpoints to a Lua handler running inside Nginx using HTTP POST request and again avoid generating a new NGINX configuration and triggering a reload. If the difference between running and new model is about more than just Endpoints we create a new NGINX configuration based on the new model, replace the current model and trigger a reload. +To get this object from the cluster, we use [Kubernetes Informers][2], in particular, `FilteredSharedInformer`. These informers allow reacting to change in using [callbacks][3] to individual changes when a new object is added, modified or removed. Unfortunately, there is no way to know if a particular change is going to affect the final configuration file. Therefore on every change, we have to rebuild a new model from scratch based on the state of cluster and compare it to the current model. If the new model equals to the current one, then we avoid generating a new NGINX configuration and triggering a reload. Otherwise, we check if the difference is only about Endpoints. If so we then send the new list of Endpoints to a Lua handler running inside Nginx using HTTP POST request and again avoid generating a new NGINX configuration and triggering a reload. If the difference between running and new model is about more than just Endpoints we create a new NGINX configuration based on the new model, replace the current model and trigger a reload. One of the uses of the model is to avoid unnecessary reloads when there's no change in the state and to detect conflicts in definitions. diff --git a/docs/user-guide/k8s-122-migration.md b/docs/user-guide/k8s-122-migration.md index 34893f931..9a1ca081d 100644 --- a/docs/user-guide/k8s-122-migration.md +++ b/docs/user-guide/k8s-122-migration.md @@ -131,7 +131,7 @@ and add the value `spec.ingressClassName=nginx` in your Ingress objects. ## I have many ingress objects in my cluster. What should I do? -If you have lot of ingress objects without ingressClass configuration, +If you have a lot of ingress objects without ingressClass configuration, you can run the ingress controller with the flag `--watch-ingress-without-class=true`. ### What is the flag `--watch-ingress-without-class`? @@ -187,10 +187,10 @@ Bear in mind that if you start Ingress-Nginx B with the command line argument `- 4. If you start Ingress-Nginx B with the command line argument `--watch-ingress-without-class=true` and you run Ingress-Nginx A with the command line argument `--watch-ingress-without-class=false` then this is a supported configuration. If you have two ingress-nginx controllers for the same cluster, both running with `--watch-ingress-without-class=true` then there is likely to be a conflict. -## Why am I am seeing "ingress class annotation is not equal to the expected by Ingress Controller" in my controller logs? +## Why am I seeing "ingress class annotation is not equal to the expected by Ingress Controller" in my controller logs? It is highly likely that you will also see the name of the ingress resource in the same error message. -This error message has been observed on use the deprecated annotation (`kubernetes.io/ingress.class`) in a Ingress resource manifest. +This error message has been observed on use the deprecated annotation (`kubernetes.io/ingress.class`) in an Ingress resource manifest. It is recommended to use the `.spec.ingressClassName` field of the Ingress resource, to specify the name of the IngressClass of the Ingress you are defining. ## How can I easily install multiple instances of the ingress-nginx controller in the same cluster? diff --git a/docs/user-guide/miscellaneous.md b/docs/user-guide/miscellaneous.md index 196ea17fc..d9b32d36f 100644 --- a/docs/user-guide/miscellaneous.md +++ b/docs/user-guide/miscellaneous.md @@ -27,7 +27,7 @@ Support for websockets is provided by NGINX out of the box. No special configura The only requirement to avoid the close of connections is the increase of the values of `proxy-read-timeout` and `proxy-send-timeout`. -The default value of this settings is `60 seconds`. +The default value of these settings is `60 seconds`. A more adequate value to support websockets is a value higher than one hour (`3600`). diff --git a/docs/user-guide/monitoring.md b/docs/user-guide/monitoring.md index 807d91afc..281207866 100644 --- a/docs/user-guide/monitoring.md +++ b/docs/user-guide/monitoring.md @@ -170,7 +170,7 @@ According to the above example, this URL will be http://10.192.0.3:31086 - By default request metrics are labeled with the hostname. When you have a wildcard domain ingress, then there will be no metrics for that ingress (to prevent the metrics from exploding in cardinality). To get metrics in this case you need to run the ingress controller with `--metrics-per-host=false` (you will lose labeling by hostname, but still have labeling by ingress). ### Grafana dashboard using ingress resource - - If you want to expose the dashboard for grafana using a ingress resource, then you can : + - If you want to expose the dashboard for grafana using an ingress resource, then you can : - change the service type of the prometheus-server service and the grafana service to "ClusterIP" like this : ``` kubectl -n ingress-nginx edit svc grafana @@ -178,8 +178,8 @@ According to the above example, this URL will be http://10.192.0.3:31086 - This will open the currently deployed service grafana in the default editor configured in your shell (vi/nvim/nano/other) - scroll down to line 34 that looks like "type: NodePort" - change it to look like "type: ClusterIP". Save and exit. - - create a ingress resource with backend as "grafana" and port as "3000" - - Similarly, you can edit the service "prometheus-server" and add a ingress resource. + - create an ingress resource with backend as "grafana" and port as "3000" + - Similarly, you can edit the service "prometheus-server" and add an ingress resource. ## Prometheus and Grafana installation using Service Monitors This document assumes you're using helm and using the kube-prometheus-stack package to install Prometheus and Grafana. diff --git a/docs/user-guide/multiple-ingress.md b/docs/user-guide/multiple-ingress.md index 179041727..6a9457a9c 100644 --- a/docs/user-guide/multiple-ingress.md +++ b/docs/user-guide/multiple-ingress.md @@ -2,7 +2,7 @@ By default, deploying multiple Ingress controllers (e.g., `ingress-nginx` & `gce`) will result in all controllers simultaneously racing to update Ingress status fields in confusing ways. -To fix this problem, use [IngressClasses](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class). The `kubernetes.io/ingress.class` annotation is not being preferred or suggested to use as it can be deprecated in future. Better to use the field `ingress.spec.ingressClassName`. +To fix this problem, use [IngressClasses](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class). The `kubernetes.io/ingress.class` annotation is not being preferred or suggested to use as it can be deprecated in the future. Better to use the field `ingress.spec.ingressClassName`. But, when user has deployed with `scope.enabled`, then the ingress class resource field is not used. From 080c905fabd95fdccbd8deb8efcc108ebd632182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=88=9A=20=20=28=E6=88=90=E9=83=BD=29?= Date: Thu, 16 Feb 2023 22:11:39 +0800 Subject: [PATCH 14/69] code clean for fsnotify (#9571) Signed-off-by: yanggang --- pkg/util/file/file_watcher.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/util/file/file_watcher.go b/pkg/util/file/file_watcher.go index eeb7b5721..daf955e52 100644 --- a/pkg/util/file/file_watcher.go +++ b/pkg/util/file/file_watcher.go @@ -72,8 +72,8 @@ func (f *OSFileWatcher) watch() error { for { select { case event := <-watcher.Events: - if event.Op&fsnotify.Create == fsnotify.Create || - event.Op&fsnotify.Write == fsnotify.Write { + if event.Has(fsnotify.Create) || + event.Has(fsnotify.Write) { if finfo, err := os.Lstat(event.Name); err != nil { log.Printf("can not lstat file: %v\n", err) } else if finfo.Mode()&os.ModeSymlink != 0 { From d6bba853511d01d336fbe3c13b34ae23dc187b62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9?= Date: Thu, 16 Feb 2023 15:15:39 +0100 Subject: [PATCH 15/69] Rework Ginkgo usage (#9522) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Rework Ginkgo usage Currently Ginkgo is launched multiple times with different options to accomodate various use-cases. In particular, some specs needs to be run sequentially because non-namespaced objects are created that conflicts with concurent Helm deployments. However Ginkgo is able to handle such cases natively, in particular specs that needs to be run sequentially are supported (Serial spec). This commit marks the specs that needs to be run sequentially as Serial specs and runs the whole test suite from a single Ginkgo invocation. As a result, a single JUnit report is now generated. Signed-off-by: Hervé Werner * Fix controller error in test Error getting ConfigMap "$NAMESPACE/tcp-services": no object matching key "$NAMESPACE/tcp-services" in local store Signed-off-by: Hervé Werner * Replace "go get" invocations by "go install" Executing "go get" changes the go.mod & go.sum files which is not the case of "go install". Signed-off-by: Hervé Werner * Always clean out the Helm deployment Signed-off-by: Hervé Werner * Add E2E test to verify that changes to one or more configmap trigger an update Signed-off-by: Hervé Werner --------- Signed-off-by: Hervé Werner --- Makefile | 2 +- internal/ingress/controller/store/store.go | 1 - internal/k8s/main.go | 2 +- test/e2e-image/e2e.sh | 77 ++++------- .../namespace-overlays/topology/values.yaml | 19 +-- test/e2e/admission/admission.go | 17 +-- test/e2e/annotations/fastcgi.go | 5 +- test/e2e/endpointslices/topology.go | 19 +-- test/e2e/framework/exec.go | 10 ++ test/e2e/framework/framework.go | 18 ++- test/e2e/framework/influxdb.go | 6 +- test/e2e/framework/k8s.go | 41 ++++-- test/e2e/leaks/lua_ssl.go | 2 +- test/e2e/run-chart-test.sh | 2 +- test/e2e/run-e2e-suite.sh | 46 +------ test/e2e/run-kind-e2e.sh | 2 +- test/e2e/settings/configmap_change.go | 4 + test/e2e/settings/namespace_selector.go | 11 +- test/e2e/settings/ocsp/ocsp.go | 4 +- test/e2e/tcpudp/tcp.go | 129 ++++++++++-------- 20 files changed, 165 insertions(+), 252 deletions(-) diff --git a/Makefile b/Makefile index 25855a224..6037ac39d 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ TAG ?= $(shell cat TAG) # e2e settings # Allow limiting the scope of the e2e tests. By default run everything -FOCUS ?= .* +FOCUS ?= # number of parallel test E2E_NODES ?= 7 # run e2e test suite with tests that check for memory leaks? (default is false) diff --git a/internal/ingress/controller/store/store.go b/internal/ingress/controller/store/store.go index b5731c4bf..7157332c3 100644 --- a/internal/ingress/controller/store/store.go +++ b/internal/ingress/controller/store/store.go @@ -701,7 +701,6 @@ func New( }, } - // TODO: add e2e test to verify that changes to one or more configmap trigger an update changeTriggerUpdate := func(name string) bool { return name == configmap || name == tcp || name == udp } diff --git a/internal/k8s/main.go b/internal/k8s/main.go index e0d2a1660..d61013a9f 100644 --- a/internal/k8s/main.go +++ b/internal/k8s/main.go @@ -78,7 +78,7 @@ func GetNodeIPOrName(kubeClient clientset.Interface, name string, useInternalIP var ( // IngressPodDetails hold information about the ingress-nginx pod IngressPodDetails *PodInfo - // IngressNodeDetails old information about the node running ingress-nginx pod + // IngressNodeDetails hold information about the node running ingress-nginx pod IngressNodeDetails *NodeInfo ) diff --git a/test/e2e-image/e2e.sh b/test/e2e-image/e2e.sh index ed13926fb..f8ecd5337 100755 --- a/test/e2e-image/e2e.sh +++ b/test/e2e-image/e2e.sh @@ -14,70 +14,39 @@ # See the License for the specific language governing permissions and # limitations under the License. -set -e +set -eu NC='\e[0m' BGREEN='\e[32m' -#SLOW_E2E_THRESHOLD=${SLOW_E2E_THRESHOLD:-"5s"} -FOCUS=${FOCUS:-.*} E2E_NODES=${E2E_NODES:-5} E2E_CHECK_LEAKS=${E2E_CHECK_LEAKS:-""} +reportFile="report-e2e-test-suite.xml" ginkgo_args=( - "-randomize-all" - "-flake-attempts=2" - "-fail-fast" - "--show-node-events" + "--fail-fast" + "--flake-attempts=2" + "--junit-report=${reportFile}" + "--nodes=${E2E_NODES}" "--poll-progress-after=180s" -# "-slow-spec-threshold=${SLOW_E2E_THRESHOLD}" - "-succinct" - "-timeout=75m" + "--randomize-all" + "--show-node-events" + "--succinct" + "--timeout=75m" ) -# Variable for the prefix of report filenames -reportFileNamePrefix="report-e2e-test-suite" - -echo -e "${BGREEN}Running e2e test suite (FOCUS=${FOCUS})...${NC}" -ginkgo "${ginkgo_args[@]}" \ - -focus="${FOCUS}" \ - -skip="\[Serial\]|\[MemoryLeak\]|\[TopologyHints\]" \ - -nodes="${E2E_NODES}" \ - --junit-report=$reportFileNamePrefix.xml \ - /e2e.test -# Create configMap out of a compressed report file for extraction later - -# Must be isolated, there is a collision if multiple helms tries to install same clusterRole at same time -echo -e "${BGREEN}Running e2e test for topology aware hints...${NC}" -ginkgo "${ginkgo_args[@]}" \ - -focus="\[TopologyHints\]" \ - -skip="\[Serial\]|\[MemoryLeak\]]" \ - -nodes="${E2E_NODES}" \ - --junit-report=$reportFileNamePrefix-topology.xml \ - /e2e.test -# Create configMap out of a compressed report file for extraction later - -echo -e "${BGREEN}Running e2e test suite with tests that require serial execution...${NC}" -ginkgo "${ginkgo_args[@]}" \ - -focus="\[Serial\]" \ - -skip="\[MemoryLeak\]" \ - --junit-report=$reportFileNamePrefix-serial.xml \ - /e2e.test -# Create configMap out of a compressed report file for extraction later - -if [[ ${E2E_CHECK_LEAKS} != "" ]]; then - echo -e "${BGREEN}Running e2e test suite with tests that check for memory leaks...${NC}" - ginkgo "${ginkgo_args[@]}" \ - -focus="\[MemoryLeak\]" \ - -skip="\[Serial\]" \ - --junit-report=$reportFileNamePrefix-memleak.xml \ - /e2e.test -# Create configMap out of a compressed report file for extraction later +if [ -n "${FOCUS}" ]; then + ginkgo_args+=("--focus=${FOCUS}") fi -for rFile in `ls $reportFileNamePrefix*` -do - gzip -k $rFile - kubectl create cm $rFile.gz --from-file $rFile.gz - kubectl label cm $rFile.gz junitreport=true -done +if [ -z "${E2E_CHECK_LEAKS}" ]; then + ginkgo_args+=("--skip=\[Memory Leak\]") +fi + +echo -e "${BGREEN}Running e2e test suite...${NC}" +(set -x; ginkgo "${ginkgo_args[@]}" /e2e.test) + +# Create configMap out of a compressed report file for extraction later +gzip -k ${reportFile} +kubectl create cm ${reportFile}.gz --from-file ${reportFile}.gz +kubectl label cm ${reportFile}.gz junitreport=true diff --git a/test/e2e-image/namespace-overlays/topology/values.yaml b/test/e2e-image/namespace-overlays/topology/values.yaml index 28b1cad19..5e27f7902 100644 --- a/test/e2e-image/namespace-overlays/topology/values.yaml +++ b/test/e2e-image/namespace-overlays/topology/values.yaml @@ -8,6 +8,7 @@ controller: digest: digestChroot: scope: + # Necessary to allow the ingress controller to get the topology information from the nodes enabled: false config: worker-processes: "1" @@ -19,12 +20,7 @@ controller: periodSeconds: 1 service: type: NodePort - electionID: ingress-controller-leader - ingressClassResource: - # We will create and remove each IC/ClusterRole/ClusterRoleBinding per test so there's no conflict - enabled: false extraArgs: - tcp-services-configmap: $NAMESPACE/tcp-services # e2e tests do not require information about ingress status update-status: "false" terminationGracePeriodSeconds: 1 @@ -33,19 +29,6 @@ controller: enableTopologyAwareRouting: true - # ulimit -c unlimited - # mkdir -p /tmp/coredump - # chmod a+rwx /tmp/coredump - # echo "/tmp/coredump/core.%e.%p.%h.%t" > /proc/sys/kernel/core_pattern - extraVolumeMounts: - - name: coredump - mountPath: /tmp/coredump - - extraVolumes: - - name: coredump - hostPath: - path: /tmp/coredump - rbac: create: true scope: false diff --git a/test/e2e/admission/admission.go b/test/e2e/admission/admission.go index bde98fddf..4a4e31980 100644 --- a/test/e2e/admission/admission.go +++ b/test/e2e/admission/admission.go @@ -32,7 +32,7 @@ import ( "k8s.io/ingress-nginx/test/e2e/framework" ) -var _ = framework.IngressNginxDescribe("[Serial] admission controller", func() { +var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller", func() { f := framework.NewDefaultFramework("admission") ginkgo.BeforeEach(func() { @@ -40,11 +40,6 @@ var _ = framework.IngressNginxDescribe("[Serial] admission controller", func() { f.NewSlowEchoDeployment() }) - ginkgo.AfterEach(func() { - err := uninstallChart(f) - assert.Nil(ginkgo.GinkgoT(), err, "uninstalling helm chart") - }) - ginkgo.It("reject ingress with global-rate-limit annotations when memcached is not configured", func() { host := "admission-test" @@ -216,16 +211,6 @@ var _ = framework.IngressNginxDescribe("[Serial] admission controller", func() { }) }) -func uninstallChart(f *framework.Framework) error { - cmd := exec.Command("helm", "uninstall", "--namespace", f.Namespace, "nginx-ingress") - _, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("unexpected error uninstalling ingress-nginx release: %v", err) - } - - return nil -} - const ( validV1Ingress = ` apiVersion: networking.k8s.io/v1 diff --git a/test/e2e/annotations/fastcgi.go b/test/e2e/annotations/fastcgi.go index 0dc6ae4a4..572eca548 100644 --- a/test/e2e/annotations/fastcgi.go +++ b/test/e2e/annotations/fastcgi.go @@ -21,7 +21,6 @@ import ( "strings" "github.com/onsi/ginkgo/v2" - "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -81,9 +80,7 @@ var _ = framework.DescribeAnnotation("backend-protocol - FastCGI", func() { }, } - cm, err := f.EnsureConfigMap(configuration) - assert.Nil(ginkgo.GinkgoT(), err, "creating configmap") - assert.NotNil(ginkgo.GinkgoT(), cm, "expected a configmap but none returned") + f.EnsureConfigMap(configuration) host := "fastcgi-params-configmap" diff --git a/test/e2e/endpointslices/topology.go b/test/e2e/endpointslices/topology.go index ce913e966..7cc67cedb 100644 --- a/test/e2e/endpointslices/topology.go +++ b/test/e2e/endpointslices/topology.go @@ -21,7 +21,6 @@ import ( "encoding/json" "fmt" "net/http" - "os/exec" "strings" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -33,7 +32,7 @@ import ( "k8s.io/ingress-nginx/test/e2e/framework" ) -var _ = framework.IngressNginxDescribe("[TopologyHints] topology aware routing", func() { +var _ = framework.IngressNginxDescribeSerial("[TopologyHints] topology aware routing", func() { f := framework.NewDefaultFramework("topology") host := "topology-svc.foo.com" @@ -41,12 +40,6 @@ var _ = framework.IngressNginxDescribe("[TopologyHints] topology aware routing", f.NewEchoDeployment(framework.WithDeploymentReplicas(2), framework.WithSvcTopologyAnnotations()) }) - ginkgo.AfterEach(func() { - // we need to uninstall chart because of clusterRole which is not destroyed with namespace - err := uninstallChart(f) - assert.Nil(ginkgo.GinkgoT(), err, "uninstalling helm chart") - }) - ginkgo.It("should return 200 when service has topology hints", func() { annotations := make(map[string]string) @@ -100,13 +93,3 @@ var _ = framework.IngressNginxDescribe("[TopologyHints] topology aware routing", } }) }) - -func uninstallChart(f *framework.Framework) error { - cmd := exec.Command("helm", "uninstall", "--namespace", f.Namespace, "nginx-ingress") - _, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("unexpected error uninstalling ingress-nginx release: %v", err) - } - - return nil -} diff --git a/test/e2e/framework/exec.go b/test/e2e/framework/exec.go index 8c8c7ddb0..0284e768c 100644 --- a/test/e2e/framework/exec.go +++ b/test/e2e/framework/exec.go @@ -152,6 +152,16 @@ func (f *Framework) KubectlProxy(port int) (int, *exec.Cmd, error) { return -1, cmd, fmt.Errorf("failed to parse port from proxy stdout: %s", output) } +func (f *Framework) UninstallChart() error { + cmd := exec.Command("helm", "uninstall", "--namespace", f.Namespace, "nginx-ingress") + _, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("unexpected error uninstalling ingress-nginx release: %v", err) + } + + return nil +} + func startCmdAndStreamOutput(cmd *exec.Cmd) (stdout, stderr io.ReadCloser, err error) { stdout, err = cmd.StdoutPipe() if err != nil { diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go index 662cd0879..cac6dfd20 100644 --- a/test/e2e/framework/framework.go +++ b/test/e2e/framework/framework.go @@ -150,7 +150,11 @@ func (f *Framework) AfterEach() { defer func(kubeClient kubernetes.Interface, ingressclass string) { defer ginkgo.GinkgoRecover() - err := deleteIngressClass(kubeClient, ingressclass) + + err := f.UninstallChart() + assert.Nil(ginkgo.GinkgoT(), err, "uninstalling helm chart") + + err = deleteIngressClass(kubeClient, ingressclass) assert.Nil(ginkgo.GinkgoT(), err, "deleting IngressClass") }(f.KubeClientSet, f.IngressClass) @@ -192,6 +196,11 @@ func IngressNginxDescribe(text string, body func()) bool { return ginkgo.Describe(text, body) } +// IngressNginxDescribeSerial wrapper function for ginkgo describe. Adds namespacing. +func IngressNginxDescribeSerial(text string, body func()) bool { + return ginkgo.Describe(text, ginkgo.Serial, body) +} + // DescribeAnnotation wrapper function for ginkgo describe. Adds namespacing. func DescribeAnnotation(text string, body func()) bool { return ginkgo.Describe("[Annotations] "+text, body) @@ -202,11 +211,6 @@ func DescribeSetting(text string, body func()) bool { return ginkgo.Describe("[Setting] "+text, body) } -// MemoryLeakIt is wrapper function for ginkgo It. Adds "[MemoryLeak]" tag and makes static analysis easier. -func MemoryLeakIt(text string, body interface{}) bool { - return ginkgo.It(text+" [MemoryLeak]", body) -} - // GetNginxIP returns the number of TCP port where NGINX is running func (f *Framework) GetNginxIP() string { s, err := f.KubeClientSet. @@ -387,7 +391,7 @@ func (f *Framework) UpdateNginxConfigMapData(key string, value string) { } // WaitForReload calls the passed function and -// asser it has caused at least 1 reload. +// asserts it has caused at least 1 reload. func (f *Framework) WaitForReload(fn func()) { initialReloadCount := getReloadCount(f.pod, f.Namespace, f.KubeClientSet) diff --git a/test/e2e/framework/influxdb.go b/test/e2e/framework/influxdb.go index c3c0e3421..43a5702e6 100644 --- a/test/e2e/framework/influxdb.go +++ b/test/e2e/framework/influxdb.go @@ -68,9 +68,7 @@ func (f *Framework) NewInfluxDBDeployment() { }, } - cm, err := f.EnsureConfigMap(configuration) - assert.Nil(ginkgo.GinkgoT(), err, "creating an Influxdb deployment") - assert.NotNil(ginkgo.GinkgoT(), cm, "expected a configmap but none returned") + f.EnsureConfigMap(configuration) deployment := &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ @@ -136,7 +134,7 @@ func (f *Framework) NewInfluxDBDeployment() { d := f.EnsureDeployment(deployment) - err = waitForPodsReady(f.KubeClientSet, DefaultTimeout, 1, f.Namespace, metav1.ListOptions{ + err := waitForPodsReady(f.KubeClientSet, DefaultTimeout, 1, f.Namespace, metav1.ListOptions{ LabelSelector: fields.SelectorFromSet(fields.Set(d.Spec.Template.ObjectMeta.Labels)).String(), }) assert.Nil(ginkgo.GinkgoT(), err, "waiting for influxdb pod to become ready") diff --git a/test/e2e/framework/k8s.go b/test/e2e/framework/k8s.go index ef9c522d6..fc3e59b08 100644 --- a/test/e2e/framework/k8s.go +++ b/test/e2e/framework/k8s.go @@ -25,9 +25,7 @@ import ( "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/v1" - api "k8s.io/api/core/v1" core "k8s.io/api/core/v1" - v1 "k8s.io/api/core/v1" networking "k8s.io/api/networking/v1" k8sErrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -36,8 +34,8 @@ import ( "k8s.io/client-go/kubernetes" ) -// EnsureSecret creates a Secret object or returns it if it already exists. -func (f *Framework) EnsureSecret(secret *api.Secret) *api.Secret { +// EnsureSecret creates a Secret object or returns it. +func (f *Framework) EnsureSecret(secret *core.Secret) *core.Secret { err := createSecretWithRetries(f.KubeClientSet, secret.Namespace, secret) assert.Nil(ginkgo.GinkgoT(), err, "creating secret") @@ -48,17 +46,30 @@ func (f *Framework) EnsureSecret(secret *api.Secret) *api.Secret { return s } -// EnsureConfigMap creates a ConfigMap object or returns it if it already exists. -func (f *Framework) EnsureConfigMap(configMap *api.ConfigMap) (*api.ConfigMap, error) { - cm, err := f.KubeClientSet.CoreV1().ConfigMaps(configMap.Namespace).Create(context.TODO(), configMap, metav1.CreateOptions{}) - if err != nil { - if k8sErrors.IsAlreadyExists(err) { - return f.KubeClientSet.CoreV1().ConfigMaps(configMap.Namespace).Update(context.TODO(), configMap, metav1.UpdateOptions{}) - } - return nil, err +// GetConfigMap gets a ConfigMap object from the given namespace, name and returns it, throws error if it does not exist. +func (f *Framework) GetConfigMap(namespace string, name string) *core.ConfigMap { + cm, err := f.KubeClientSet.CoreV1().ConfigMaps(namespace).Get(context.TODO(), name, metav1.GetOptions{}) + assert.Nil(ginkgo.GinkgoT(), err, "getting configmap") + assert.NotNil(ginkgo.GinkgoT(), cm, "expected a configmap but none returned") + return cm +} + +// EnsureConfigMap creates or updates an existing ConfigMap object or returns it. +func (f *Framework) EnsureConfigMap(configMap *core.ConfigMap) *core.ConfigMap { + cm := configMap.DeepCopy() + // Clean out ResourceVersion field if present + if cm.ObjectMeta.ResourceVersion != "" { + cm.ObjectMeta.ResourceVersion = "" } - return cm, nil + res, err := f.KubeClientSet.CoreV1().ConfigMaps(configMap.Namespace).Create(context.TODO(), cm, metav1.CreateOptions{}) + if k8sErrors.IsAlreadyExists(err) { + res, err = f.KubeClientSet.CoreV1().ConfigMaps(configMap.Namespace).Update(context.TODO(), cm, metav1.UpdateOptions{}) + } + assert.Nil(ginkgo.GinkgoT(), err, "updating configmap") + assert.NotNil(ginkgo.GinkgoT(), res, "updating configmap") + + return res } // GetIngress gets an Ingress object from the given namespace, name and returns it, throws error if it does not exists. @@ -293,7 +304,7 @@ func createDeploymentWithRetries(c kubernetes.Interface, namespace string, obj * return retryWithExponentialBackOff(createFunc) } -func createSecretWithRetries(c kubernetes.Interface, namespace string, obj *v1.Secret) error { +func createSecretWithRetries(c kubernetes.Interface, namespace string, obj *core.Secret) error { if obj == nil { return fmt.Errorf("Object provided to create is empty") } @@ -313,7 +324,7 @@ func createSecretWithRetries(c kubernetes.Interface, namespace string, obj *v1.S return retryWithExponentialBackOff(createFunc) } -func createServiceWithRetries(c kubernetes.Interface, namespace string, obj *v1.Service) error { +func createServiceWithRetries(c kubernetes.Interface, namespace string, obj *core.Service) error { if obj == nil { return fmt.Errorf("Object provided to create is empty") } diff --git a/test/e2e/leaks/lua_ssl.go b/test/e2e/leaks/lua_ssl.go index 8ebd05ccb..e63a1e353 100644 --- a/test/e2e/leaks/lua_ssl.go +++ b/test/e2e/leaks/lua_ssl.go @@ -39,7 +39,7 @@ var _ = framework.IngressNginxDescribe("[Memory Leak] Dynamic Certificates", fun f.NewEchoDeployment() }) - framework.MemoryLeakIt("should not leak memory from ingress SSL certificates or configuration updates", func() { + ginkgo.It("should not leak memory from ingress SSL certificates or configuration updates", func() { hostCount := 1000 iterations := 10 diff --git a/test/e2e/run-chart-test.sh b/test/e2e/run-chart-test.sh index e501ca6fe..d01ab4486 100755 --- a/test/e2e/run-chart-test.sh +++ b/test/e2e/run-chart-test.sh @@ -78,7 +78,7 @@ fi if [ "${SKIP_IMAGE_CREATION:-false}" = "false" ]; then if ! command -v ginkgo &> /dev/null; then - go get github.com/onsi/ginkgo/v2/ginkgo@v2.6.1 + go install github.com/onsi/ginkgo/v2/ginkgo@v2.6.1 fi echo "[dev-env] building image" make -C ${DIR}/../../ clean-image build image diff --git a/test/e2e/run-e2e-suite.sh b/test/e2e/run-e2e-suite.sh index 7920c0523..b1de8bf9a 100755 --- a/test/e2e/run-e2e-suite.sh +++ b/test/e2e/run-e2e-suite.sh @@ -49,15 +49,9 @@ if [ "$missing" = true ]; then exit 1 fi -E2E_CHECK_LEAKS=${E2E_CHECK_LEAKS:-} -FOCUS=${FOCUS:-.*} - BASEDIR=$(dirname "$0") NGINX_BASE_IMAGE=$(cat $BASEDIR/../../NGINX_BASE) -export E2E_CHECK_LEAKS -export FOCUS - echo -e "${BGREEN}Granting permissions to ingress-nginx e2e service account...${NC}" kubectl create serviceaccount ingress-nginx-e2e || true kubectl create clusterrolebinding permissive-binding \ @@ -66,7 +60,6 @@ kubectl create clusterrolebinding permissive-binding \ --user=kubelet \ --serviceaccount=default:ingress-nginx-e2e || true - VER=$(kubectl version --client=false -o json |jq '.serverVersion.minor |tonumber') if [ $VER -lt 24 ]; then echo -e "${BGREEN}Waiting service account...${NC}"; \ @@ -76,7 +69,6 @@ if [ $VER -lt 24 ]; then done fi - echo -e "Starting the e2e test pod" kubectl run --rm \ @@ -90,38 +82,10 @@ kubectl run --rm \ e2e --image=nginx-ingress-controller:e2e # Get the junit-reports stored in the configMaps created during e2etests -echo "Getting the report files out now.." +echo "Getting the report file out now.." reportsDir="test/junitreports" -reportFileName="report-e2e-test-suite" -[ ! -e ${reportsDir} ] && mkdir $reportsDir +reportFile="report-e2e-test-suite.xml.gz" +mkdir -p $reportsDir cd $reportsDir - -# TODO: Seeking Rikatz help here to extract in a loop. Tried things like below without success -#for cmName in `k get cm -l junitreport=true -o json | jq '.items[].binaryData | keys[]' | tr '\"' ' '` -#do -# -# -# kubectl get cm -l junitreport=true -o json | jq -r '[.items[].binaryData | to_entries[] | {"key": .key, "value": .value }] | from_entries' -# - -# Below lines successfully extract the report but they are one line per report. -# We only have 3 ginkgo reports so its ok for now -# But still, ideally this should be a loop as talked about in comments a few lines above -kubectl get cm $reportFileName.xml.gz -o "jsonpath={.binaryData['report-e2e-test-suite\.xml\.gz']}" > $reportFileName.xml.gz.base64 -kubectl get cm $reportFileName-serial.xml.gz -o "jsonpath={.binaryData['report-e2e-test-suite-serial\.xml\.gz']}" > $reportFileName-serial.xml.gz.base64 - -cat $reportFileName.xml.gz.base64 | base64 -d > $reportFileName.xml.gz -cat $reportFileName-serial.xml.gz.base64 | base64 -d > $reportFileName-serial.xml.gz - -gzip -d $reportFileName.xml.gz -gzip -d $reportFileName-serial.xml.gz - -rm *.base64 -cd ../.. - -# TODO Temporary: if condition to check if the memleak cm exists and only then try the extract for the memleak report -# -#kubectl get cm $reportFileName-serial -o "jsonpath={.data['report-e2e-test-suite-memleak\.xml\.gz']}" > $reportFileName-memleak.base64 -#cat $reportFileName-memleak.base64 | base64 -d > $reportFileName-memleak.xml.gz -#gzip -d $reportFileName-memleak.xml.gz -echo "done getting the reports files out.." +kubectl get cm $reportFile -o "jsonpath={.binaryData['${reportFile//\./\\.}']}" | base64 -d | gunzip > ${reportFile%\.gz} +echo "done getting the report file out.." diff --git a/test/e2e/run-kind-e2e.sh b/test/e2e/run-kind-e2e.sh index bb61706b4..df927bd1c 100755 --- a/test/e2e/run-kind-e2e.sh +++ b/test/e2e/run-kind-e2e.sh @@ -95,7 +95,7 @@ fi if [ "${SKIP_E2E_IMAGE_CREATION}" = "false" ]; then if ! command -v ginkgo &> /dev/null; then - go get github.com/onsi/ginkgo/v2/ginkgo@v2.6.1 + go install github.com/onsi/ginkgo/v2/ginkgo@v2.6.1 fi echo "[dev-env] .. done building controller images" diff --git a/test/e2e/settings/configmap_change.go b/test/e2e/settings/configmap_change.go index be3ab0b11..3e37b62cd 100644 --- a/test/e2e/settings/configmap_change.go +++ b/test/e2e/settings/configmap_change.go @@ -73,5 +73,9 @@ var _ = framework.DescribeSetting("Configmap change", func() { return strings.ContainsAny(cfg, "error_log /var/log/nginx/error.log debug;") }) assert.NotEqual(ginkgo.GinkgoT(), checksum, newChecksum) + + logs, err := f.NginxLogs() + assert.Nil(ginkgo.GinkgoT(), err, "obtaining nginx logs") + assert.Contains(ginkgo.GinkgoT(), logs, "Backend successfully reloaded") }) }) diff --git a/test/e2e/settings/namespace_selector.go b/test/e2e/settings/namespace_selector.go index a23514dca..3bf856566 100644 --- a/test/e2e/settings/namespace_selector.go +++ b/test/e2e/settings/namespace_selector.go @@ -27,7 +27,7 @@ import ( "k8s.io/ingress-nginx/test/e2e/framework" ) -var _ = framework.IngressNginxDescribe("[Flag] watch namespace selector", func() { +var _ = framework.IngressNginxDescribeSerial("[Flag] watch namespace selector", func() { f := framework.NewDefaultFramework("namespace-selector") notMatchedHost, matchedHost := "bar", "foo" var notMatchedNs string @@ -45,7 +45,7 @@ var _ = framework.IngressNginxDescribe("[Flag] watch namespace selector", func() cleanupNamespace := func(ns string) { err := framework.DeleteKubeNamespace(f.KubeClientSet, ns) - assert.Nil(ginkgo.GinkgoT(), err, "deleting temporarily crated namespace") + assert.Nil(ginkgo.GinkgoT(), err, "deleting temporarily created namespace") } ginkgo.BeforeEach(func() { @@ -56,13 +56,6 @@ var _ = framework.IngressNginxDescribe("[Flag] watch namespace selector", func() ginkgo.AfterEach(func() { cleanupNamespace(notMatchedNs) cleanupNamespace(matchedNs) - - // cleanup clusterrole/clusterrolebinding created by installing chart with controller.scope.enabled=false - err := f.KubeClientSet.RbacV1().ClusterRoles().Delete(context.TODO(), "nginx-ingress", metav1.DeleteOptions{}) - assert.Nil(ginkgo.GinkgoT(), err, "deleting clusterrole nginx-ingress") - - err = f.KubeClientSet.RbacV1().ClusterRoleBindings().Delete(context.TODO(), "nginx-ingress", metav1.DeleteOptions{}) - assert.Nil(ginkgo.GinkgoT(), err, "deleting clusterrolebinging nginx-ingress") }) ginkgo.Context("With specific watch-namespace-selector flags", func() { diff --git a/test/e2e/settings/ocsp/ocsp.go b/test/e2e/settings/ocsp/ocsp.go index ea137aeb1..adf4351e7 100644 --- a/test/e2e/settings/ocsp/ocsp.go +++ b/test/e2e/settings/ocsp/ocsp.go @@ -85,7 +85,7 @@ var _ = framework.DescribeSetting("OCSP", func() { cfsslDB, err := os.ReadFile("empty.db") assert.Nil(ginkgo.GinkgoT(), err) - cmap, err := f.EnsureConfigMap(&corev1.ConfigMap{ + f.EnsureConfigMap(&corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "ocspserve", Namespace: f.Namespace, @@ -95,8 +95,6 @@ var _ = framework.DescribeSetting("OCSP", func() { "db-config.json": []byte(`{"driver":"sqlite3","data_source":"/data/empty.db"}`), }, }) - assert.Nil(ginkgo.GinkgoT(), err) - assert.NotNil(ginkgo.GinkgoT(), cmap) d, s := ocspserveDeployment(f.Namespace) f.EnsureDeployment(d) diff --git a/test/e2e/tcpudp/tcp.go b/test/e2e/tcpudp/tcp.go index b62134a03..16a633b63 100644 --- a/test/e2e/tcpudp/tcp.go +++ b/test/e2e/tcpudp/tcp.go @@ -21,6 +21,7 @@ import ( "fmt" "net" "net/http" + "regexp" "strings" "time" @@ -36,58 +37,39 @@ import ( var _ = framework.IngressNginxDescribe("[TCP] tcp-services", func() { f := framework.NewDefaultFramework("tcp") + var ip string + + ginkgo.BeforeEach(func() { + ip = f.GetNginxIP() + }) ginkgo.It("should expose a TCP service", func() { f.NewEchoDeployment() - config, err := f.KubeClientSet. - CoreV1(). - ConfigMaps(f.Namespace). - Get(context.TODO(), "tcp-services", metav1.GetOptions{}) - assert.Nil(ginkgo.GinkgoT(), err, "unexpected error obtaining tcp-services configmap") - assert.NotNil(ginkgo.GinkgoT(), config, "expected a configmap but none returned") - - if config.Data == nil { - config.Data = map[string]string{} + cm := f.GetConfigMap(f.Namespace, "tcp-services") + cm.Data = map[string]string{ + "8080": fmt.Sprintf("%v/%v:80", f.Namespace, framework.EchoService), } + f.EnsureConfigMap(cm) - config.Data["8080"] = fmt.Sprintf("%v/%v:80", f.Namespace, framework.EchoService) - - _, err = f.KubeClientSet. - CoreV1(). - ConfigMaps(f.Namespace). - Update(context.TODO(), config, metav1.UpdateOptions{}) - assert.Nil(ginkgo.GinkgoT(), err, "unexpected error updating configmap") - - svc, err := f.KubeClientSet. - CoreV1(). - Services(f.Namespace). - Get(context.TODO(), "nginx-ingress-controller", metav1.GetOptions{}) - assert.Nil(ginkgo.GinkgoT(), err, "unexpected error obtaining ingress-nginx service") - assert.NotNil(ginkgo.GinkgoT(), svc, "expected a service but none returned") - + svc := f.GetService(f.Namespace, "nginx-ingress-controller") svc.Spec.Ports = append(svc.Spec.Ports, corev1.ServicePort{ Name: framework.EchoService, Port: 8080, TargetPort: intstr.FromInt(8080), }) - _, err = f.KubeClientSet. + _, err := f.KubeClientSet. CoreV1(). Services(f.Namespace). Update(context.TODO(), svc, metav1.UpdateOptions{}) assert.Nil(ginkgo.GinkgoT(), err, "unexpected error updating service") - // wait for update and nginx reload and new endpoint is available - framework.Sleep() - f.WaitForNginxConfiguration( func(cfg string) bool { return strings.Contains(cfg, fmt.Sprintf(`ngx.var.proxy_upstream_name="tcp-%v-%v-80"`, f.Namespace, framework.EchoService)) }) - ip := f.GetNginxIP() - f.HTTPTestClient(). GET("/"). WithURL(fmt.Sprintf("http://%v:8080", ip)). @@ -122,44 +104,25 @@ var _ = framework.IngressNginxDescribe("[TCP] tcp-services", func() { } f.EnsureService(externalService) - // Expose the `external name` port on the `ingress-nginx` service - svc, err := f.KubeClientSet. - CoreV1(). - Services(f.Namespace). - Get(context.TODO(), "nginx-ingress-controller", metav1.GetOptions{}) - assert.Nil(ginkgo.GinkgoT(), err, "unexpected error obtaining ingress-nginx service") - assert.NotNil(ginkgo.GinkgoT(), svc, "expected a service but none returned") - + // Expose the `external name` port on the `ingress-nginx-controller` service + svc := f.GetService(f.Namespace, "nginx-ingress-controller") svc.Spec.Ports = append(svc.Spec.Ports, corev1.ServicePort{ Name: "dns-svc", Port: 5353, TargetPort: intstr.FromInt(5353), }) - _, err = f.KubeClientSet. + _, err := f.KubeClientSet. CoreV1(). Services(f.Namespace). Update(context.TODO(), svc, metav1.UpdateOptions{}) assert.Nil(ginkgo.GinkgoT(), err, "unexpected error updating service") // Update the TCP configmap to link port 5353 to the DNS external name service - config, err := f.KubeClientSet. - CoreV1(). - ConfigMaps(f.Namespace). - Get(context.TODO(), "tcp-services", metav1.GetOptions{}) - assert.Nil(ginkgo.GinkgoT(), err, "unexpected error obtaining tcp-services configmap") - assert.NotNil(ginkgo.GinkgoT(), config, "expected a configmap but none returned") - - if config.Data == nil { - config.Data = map[string]string{} + config := f.GetConfigMap(f.Namespace, "tcp-services") + config.Data = map[string]string{ + "5353": fmt.Sprintf("%v/dns-external-name-svc:5353", f.Namespace), } - - config.Data["5353"] = fmt.Sprintf("%v/dns-external-name-svc:5353", f.Namespace) - - _, err = f.KubeClientSet. - CoreV1(). - ConfigMaps(f.Namespace). - Update(context.TODO(), config, metav1.UpdateOptions{}) - assert.Nil(ginkgo.GinkgoT(), err, "unexpected error updating configmap") + f.EnsureConfigMap(config) // Validate that the generated nginx config contains the expected `proxy_upstream_name` value f.WaitForNginxConfiguration( @@ -168,7 +131,6 @@ var _ = framework.IngressNginxDescribe("[TCP] tcp-services", func() { }) // Execute the test. Use the `external name` service to resolve a domain name. - ip := f.GetNginxIP() resolver := net.Resolver{ PreferGo: true, Dial: func(ctx context.Context, network, address string) (net.Conn, error) { @@ -203,4 +165,57 @@ var _ = framework.IngressNginxDescribe("[TCP] tcp-services", func() { assert.Nil(ginkgo.GinkgoT(), err, "unexpected error from DNS resolver") assert.Contains(ginkgo.GinkgoT(), ips, "8.8.4.4") }) + + ginkgo.It("should reload after an update in the configuration", func() { + + ginkgo.By("setting up a first deployment") + f.NewEchoDeployment(framework.WithDeploymentName("first-service")) + + cm := f.GetConfigMap(f.Namespace, "tcp-services") + cm.Data = map[string]string{ + "8080": fmt.Sprintf("%v/first-service:80", f.Namespace), + } + f.EnsureConfigMap(cm) + + checksumRegex := regexp.MustCompile(`Configuration checksum:\s+(\d+)`) + checksum := "" + + f.WaitForNginxConfiguration( + func(cfg string) bool { + // before returning, extract the current checksum + match := checksumRegex.FindStringSubmatch(cfg) + if len(match) > 0 { + checksum = match[1] + } + + return strings.Contains(cfg, fmt.Sprintf(`ngx.var.proxy_upstream_name="tcp-%v-first-service-80"`, + f.Namespace)) + }) + assert.NotEmpty(ginkgo.GinkgoT(), checksum) + + ginkgo.By("updating the tcp service to a second deployment") + f.NewEchoDeployment(framework.WithDeploymentName("second-service")) + + cm = f.GetConfigMap(f.Namespace, "tcp-services") + cm.Data["8080"] = fmt.Sprintf("%v/second-service:80", f.Namespace) + f.EnsureConfigMap(cm) + + newChecksum := "" + f.WaitForNginxConfiguration( + func(cfg string) bool { + match := checksumRegex.FindStringSubmatch(cfg) + if len(match) > 0 { + newChecksum = match[1] + } + + return strings.Contains(cfg, fmt.Sprintf(`ngx.var.proxy_upstream_name="tcp-%v-second-service-80"`, + f.Namespace)) + }) + assert.NotEqual(ginkgo.GinkgoT(), checksum, newChecksum) + + logs, err := f.NginxLogs() + assert.Nil(ginkgo.GinkgoT(), err, "obtaining nginx logs") + assert.Contains(ginkgo.GinkgoT(), logs, "Backend successfully reloaded") + }) + }) From 4aef45c17734d7dcba32a2032f97ac604c59d7bd Mon Sep 17 00:00:00 2001 From: Toon Schoenmakers Date: Fri, 17 Feb 2023 22:48:10 +0100 Subject: [PATCH 16/69] controller: Don't panic when ready condition in a endpointslice is missing (#9550) --- internal/ingress/controller/endpointslices.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/ingress/controller/endpointslices.go b/internal/ingress/controller/endpointslices.go index 34d5266dd..56e7a2dcb 100644 --- a/internal/ingress/controller/endpointslices.go +++ b/internal/ingress/controller/endpointslices.go @@ -128,7 +128,7 @@ func getEndpointsFromSlices(s *corev1.Service, port *corev1.ServicePort, proto c } for _, ep := range eps.Endpoints { - if !(*ep.Conditions.Ready) { + if (ep.Conditions.Ready != nil) && !(*ep.Conditions.Ready) { continue } epHasZone := false From 9126401eebf81e75bed25b5c7a1d0bbf94e2ecb6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Feb 2023 16:00:03 -0800 Subject: [PATCH 17/69] Bump golang.org/x/net in /images/kube-webhook-certgen/rootfs (#9645) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.1.0 to 0.7.0. - [Release notes](https://github.com/golang/net/releases) - [Commits](https://github.com/golang/net/compare/v0.1.0...v0.7.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- images/kube-webhook-certgen/rootfs/go.mod | 8 ++++---- images/kube-webhook-certgen/rootfs/go.sum | 20 ++++++++------------ 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/images/kube-webhook-certgen/rootfs/go.mod b/images/kube-webhook-certgen/rootfs/go.mod index b98adf58b..a6e2b7ed2 100644 --- a/images/kube-webhook-certgen/rootfs/go.mod +++ b/images/kube-webhook-certgen/rootfs/go.mod @@ -29,11 +29,11 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tidwall/gjson v1.14.0 // indirect - golang.org/x/net v0.1.0 // indirect + golang.org/x/net v0.7.0 // indirect golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect - golang.org/x/sys v0.1.0 // indirect - golang.org/x/term v0.1.0 // indirect - golang.org/x/text v0.4.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/term v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect google.golang.org/appengine v1.6.5 // indirect google.golang.org/protobuf v1.26.0 // indirect diff --git a/images/kube-webhook-certgen/rootfs/go.sum b/images/kube-webhook-certgen/rootfs/go.sum index 0270e3297..7817b7f29 100644 --- a/images/kube-webhook-certgen/rootfs/go.sum +++ b/images/kube-webhook-certgen/rootfs/go.sum @@ -89,7 +89,6 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.16.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -484,8 +483,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -545,16 +544,14 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -562,8 +559,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -708,7 +705,6 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA= gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From d21ae2dbf6810158e912dcba0ef5f5775f823978 Mon Sep 17 00:00:00 2001 From: Long Wu Yuan Date: Sat, 18 Feb 2023 17:11:37 +0530 Subject: [PATCH 18/69] changed v1.6.3 to v1.6.4 on deploy docs (#9647) --- docs/deploy/index.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/deploy/index.md b/docs/deploy/index.md index 57df7a215..49340e2f5 100644 --- a/docs/deploy/index.md +++ b/docs/deploy/index.md @@ -62,7 +62,7 @@ It will install the controller in the `ingress-nginx` namespace, creating that n **If you don't have Helm** or if you prefer to use a YAML manifest, you can run the following command instead: ```console -kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.3/deploy/static/provider/cloud/deploy.yaml +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/cloud/deploy.yaml ``` !!! info @@ -225,7 +225,7 @@ In AWS, we use a Network load balancer (NLB) to expose the NGINX Ingress control ##### Network Load Balancer (NLB) ```console -kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.3/deploy/static/provider/aws/deploy.yaml +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/aws/deploy.yaml ``` ##### TLS termination in AWS Load Balancer (NLB) @@ -233,10 +233,10 @@ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/cont By default, TLS is terminated in the ingress controller. But it is also possible to terminate TLS in the Load Balancer. This section explains how to do that on AWS using an NLB. -1. Download the [deploy.yaml](https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.3/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml) template +1. Download the [deploy.yaml](https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml) template ```console - wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.3/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml + wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml ``` 2. Edit the file and change the VPC CIDR in use for the Kubernetes cluster: @@ -282,7 +282,7 @@ Then, the ingress controller can be installed like this: ```console -kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.3/deploy/static/provider/cloud/deploy.yaml +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/cloud/deploy.yaml ``` !!! warning @@ -299,7 +299,7 @@ Proxy-protocol is supported in GCE check the [Official Documentations on how to #### Azure ```console -kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.3/deploy/static/provider/cloud/deploy.yaml +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/cloud/deploy.yaml ``` More information with regard to Azure annotations for ingress controller can be found in the [official AKS documentation](https://docs.microsoft.com/en-us/azure/aks/ingress-internal-ip#create-an-ingress-controller). @@ -307,7 +307,7 @@ More information with regard to Azure annotations for ingress controller can be #### Digital Ocean ```console -kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.3/deploy/static/provider/do/deploy.yaml +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/do/deploy.yaml ``` - By default the service object of the ingress-nginx-controller for Digital-Ocean, only configures one annotation. Its this one `service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: "true"`. While this makes the service functional, it was reported that the Digital-Ocean LoadBalancer graphs shows `no data`, unless a few other annotations are also configured. Some of these other annotations require values that can not be generic and hence not forced in a out-of-the-box installation. These annotations and a discussion on them is well documented in [this issue](https://github.com/kubernetes/ingress-nginx/issues/8965). Please refer to the issue to add annotations, with values specific to user, to get graphs of the DO-LB populated with data. @@ -315,7 +315,7 @@ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/cont #### Scaleway ```console -kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.3/deploy/static/provider/scw/deploy.yaml +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/scw/deploy.yaml ``` #### Exoscale @@ -330,7 +330,7 @@ The full list of annotations supported by Exoscale is available in the Exoscale #### Oracle Cloud Infrastructure ```console -kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.3/deploy/static/provider/cloud/deploy.yaml +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/cloud/deploy.yaml ``` A @@ -357,7 +357,7 @@ For quick testing, you can use a This should work on almost every cluster, but it will typically use a port in the range 30000-32767. ```console -kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.3/deploy/static/provider/baremetal/deploy.yaml +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/baremetal/deploy.yaml ``` For more information about bare metal deployments (and how to use port 80 instead of a random port in the 30000-32767 range), @@ -429,4 +429,4 @@ of the NGINX Ingress Controller (e.g. version 0.49). The Helm chart of the NGINX Ingress Controller switched to version 1 in version 4 of the chart. In other words, if you're running Kubernetes 1.19 or earlier, you should use version 3.X of the chart (this can be done by adding -`--version='<4'` to the `helm install` command). +`--version='<4'` to the `helm install` command ). From c5d73d58c69f71a8d1aecad6b5c15b5ede4a23e8 Mon Sep 17 00:00:00 2001 From: Mitsuo Heijo <25817501+johejo@users.noreply.github.com> Date: Thu, 23 Feb 2023 00:27:57 +0900 Subject: [PATCH 19/69] migrate mitchellh/hashstructure to v2 (#9651) --- go.mod | 2 +- go.sum | 4 ++-- internal/ingress/controller/controller.go | 4 ++-- internal/ingress/controller/template/configmap.go | 4 ++-- internal/ingress/controller/template/configmap_test.go | 8 ++++---- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index d942c1637..2b51cda17 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/json-iterator/go v1.1.12 github.com/kylelemons/godebug v1.1.0 github.com/mitchellh/go-ps v1.0.0 - github.com/mitchellh/hashstructure v1.1.0 + github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/mitchellh/mapstructure v1.5.0 github.com/moul/pb v0.0.0-20220425114252-bca18df4138c github.com/ncabatoff/process-exporter v0.7.10 diff --git a/go.sum b/go.sum index b1f6269a6..fe147d4a5 100644 --- a/go.sum +++ b/go.sum @@ -248,8 +248,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= -github.com/mitchellh/hashstructure v1.1.0 h1:P6P1hdjqAAknpY/M1CGipelZgp+4y9ja9kmUZPXP+H0= -github.com/mitchellh/hashstructure v1.1.0/go.mod h1:xUDAozZz0Wmdiufv0uyhnHkUTN6/6d8ulp4AwfLKrmA= +github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= +github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mmarkdown/mmark v2.0.40+incompatible h1:vMeUeDzBK3H+/mU0oMVfMuhSXJlIA+DE/DMPQNAj5C4= diff --git a/internal/ingress/controller/controller.go b/internal/ingress/controller/controller.go index a77d2ff37..1914765d8 100644 --- a/internal/ingress/controller/controller.go +++ b/internal/ingress/controller/controller.go @@ -23,7 +23,7 @@ import ( "strings" "time" - "github.com/mitchellh/hashstructure" + "github.com/mitchellh/hashstructure/v2" apiv1 "k8s.io/api/core/v1" networking "k8s.io/api/networking/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" @@ -187,7 +187,7 @@ func (n *NGINXController) syncIngress(interface{}) error { if !utilingress.IsDynamicConfigurationEnough(pcfg, n.runningConfig) { klog.InfoS("Configuration changes detected, backend reload required") - hash, _ := hashstructure.Hash(pcfg, &hashstructure.HashOptions{ + hash, _ := hashstructure.Hash(pcfg, hashstructure.FormatV1, &hashstructure.HashOptions{ TagName: "json", }) diff --git a/internal/ingress/controller/template/configmap.go b/internal/ingress/controller/template/configmap.go index 61e8e4998..c73f3b6c0 100644 --- a/internal/ingress/controller/template/configmap.go +++ b/internal/ingress/controller/template/configmap.go @@ -26,7 +26,7 @@ import ( "k8s.io/klog/v2" - "github.com/mitchellh/hashstructure" + "github.com/mitchellh/hashstructure/v2" "github.com/mitchellh/mapstructure" "k8s.io/apimachinery/pkg/util/sets" @@ -431,7 +431,7 @@ func ReadConfig(src map[string]string) config.Configuration { klog.Warningf("unexpected error merging defaults: %v", err) } - hash, err := hashstructure.Hash(to, &hashstructure.HashOptions{ + hash, err := hashstructure.Hash(to, hashstructure.FormatV1, &hashstructure.HashOptions{ TagName: "json", }) if err != nil { diff --git a/internal/ingress/controller/template/configmap_test.go b/internal/ingress/controller/template/configmap_test.go index ebe55d192..dad841694 100644 --- a/internal/ingress/controller/template/configmap_test.go +++ b/internal/ingress/controller/template/configmap_test.go @@ -23,7 +23,7 @@ import ( "time" "github.com/kylelemons/godebug/pretty" - "github.com/mitchellh/hashstructure" + "github.com/mitchellh/hashstructure/v2" "k8s.io/ingress-nginx/internal/ingress/annotations/authreq" "k8s.io/ingress-nginx/internal/ingress/controller/config" @@ -104,7 +104,7 @@ func TestMergeConfigMapToStruct(t *testing.T) { def.DefaultType = "text/plain" def.DebugConnections = []string{"127.0.0.1", "1.1.1.1/24", "::1"} - hash, err := hashstructure.Hash(def, &hashstructure.HashOptions{ + hash, err := hashstructure.Hash(def, hashstructure.FormatV1, &hashstructure.HashOptions{ TagName: "json", }) if err != nil { @@ -134,7 +134,7 @@ func TestMergeConfigMapToStruct(t *testing.T) { def.LuaSharedDicts = defaultLuaSharedDicts def.DisableIpv6DNS = true - hash, err = hashstructure.Hash(def, &hashstructure.HashOptions{ + hash, err = hashstructure.Hash(def, hashstructure.FormatV1, &hashstructure.HashOptions{ TagName: "json", }) if err != nil { @@ -155,7 +155,7 @@ func TestMergeConfigMapToStruct(t *testing.T) { def.WhitelistSourceRange = []string{"1.1.1.1/32"} def.DisableIpv6DNS = true - hash, err = hashstructure.Hash(def, &hashstructure.HashOptions{ + hash, err = hashstructure.Hash(def, hashstructure.FormatV1, &hashstructure.HashOptions{ TagName: "json", }) if err != nil { From 6865ee0fba2d0f4256463d3fce747d89d4c69698 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Feb 2023 07:37:57 -0800 Subject: [PATCH 20/69] Bump golang.org/x/net from 0.6.0 to 0.7.0 (#9646) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.6.0 to 0.7.0. - [Release notes](https://github.com/golang/net/releases) - [Commits](https://github.com/golang/net/compare/v0.6.0...v0.7.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2b51cda17..2b485801f 100644 --- a/go.mod +++ b/go.mod @@ -99,7 +99,7 @@ require ( github.com/yudai/pp v2.0.1+incompatible // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect golang.org/x/mod v0.7.0 // indirect - golang.org/x/net v0.6.0 // indirect + golang.org/x/net v0.7.0 // indirect golang.org/x/oauth2 v0.4.0 // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/term v0.5.0 // indirect diff --git a/go.sum b/go.sum index fe147d4a5..741fa7b5b 100644 --- a/go.sum +++ b/go.sum @@ -471,8 +471,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= From 33b3dc32153699517908404099cff779dac0b296 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Feb 2023 07:39:57 -0800 Subject: [PATCH 21/69] Bump github.com/prometheus/common from 0.39.0 to 0.40.0 (#9653) Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.39.0 to 0.40.0. - [Release notes](https://github.com/prometheus/common/releases) - [Commits](https://github.com/prometheus/common/compare/v0.39.0...v0.40.0) --- updated-dependencies: - dependency-name: github.com/prometheus/common dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2b485801f..8c4a7123c 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 - github.com/prometheus/common v0.39.0 + github.com/prometheus/common v0.40.0 github.com/spf13/cobra v1.6.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.1 diff --git a/go.sum b/go.sum index 741fa7b5b..31c11e5a4 100644 --- a/go.sum +++ b/go.sum @@ -320,8 +320,8 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= -github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= +github.com/prometheus/common v0.40.0 h1:Afz7EVRqGg2Mqqf4JuF9vdvp1pi220m55Pi9T2JnO4Q= +github.com/prometheus/common v0.40.0/go.mod h1:L65ZJPSmfn/UBWLQIHV7dBrKFidB/wPlF1y5TlSt9OE= github.com/prometheus/exporter-toolkit v0.7.0/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= From dc61f6cd8bdc9dfa87ee8924d16838549242cf2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 04:26:19 -0800 Subject: [PATCH 22/69] Bump github.com/stretchr/testify from 1.8.1 to 1.8.2 (#9675) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.1 to 1.8.2. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.1...v1.8.2) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8c4a7123c..00765b534 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/prometheus/common v0.40.0 github.com/spf13/cobra v1.6.1 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.8.1 + github.com/stretchr/testify v1.8.2 github.com/yudai/gojsondiff v1.0.0 github.com/zakjan/cert-chain-resolver v0.0.0-20211122211144-c6b0b792af9a golang.org/x/crypto v0.6.0 diff --git a/go.sum b/go.sum index 31c11e5a4..6274257aa 100644 --- a/go.sum +++ b/go.sum @@ -364,8 +364,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/urfave/cli v1.17.1-0.20160602030128-01a33823596e/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= From 640bdac76d8c5b0505b10255a3195709b971154f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 5 Mar 2023 10:56:57 -0800 Subject: [PATCH 23/69] Bump golang.org/x/sys in /images/custom-error-pages/rootfs (#9671) Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.0.0-20210603081109-ebe580a85c40 to 0.1.0. - [Release notes](https://github.com/golang/sys/releases) - [Commits](https://github.com/golang/sys/commits/v0.1.0) --- updated-dependencies: - dependency-name: golang.org/x/sys dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- images/custom-error-pages/rootfs/go.mod | 2 +- images/custom-error-pages/rootfs/go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/images/custom-error-pages/rootfs/go.mod b/images/custom-error-pages/rootfs/go.mod index 515b72c09..2e762d091 100644 --- a/images/custom-error-pages/rootfs/go.mod +++ b/images/custom-error-pages/rootfs/go.mod @@ -12,6 +12,6 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.26.0 // indirect github.com/prometheus/procfs v0.6.0 // indirect - golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 // indirect + golang.org/x/sys v0.1.0 // indirect google.golang.org/protobuf v1.28.0 // indirect ) diff --git a/images/custom-error-pages/rootfs/go.sum b/images/custom-error-pages/rootfs/go.sum index d071619b7..a5f86cade 100644 --- a/images/custom-error-pages/rootfs/go.sum +++ b/images/custom-error-pages/rootfs/go.sum @@ -113,8 +113,9 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 82e836fbe89815ba57dcc1c8f9e370773d6bf291 Mon Sep 17 00:00:00 2001 From: cui fliter Date: Mon, 6 Mar 2023 03:00:57 +0800 Subject: [PATCH 24/69] fix some comments (#9688) Signed-off-by: cui fliter --- docs/developer-guide/code-overview.md | 2 +- images/kube-webhook-certgen/rootfs/pkg/k8s/k8s.go | 2 +- internal/ingress/controller/endpointslices.go | 2 +- internal/ingress/controller/template/template.go | 2 +- magefiles/helm.go | 7 ++++--- pkg/util/ingress/ingress.go | 2 +- test/e2e/settings/ssl_passthrough.go | 2 +- 7 files changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/developer-guide/code-overview.md b/docs/developer-guide/code-overview.md index c55fb69f9..a26083c6a 100644 --- a/docs/developer-guide/code-overview.md +++ b/docs/developer-guide/code-overview.md @@ -104,7 +104,7 @@ Describe here `kubectl plugin`, `dbg`, `waitshutdown` and cover the hack scripts ### kubectl plugin -It containes kubectl plugin for inspecting your ingress-nginx deployments. +It contains kubectl plugin for inspecting your ingress-nginx deployments. This part of code can be found in [cmd/plugin](https://github.com/kubernetes/ingress-nginx/tree/main/cmd/plugin) directory Detail functions flow and available flow can be found in [kubectl-plugin](https://github.com/kubernetes/ingress-nginx/blob/main/docs/kubectl-plugin.md) diff --git a/images/kube-webhook-certgen/rootfs/pkg/k8s/k8s.go b/images/kube-webhook-certgen/rootfs/pkg/k8s/k8s.go index 0034235fb..6018b4253 100644 --- a/images/kube-webhook-certgen/rootfs/pkg/k8s/k8s.go +++ b/images/kube-webhook-certgen/rootfs/pkg/k8s/k8s.go @@ -105,7 +105,7 @@ func (k8s *k8s) patchAPIService(ctx context.Context, objectName string, ca []byt return nil } -// PatchWebhookConfigurations will patch validatingWebhook and mutatingWebhook clientConfig configurations with +// patchWebhookConfigurations will patch validatingWebhook and mutatingWebhook clientConfig configurations with // the provided ca data. If failurePolicy is provided, patch all webhooks with this value func (k8s *k8s) patchWebhookConfigurations( ctx context.Context, diff --git a/internal/ingress/controller/endpointslices.go b/internal/ingress/controller/endpointslices.go index 56e7a2dcb..ca6e595c8 100644 --- a/internal/ingress/controller/endpointslices.go +++ b/internal/ingress/controller/endpointslices.go @@ -34,7 +34,7 @@ import ( "k8s.io/ingress-nginx/pkg/apis/ingress" ) -// getEndpoints returns a list of Endpoint structs for a given service/target port combination. +// getEndpointsFromSlices returns a list of Endpoint structs for a given service/target port combination. func getEndpointsFromSlices(s *corev1.Service, port *corev1.ServicePort, proto corev1.Protocol, zoneForHints string, getServiceEndpointsSlices func(string) ([]*discoveryv1.EndpointSlice, error)) []ingress.Endpoint { diff --git a/internal/ingress/controller/template/template.go b/internal/ingress/controller/template/template.go index ea9807bd0..f3283a782 100644 --- a/internal/ingress/controller/template/template.go +++ b/internal/ingress/controller/template/template.go @@ -1732,7 +1732,7 @@ func buildServerName(hostname string) string { return `~^(?[\w-]+)\.` + strings.Join(parts, "\\.") + `$` } -// parseComplexNGINXVar parses things like "$my${complex}ngx\$var" into +// parseComplexNginxVarIntoLuaTable parses things like "$my${complex}ngx\$var" into // [["$var", "complex", "my", "ngx"]]. In other words, 2nd and 3rd elements // in the result are actual NGINX variable names, whereas first and 4th elements // are string literals. diff --git a/magefiles/helm.go b/magefiles/helm.go index e69c4e029..93c440584 100644 --- a/magefiles/helm.go +++ b/magefiles/helm.go @@ -20,14 +20,15 @@ package main import ( "fmt" + "os" + "strings" + semver "github.com/blang/semver/v4" "github.com/helm/helm/pkg/chartutil" "github.com/magefile/mage/mg" "github.com/magefile/mage/sh" yamlpath "github.com/vmware-labs/yaml-jsonpath/pkg/yamlpath" "gopkg.in/yaml.v3" - "os" - "strings" ) const HelmChartPath = "charts/ingress-nginx/Chart.yaml" @@ -114,7 +115,7 @@ func UpdateChartChangelog() { } -// UpdateAppVersion Updates the Helm App Version of Ingress Nginx Controller +// UpdateChartValue Updates the Helm ChartValue func (Helm) UpdateChartValue(key, value string) { updateChartValue(key, value) } diff --git a/pkg/util/ingress/ingress.go b/pkg/util/ingress/ingress.go index 39ca3f883..e69ca7b29 100644 --- a/pkg/util/ingress/ingress.go +++ b/pkg/util/ingress/ingress.go @@ -46,7 +46,7 @@ func GetRemovedHosts(rucfg, newcfg *ingress.Configuration) []string { return oldSet.Difference(newSet).List() } -// GetRemovedCertificateSerialNumber extracts the difference of certificates between two configurations +// GetRemovedCertificateSerialNumbers extracts the difference of certificates between two configurations func GetRemovedCertificateSerialNumbers(rucfg, newcfg *ingress.Configuration) []string { oldCertificates := sets.NewString() newCertificates := sets.NewString() diff --git a/test/e2e/settings/ssl_passthrough.go b/test/e2e/settings/ssl_passthrough.go index 77a3c990e..a906a2d11 100644 --- a/test/e2e/settings/ssl_passthrough.go +++ b/test/e2e/settings/ssl_passthrough.go @@ -81,7 +81,7 @@ var _ = framework.IngressNginxDescribe("[Flag] enable-ssl-passthrough", func() { host := "testpassthrough.com" echoName := "echopass" - /* Even with enable-ssl-passthrough enabled, only annotated ingresses may receive the trafic */ + /* Even with enable-ssl-passthrough enabled, only annotated ingresses may receive the traffic */ annotations := map[string]string{ "nginx.ingress.kubernetes.io/ssl-passthrough": "true", } From c84003e3b1e34d8a3c8cce6a026c267e37a0fbea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 5 Mar 2023 12:10:58 -0800 Subject: [PATCH 25/69] Bump golang.org/x/net in /magefiles (#9692) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20220722155237-a158d28d115b to 0.7.0. - [Release notes](https://github.com/golang/net/releases) - [Commits](https://github.com/golang/net/commits/v0.7.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- magefiles/go.mod | 2 +- magefiles/go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/magefiles/go.mod b/magefiles/go.mod index 31c11a061..613e5fb1f 100644 --- a/magefiles/go.mod +++ b/magefiles/go.mod @@ -23,7 +23,7 @@ require ( github.com/google/go-querystring v1.1.0 // indirect github.com/stretchr/testify v1.8.1 // indirect golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect - golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect + golang.org/x/net v0.7.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/magefiles/go.sum b/magefiles/go.sum index 38a4235f6..f6b4786a5 100644 --- a/magefiles/go.sum +++ b/magefiles/go.sum @@ -64,17 +64,17 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s3 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= From 0bb07bffd02e104b68d3ab7e5603924e8d117bde Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Mar 2023 23:22:18 -0800 Subject: [PATCH 26/69] Bump sigs.k8s.io/controller-runtime from 0.14.2 to 0.14.5 (#9697) Bumps [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) from 0.14.2 to 0.14.5. - [Release notes](https://github.com/kubernetes-sigs/controller-runtime/releases) - [Changelog](https://github.com/kubernetes-sigs/controller-runtime/blob/main/RELEASE.md) - [Commits](https://github.com/kubernetes-sigs/controller-runtime/compare/v0.14.2...v0.14.5) --- updated-dependencies: - dependency-name: sigs.k8s.io/controller-runtime dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 00765b534..0ffda4dcf 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( k8s.io/component-base v0.26.1 k8s.io/klog/v2 v2.90.0 pault.ag/go/sniff v0.0.0-20200207005214-cf7e4d167732 - sigs.k8s.io/controller-runtime v0.14.2 + sigs.k8s.io/controller-runtime v0.14.5 sigs.k8s.io/mdtoc v1.1.0 ) diff --git a/go.sum b/go.sum index 6274257aa..a9f0db95e 100644 --- a/go.sum +++ b/go.sum @@ -767,8 +767,8 @@ pault.ag/go/sniff v0.0.0-20200207005214-cf7e4d167732/go.mod h1:lpvCfhqEHNJSSpG5R rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/controller-runtime v0.14.2 h1:P6IwDhbsRWsBClt/8/h8Zy36bCuGuW5Op7MHpFrN/60= -sigs.k8s.io/controller-runtime v0.14.2/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= +sigs.k8s.io/controller-runtime v0.14.5 h1:6xaWFqzT5KuAQ9ufgUaj1G/+C4Y1GRkhrxl+BJ9i+5s= +sigs.k8s.io/controller-runtime v0.14.5/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/kustomize/api v0.12.1 h1:7YM7gW3kYBwtKvoY216ZzY+8hM+lV53LUayghNRJ0vM= From ec2fe2b6d1e99202d15b6c0577bcfd69cf461c3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Mar 2023 11:54:41 -0800 Subject: [PATCH 27/69] Bump github.com/prometheus/common from 0.40.0 to 0.41.0 (#9698) Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.40.0 to 0.41.0. - [Release notes](https://github.com/prometheus/common/releases) - [Commits](https://github.com/prometheus/common/compare/v0.40.0...v0.41.0) --- updated-dependencies: - dependency-name: github.com/prometheus/common dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 0ffda4dcf..e85419dcc 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 - github.com/prometheus/common v0.40.0 + github.com/prometheus/common v0.41.0 github.com/spf13/cobra v1.6.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.2 @@ -100,7 +100,7 @@ require ( go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect golang.org/x/mod v0.7.0 // indirect golang.org/x/net v0.7.0 // indirect - golang.org/x/oauth2 v0.4.0 // indirect + golang.org/x/oauth2 v0.5.0 // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/term v0.5.0 // indirect golang.org/x/text v0.7.0 // indirect diff --git a/go.sum b/go.sum index a9f0db95e..0729873ef 100644 --- a/go.sum +++ b/go.sum @@ -320,8 +320,8 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.40.0 h1:Afz7EVRqGg2Mqqf4JuF9vdvp1pi220m55Pi9T2JnO4Q= -github.com/prometheus/common v0.40.0/go.mod h1:L65ZJPSmfn/UBWLQIHV7dBrKFidB/wPlF1y5TlSt9OE= +github.com/prometheus/common v0.41.0 h1:npo01n6vUlRViIj5fgwiK8vlNIh8bnoxqh3gypKsyAw= +github.com/prometheus/common v0.41.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/exporter-toolkit v0.7.0/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -479,8 +479,8 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 4f74e03aad663c7d72edaa36d8e874f1ebe1aa2d Mon Sep 17 00:00:00 2001 From: Alan Clucas Date: Thu, 9 Mar 2023 15:26:04 +0000 Subject: [PATCH 28/69] Indent values.yaml using 2 instead of 4 spaces (#9656) * Generate values.yaml with indentation of 2 Signed-off-by: Alan Clucas * Fix review comments --------- Signed-off-by: Alan Clucas --- magefiles/helm.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/magefiles/helm.go b/magefiles/helm.go index 93c440584..d56cbed78 100644 --- a/magefiles/helm.go +++ b/magefiles/helm.go @@ -19,6 +19,7 @@ limitations under the License. package main import ( + "bytes" "fmt" "os" "strings" @@ -146,9 +147,12 @@ func updateChartValue(key, value string) { } //// write to file - newValueFile, err := yaml.Marshal(&n) + var b bytes.Buffer + yamlEncoder := yaml.NewEncoder(&b) + yamlEncoder.SetIndent(2) + err = yamlEncoder.Encode(&n) CheckIfError(err, "HELM Could not Marshal new Values file") - err = os.WriteFile(HelmChartValues, newValueFile, 0644) + err = os.WriteFile(HelmChartValues, b.Bytes(), 0644) CheckIfError(err, "HELM Could not write new Values file to %s", HelmChartValues) Info("HELM Ingress Nginx Helm Chart update %s %s", key, value) From 1b11527f59388e53b84105589508862fa3229417 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Mar 2023 08:54:40 -0800 Subject: [PATCH 29/69] Bump k8s.io/component-base from 0.26.1 to 0.26.2 (#9696) Bumps [k8s.io/component-base](https://github.com/kubernetes/component-base) from 0.26.1 to 0.26.2. - [Release notes](https://github.com/kubernetes/component-base/releases) - [Commits](https://github.com/kubernetes/component-base/compare/v0.26.1...v0.26.2) --- updated-dependencies: - dependency-name: k8s.io/component-base dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index e85419dcc..39e76c331 100644 --- a/go.mod +++ b/go.mod @@ -30,14 +30,14 @@ require ( google.golang.org/grpc/examples v0.0.0-20221220003428-4f16fbe410f7 gopkg.in/go-playground/pool.v3 v3.1.1 gopkg.in/mcuadros/go-syslog.v2 v2.3.0 - k8s.io/api v0.26.1 + k8s.io/api v0.26.2 k8s.io/apiextensions-apiserver v0.26.1 - k8s.io/apimachinery v0.26.1 + k8s.io/apimachinery v0.26.2 k8s.io/apiserver v0.26.1 k8s.io/cli-runtime v0.26.0 - k8s.io/client-go v0.26.1 + k8s.io/client-go v0.26.2 k8s.io/code-generator v0.26.1 - k8s.io/component-base v0.26.1 + k8s.io/component-base v0.26.2 k8s.io/klog/v2 v2.90.0 pault.ag/go/sniff v0.0.0-20200207005214-cf7e4d167732 sigs.k8s.io/controller-runtime v0.14.5 diff --git a/go.sum b/go.sum index 0729873ef..d299919fb 100644 --- a/go.sum +++ b/go.sum @@ -737,22 +737,22 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ= -k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= +k8s.io/api v0.26.2 h1:dM3cinp3PGB6asOySalOZxEG4CZ0IAdJsrYZXE/ovGQ= +k8s.io/api v0.26.2/go.mod h1:1kjMQsFE+QHPfskEcVNgL3+Hp88B80uj0QtSOlj8itU= k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM= -k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ= -k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= +k8s.io/apimachinery v0.26.2 h1:da1u3D5wfR5u2RpLhE/ZtZS2P7QvDgLZTi9wrNZl/tQ= +k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= k8s.io/apiserver v0.26.1 h1:6vmnAqCDO194SVCPU3MU8NcDgSqsUA62tBUSWrFXhsc= k8s.io/apiserver v0.26.1/go.mod h1:wr75z634Cv+sifswE9HlAo5FQ7UoUauIICRlOE+5dCg= k8s.io/cli-runtime v0.26.0 h1:aQHa1SyUhpqxAw1fY21x2z2OS5RLtMJOCj7tN4oq8mw= k8s.io/cli-runtime v0.26.0/go.mod h1:o+4KmwHzO/UK0wepE1qpRk6l3o60/txUZ1fEXWGIKTY= -k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= -k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= +k8s.io/client-go v0.26.2 h1:s1WkVujHX3kTp4Zn4yGNFK+dlDXy1bAAkIl+cFAiuYI= +k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU= k8s.io/code-generator v0.26.1 h1:dusFDsnNSKlMFYhzIM0jAO1OlnTN5WYwQQ+Ai12IIlo= k8s.io/code-generator v0.26.1/go.mod h1:OMoJ5Dqx1wgaQzKgc+ZWaZPfGjdRq/Y3WubFrZmeI3I= -k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4= -k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU= +k8s.io/component-base v0.26.2 h1:IfWgCGUDzrD6wLLgXEstJKYZKAFS2kO+rBRi0p3LqcI= +k8s.io/component-base v0.26.2/go.mod h1:DxbuIe9M3IZPRxPIzhch2m1eT7uFrSBJUBuVCQEBivs= k8s.io/gengo v0.0.0-20220902162205-c0856e24416d h1:U9tB195lKdzwqicbJvyJeOXV7Klv+wNAWENRnXEGi08= k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= From 67ca41d797bd4471ddb8ac95c7df51c945893e43 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Mar 2023 11:34:41 -0800 Subject: [PATCH 30/69] Bump golang.org/x/crypto in /magefiles (#9691) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.0.0-20210817164053-32db794688a5 to 0.1.0. - [Release notes](https://github.com/golang/crypto/releases) - [Commits](https://github.com/golang/crypto/commits/v0.1.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- magefiles/go.mod | 2 +- magefiles/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/magefiles/go.mod b/magefiles/go.mod index 613e5fb1f..9ad1e11c9 100644 --- a/magefiles/go.mod +++ b/magefiles/go.mod @@ -22,7 +22,7 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/stretchr/testify v1.8.1 // indirect - golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect + golang.org/x/crypto v0.1.0 // indirect golang.org/x/net v0.7.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.0 // indirect diff --git a/magefiles/go.sum b/magefiles/go.sum index f6b4786a5..9c0c8ee7f 100644 --- a/magefiles/go.sum +++ b/magefiles/go.sum @@ -60,8 +60,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= From 5dabf2155868f3415520abe74423f2479cef4599 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Mar 2023 11:36:42 -0800 Subject: [PATCH 31/69] Bump k8s.io/klog/v2 from 2.90.0 to 2.90.1 (#9694) Bumps [k8s.io/klog/v2](https://github.com/kubernetes/klog) from 2.90.0 to 2.90.1. - [Release notes](https://github.com/kubernetes/klog/releases) - [Changelog](https://github.com/kubernetes/klog/blob/main/RELEASE.md) - [Commits](https://github.com/kubernetes/klog/compare/v2.90.0...v2.90.1) --- updated-dependencies: - dependency-name: k8s.io/klog/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 39e76c331..bf0f83625 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( k8s.io/client-go v0.26.2 k8s.io/code-generator v0.26.1 k8s.io/component-base v0.26.2 - k8s.io/klog/v2 v2.90.0 + k8s.io/klog/v2 v2.90.1 pault.ag/go/sniff v0.0.0-20200207005214-cf7e4d167732 sigs.k8s.io/controller-runtime v0.14.5 sigs.k8s.io/mdtoc v1.1.0 diff --git a/go.sum b/go.sum index d299919fb..a46367fb7 100644 --- a/go.sum +++ b/go.sum @@ -756,8 +756,8 @@ k8s.io/component-base v0.26.2/go.mod h1:DxbuIe9M3IZPRxPIzhch2m1eT7uFrSBJUBuVCQEB k8s.io/gengo v0.0.0-20220902162205-c0856e24416d h1:U9tB195lKdzwqicbJvyJeOXV7Klv+wNAWENRnXEGi08= k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.90.0 h1:VkTxIV/FjRXn1fgNNcKGM8cfmL1Z33ZjXRTVxKCoF5M= -k8s.io/klog/v2 v2.90.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= +k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= From ddcfaecb3c4f6820f570f1ac926f16a3a433f586 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Mar 2023 11:38:39 -0800 Subject: [PATCH 32/69] Bump github.com/onsi/ginkgo/v2 from 2.6.1 to 2.9.0 (#9695) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.6.1 to 2.9.0. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.6.1...v2.9.0) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 +++++--- go.sum | 18 +++++++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index bf0f83625..011d69e63 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 github.com/moul/pb v0.0.0-20220425114252-bca18df4138c github.com/ncabatoff/process-exporter v0.7.10 - github.com/onsi/ginkgo/v2 v2.6.1 + github.com/onsi/ginkgo/v2 v2.9.0 github.com/opencontainers/runc v1.1.4 github.com/pmezard/go-difflib v1.0.0 github.com/prometheus/client_golang v1.14.0 @@ -62,6 +62,7 @@ require ( github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonreference v0.20.0 // indirect github.com/go-openapi/swag v0.19.14 // indirect + github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/godbus/dbus/v5 v5.0.6 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -71,6 +72,7 @@ require ( github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.1.0 // indirect + github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.0 // indirect github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect @@ -98,14 +100,14 @@ require ( github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect github.com/yudai/pp v2.0.1+incompatible // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect - golang.org/x/mod v0.7.0 // indirect + golang.org/x/mod v0.8.0 // indirect golang.org/x/net v0.7.0 // indirect golang.org/x/oauth2 v0.5.0 // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/term v0.5.0 // indirect golang.org/x/text v0.7.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.4.0 // indirect + golang.org/x/tools v0.6.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect google.golang.org/protobuf v1.28.1 // indirect diff --git a/go.sum b/go.sum index a46367fb7..1c709138d 100644 --- a/go.sum +++ b/go.sum @@ -118,6 +118,7 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro= @@ -187,6 +188,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -200,6 +203,7 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= @@ -285,11 +289,11 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.6.1 h1:1xQPCjcqYw/J5LchOcp4/2q/jzJFjiAOc25chhnDw+Q= -github.com/onsi/ginkgo/v2 v2.6.1/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= +github.com/onsi/ginkgo/v2 v2.9.0 h1:Tugw2BKlNHTMfG+CheOITkYvk4LAh6MFOvikhGVnhE8= +github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E= +github.com/onsi/gomega v1.27.1 h1:rfztXRbg6nv/5f+Raen9RcGoSecHIFgBBLQK3Wdj754= github.com/opencontainers/runc v1.1.4 h1:nRCz/8sKg6K6jgYAFLDlXzPeITBZJyX28DBVhWD+5dg= github.com/opencontainers/runc v1.1.4/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= @@ -435,8 +439,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -604,8 +608,8 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 66a760794f91809bcd897cbdb45435653d73fd92 Mon Sep 17 00:00:00 2001 From: James Strong Date: Sat, 11 Mar 2023 23:38:39 -0500 Subject: [PATCH 33/69] update to golang 1.20 (#9690) update alpine and golang remove nano update go modules remove need for openssl external cli fix stale Signed-off-by: James Strong --- .github/workflows/ci.yaml | 12 +++++------ .github/workflows/plugin.yaml | 2 +- .github/workflows/stale.yaml | 4 ++-- go.mod | 4 ++-- go.sum | 4 ++-- images/cfssl/rootfs/Dockerfile | 2 +- images/custom-error-pages/rootfs/Dockerfile | 2 +- images/custom-error-pages/rootfs/go.mod | 2 +- .../rootfs/Dockerfile | 2 +- images/ext-auth-example-authsvc/rootfs/go.mod | 2 +- images/ext-auth-example-authsvc/rootfs/go.sum | 21 +++++++++++++++++-- images/fastcgi-helloserver/rootfs/Dockerfile | 2 +- .../go-grpc-greeter-server/rootfs/Dockerfile | 2 +- images/httpbin/rootfs/Dockerfile | 2 +- images/kube-webhook-certgen/rootfs/Dockerfile | 2 +- images/kube-webhook-certgen/rootfs/go.mod | 2 +- images/nginx/rootfs/Dockerfile | 5 ++--- images/opentelemetry/rootfs/Dockerfile | 4 ++-- images/test-runner/Makefile | 2 +- magefiles/go.mod | 2 +- rootfs/Dockerfile-chroot | 4 ++-- test/e2e-image/Dockerfile | 2 +- test/e2e/annotations/auth.go | 8 ++++--- test/e2e/settings/no_auth_locations.go | 5 +++-- 24 files changed, 59 insertions(+), 40 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 61f5970db..b9a400747 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -88,7 +88,7 @@ jobs: id: go uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 with: - go-version: '1.19' + go-version: '1.20' check-latest: true - name: Run Lint @@ -107,7 +107,7 @@ jobs: id: go uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 with: - go-version: '1.19' + go-version: '1.20' check-latest: true - name: Run go-fmt @@ -126,7 +126,7 @@ jobs: id: go uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 with: - go-version: '1.19' + go-version: '1.20' check-latest: true - name: Run test @@ -147,7 +147,7 @@ jobs: id: go uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 with: - go-version: '1.19' + go-version: '1.20' check-latest: true - name: Set up QEMU @@ -213,7 +213,7 @@ jobs: - name: Setup Go uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 with: - go-version: '1.19' + go-version: '1.20' check-latest: true - name: cache @@ -485,7 +485,7 @@ jobs: if: ${{ steps.filter-images.outputs.kube-webhook-certgen == 'true' }} uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 with: - go-version: '1.19' + go-version: '1.20' check-latest: true - name: kube-webhook-certgen image build diff --git a/.github/workflows/plugin.yaml b/.github/workflows/plugin.yaml index 779cd1da8..cb0f73489 100644 --- a/.github/workflows/plugin.yaml +++ b/.github/workflows/plugin.yaml @@ -24,7 +24,7 @@ jobs: - name: Set up Go uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 with: - go-version: 1.19 + go-version: 1.20 check-latest: true - name: Run GoReleaser diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index 736585e05..8a172d370 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -15,8 +15,8 @@ jobs: steps: - uses: actions/stale@6f05e4244c9a0b2ed3401882b05d701dd0a7289b # v7.0.0 with: - stale-issue-message: 'This is stale, but we won't close it automatically, just bare in mind the maintainers may be busy with other tasks and will reach your issue ASAP. If you have any question or request to prioritize this, please reach `#ingress-nginx-dev` on Kubernetes Slack.' - stale-pr-message: 'This is stale, but we won't close it automatically, just bare in mind the maintainers may be busy with other tasks and will reach your issue ASAP. If you have any question or request to prioritize this, please reach `#ingress-nginx-dev` on Kubernetes Slack.' + stale-issue-message: "This is stale, but we won't close it automatically, just bare in mind the maintainers may be busy with other tasks and will reach your issue ASAP. If you have any question or request to prioritize this, please reach `#ingress-nginx-dev` on Kubernetes Slack." + stale-pr-message: "This is stale, but we won't close it automatically, just bare in mind the maintainers may be busy with other tasks and will reach your issue ASAP. If you have any question or request to prioritize this, please reach `#ingress-nginx-dev` on Kubernetes Slack." stale-issue-label: lifecycle/frozen stale-pr-label: lifecycle/frozen days-before-issue-stale: 30 diff --git a/go.mod b/go.mod index 011d69e63..a653632f5 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module k8s.io/ingress-nginx -go 1.19 +go 1.20 require ( github.com/armon/go-proxyproto v0.0.0-20210323213023-7e956b284f0a @@ -93,7 +93,7 @@ require ( github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/procfs v0.8.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect github.com/sergi/go-diff v1.1.0 // indirect github.com/sirupsen/logrus v1.8.1 // indirect github.com/xlab/treeprint v1.1.0 // indirect diff --git a/go.sum b/go.sum index 1c709138d..ff41229cf 100644 --- a/go.sum +++ b/go.sum @@ -332,8 +332,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= diff --git a/images/cfssl/rootfs/Dockerfile b/images/cfssl/rootfs/Dockerfile index f9370c210..7841e189c 100644 --- a/images/cfssl/rootfs/Dockerfile +++ b/images/cfssl/rootfs/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM alpine:3.17.0 +FROM alpine:3.17.2 RUN echo "@testing http://nl.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories RUN apk add --no-cache \ diff --git a/images/custom-error-pages/rootfs/Dockerfile b/images/custom-error-pages/rootfs/Dockerfile index ef825dec1..942228eac 100755 --- a/images/custom-error-pages/rootfs/Dockerfile +++ b/images/custom-error-pages/rootfs/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM golang:1.19.4-alpine3.17 as builder +FROM golang:1.20.1-alpine3.17 as builder RUN apk add git WORKDIR /go/src/k8s.io/ingress-nginx/images/custom-error-pages diff --git a/images/custom-error-pages/rootfs/go.mod b/images/custom-error-pages/rootfs/go.mod index 2e762d091..89e47a4b5 100644 --- a/images/custom-error-pages/rootfs/go.mod +++ b/images/custom-error-pages/rootfs/go.mod @@ -1,6 +1,6 @@ module k8s.io/ingress-nginx/custom-error-pages -go 1.19 +go 1.20 require github.com/prometheus/client_golang v1.11.1 diff --git a/images/ext-auth-example-authsvc/rootfs/Dockerfile b/images/ext-auth-example-authsvc/rootfs/Dockerfile index d54df8ab9..c604651d4 100644 --- a/images/ext-auth-example-authsvc/rootfs/Dockerfile +++ b/images/ext-auth-example-authsvc/rootfs/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.19.4-alpine3.17 as builder +FROM golang:1.20.1-alpine3.17 as builder RUN mkdir /authsvc WORKDIR /authsvc COPY . ./ diff --git a/images/ext-auth-example-authsvc/rootfs/go.mod b/images/ext-auth-example-authsvc/rootfs/go.mod index 0be630b8b..cc5124072 100644 --- a/images/ext-auth-example-authsvc/rootfs/go.mod +++ b/images/ext-auth-example-authsvc/rootfs/go.mod @@ -1,6 +1,6 @@ module example.com/authsvc -go 1.19 +go 1.20 require k8s.io/apimachinery v0.23.1 diff --git a/images/ext-auth-example-authsvc/rootfs/go.sum b/images/ext-auth-example-authsvc/rootfs/go.sum index 2ca056fae..6e3fab295 100644 --- a/images/ext-auth-example-authsvc/rootfs/go.sum +++ b/images/ext-auth-example-authsvc/rootfs/go.sum @@ -105,7 +105,19 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -129,7 +141,12 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= diff --git a/images/fastcgi-helloserver/rootfs/Dockerfile b/images/fastcgi-helloserver/rootfs/Dockerfile index 0213baf87..7d9220ddf 100755 --- a/images/fastcgi-helloserver/rootfs/Dockerfile +++ b/images/fastcgi-helloserver/rootfs/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM golang:1.19.4-alpine3.17 as builder +FROM golang:1.20.1-alpine3.17 as builder WORKDIR /go/src/k8s.io/ingress-nginx/images/fastcgi diff --git a/images/go-grpc-greeter-server/rootfs/Dockerfile b/images/go-grpc-greeter-server/rootfs/Dockerfile index 547842512..67aed038e 100644 --- a/images/go-grpc-greeter-server/rootfs/Dockerfile +++ b/images/go-grpc-greeter-server/rootfs/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.19.4-alpine3.17 as build +FROM golang:1.20.1-alpine3.17 as build WORKDIR /go/src/greeter-server diff --git a/images/httpbin/rootfs/Dockerfile b/images/httpbin/rootfs/Dockerfile index 1a9b55ba5..0e490be74 100644 --- a/images/httpbin/rootfs/Dockerfile +++ b/images/httpbin/rootfs/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM alpine:3.17.0 +FROM alpine:3.17.2 ENV LC_ALL=C.UTF-8 ENV LANG=C.UTF-8 diff --git a/images/kube-webhook-certgen/rootfs/Dockerfile b/images/kube-webhook-certgen/rootfs/Dockerfile index 32847fd39..40a2c31ac 100644 --- a/images/kube-webhook-certgen/rootfs/Dockerfile +++ b/images/kube-webhook-certgen/rootfs/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM --platform=$BUILDPLATFORM golang:1.19.4 as builder +FROM --platform=$BUILDPLATFORM golang:1.20.1 as builder ARG BUILDPLATFORM ARG TARGETARCH diff --git a/images/kube-webhook-certgen/rootfs/go.mod b/images/kube-webhook-certgen/rootfs/go.mod index a6e2b7ed2..49f95828f 100644 --- a/images/kube-webhook-certgen/rootfs/go.mod +++ b/images/kube-webhook-certgen/rootfs/go.mod @@ -1,6 +1,6 @@ module github.com/jet/kube-webhook-certgen -go 1.19 +go 1.20 require ( github.com/onrik/logrus v0.9.0 diff --git a/images/nginx/rootfs/Dockerfile b/images/nginx/rootfs/Dockerfile index a9b01ff82..3279af5d5 100644 --- a/images/nginx/rootfs/Dockerfile +++ b/images/nginx/rootfs/Dockerfile @@ -11,7 +11,7 @@ # 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. -FROM alpine:3.17.0 as builder +FROM alpine:3.17.2 as builder COPY . / @@ -21,7 +21,7 @@ RUN apk update \ && /build.sh # Use a multi-stage build -FROM alpine:3.17.0 +FROM alpine:3.17.2 ENV PATH=$PATH:/usr/local/luajit/bin:/usr/local/nginx/sbin:/usr/local/nginx/bin @@ -49,7 +49,6 @@ RUN apk update \ libmaxminddb \ yaml-cpp \ dumb-init \ - nano \ tzdata \ && ln -s /usr/local/nginx/sbin/nginx /sbin/nginx \ && adduser -S -D -H -u 101 -h /usr/local/nginx \ diff --git a/images/opentelemetry/rootfs/Dockerfile b/images/opentelemetry/rootfs/Dockerfile index aa4e219af..33f5bcb36 100644 --- a/images/opentelemetry/rootfs/Dockerfile +++ b/images/opentelemetry/rootfs/Dockerfile @@ -13,7 +13,7 @@ # limitations under the License. -FROM alpine:3.17.0 as base +FROM alpine:3.17.2 as base RUN mkdir -p /opt/third_party/install COPY . /opt/third_party/ @@ -39,7 +39,7 @@ COPY --from=grpc /opt/third_party/install/ /usr COPY --from=otel-cpp /opt/third_party/install/ /usr RUN bash /opt/third_party/build.sh -n -FROM alpine:3.17.0 as final +FROM alpine:3.17.2 as final COPY --from=base /opt/third_party/init_module.sh /usr/local/bin/init_module.sh COPY --from=nginx /etc/nginx/modules /etc/nginx/modules COPY --from=nginx /opt/third_party/install/lib /etc/nginx/modules diff --git a/images/test-runner/Makefile b/images/test-runner/Makefile index 4d71b8ad5..a8c3a4560 100644 --- a/images/test-runner/Makefile +++ b/images/test-runner/Makefile @@ -39,7 +39,7 @@ build: ensure-buildx --progress=$(PROGRESS) \ --pull \ --build-arg BASE_IMAGE=$(NGINX_BASE_IMAGE) \ - --build-arg GOLANG_VERSION=1.19.4 \ + --build-arg GOLANG_VERSION=1.20.1 \ --build-arg ETCD_VERSION=3.4.3-0 \ --build-arg K8S_RELEASE=v1.24.2 \ --build-arg RESTY_CLI_VERSION=0.27 \ diff --git a/magefiles/go.mod b/magefiles/go.mod index 9ad1e11c9..40b909600 100644 --- a/magefiles/go.mod +++ b/magefiles/go.mod @@ -1,6 +1,6 @@ module github.com/kubernetes/ingress-nginx/magefiles -go 1.19 +go 1.20 require ( github.com/blang/semver/v4 v4.0.0 diff --git a/rootfs/Dockerfile-chroot b/rootfs/Dockerfile-chroot index bdb9be60b..7ab8584a7 100644 --- a/rootfs/Dockerfile-chroot +++ b/rootfs/Dockerfile-chroot @@ -23,7 +23,7 @@ RUN apk update \ && apk upgrade \ && /chroot.sh -FROM alpine:3.17.0 +FROM alpine:3.17.2 ARG TARGETARCH ARG VERSION @@ -49,8 +49,8 @@ RUN apk update \ && apk upgrade \ && apk add -U --no-cache \ bash \ - curl \ openssl \ + curl \ ca-certificates \ dumb-init \ tzdata \ diff --git a/test/e2e-image/Dockerfile b/test/e2e-image/Dockerfile index ab4ba5026..09ce36cc5 100644 --- a/test/e2e-image/Dockerfile +++ b/test/e2e-image/Dockerfile @@ -1,7 +1,7 @@ ARG E2E_BASE_IMAGE FROM ${E2E_BASE_IMAGE} AS BASE -FROM alpine:3.16.2 +FROM alpine:3.17.2 RUN apk add -U --no-cache \ ca-certificates \ diff --git a/test/e2e/annotations/auth.go b/test/e2e/annotations/auth.go index 1f0f4c3b2..e3d0bcb2e 100644 --- a/test/e2e/annotations/auth.go +++ b/test/e2e/annotations/auth.go @@ -19,9 +19,9 @@ package annotations import ( "context" "fmt" + "golang.org/x/crypto/bcrypt" "net/http" "net/url" - "os/exec" "regexp" "strings" "time" @@ -899,7 +899,8 @@ http { // Auth error func buildSecret(username, password, name, namespace string) *corev1.Secret { - out, err := exec.Command("openssl", "passwd", "-crypt", password).CombinedOutput() + //out, err := exec.Command("openssl", "passwd", "-crypt", password).CombinedOutput() + out, err := bcrypt.GenerateFromPassword([]byte(password), 14) encpass := fmt.Sprintf("%v:%s\n", username, out) assert.Nil(ginkgo.GinkgoT(), err) @@ -917,7 +918,8 @@ func buildSecret(username, password, name, namespace string) *corev1.Secret { } func buildMapSecret(username, password, name, namespace string) *corev1.Secret { - out, err := exec.Command("openssl", "passwd", "-crypt", password).CombinedOutput() + //out, err := exec.Command("openssl", "passwd", "-crypt", password).CombinedOutput() + out, err := bcrypt.GenerateFromPassword([]byte(password), 14) assert.Nil(ginkgo.GinkgoT(), err) return &corev1.Secret{ diff --git a/test/e2e/settings/no_auth_locations.go b/test/e2e/settings/no_auth_locations.go index 70ec3be8f..2fc4b6455 100644 --- a/test/e2e/settings/no_auth_locations.go +++ b/test/e2e/settings/no_auth_locations.go @@ -18,8 +18,8 @@ package settings import ( "fmt" + "golang.org/x/crypto/bcrypt" "net/http" - "os/exec" "strings" "github.com/onsi/ginkgo/v2" @@ -147,7 +147,8 @@ func buildBasicAuthIngressWithSecondPath(host, namespace, secretName, pathName s } func buildSecret(username, password, name, namespace string) *corev1.Secret { - out, err := exec.Command("openssl", "passwd", "-crypt", password).CombinedOutput() + //out, err := exec.Command("openssl", "passwd", "-crypt", password).CombinedOutput() + out, err := bcrypt.GenerateFromPassword([]byte(password), 14) assert.Nil(ginkgo.GinkgoT(), err, "creating password") encpass := fmt.Sprintf("%v:%s\n", username, out) From f93d11b4cf549c4c443c0d81cf15fbecfd0b3388 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 12 Mar 2023 05:18:40 -0700 Subject: [PATCH 34/69] Bump helm/chart-releaser-action from 1.4.1 to 1.5.0 (#9720) Bumps [helm/chart-releaser-action](https://github.com/helm/chart-releaser-action) from 1.4.1 to 1.5.0. - [Release notes](https://github.com/helm/chart-releaser-action/releases) - [Commits](https://github.com/helm/chart-releaser-action/compare/98bccfd32b0f76149d188912ac8e45ddd3f8695f...be16258da8010256c6e82849661221415f031968) --- updated-dependencies: - dependency-name: helm/chart-releaser-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/helm.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/helm.yaml b/.github/workflows/helm.yaml index 2bd271bb2..b1db0c1d8 100644 --- a/.github/workflows/helm.yaml +++ b/.github/workflows/helm.yaml @@ -73,7 +73,7 @@ jobs: git config --global user.email "$GITHUB_ACTOR@users.noreply.github.com" - name: Helm Chart Releaser - uses: helm/chart-releaser-action@98bccfd32b0f76149d188912ac8e45ddd3f8695f # v1.4.1 + uses: helm/chart-releaser-action@be16258da8010256c6e82849661221415f031968 # v1.5.0 env: CR_SKIP_EXISTING: "false" CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" From b87645fe5318dc6fe9b00b3d9c6c25b5098d9e0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 12 Mar 2023 05:20:40 -0700 Subject: [PATCH 35/69] Bump docker/setup-buildx-action from 2.2.1 to 2.5.0 (#9719) Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2.2.1 to 2.5.0. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/8c0edbc76e98fa90f69d9a2c020dcb50019dc325...4b4e9c3e2d4531116a6f8ba8e71fc6e2cb6e6c8c) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b9a400747..db9f69c41 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -155,7 +155,7 @@ jobs: - name: Set up Docker Buildx id: buildx - uses: docker/setup-buildx-action@8c0edbc76e98fa90f69d9a2c020dcb50019dc325 # v2.2.1 + uses: docker/setup-buildx-action@4b4e9c3e2d4531116a6f8ba8e71fc6e2cb6e6c8c # v2.5.0 with: version: latest From e2d076c4fc52f6c9cdcf9af93d9ae41821303faa Mon Sep 17 00:00:00 2001 From: Do Hoang Khiem Date: Tue, 14 Mar 2023 18:32:18 +0700 Subject: [PATCH 36/69] HPA: autoscaling/v2beta1 deprecated, bump apiVersion to v2 for defaultBackend (#9731) --- charts/ingress-nginx/README.md | 1 + charts/ingress-nginx/templates/default-backend-hpa.yaml | 2 +- charts/ingress-nginx/values.yaml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/charts/ingress-nginx/README.md b/charts/ingress-nginx/README.md index 49bb38273..5e7fa85a1 100644 --- a/charts/ingress-nginx/README.md +++ b/charts/ingress-nginx/README.md @@ -456,6 +456,7 @@ Kubernetes: `>=1.20.0-0` | controller.watchIngressWithoutClass | bool | `false` | Process Ingress objects without ingressClass annotation/ingressClassName field Overrides value for --watch-ingress-without-class flag of the controller binary Defaults to false | | defaultBackend.affinity | object | `{}` | | | defaultBackend.autoscaling.annotations | object | `{}` | | +| defaultBackend.autoscaling.apiVersion | string | `"autoscaling/v2"` | | | defaultBackend.autoscaling.enabled | bool | `false` | | | defaultBackend.autoscaling.maxReplicas | int | `2` | | | defaultBackend.autoscaling.minReplicas | int | `1` | | diff --git a/charts/ingress-nginx/templates/default-backend-hpa.yaml b/charts/ingress-nginx/templates/default-backend-hpa.yaml index 594d26525..f9ae0b276 100644 --- a/charts/ingress-nginx/templates/default-backend-hpa.yaml +++ b/charts/ingress-nginx/templates/default-backend-hpa.yaml @@ -1,5 +1,5 @@ {{- if and .Values.defaultBackend.enabled .Values.defaultBackend.autoscaling.enabled }} -apiVersion: autoscaling/v2beta1 +apiVersion: {{ .Values.defaultBackend.autoscaling.apiVersion }} kind: HorizontalPodAutoscaler metadata: labels: diff --git a/charts/ingress-nginx/values.yaml b/charts/ingress-nginx/values.yaml index 202cd4a23..031078499 100644 --- a/charts/ingress-nginx/values.yaml +++ b/charts/ingress-nginx/values.yaml @@ -827,6 +827,7 @@ defaultBackend: # emptyDir: {} autoscaling: + apiVersion: autoscaling/v2 annotations: {} enabled: false minReplicas: 1 From 520384b1103d8382c857c0f86551dab2343eda2c Mon Sep 17 00:00:00 2001 From: Long Wu Yuan Date: Tue, 14 Mar 2023 17:06:17 +0530 Subject: [PATCH 37/69] bumped ginkgo to v2.9.0 (#9722) --- build/run-in-docker.sh | 2 +- images/test-runner/rootfs/Dockerfile | 2 +- test/e2e/run-chart-test.sh | 2 +- test/e2e/run-kind-e2e.sh | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/run-in-docker.sh b/build/run-in-docker.sh index 44ca2d5f7..d375c4336 100755 --- a/build/run-in-docker.sh +++ b/build/run-in-docker.sh @@ -87,7 +87,7 @@ if [[ "$DOCKER_IN_DOCKER_ENABLED" == "true" ]]; then echo "..reached DIND check TRUE block, inside run-in-docker.sh" echo "FLAGS=$FLAGS" #go env - go install -mod=mod github.com/onsi/ginkgo/v2/ginkgo@v2.6.1 + go install -mod=mod github.com/onsi/ginkgo/v2/ginkgo@v2.9.0 find / -type f -name ginkgo 2>/dev/null which ginkgo /bin/bash -c "${FLAGS}" diff --git a/images/test-runner/rootfs/Dockerfile b/images/test-runner/rootfs/Dockerfile index 1e8bc3643..7872b7a2b 100644 --- a/images/test-runner/rootfs/Dockerfile +++ b/images/test-runner/rootfs/Dockerfile @@ -55,7 +55,7 @@ ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH" -RUN go install github.com/onsi/ginkgo/v2/ginkgo@v2.6.1 && go install golang.org/x/lint/golint@latest +RUN go install github.com/onsi/ginkgo/v2/ginkgo@v2.9.0 && go install golang.org/x/lint/golint@latest ARG RESTY_CLI_VERSION ARG RESTY_CLI_SHA diff --git a/test/e2e/run-chart-test.sh b/test/e2e/run-chart-test.sh index d01ab4486..813e296cf 100755 --- a/test/e2e/run-chart-test.sh +++ b/test/e2e/run-chart-test.sh @@ -78,7 +78,7 @@ fi if [ "${SKIP_IMAGE_CREATION:-false}" = "false" ]; then if ! command -v ginkgo &> /dev/null; then - go install github.com/onsi/ginkgo/v2/ginkgo@v2.6.1 + go install github.com/onsi/ginkgo/v2/ginkgo@v2.9.0 fi echo "[dev-env] building image" make -C ${DIR}/../../ clean-image build image diff --git a/test/e2e/run-kind-e2e.sh b/test/e2e/run-kind-e2e.sh index df927bd1c..d3ea18b6d 100755 --- a/test/e2e/run-kind-e2e.sh +++ b/test/e2e/run-kind-e2e.sh @@ -95,7 +95,7 @@ fi if [ "${SKIP_E2E_IMAGE_CREATION}" = "false" ]; then if ! command -v ginkgo &> /dev/null; then - go install github.com/onsi/ginkgo/v2/ginkgo@v2.6.1 + go install github.com/onsi/ginkgo/v2/ginkgo@v2.9.0 fi echo "[dev-env] .. done building controller images" @@ -112,4 +112,4 @@ echo "[dev-env] copying docker images to cluster..." kind load docker-image --name="${KIND_CLUSTER_NAME}" --nodes="${KIND_WORKERS}" nginx-ingress-controller:e2e kind load docker-image --name="${KIND_CLUSTER_NAME}" --nodes="${KIND_WORKERS}" "${REGISTRY}"/controller:"${TAG}" echo "[dev-env] running e2e tests..." -make -C "${DIR}"/../../ e2e-test \ No newline at end of file +make -C "${DIR}"/../../ e2e-test From 47eb3a17fd95e9205dbe0c6bdb474ac4603f498d Mon Sep 17 00:00:00 2001 From: Marco Ebert Date: Tue, 14 Mar 2023 14:44:17 +0100 Subject: [PATCH 38/69] Deployment/DaemonSet: Label pods using `ingress-nginx.labels`. (#9732) --- charts/ingress-nginx/templates/controller-daemonset.yaml | 2 +- charts/ingress-nginx/templates/controller-deployment.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/ingress-nginx/templates/controller-daemonset.yaml b/charts/ingress-nginx/templates/controller-daemonset.yaml index e6721566b..efa273dac 100644 --- a/charts/ingress-nginx/templates/controller-daemonset.yaml +++ b/charts/ingress-nginx/templates/controller-daemonset.yaml @@ -33,7 +33,7 @@ spec: {{- end }} {{- end }} labels: - {{- include "ingress-nginx.selectorLabels" . | nindent 8 }} + {{- include "ingress-nginx.labels" . | nindent 8 }} app.kubernetes.io/component: controller {{- with .Values.controller.labels }} {{- toYaml . | nindent 8 }} diff --git a/charts/ingress-nginx/templates/controller-deployment.yaml b/charts/ingress-nginx/templates/controller-deployment.yaml index 9f1cf70db..36d7670e3 100644 --- a/charts/ingress-nginx/templates/controller-deployment.yaml +++ b/charts/ingress-nginx/templates/controller-deployment.yaml @@ -37,7 +37,7 @@ spec: {{- end }} {{- end }} labels: - {{- include "ingress-nginx.selectorLabels" . | nindent 8 }} + {{- include "ingress-nginx.labels" . | nindent 8 }} app.kubernetes.io/component: controller {{- with .Values.controller.labels }} {{- toYaml . | nindent 8 }} From 2d15a9946b0017d0888b59066862c48f09ad6fa3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Mar 2023 07:22:17 -0700 Subject: [PATCH 39/69] Bump actions/upload-artifact from 3.1.1 to 3.1.2 (#9717) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3.1.1 to 3.1.2. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/83fd05a356d7e2593de66fc9913b3002723633cb...0b7f8abb1508181956e8e162db84b466c27e18ce) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 6 +++--- .github/workflows/scorecards.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index db9f69c41..56d87c000 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -188,7 +188,7 @@ jobs: | pigz > docker.tar.gz - name: cache - uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # v3.1.1 + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 with: name: docker.tar.gz path: docker.tar.gz @@ -320,7 +320,7 @@ jobs: make kind-e2e-test - name: Uplaod e2e junit-reports - uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # v3.1.1 + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 if: success() || failure() with: name: e2e-test-reports-${{ matrix.k8s }} @@ -375,7 +375,7 @@ jobs: make kind-e2e-test - name: Uplaod e2e junit-reports - uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # v3.1.1 + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 if: success() || failure() with: name: e2e-test-reports-chroot-${{ matrix.k8s }} diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 6af70e691..8a3af47de 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -51,7 +51,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # v3.1.1 + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 with: name: SARIF file path: results.sarif From 7a95a43df63627d7fe1a4db6eceb1c83bf556d8f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Mar 2023 07:24:23 -0700 Subject: [PATCH 40/69] Bump goreleaser/goreleaser-action from 4.1.0 to 4.2.0 (#9718) Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 4.1.0 to 4.2.0. - [Release notes](https://github.com/goreleaser/goreleaser-action/releases) - [Commits](https://github.com/goreleaser/goreleaser-action/compare/8f67e590f2d095516493f017008adc464e63adb1...f82d6c1c344bcacabba2c841718984797f664a6b) --- updated-dependencies: - dependency-name: goreleaser/goreleaser-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/plugin.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/plugin.yaml b/.github/workflows/plugin.yaml index cb0f73489..760420765 100644 --- a/.github/workflows/plugin.yaml +++ b/.github/workflows/plugin.yaml @@ -28,7 +28,7 @@ jobs: check-latest: true - name: Run GoReleaser - uses: goreleaser/goreleaser-action@8f67e590f2d095516493f017008adc464e63adb1 # v4.1.0 + uses: goreleaser/goreleaser-action@f82d6c1c344bcacabba2c841718984797f664a6b # v4.2.0 with: version: latest args: release --rm-dist From 778577253e612181114e694028105e046d16c90e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Mar 2023 07:26:18 -0700 Subject: [PATCH 41/69] Bump actions/download-artifact from 3.0.1 to 3.0.2 (#9721) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3.0.1 to 3.0.2. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/9782bd6a9848b53b110e712e20e42d89988822b7...9bc31d5ccc31df68ecc42ccf4149144866c47d8a) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 56d87c000..00049bddf 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -217,7 +217,7 @@ jobs: check-latest: true - name: cache - uses: actions/download-artifact@9782bd6a9848b53b110e712e20e42d89988822b7 # v3.0.1 + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: docker.tar.gz @@ -291,7 +291,7 @@ jobs: uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 - name: cache - uses: actions/download-artifact@9782bd6a9848b53b110e712e20e42d89988822b7 # v3.0.1 + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: docker.tar.gz @@ -345,7 +345,7 @@ jobs: uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 - name: cache - uses: actions/download-artifact@9782bd6a9848b53b110e712e20e42d89988822b7 # v3.0.1 + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: docker.tar.gz From 4d443962d698ce022e71db4373ce48ef6b5964c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Mar 2023 07:28:16 -0700 Subject: [PATCH 42/69] Bump golang.org/x/crypto from 0.6.0 to 0.7.0 (#9723) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.6.0 to 0.7.0. - [Release notes](https://github.com/golang/crypto/releases) - [Commits](https://github.com/golang/crypto/compare/v0.6.0...v0.7.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index a653632f5..9144ff337 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/stretchr/testify v1.8.2 github.com/yudai/gojsondiff v1.0.0 github.com/zakjan/cert-chain-resolver v0.0.0-20211122211144-c6b0b792af9a - golang.org/x/crypto v0.6.0 + golang.org/x/crypto v0.7.0 google.golang.org/grpc v1.53.0 google.golang.org/grpc/examples v0.0.0-20221220003428-4f16fbe410f7 gopkg.in/go-playground/pool.v3 v3.1.1 @@ -101,11 +101,11 @@ require ( github.com/yudai/pp v2.0.1+incompatible // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect golang.org/x/mod v0.8.0 // indirect - golang.org/x/net v0.7.0 // indirect + golang.org/x/net v0.8.0 // indirect golang.org/x/oauth2 v0.5.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/term v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/term v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.6.0 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/go.sum b/go.sum index ff41229cf..813771bbc 100644 --- a/go.sum +++ b/go.sum @@ -407,8 +407,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -475,8 +475,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -546,19 +546,19 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From ce18c5e552158ff512afd8034de361fc42a2b381 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Mar 2023 07:30:17 -0700 Subject: [PATCH 43/69] Bump github.com/prometheus/common from 0.41.0 to 0.42.0 (#9724) Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.41.0 to 0.42.0. - [Release notes](https://github.com/prometheus/common/releases) - [Commits](https://github.com/prometheus/common/compare/v0.41.0...v0.42.0) --- updated-dependencies: - dependency-name: github.com/prometheus/common dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9144ff337..4c4bc903a 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 - github.com/prometheus/common v0.41.0 + github.com/prometheus/common v0.42.0 github.com/spf13/cobra v1.6.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.2 diff --git a/go.sum b/go.sum index 813771bbc..c3a2152b7 100644 --- a/go.sum +++ b/go.sum @@ -324,8 +324,8 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.41.0 h1:npo01n6vUlRViIj5fgwiK8vlNIh8bnoxqh3gypKsyAw= -github.com/prometheus/common v0.41.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/exporter-toolkit v0.7.0/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= From dba7ae04f5074ef49d1a61811660ad00680f0e6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Mar 2023 07:32:16 -0700 Subject: [PATCH 44/69] Bump actions/dependency-review-action from 3.0.2 to 3.0.3 (#9727) Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 3.0.2 to 3.0.3. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/0ff3da6f81b812d4ec3cf37a04e2308c7a723730...c090f4e553673e6e505ea70d6a95362ee12adb94) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/depreview.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/depreview.yaml b/.github/workflows/depreview.yaml index 758e4b95f..0ecdcd55c 100644 --- a/.github/workflows/depreview.yaml +++ b/.github/workflows/depreview.yaml @@ -11,4 +11,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 - name: 'Dependency Review' - uses: actions/dependency-review-action@0ff3da6f81b812d4ec3cf37a04e2308c7a723730 # v3.0.2 + uses: actions/dependency-review-action@c090f4e553673e6e505ea70d6a95362ee12adb94 # v3.0.3 From 3cd4ff93fe6cef93665604fd490f100fe65a3f53 Mon Sep 17 00:00:00 2001 From: longwuyuan Date: Wed, 15 Mar 2023 23:44:25 +0530 Subject: [PATCH 45/69] changed test-runner-image tag and sha --- build/run-in-docker.sh | 2 +- test/e2e-image/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/run-in-docker.sh b/build/run-in-docker.sh index d375c4336..3a6aeb43d 100755 --- a/build/run-in-docker.sh +++ b/build/run-in-docker.sh @@ -44,7 +44,7 @@ function cleanup { } trap cleanup EXIT -E2E_IMAGE=${E2E_IMAGE:-registry.k8s.io/ingress-nginx/e2e-test-runner:v20221221-controller-v1.5.1-62-g6ffaef32a@sha256:8f025472964cd15ae2d379503aba150565a8d78eb36b41ddfc5f1e3b1ca81a8e} +E2E_IMAGE=${E2E_IMAGE:-registry.k8s.io/ingress-nginx/e2e-test-runner:v20230314-helm-chart-4.5.2-32-g520384b11@sha256:754c62f9a5efd1ee515ee908ecc16c0c4d1dda96a8cc8019667182a55f3a9035} if [[ "$RUNTIME" == podman ]]; then # Podman does not support both tag and digest diff --git a/test/e2e-image/Makefile b/test/e2e-image/Makefile index f89bf6bf2..001146f65 100644 --- a/test/e2e-image/Makefile +++ b/test/e2e-image/Makefile @@ -1,6 +1,6 @@ DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) -E2E_BASE_IMAGE="registry.k8s.io/ingress-nginx/e2e-test-runner:v20221221-controller-v1.5.1-62-g6ffaef32a@sha256:8f025472964cd15ae2d379503aba150565a8d78eb36b41ddfc5f1e3b1ca81a8e" +E2E_BASE_IMAGE="registry.k8s.io/ingress-nginx/e2e-test-runner:v20230314-helm-chart-4.5.2-32-g520384b11@sha256:754c62f9a5efd1ee515ee908ecc16c0c4d1dda96a8cc8019667182a55f3a9035" image: echo "..entered Makefile in /test/e2e-image" From 2324ad0d0556d07aa39c4b8872e1b8419f338e33 Mon Sep 17 00:00:00 2001 From: Saumya <76432998+SaumyaBhushan@users.noreply.github.com> Date: Thu, 16 Mar 2023 13:57:18 +0530 Subject: [PATCH 46/69] updated NGINX_BASE image with latest tag (#9747) --- NGINX_BASE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NGINX_BASE b/NGINX_BASE index 72093c593..bf23fa5a7 100644 --- a/NGINX_BASE +++ b/NGINX_BASE @@ -1 +1 @@ -registry.k8s.io/ingress-nginx/nginx:21aa7f55a3325c1c26de0dfb62ede4c0a809a994@sha256:da6b877ed96dada46ed6e379051c2dd461dd5d329af7a7531820ad3e16197e20 \ No newline at end of file +registry.k8s.io/ingress-nginx/nginx:66a760794f91809bcd897cbdb45435653d73fd92@sha256:86c1581e69dc92d107f8edd36724890ea682a3afda8c1fb1ba41aabc7bc0128d \ No newline at end of file From 58e5a2c01f72bd1e4d9e924d5059b29350577d76 Mon Sep 17 00:00:00 2001 From: Marco Ebert Date: Fri, 17 Mar 2023 02:39:16 +0100 Subject: [PATCH 47/69] Chart: Drop `controller.headers`, rework DH param secret. (#9659) --- charts/ingress-nginx/README.md | 2 +- charts/ingress-nginx/templates/NOTES.txt | 7 ------- .../controller-configmap-proxyheaders.yaml | 9 ++------- .../templates/controller-configmap.yaml | 7 +++---- .../templates/controller-secret.yaml | 15 +++++++++++++++ .../ingress-nginx/templates/dh-param-secret.yaml | 10 ---------- charts/ingress-nginx/values.yaml | 2 +- 7 files changed, 22 insertions(+), 30 deletions(-) create mode 100644 charts/ingress-nginx/templates/controller-secret.yaml delete mode 100644 charts/ingress-nginx/templates/dh-param-secret.yaml diff --git a/charts/ingress-nginx/README.md b/charts/ingress-nginx/README.md index 5e7fa85a1..a72805054 100644 --- a/charts/ingress-nginx/README.md +++ b/charts/ingress-nginx/README.md @@ -509,7 +509,7 @@ Kubernetes: `>=1.20.0-0` | defaultBackend.serviceAccount.name | string | `""` | | | defaultBackend.tolerations | list | `[]` | Node tolerations for server scheduling to nodes with taints # Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ # | | defaultBackend.updateStrategy | object | `{}` | The update strategy to apply to the Deployment or DaemonSet # | -| dhParam | string | `nil` | A base64-encoded Diffie-Hellman parameter. This can be generated with: `openssl dhparam 4096 2> /dev/null | base64` # Ref: https://github.com/kubernetes/ingress-nginx/tree/main/docs/examples/customization/ssl-dh-param | +| dhParam | string | `""` | A base64-encoded Diffie-Hellman parameter. This can be generated with: `openssl dhparam 4096 2> /dev/null | base64` # Ref: https://github.com/kubernetes/ingress-nginx/tree/main/docs/examples/customization/ssl-dh-param | | imagePullSecrets | list | `[]` | Optional array of imagePullSecrets containing private registry credentials # Ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ | | podSecurityPolicy.enabled | bool | `false` | | | portNamePrefix | string | `""` | Prefix for TCP and UDP ports names in ingress controller service # Some cloud providers, like Yandex Cloud may have a requirements for a port name regex to support cloud load balancer integration | diff --git a/charts/ingress-nginx/templates/NOTES.txt b/charts/ingress-nginx/templates/NOTES.txt index 8985c56c0..9fe35c785 100644 --- a/charts/ingress-nginx/templates/NOTES.txt +++ b/charts/ingress-nginx/templates/NOTES.txt @@ -71,10 +71,3 @@ If TLS is enabled for the Ingress, a Secret containing the certificate and key m tls.crt: tls.key: type: kubernetes.io/tls - -{{- if .Values.controller.headers }} -################################################################################# -###### WARNING: `controller.headers` has been deprecated! ##### -###### It has been renamed to `controller.proxySetHeaders`. ##### -################################################################################# -{{- end }} diff --git a/charts/ingress-nginx/templates/controller-configmap-proxyheaders.yaml b/charts/ingress-nginx/templates/controller-configmap-proxyheaders.yaml index f8d15faf9..38feb721f 100644 --- a/charts/ingress-nginx/templates/controller-configmap-proxyheaders.yaml +++ b/charts/ingress-nginx/templates/controller-configmap-proxyheaders.yaml @@ -1,4 +1,4 @@ -{{- if or .Values.controller.proxySetHeaders .Values.controller.headers -}} +{{- if .Values.controller.proxySetHeaders -}} apiVersion: v1 kind: ConfigMap metadata: @@ -10,10 +10,5 @@ metadata: {{- end }} name: {{ include "ingress-nginx.fullname" . }}-custom-proxy-headers namespace: {{ .Release.Namespace }} -data: -{{- if .Values.controller.proxySetHeaders }} -{{ toYaml .Values.controller.proxySetHeaders | indent 2 }} -{{ else if and .Values.controller.headers (not .Values.controller.proxySetHeaders) }} -{{ toYaml .Values.controller.headers | indent 2 }} -{{- end }} +data: {{ toYaml .Values.controller.proxySetHeaders | nindent 2 }} {{- end }} diff --git a/charts/ingress-nginx/templates/controller-configmap.yaml b/charts/ingress-nginx/templates/controller-configmap.yaml index f28b26e1e..9ec2b8369 100644 --- a/charts/ingress-nginx/templates/controller-configmap.yaml +++ b/charts/ingress-nginx/templates/controller-configmap.yaml @@ -17,13 +17,12 @@ data: {{- if .Values.controller.addHeaders }} add-headers: {{ .Release.Namespace }}/{{ include "ingress-nginx.fullname" . }}-custom-add-headers {{- end }} -{{- if or .Values.controller.proxySetHeaders .Values.controller.headers }} +{{- if .Values.controller.proxySetHeaders }} proxy-set-headers: {{ .Release.Namespace }}/{{ include "ingress-nginx.fullname" . }}-custom-proxy-headers {{- end }} {{- if .Values.dhParam }} - ssl-dh-param: {{ printf "%s/%s" .Release.Namespace (include "ingress-nginx.controller.fullname" .) }} + ssl-dh-param: {{ .Release.Namespace }}/{{ include "ingress-nginx.controller.fullname" . }} {{- end }} {{- range $key, $value := .Values.controller.config }} - {{- $key | nindent 2 }}: {{ $value | quote }} + {{- $key | nindent 2 }}: {{ $value | quote }} {{- end }} - diff --git a/charts/ingress-nginx/templates/controller-secret.yaml b/charts/ingress-nginx/templates/controller-secret.yaml new file mode 100644 index 000000000..f3744232f --- /dev/null +++ b/charts/ingress-nginx/templates/controller-secret.yaml @@ -0,0 +1,15 @@ +{{- if .Values.dhParam -}} +apiVersion: v1 +kind: Secret +metadata: + labels: + {{- include "ingress-nginx.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "ingress-nginx.controller.fullname" . }} + namespace: {{ .Release.Namespace }} +data: + dhparam.pem: {{ .Values.dhParam }} +{{- end }} diff --git a/charts/ingress-nginx/templates/dh-param-secret.yaml b/charts/ingress-nginx/templates/dh-param-secret.yaml deleted file mode 100644 index 12e7a4f63..000000000 --- a/charts/ingress-nginx/templates/dh-param-secret.yaml +++ /dev/null @@ -1,10 +0,0 @@ -{{- with .Values.dhParam -}} -apiVersion: v1 -kind: Secret -metadata: - name: {{ include "ingress-nginx.controller.fullname" $ }} - labels: - {{- include "ingress-nginx.labels" $ | nindent 4 }} -data: - dhparam.pem: {{ . }} -{{- end }} diff --git a/charts/ingress-nginx/values.yaml b/charts/ingress-nginx/values.yaml index 031078499..1fab6f52a 100644 --- a/charts/ingress-nginx/values.yaml +++ b/charts/ingress-nginx/values.yaml @@ -886,4 +886,4 @@ portNamePrefix: "" # -- (string) A base64-encoded Diffie-Hellman parameter. # This can be generated with: `openssl dhparam 4096 2> /dev/null | base64` ## Ref: https://github.com/kubernetes/ingress-nginx/tree/main/docs/examples/customization/ssl-dh-param -dhParam: +dhParam: "" From fec1dbe3a122089a92c1f794fa2ca6b389640d49 Mon Sep 17 00:00:00 2001 From: Saumya <76432998+SaumyaBhushan@users.noreply.github.com> Date: Sun, 19 Mar 2023 03:43:16 +0530 Subject: [PATCH 48/69] changes Makefile of echo folder to trigger code-build (#9754) --- images/echo/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/echo/Makefile b/images/echo/Makefile index 500704e81..0ab1c945f 100644 --- a/images/echo/Makefile +++ b/images/echo/Makefile @@ -4,7 +4,7 @@ # 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 +# 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, From 1e629fae1d12a6bf3151f709ecdb96b5b1165ebb Mon Sep 17 00:00:00 2001 From: Saumya <76432998+SaumyaBhushan@users.noreply.github.com> Date: Sun, 19 Mar 2023 03:45:16 +0530 Subject: [PATCH 49/69] added upgrade ginkgo documentation for contributors (#9753) --- ginkgo_upgrade.md | 131 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 ginkgo_upgrade.md diff --git a/ginkgo_upgrade.md b/ginkgo_upgrade.md new file mode 100644 index 000000000..1ed996cd1 --- /dev/null +++ b/ginkgo_upgrade.md @@ -0,0 +1,131 @@ +# GINKGO UPGRADE + +#### Bumping ginkgo in the project requires four PRs. + +## 1. Dependabot PR + +- Dependabot automatically updates `ginkgo version` but only in [go.mod ](go.mod) and [go.sum ](go.sum) files. +- This is an automatically generated PR by Dependabot but it needs approval from maintainers to get merged. + +## 2. Edit-hardcoded-version PR + +### a. Make changes to appropriate files in required directories + +- Make changes in files where gingko version is hardcoded. These files are : + - [run-in-docker.sh ](build/run-in-docker.sh) + - [Dockerfile ](images/test-runner/rootfs/Dockerfile) + - [run.sh ](test/e2e/run.sh) + - [run-chart-test.sh ](test/e2e/run-chart-test.sh) + +### b. Create PR + +- Open pull request(s) accordingly, to fire cloudbuild for building the component's image (if applicable). + +### c. Merge + +- Merging will fire cloudbuild, which will result in images being promoted to the [staging container registry](https://console.cloud.google.com/gcr/images/k8s-staging-ingress-nginx). + +### d. Make sure cloudbuild is a success + +- Wait for [cloud build](https://console.cloud.google.com/cloud-build/builds?project=k8s-staging-ingress-nginx). If you don't have access to cloudbuild, you can also have a look at [this](https://prow.k8s.io/?repo=kubernetes%2Fingress-nginx&job=post-*), to see the progress of the build. + +- Proceed only after cloud-build is successful in building a new Ingress-Nginx-Controller image. + + +## 3. PROMOTE the new-testrunner-image PR: + +Promoting the images basically means that images, that were pushed to staging container registry in the steps above, now are also pushed to the public container registry. Thus are publicly available. Follow these steps to promote images: +- When you make changes to the `Dockerfile` or other core content under [images directory ](images), it generates a new image in google cloudbuild. This is because kubernetes projects need to use the infra provided for the kubernetes projects. The new image is always only pushed to the staging repository of K8S. From the staging repo, the new image needs to be promoted to the production repo. And once promoted, its possible to use the sha of the new image in the code. + +### a. Get the sha + +- Get the sha of the new image(s) of the controller, from the cloudbuild, from steps above + + - The sha is available in output from [cloud build](https://console.cloud.google.com/cloud-build/builds?project=k8s-staging-ingress-nginx) + + - The sha is also visible [here](https://console.cloud.google.com/gcr/images/k8s-staging-ingress-nginx/global/e2e-test-runner) + + - The sha is also visible [here]((https://prow.k8s.io/?repo=kubernetes%2Fingress-nginx&job=post-*)), after cloud build is finished. Click on the respective job, go to `Artifacts` section in the UI, then again `artifacts` in the directory browser. In the `build.log` at the very bottom you see something like this: + + ``` + ... + pushing manifest for gcr.io/k8s-staging-ingress-nginx/controller:v1.0.2@sha256:e15fac6e8474d77e1f017edc33d804ce72a184e3c0a30963b2a0d7f0b89f6b16 + ... + ``` + +### b. Add the new image to [k8s.io](http://github.com/kubernetes/k8s.io) + +- The sha(s) from the step before (and the tag(s) for the new image(s) have to be added, as a new line, in a file, of the [k8s.io](http://github.com/kubernetes/k8s.io) project of Kubernetes organization. + +- Fork that other project (if you don't have a fork already). + +- Other project to fork [Github repo kubernetes/k8s.io](http://github.com/kubernetes/k8s.io) + +- Fetch --all and rebase to upstream if already forked. + +- Create a branch in your fork, named as the issue number for this release + +- In the related branch, of your fork, edit the file k8s.gcr.io/images/k8s-staging-ingress-nginx/images.yaml. + +- For making it easier, you can edit your branch directly in the browser. But be careful about making any mistake. + +- Insert the sha(s) & the tag(s), in a new line, in this file [Project kubernetes/k8s.io Ingress-Nginx-Controller Images](https://github.com/kubernetes/k8s.io/blob/main/k8s.gcr.io/images/k8s-staging-ingress-nginx/images.yaml) Look at this [example PR and the diff](https://github.com/kubernetes/k8s.io/pull/4499) to see how it was done before + +- Save and commit + +### c. Create PR + +- Open pull request to promote the new e2e-test-runner image. + +### d. Merge + +- Merge success is required. + +- Proceed only after cloud-build is successful in building a new e2e-test-runner image. + + +## 4. Change testrunner-image-sha PR + +### a. Get the sha + +- Make sure to get the tag and sha of the promoted image from the step before, either from cloudbuild or from [here](https://console.cloud.google.com/gcr/images/k8s-artifacts-prod/us/ingress-nginx/e2e-test-runner). + +### a. Make sure your git workspace is ready + +- Get your git workspace ready + + - If not using a pre-existing fork, then Fork the repo kubernetes/ingress-nginx + + - Clone (to laptop or wherever) + + - Add upstream + + - Set upstream url to no_push + + - Checkout & switch to branch, named as per related new-release-issue-number + + - If already forked, and upstream already added, then `git fetch --all` and `git rebase upstream/main` (not origin) + + - Checkout a branch in your fork's clone + + - Perform any other diligence as needed + +- Prefer to edit only and only in your branch, in your Fork + +### b. Change testrunner-image-sha + +- You need update the testrunner-image-sha in the following files : + + - [run-in-docker.sh](https://github.com/kubernetes/ingress-nginx/blob/main/build/run-in-docker.sh#L41) + - [Makefile](https://github.com/kubernetes/ingress-nginx/blob/main/test/e2e-image/Makefile#L3) + +### c. Create PR + +- Look at this PR for how it was done before [example PR](https://github.com/kubernetes/ingress-nginx/pull/9444) +- Create a PR + +### d. Merge + +- Finally merge the PR. + +## END ## \ No newline at end of file From 6eb52c39c8d964e3e23d537a23c1aadb1befb3fd Mon Sep 17 00:00:00 2001 From: Saumya <76432998+SaumyaBhushan@users.noreply.github.com> Date: Sun, 19 Mar 2023 03:47:15 +0530 Subject: [PATCH 50/69] updated nginx-error digest and tags (#9755) --- .../custom-errors/custom-default-backend.helm.values.yaml | 2 +- .../customization/custom-errors/custom-default-backend.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/examples/customization/custom-errors/custom-default-backend.helm.values.yaml b/docs/examples/customization/custom-errors/custom-default-backend.helm.values.yaml index 670208559..807da71a4 100644 --- a/docs/examples/customization/custom-errors/custom-default-backend.helm.values.yaml +++ b/docs/examples/customization/custom-errors/custom-default-backend.helm.values.yaml @@ -6,7 +6,7 @@ defaultBackend: image: registry: registry.k8s.io image: ingress-nginx/nginx-errors - tag: "v20220916-gd32f8c343@sha256:09c421ac743bace19ab77979b82186941c5125c95e62cdb40bdf41293b5c275c" + tag: "v20230312-helm-chart-4.5.2-28-g66a760794@sha256:332be6ff8c4e93e8845963932f98839dfd52ae49829c29e06475368a3e4fbd9e" extraVolumes: - name: custom-error-pages configMap: diff --git a/docs/examples/customization/custom-errors/custom-default-backend.yaml b/docs/examples/customization/custom-errors/custom-default-backend.yaml index 072beab3b..5fc5c55e4 100644 --- a/docs/examples/customization/custom-errors/custom-default-backend.yaml +++ b/docs/examples/customization/custom-errors/custom-default-backend.yaml @@ -36,7 +36,7 @@ spec: spec: containers: - name: nginx-error-server - image: registry.k8s.io/ingress-nginx/nginx-errors:v20220916-gd32f8c343@sha256:09c421ac743bace19ab77979b82186941c5125c95e62cdb40bdf41293b5c275c + image: registry.k8s.io/ingress-nginx/nginx-errors:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:332be6ff8c4e93e8845963932f98839dfd52ae49829c29e06475368a3e4fbd9e ports: - containerPort: 8080 # Setting the environment variable DEBUG we can see the headers sent From 45dae623c74515382d3566a3643c105d0f6d2b2e Mon Sep 17 00:00:00 2001 From: Saumya <76432998+SaumyaBhushan@users.noreply.github.com> Date: Sun, 19 Mar 2023 21:29:16 +0530 Subject: [PATCH 51/69] updated kube-webhook-certgen digest and tags (#9756) --- charts/ingress-nginx/README.md | 4 ++-- charts/ingress-nginx/values.yaml | 4 ++-- deploy/static/provider/aws/deploy.yaml | 4 ++-- .../static/provider/aws/nlb-with-tls-termination/deploy.yaml | 4 ++-- deploy/static/provider/baremetal/deploy.yaml | 4 ++-- deploy/static/provider/cloud/deploy.yaml | 4 ++-- deploy/static/provider/do/deploy.yaml | 4 ++-- deploy/static/provider/exoscale/deploy.yaml | 4 ++-- deploy/static/provider/kind/deploy.yaml | 4 ++-- deploy/static/provider/scw/deploy.yaml | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/charts/ingress-nginx/README.md b/charts/ingress-nginx/README.md index a72805054..6725bb2bb 100644 --- a/charts/ingress-nginx/README.md +++ b/charts/ingress-nginx/README.md @@ -271,11 +271,11 @@ Kubernetes: `>=1.20.0-0` | controller.admissionWebhooks.networkPolicyEnabled | bool | `false` | | | controller.admissionWebhooks.objectSelector | object | `{}` | | | controller.admissionWebhooks.patch.enabled | bool | `true` | | -| controller.admissionWebhooks.patch.image.digest | string | `"sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f"` | | +| controller.admissionWebhooks.patch.image.digest | string | `"sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f"` | | | controller.admissionWebhooks.patch.image.image | string | `"ingress-nginx/kube-webhook-certgen"` | | | controller.admissionWebhooks.patch.image.pullPolicy | string | `"IfNotPresent"` | | | controller.admissionWebhooks.patch.image.registry | string | `"registry.k8s.io"` | | -| controller.admissionWebhooks.patch.image.tag | string | `"v20220916-gd32f8c343"` | | +| controller.admissionWebhooks.patch.image.tag | string | `"v20230312-helm-chart-4.5.2-28-g66a760794"` | | | controller.admissionWebhooks.patch.labels | object | `{}` | Labels to be added to patch job resources | | controller.admissionWebhooks.patch.nodeSelector."kubernetes.io/os" | string | `"linux"` | | | controller.admissionWebhooks.patch.podAnnotations | object | `{}` | | diff --git a/charts/ingress-nginx/values.yaml b/charts/ingress-nginx/values.yaml index 1fab6f52a..f6064911a 100644 --- a/charts/ingress-nginx/values.yaml +++ b/charts/ingress-nginx/values.yaml @@ -598,8 +598,8 @@ controller: ## for backwards compatibility consider setting the full image url via the repository value below ## use *either* current default registry/image or repository format or installing chart by providing the values.yaml will fail ## repository: - tag: v20220916-gd32f8c343 - digest: sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + tag: v20230312-helm-chart-4.5.2-28-g66a760794 + digest: sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f pullPolicy: IfNotPresent # -- Provide a priority class name to the webhook patching job ## diff --git a/deploy/static/provider/aws/deploy.yaml b/deploy/static/provider/aws/deploy.yaml index 487340a73..bf4ffce19 100644 --- a/deploy/static/provider/aws/deploy.yaml +++ b/deploy/static/provider/aws/deploy.yaml @@ -537,7 +537,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f imagePullPolicy: IfNotPresent name: create securityContext: @@ -586,7 +586,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f imagePullPolicy: IfNotPresent name: patch securityContext: diff --git a/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml b/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml index 4763623c8..0b58831a3 100644 --- a/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml +++ b/deploy/static/provider/aws/nlb-with-tls-termination/deploy.yaml @@ -549,7 +549,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f imagePullPolicy: IfNotPresent name: create securityContext: @@ -598,7 +598,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f imagePullPolicy: IfNotPresent name: patch securityContext: diff --git a/deploy/static/provider/baremetal/deploy.yaml b/deploy/static/provider/baremetal/deploy.yaml index a642d67da..d141e8ca6 100644 --- a/deploy/static/provider/baremetal/deploy.yaml +++ b/deploy/static/provider/baremetal/deploy.yaml @@ -531,7 +531,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f imagePullPolicy: IfNotPresent name: create securityContext: @@ -580,7 +580,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f imagePullPolicy: IfNotPresent name: patch securityContext: diff --git a/deploy/static/provider/cloud/deploy.yaml b/deploy/static/provider/cloud/deploy.yaml index 8b09efac1..97c22739b 100644 --- a/deploy/static/provider/cloud/deploy.yaml +++ b/deploy/static/provider/cloud/deploy.yaml @@ -533,7 +533,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f imagePullPolicy: IfNotPresent name: create securityContext: @@ -582,7 +582,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f imagePullPolicy: IfNotPresent name: patch securityContext: diff --git a/deploy/static/provider/do/deploy.yaml b/deploy/static/provider/do/deploy.yaml index 7461d9794..5b7c86670 100644 --- a/deploy/static/provider/do/deploy.yaml +++ b/deploy/static/provider/do/deploy.yaml @@ -536,7 +536,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f imagePullPolicy: IfNotPresent name: create securityContext: @@ -585,7 +585,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f imagePullPolicy: IfNotPresent name: patch securityContext: diff --git a/deploy/static/provider/exoscale/deploy.yaml b/deploy/static/provider/exoscale/deploy.yaml index be0e2f587..c8236ef20 100644 --- a/deploy/static/provider/exoscale/deploy.yaml +++ b/deploy/static/provider/exoscale/deploy.yaml @@ -542,7 +542,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f imagePullPolicy: IfNotPresent name: create securityContext: @@ -591,7 +591,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f imagePullPolicy: IfNotPresent name: patch securityContext: diff --git a/deploy/static/provider/kind/deploy.yaml b/deploy/static/provider/kind/deploy.yaml index abb310999..a8fd055c9 100644 --- a/deploy/static/provider/kind/deploy.yaml +++ b/deploy/static/provider/kind/deploy.yaml @@ -547,7 +547,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f imagePullPolicy: IfNotPresent name: create securityContext: @@ -596,7 +596,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f imagePullPolicy: IfNotPresent name: patch securityContext: diff --git a/deploy/static/provider/scw/deploy.yaml b/deploy/static/provider/scw/deploy.yaml index fdc3c6cde..1f04b9b9e 100644 --- a/deploy/static/provider/scw/deploy.yaml +++ b/deploy/static/provider/scw/deploy.yaml @@ -536,7 +536,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f imagePullPolicy: IfNotPresent name: create securityContext: @@ -585,7 +585,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343@sha256:39c5b2e3310dc4264d638ad28d9d1d96c4cbb2b2dcfb52368fe4e3c63f61e10f + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f imagePullPolicy: IfNotPresent name: patch securityContext: From 1f4fb4133240794cdd2fcc2c1b5171ff5b8b9d01 Mon Sep 17 00:00:00 2001 From: Saumya <76432998+SaumyaBhushan@users.noreply.github.com> Date: Sun, 19 Mar 2023 21:33:16 +0530 Subject: [PATCH 52/69] updated digest and sha for e2e-test-cfssl (#9757) --- test/e2e/settings/ocsp/ocsp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/settings/ocsp/ocsp.go b/test/e2e/settings/ocsp/ocsp.go index adf4351e7..483013f59 100644 --- a/test/e2e/settings/ocsp/ocsp.go +++ b/test/e2e/settings/ocsp/ocsp.go @@ -290,7 +290,7 @@ func ocspserveDeployment(namespace string) (*appsv1.Deployment, *corev1.Service) Containers: []corev1.Container{ { Name: name, - Image: "registry.k8s.io/ingress-nginx/e2e-test-cfssl@sha256:c1b273763048944dd7d22d37adfc65be4fa6a5f6068204292573c6cdc5ea3457", + Image: "registry.k8s.io/ingress-nginx/e2e-test-cfssl@sha256:d02c1e18f573449966999fc850f1fed3d37621bf77797562cbe77ebdb06a66ea", Command: []string{ "/bin/bash", "-c", From 18c3a91a0462b8182a2ff61461f002f32749aaef Mon Sep 17 00:00:00 2001 From: Saumya <76432998+SaumyaBhushan@users.noreply.github.com> Date: Mon, 20 Mar 2023 01:13:16 +0530 Subject: [PATCH 53/69] updated digest and sha for opentelemetry (#9758) --- charts/ingress-nginx/README.md | 2 +- charts/ingress-nginx/values.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/ingress-nginx/README.md b/charts/ingress-nginx/README.md index 6725bb2bb..6da71a144 100644 --- a/charts/ingress-nginx/README.md +++ b/charts/ingress-nginx/README.md @@ -395,7 +395,7 @@ Kubernetes: `>=1.20.0-0` | controller.nodeSelector | object | `{"kubernetes.io/os":"linux"}` | Node labels for controller pod assignment # Ref: https://kubernetes.io/docs/user-guide/node-selection/ # | | controller.opentelemetry.containerSecurityContext.allowPrivilegeEscalation | bool | `false` | | | controller.opentelemetry.enabled | bool | `false` | | -| controller.opentelemetry.image | string | `"registry.k8s.io/ingress-nginx/opentelemetry:v20230107-helm-chart-4.4.2-2-g96b3d2165@sha256:331b9bebd6acfcd2d3048abbdd86555f5be76b7e3d0b5af4300b04235c6056c9"` | | +| controller.opentelemetry.image | string | `"registry.k8s.io/ingress-nginx/opentelemetry:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:40f766ac4a9832f36f217bb0e98d44c8d38faeccbfe861fbc1a76af7e9ab257f"` | | | controller.podAnnotations | object | `{}` | Annotations to be added to controller pods # | | controller.podLabels | object | `{}` | Labels to add to the pod container metadata | | controller.podSecurityContext | object | `{}` | Security Context policies for controller pods | diff --git a/charts/ingress-nginx/values.yaml b/charts/ingress-nginx/values.yaml index f6064911a..f043c17cb 100644 --- a/charts/ingress-nginx/values.yaml +++ b/charts/ingress-nginx/values.yaml @@ -536,7 +536,7 @@ controller: opentelemetry: enabled: false - image: registry.k8s.io/ingress-nginx/opentelemetry:v20230107-helm-chart-4.4.2-2-g96b3d2165@sha256:331b9bebd6acfcd2d3048abbdd86555f5be76b7e3d0b5af4300b04235c6056c9 + image: registry.k8s.io/ingress-nginx/opentelemetry:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:40f766ac4a9832f36f217bb0e98d44c8d38faeccbfe861fbc1a76af7e9ab257f containerSecurityContext: allowPrivilegeEscalation: false admissionWebhooks: From f75b12e690151d6a2e1f692ff22fc01152cbd162 Mon Sep 17 00:00:00 2001 From: Saumya <76432998+SaumyaBhushan@users.noreply.github.com> Date: Mon, 20 Mar 2023 01:17:16 +0530 Subject: [PATCH 54/69] updated digest and sha for e2e-test-fastcgi-helloserver (#9759) --- test/e2e/framework/fastcgi_helloserver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/framework/fastcgi_helloserver.go b/test/e2e/framework/fastcgi_helloserver.go index c3e89c7f5..719048c06 100644 --- a/test/e2e/framework/fastcgi_helloserver.go +++ b/test/e2e/framework/fastcgi_helloserver.go @@ -58,7 +58,7 @@ func (f *Framework) NewNewFastCGIHelloServerDeploymentWithReplicas(replicas int3 Containers: []corev1.Container{ { Name: "fastcgi-helloserver", - Image: "registry.k8s.io/ingress-nginx/e2e-test-fastcgi-helloserver@sha256:723b8187e1768d199b93fd939c37c1ce9427dcbca72ec6415f4d890bca637fcc", + Image: "registry.k8s.io/ingress-nginx/e2e-test-fastcgi-helloserver@sha256:0e08c836cc58f1ea862578de99b13bc4264fe071e816f96dc1d79857bfba7473", Env: []corev1.EnvVar{}, Ports: []corev1.ContainerPort{ { From 2d3554794314139e87ac47c3f75e5f6f5d48a467 Mon Sep 17 00:00:00 2001 From: Saumya <76432998+SaumyaBhushan@users.noreply.github.com> Date: Mon, 20 Mar 2023 01:17:24 +0530 Subject: [PATCH 55/69] updated digest and sha for e2e-test-echo (#9760) --- .../customization/external-auth-headers/echo-service.yaml | 2 +- test/e2e/framework/deployment.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/examples/customization/external-auth-headers/echo-service.yaml b/docs/examples/customization/external-auth-headers/echo-service.yaml index 0fe37be56..57df4d628 100644 --- a/docs/examples/customization/external-auth-headers/echo-service.yaml +++ b/docs/examples/customization/external-auth-headers/echo-service.yaml @@ -18,7 +18,7 @@ spec: terminationGracePeriodSeconds: 60 containers: - name: echo-service - image: registry.k8s.io/ingress-nginx/e2e-test-echo:v20220819-ga98c63787@sha256:778ac6d1188c8de8ecabeddd3c37b72c8adc8c712bad2bd7a81fb23a3514934c + image: registry.k8s.io/ingress-nginx/e2e-test-echo:v20230318-helm-chart-4.5.2-44-gfec1dbe3a@sha256:4938d1d91a2b7d19454460a8c1b010b89f6ff92d2987fd889ac3e8fc3b70d91a ports: - containerPort: 8080 resources: diff --git a/test/e2e/framework/deployment.go b/test/e2e/framework/deployment.go index 8115fd12e..4627a8892 100644 --- a/test/e2e/framework/deployment.go +++ b/test/e2e/framework/deployment.go @@ -93,7 +93,7 @@ func (f *Framework) NewEchoDeployment(opts ...func(*deploymentOptions)) { o(options) } - deployment := newDeployment(options.name, options.namespace, "registry.k8s.io/ingress-nginx/e2e-test-echo@sha256:778ac6d1188c8de8ecabeddd3c37b72c8adc8c712bad2bd7a81fb23a3514934c", 80, int32(options.replicas), + deployment := newDeployment(options.name, options.namespace, "registry.k8s.io/ingress-nginx/e2e-test-echo@sha256:4938d1d91a2b7d19454460a8c1b010b89f6ff92d2987fd889ac3e8fc3b70d91a", 80, int32(options.replicas), nil, nil, nil, []corev1.VolumeMount{}, []corev1.Volume{}, From 9a1cfc7181d0afc1e405962c5308abaa0501b751 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 11:01:37 +0000 Subject: [PATCH 56/69] Bump securego/gosec from 2.14.0 to 2.15.0 Bumps [securego/gosec](https://github.com/securego/gosec) from 2.14.0 to 2.15.0. - [Release notes](https://github.com/securego/gosec/releases) - [Changelog](https://github.com/securego/gosec/blob/master/.goreleaser.yml) - [Commits](https://github.com/securego/gosec/compare/1af1d5bb49259b62e45c505db397dd2ada5d74f8...a459eb0ba387d9bd083d5c2e2354dbeef2465038) --- updated-dependencies: - dependency-name: securego/gosec dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 00049bddf..3d7c21c3d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -68,7 +68,7 @@ jobs: uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 - name: Run Gosec Security Scanner - uses: securego/gosec@1af1d5bb49259b62e45c505db397dd2ada5d74f8 # v2.14.0 + uses: securego/gosec@a459eb0ba387d9bd083d5c2e2354dbeef2465038 # v2.15.0 with: # G601 for zz_generated.deepcopy.go # G306 TODO: Expect WriteFile permissions to be 0600 or less From 12da492f0112a5833f6437e00a485c23562856b2 Mon Sep 17 00:00:00 2001 From: Ole-Martin Bratteng <1681525+omBratteng@users.noreply.github.com> Date: Mon, 20 Mar 2023 13:05:18 +0100 Subject: [PATCH 57/69] docs(helm): fix value key in readme for enabling certManager (#9640) --- charts/ingress-nginx/README.md | 2 +- charts/ingress-nginx/README.md.gotmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/ingress-nginx/README.md b/charts/ingress-nginx/README.md index 6da71a144..9659df139 100644 --- a/charts/ingress-nginx/README.md +++ b/charts/ingress-nginx/README.md @@ -228,7 +228,7 @@ A validating and configuration requires the endpoint to which the request is sen #### Alternatives It should be possible to use [cert-manager/cert-manager](https://github.com/cert-manager/cert-manager) if a more complete solution is required. -You can enable automatic self-signed TLS certificate provisioning via cert-manager by setting the `controller.admissionWebhooks.certManager.enable` value to true. +You can enable automatic self-signed TLS certificate provisioning via cert-manager by setting the `controller.admissionWebhooks.certManager.enabled` value to true. Please ensure that cert-manager is correctly installed and configured. diff --git a/charts/ingress-nginx/README.md.gotmpl b/charts/ingress-nginx/README.md.gotmpl index 78e4f38d4..99a2a62cb 100644 --- a/charts/ingress-nginx/README.md.gotmpl +++ b/charts/ingress-nginx/README.md.gotmpl @@ -227,7 +227,7 @@ A validating and configuration requires the endpoint to which the request is sen #### Alternatives It should be possible to use [cert-manager/cert-manager](https://github.com/cert-manager/cert-manager) if a more complete solution is required. -You can enable automatic self-signed TLS certificate provisioning via cert-manager by setting the `controller.admissionWebhooks.certManager.enable` value to true. +You can enable automatic self-signed TLS certificate provisioning via cert-manager by setting the `controller.admissionWebhooks.certManager.enabled` value to true. Please ensure that cert-manager is correctly installed and configured. From 1936973ea9d95b62fe8077e1cb36b2471d2c16b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 09:33:19 -0700 Subject: [PATCH 58/69] Bump actions/add-to-project from 0.4.0 to 0.4.1 (#9765) Bumps [actions/add-to-project](https://github.com/actions/add-to-project) from 0.4.0 to 0.4.1. - [Release notes](https://github.com/actions/add-to-project/releases) - [Commits](https://github.com/actions/add-to-project/compare/960fbad431afda394cfcf8743445e741acd19e85...4756e6330fe1e0a736690d3cfd9f11c9399c2ed4) --- updated-dependencies: - dependency-name: actions/add-to-project dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/project.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/project.yml b/.github/workflows/project.yml index d75435712..35d6d3e5c 100644 --- a/.github/workflows/project.yml +++ b/.github/workflows/project.yml @@ -13,7 +13,7 @@ jobs: repository-projects: write issues: write steps: - - uses: actions/add-to-project@960fbad431afda394cfcf8743445e741acd19e85 # v0.4.0 + - uses: actions/add-to-project@4756e6330fe1e0a736690d3cfd9f11c9399c2ed4 # v0.4.1 with: project-url: https://github.com/orgs/kubernetes/projects/104 github-token: ${{ secrets.PROJECT_WRITER }} From 5c0b70764395832d243cd6647aa384c891c453da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Mar 2023 06:33:08 -0700 Subject: [PATCH 59/69] Bump actions/dependency-review-action from 3.0.3 to 3.0.4 (#9766) Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 3.0.3 to 3.0.4. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/c090f4e553673e6e505ea70d6a95362ee12adb94...f46c48ed6d4f1227fb2d9ea62bf6bcbed315589e) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/depreview.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/depreview.yaml b/.github/workflows/depreview.yaml index 0ecdcd55c..571610dc6 100644 --- a/.github/workflows/depreview.yaml +++ b/.github/workflows/depreview.yaml @@ -11,4 +11,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 - name: 'Dependency Review' - uses: actions/dependency-review-action@c090f4e553673e6e505ea70d6a95362ee12adb94 # v3.0.3 + uses: actions/dependency-review-action@f46c48ed6d4f1227fb2d9ea62bf6bcbed315589e # v3.0.4 From 9b3599206c0b5789523678a7f09d8c12d9f41cb7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Mar 2023 06:35:10 -0700 Subject: [PATCH 60/69] Bump k8s.io/component-base from 0.26.2 to 0.26.3 (#9764) Bumps [k8s.io/component-base](https://github.com/kubernetes/component-base) from 0.26.2 to 0.26.3. - [Release notes](https://github.com/kubernetes/component-base/releases) - [Commits](https://github.com/kubernetes/component-base/compare/v0.26.2...v0.26.3) --- updated-dependencies: - dependency-name: k8s.io/component-base dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 4c4bc903a..f351bae17 100644 --- a/go.mod +++ b/go.mod @@ -30,14 +30,14 @@ require ( google.golang.org/grpc/examples v0.0.0-20221220003428-4f16fbe410f7 gopkg.in/go-playground/pool.v3 v3.1.1 gopkg.in/mcuadros/go-syslog.v2 v2.3.0 - k8s.io/api v0.26.2 + k8s.io/api v0.26.3 k8s.io/apiextensions-apiserver v0.26.1 - k8s.io/apimachinery v0.26.2 + k8s.io/apimachinery v0.26.3 k8s.io/apiserver v0.26.1 k8s.io/cli-runtime v0.26.0 - k8s.io/client-go v0.26.2 + k8s.io/client-go v0.26.3 k8s.io/code-generator v0.26.1 - k8s.io/component-base v0.26.2 + k8s.io/component-base v0.26.3 k8s.io/klog/v2 v2.90.1 pault.ag/go/sniff v0.0.0-20200207005214-cf7e4d167732 sigs.k8s.io/controller-runtime v0.14.5 diff --git a/go.sum b/go.sum index c3a2152b7..00918fc47 100644 --- a/go.sum +++ b/go.sum @@ -741,22 +741,22 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.26.2 h1:dM3cinp3PGB6asOySalOZxEG4CZ0IAdJsrYZXE/ovGQ= -k8s.io/api v0.26.2/go.mod h1:1kjMQsFE+QHPfskEcVNgL3+Hp88B80uj0QtSOlj8itU= +k8s.io/api v0.26.3 h1:emf74GIQMTik01Aum9dPP0gAypL8JTLl/lHa4V9RFSU= +k8s.io/api v0.26.3/go.mod h1:PXsqwPMXBSBcL1lJ9CYDKy7kIReUydukS5JiRlxC3qE= k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM= -k8s.io/apimachinery v0.26.2 h1:da1u3D5wfR5u2RpLhE/ZtZS2P7QvDgLZTi9wrNZl/tQ= -k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= +k8s.io/apimachinery v0.26.3 h1:dQx6PNETJ7nODU3XPtrwkfuubs6w7sX0M8n61zHIV/k= +k8s.io/apimachinery v0.26.3/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= k8s.io/apiserver v0.26.1 h1:6vmnAqCDO194SVCPU3MU8NcDgSqsUA62tBUSWrFXhsc= k8s.io/apiserver v0.26.1/go.mod h1:wr75z634Cv+sifswE9HlAo5FQ7UoUauIICRlOE+5dCg= k8s.io/cli-runtime v0.26.0 h1:aQHa1SyUhpqxAw1fY21x2z2OS5RLtMJOCj7tN4oq8mw= k8s.io/cli-runtime v0.26.0/go.mod h1:o+4KmwHzO/UK0wepE1qpRk6l3o60/txUZ1fEXWGIKTY= -k8s.io/client-go v0.26.2 h1:s1WkVujHX3kTp4Zn4yGNFK+dlDXy1bAAkIl+cFAiuYI= -k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU= +k8s.io/client-go v0.26.3 h1:k1UY+KXfkxV2ScEL3gilKcF7761xkYsSD6BC9szIu8s= +k8s.io/client-go v0.26.3/go.mod h1:ZPNu9lm8/dbRIPAgteN30RSXea6vrCpFvq+MateTUuQ= k8s.io/code-generator v0.26.1 h1:dusFDsnNSKlMFYhzIM0jAO1OlnTN5WYwQQ+Ai12IIlo= k8s.io/code-generator v0.26.1/go.mod h1:OMoJ5Dqx1wgaQzKgc+ZWaZPfGjdRq/Y3WubFrZmeI3I= -k8s.io/component-base v0.26.2 h1:IfWgCGUDzrD6wLLgXEstJKYZKAFS2kO+rBRi0p3LqcI= -k8s.io/component-base v0.26.2/go.mod h1:DxbuIe9M3IZPRxPIzhch2m1eT7uFrSBJUBuVCQEBivs= +k8s.io/component-base v0.26.3 h1:oC0WMK/ggcbGDTkdcqefI4wIZRYdK3JySx9/HADpV0g= +k8s.io/component-base v0.26.3/go.mod h1:5kj1kZYwSC6ZstHJN7oHBqcJC6yyn41eR+Sqa/mQc8E= k8s.io/gengo v0.0.0-20220902162205-c0856e24416d h1:U9tB195lKdzwqicbJvyJeOXV7Klv+wNAWENRnXEGi08= k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= From 00bfb2e84a3cbbce501d5e23cf112772cae6eb0e Mon Sep 17 00:00:00 2001 From: Adam Jacques Date: Tue, 21 Mar 2023 06:37:08 -0700 Subject: [PATCH 61/69] Fix several Helm YAML issues with extraModules and extraInitContainers (#9709) * Fix indention issue for DaemonSets when using extraModules and extraInitContainers * Improve documentation * Unify and fix templating * Enable support for the opentelemetry from values.yaml --- .../templates/controller-daemonset.yaml | 19 ++++++++----------- .../templates/controller-deployment.yaml | 2 +- charts/ingress-nginx/values.yaml | 2 ++ 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/charts/ingress-nginx/templates/controller-daemonset.yaml b/charts/ingress-nginx/templates/controller-daemonset.yaml index efa273dac..bce21a7d6 100644 --- a/charts/ingress-nginx/templates/controller-daemonset.yaml +++ b/charts/ingress-nginx/templates/controller-daemonset.yaml @@ -178,17 +178,14 @@ spec: {{- end }} {{- if .Values.controller.extraModules }} {{- range .Values.controller.extraModules }} - - name: {{ .Name }} - image: {{ .Image }} - command: ['sh', '-c', '/usr/local/bin/init_module.sh'] - {{- if (or $.Values.controller.containerSecurityContext .containerSecurityContext) }} - securityContext: {{ .containerSecurityContext | default $.Values.controller.containerSecurityContext | toYaml | nindent 14 }} - {{- end }} - volumeMounts: - - name: modules - mountPath: /modules_mount + {{ $containerSecurityContext := .containerSecurityContext | default $.Values.controller.containerSecurityContext }} +{{ include "extraModules" (dict "name" .name "image" .image "containerSecurityContext" $containerSecurityContext) | indent 8 }} {{- end }} {{- end }} + {{- if .Values.controller.opentelemetry.enabled}} + {{ $otelContainerSecurityContext := $.Values.controller.opentelemetry.containerSecurityContext | default $.Values.controller.containerSecurityContext }} + {{- include "extraModules" (dict "name" "opentelemetry" "image" .Values.controller.opentelemetry.image "containerSecurityContext" $otelContainerSecurityContext) | nindent 8}} + {{- end}} {{- end }} {{- if .Values.controller.hostNetwork }} hostNetwork: {{ .Values.controller.hostNetwork }} @@ -207,9 +204,9 @@ spec: {{- end }} serviceAccountName: {{ template "ingress-nginx.serviceAccountName" . }} terminationGracePeriodSeconds: {{ .Values.controller.terminationGracePeriodSeconds }} - {{- if (or .Values.controller.customTemplate.configMapName .Values.controller.extraVolumeMounts .Values.controller.admissionWebhooks.enabled .Values.controller.extraVolumes .Values.controller.extraModules) }} + {{- if (or .Values.controller.customTemplate.configMapName .Values.controller.extraVolumeMounts .Values.controller.admissionWebhooks.enabled .Values.controller.extraVolumes .Values.controller.extraModules .Values.controller.opentelemetry.enabled) }} volumes: - {{- if .Values.controller.extraModules }} + {{- if (or .Values.controller.extraModules .Values.controller.opentelemetry.enabled)}} - name: modules emptyDir: {} {{- end }} diff --git a/charts/ingress-nginx/templates/controller-deployment.yaml b/charts/ingress-nginx/templates/controller-deployment.yaml index 36d7670e3..323d87623 100644 --- a/charts/ingress-nginx/templates/controller-deployment.yaml +++ b/charts/ingress-nginx/templates/controller-deployment.yaml @@ -185,7 +185,7 @@ spec: {{- if .Values.controller.extraModules }} {{- range .Values.controller.extraModules }} {{ $containerSecurityContext := .containerSecurityContext | default $.Values.controller.containerSecurityContext }} - {{- include "extraModules" (dict "name" .name "image" .image "containerSecurityContext" $containerSecurityContext | nindent 8) }} +{{ include "extraModules" (dict "name" .name "image" .image "containerSecurityContext" $containerSecurityContext) | indent 8 }} {{- end }} {{- end }} {{- if .Values.controller.opentelemetry.enabled}} diff --git a/charts/ingress-nginx/values.yaml b/charts/ingress-nginx/values.yaml index f043c17cb..1a538f810 100644 --- a/charts/ingress-nginx/values.yaml +++ b/charts/ingress-nginx/values.yaml @@ -527,6 +527,8 @@ controller: # -- Modules, which are mounted into the core nginx image. See values.yaml for a sample to add opentelemetry module extraModules: [] + # - name: mytestmodule + # image: registry.k8s.io/ingress-nginx/mytestmodule # containerSecurityContext: # allowPrivilegeEscalation: false # From 9e097fb79d1e8f0eb792107167f6a707ee9f0b3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Mar 2023 06:39:07 -0700 Subject: [PATCH 62/69] Bump aquasecurity/trivy-action from 0.8.0 to 0.9.2 (#9767) Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.8.0 to 0.9.2. - [Release notes](https://github.com/aquasecurity/trivy-action/releases) - [Commits](https://github.com/aquasecurity/trivy-action/compare/9ab158e8597f3b310480b9a69402b419bc03dbd5...1f0aa582c8c8f5f7639610d6d38baddfea4fdcee) --- updated-dependencies: - dependency-name: aquasecurity/trivy-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/vulnerability-scans.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/vulnerability-scans.yaml b/.github/workflows/vulnerability-scans.yaml index b19031ff6..88ba16fa2 100644 --- a/.github/workflows/vulnerability-scans.yaml +++ b/.github/workflows/vulnerability-scans.yaml @@ -60,7 +60,7 @@ jobs: - name: Scan image with AquaSec/Trivy id: scan - uses: aquasecurity/trivy-action@9ab158e8597f3b310480b9a69402b419bc03dbd5 # v0.8.0 + uses: aquasecurity/trivy-action@1f0aa582c8c8f5f7639610d6d38baddfea4fdcee # v0.9.2 with: image-ref: registry.k8s.io/ingress-nginx/controller:${{ matrix.versions }} format: 'sarif' From e3c9382fc927cfbdfaa7a006b5ef2b0c332242d1 Mon Sep 17 00:00:00 2001 From: Taehyun Kim Date: Tue, 21 Mar 2023 22:41:08 +0900 Subject: [PATCH 63/69] fix: controller psp's volume config (#9740) * fix: controller psp's volume config * revert chart version --- charts/ingress-nginx/templates/controller-psp.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/ingress-nginx/templates/controller-psp.yaml b/charts/ingress-nginx/templates/controller-psp.yaml index 2e0499ce9..3c499b9d4 100644 --- a/charts/ingress-nginx/templates/controller-psp.yaml +++ b/charts/ingress-nginx/templates/controller-psp.yaml @@ -28,9 +28,9 @@ spec: volumes: - 'configMap' - 'emptyDir' - #- 'projected' + - 'projected' - 'secret' - #- 'downwardAPI' + - 'downwardAPI' {{- if .Values.controller.hostNetwork }} hostNetwork: {{ .Values.controller.hostNetwork }} {{- end }} From 43168a7fe119b8e6a8b99944fa29e94b46a1e216 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Mar 2023 13:42:46 +0000 Subject: [PATCH 64/69] Bump actions/checkout from 3.2.0 to 3.4.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.4.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...24cb9080177205b6e8c946b17badbe402adc938f) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yaml | 22 +++++++++++----------- .github/workflows/depreview.yaml | 2 +- .github/workflows/docs.yaml | 4 ++-- .github/workflows/helm.yaml | 4 ++-- .github/workflows/perftest.yaml | 2 +- .github/workflows/plugin.yaml | 2 +- .github/workflows/scorecards.yml | 2 +- .github/workflows/vulnerability-scans.yaml | 4 ++-- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3d7c21c3d..3ce77b419 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -39,7 +39,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1 id: filter @@ -65,7 +65,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - name: Run Gosec Security Scanner uses: securego/gosec@a459eb0ba387d9bd083d5c2e2354dbeef2465038 # v2.15.0 @@ -82,7 +82,7 @@ jobs: (needs.changes.outputs.go == 'true') steps: - name: Checkout - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - name: Set up Go id: go @@ -101,7 +101,7 @@ jobs: (needs.changes.outputs.go == 'true') steps: - name: Checkout - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - name: Set up Go id: go @@ -120,7 +120,7 @@ jobs: (needs.changes.outputs.go == 'true') steps: - name: Checkout - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - name: Set up Go id: go @@ -141,7 +141,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - name: Set up Go id: go @@ -208,7 +208,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - name: Setup Go uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 @@ -288,7 +288,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - name: cache uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 @@ -342,7 +342,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - name: cache uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 @@ -391,7 +391,7 @@ jobs: PLATFORMS: linux/amd64,linux/arm64 steps: - name: Checkout - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1 id: filter-images @@ -464,7 +464,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1 id: filter-images diff --git a/.github/workflows/depreview.yaml b/.github/workflows/depreview.yaml index 571610dc6..46a587ded 100644 --- a/.github/workflows/depreview.yaml +++ b/.github/workflows/depreview.yaml @@ -9,6 +9,6 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - name: 'Dependency Review' uses: actions/dependency-review-action@f46c48ed6d4f1227fb2d9ea62bf6bcbed315589e # v3.0.4 diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 241921ecf..3ab49ef10 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1 id: filter @@ -47,7 +47,7 @@ jobs: steps: - name: Checkout master - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - name: Deploy uses: ./.github/actions/mkdocs diff --git a/.github/workflows/helm.yaml b/.github/workflows/helm.yaml index b1db0c1d8..4e7fde34f 100644 --- a/.github/workflows/helm.yaml +++ b/.github/workflows/helm.yaml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - name: Run Artifact Hub lint run: | @@ -61,7 +61,7 @@ jobs: steps: - name: Checkout master - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 with: # Fetch entire history. Required for chart-releaser; see https://github.com/helm/chart-releaser-action/issues/13#issuecomment-602063896 fetch-depth: 0 diff --git a/.github/workflows/perftest.yaml b/.github/workflows/perftest.yaml index 89dfdfad6..dd31420bf 100644 --- a/.github/workflows/perftest.yaml +++ b/.github/workflows/perftest.yaml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - name: Install K6 run: | diff --git a/.github/workflows/plugin.yaml b/.github/workflows/plugin.yaml index 760420765..87ba6aca9 100644 --- a/.github/workflows/plugin.yaml +++ b/.github/workflows/plugin.yaml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 with: fetch-depth: 0 diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 8a3af47de..529cc7c28 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -27,7 +27,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 with: persist-credentials: false diff --git a/.github/workflows/vulnerability-scans.yaml b/.github/workflows/vulnerability-scans.yaml index 88ba16fa2..9649140ec 100644 --- a/.github/workflows/vulnerability-scans.yaml +++ b/.github/workflows/vulnerability-scans.yaml @@ -22,7 +22,7 @@ jobs: versions: ${{ steps.version.outputs.TAGS }} steps: - name: Checkout code - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 with: fetch-depth: 0 @@ -52,7 +52,7 @@ jobs: versions: ${{ fromJSON(needs.version.outputs.versions) }} steps: - name: Checkout code - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 - shell: bash id: test From e4a66fd2f625de3bcc7aaa793b31f529a0662009 Mon Sep 17 00:00:00 2001 From: Sergei Kaznakhovskii Date: Tue, 21 Mar 2023 07:47:09 -0600 Subject: [PATCH 65/69] Fix canary-weight-total annotation ignored in rule backends (#9729) * Missed canary weight total - added canary weight total for spec rules * - added e2e test --- internal/ingress/controller/controller.go | 30 +++++++++++------------ test/e2e/annotations/canary.go | 27 ++++++++++++++++++++ 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/internal/ingress/controller/controller.go b/internal/ingress/controller/controller.go index 1914765d8..20f8c8687 100644 --- a/internal/ingress/controller/controller.go +++ b/internal/ingress/controller/controller.go @@ -33,6 +33,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" "k8s.io/ingress-nginx/internal/ingress/annotations" + "k8s.io/ingress-nginx/internal/ingress/annotations/canary" "k8s.io/ingress-nginx/internal/ingress/annotations/log" "k8s.io/ingress-nginx/internal/ingress/annotations/parser" "k8s.io/ingress-nginx/internal/ingress/annotations/proxy" @@ -968,14 +969,7 @@ func (n *NGINXController) createUpstreams(data []*ingress.Ingress, du *ingress.B // configure traffic shaping for canary if anns.Canary.Enabled { upstreams[defBackend].NoServer = true - upstreams[defBackend].TrafficShapingPolicy = ingress.TrafficShapingPolicy{ - Weight: anns.Canary.Weight, - WeightTotal: anns.Canary.WeightTotal, - Header: anns.Canary.Header, - HeaderValue: anns.Canary.HeaderValue, - HeaderPattern: anns.Canary.HeaderPattern, - Cookie: anns.Canary.Cookie, - } + upstreams[defBackend].TrafficShapingPolicy = newTrafficShapingPolicy(anns.Canary) } if len(upstreams[defBackend].Endpoints) == 0 { @@ -1040,13 +1034,7 @@ func (n *NGINXController) createUpstreams(data []*ingress.Ingress, du *ingress.B // configure traffic shaping for canary if anns.Canary.Enabled { upstreams[name].NoServer = true - upstreams[name].TrafficShapingPolicy = ingress.TrafficShapingPolicy{ - Weight: anns.Canary.Weight, - Header: anns.Canary.Header, - HeaderValue: anns.Canary.HeaderValue, - HeaderPattern: anns.Canary.HeaderPattern, - Cookie: anns.Canary.Cookie, - } + upstreams[name].TrafficShapingPolicy = newTrafficShapingPolicy(anns.Canary) } if len(upstreams[name].Endpoints) == 0 { @@ -1819,3 +1807,15 @@ func (n *NGINXController) getStreamSnippets(ingresses []*ingress.Ingress) []stri } return snippets } + +// newTrafficShapingPolicy creates new ingress.TrafficShapingPolicy instance using canary configuration +func newTrafficShapingPolicy(cfg canary.Config) ingress.TrafficShapingPolicy { + return ingress.TrafficShapingPolicy{ + Weight: cfg.Weight, + WeightTotal: cfg.WeightTotal, + Header: cfg.Header, + HeaderValue: cfg.HeaderValue, + HeaderPattern: cfg.HeaderPattern, + Cookie: cfg.Cookie, + } +} diff --git a/test/e2e/annotations/canary.go b/test/e2e/annotations/canary.go index 893a4dc8b..6dd81fdd8 100644 --- a/test/e2e/annotations/canary.go +++ b/test/e2e/annotations/canary.go @@ -830,6 +830,33 @@ var _ = framework.DescribeAnnotation("canary-*", func() { TestMainlineCanaryDistribution(f, host) }) + + ginkgo.It("should route requests split between mainline and canary if canary weight is 100 and weight total is 200", func() { + host := "foo" + annotations := map[string]string{} + + ing := framework.NewSingleIngress(host, "/", host, + f.Namespace, framework.EchoService, 80, annotations) + f.EnsureIngress(ing) + + f.WaitForNginxServer(host, + func(server string) bool { + return strings.Contains(server, "server_name foo") + }) + + canaryIngName := fmt.Sprintf("%v-canary", host) + canaryAnnotations := map[string]string{ + "nginx.ingress.kubernetes.io/canary": "true", + "nginx.ingress.kubernetes.io/canary-weight": "100", + "nginx.ingress.kubernetes.io/canary-weight-total": "200", + } + + canaryIng := framework.NewSingleIngress(canaryIngName, "/", host, + f.Namespace, canaryService, 80, canaryAnnotations) + f.EnsureIngress(canaryIng) + + TestMainlineCanaryDistribution(f, host) + }) }) ginkgo.Context("Single canary Ingress", func() { From c075793ae5ee52e28cf8420c33cf3b73022161e1 Mon Sep 17 00:00:00 2001 From: James Strong Date: Tue, 21 Mar 2023 16:34:12 -0400 Subject: [PATCH 66/69] drop k8s 1.23 support (#9772) Signed-off-by: James Strong --- .github/workflows/ci.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3ce77b419..c2c108638 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -204,7 +204,7 @@ jobs: strategy: matrix: - k8s: [v1.23.13, v1.24.7, v1.25.3, v1.26.0] + k8s: [v1.24.7, v1.25.3, v1.26.0] steps: - name: Checkout @@ -284,7 +284,7 @@ jobs: strategy: matrix: - k8s: [v1.23.13, v1.24.7, v1.25.3, v1.26.0] + k8s: [v1.24.7, v1.25.3, v1.26.0] steps: - name: Checkout @@ -337,7 +337,7 @@ jobs: strategy: matrix: - k8s: [v1.23.13, v1.24.7, v1.25.3, v1.26.0] + k8s: [v1.24.7, v1.25.3, v1.26.0] steps: @@ -460,7 +460,7 @@ jobs: strategy: matrix: - k8s: [v1.23.13, v1.24.7, v1.25.3, v1.26.0] + k8s: [v1.24.7, v1.25.3, v1.26.0] steps: - name: Checkout From c8cb9167d3bfe6a2ed50796e179b3aec648a7e16 Mon Sep 17 00:00:00 2001 From: Ehsan Saei <71217171+esigo@users.noreply.github.com> Date: Wed, 22 Mar 2023 19:58:22 +0100 Subject: [PATCH 67/69] feat: OpenTelemetry module integration (#9062) * OpenTelemetry module integration * e2e test * e2e test fix * default OpentelemetryConfig * e2e values * mount otel module for otel test only * propagate IS_CHROOT * propagate IS_CHROOT e2e test * code doc * comments * golint * opentelemetry doc * zipkin * zipkin * typo * update e2e test OpenTelemetry value * use opentelemetry value * revert merge conflict * fix * format * review comments * clean --- docs/images/otel-grafana-demo.png | Bin 0 -> 123976 bytes docs/images/otel-jaeger-demo.png | Bin 0 -> 120283 bytes docs/images/otel-zipkin-demo.png | Bin 0 -> 133964 bytes docs/kubectl-plugin.md | 1 + .../nginx-configuration/annotations.md | 20 ++ .../nginx-configuration/configmap.md | 53 ++++ .../third-party-addons/opentelemetry.md | 260 ++++++++++++++++++ internal/ingress/annotations/annotations.go | 3 + .../ingress/annotations/opentelemetry/main.go | 101 +++++++ .../annotations/opentelemetry/main_test.go | 170 ++++++++++++ internal/ingress/controller/config/config.go | 55 ++++ internal/ingress/controller/controller.go | 1 + internal/ingress/controller/nginx.go | 43 +++ .../ingress/controller/template/template.go | 96 +++++++ .../controller/template/template_test.go | 153 +++++++++++ mkdocs.yml | 1 + pkg/apis/ingress/types.go | 4 + pkg/apis/ingress/types_equals.go | 4 + rootfs/etc/nginx/template/nginx.tmpl | 26 ++ test/e2e/framework/exec.go | 7 +- test/e2e/run-e2e-suite.sh | 1 + test/e2e/settings/opentelemetry.go | 119 ++++++++ test/e2e/wait-for-nginx.sh | 15 +- 23 files changed, 1131 insertions(+), 2 deletions(-) create mode 100644 docs/images/otel-grafana-demo.png create mode 100644 docs/images/otel-jaeger-demo.png create mode 100644 docs/images/otel-zipkin-demo.png mode change 100755 => 100644 docs/user-guide/nginx-configuration/configmap.md create mode 100644 docs/user-guide/third-party-addons/opentelemetry.md create mode 100644 internal/ingress/annotations/opentelemetry/main.go create mode 100644 internal/ingress/annotations/opentelemetry/main_test.go mode change 100755 => 100644 rootfs/etc/nginx/template/nginx.tmpl create mode 100644 test/e2e/settings/opentelemetry.go diff --git a/docs/images/otel-grafana-demo.png b/docs/images/otel-grafana-demo.png new file mode 100644 index 0000000000000000000000000000000000000000..61b50c8612dc1aaa80de0bc416dc683f39bd201a GIT binary patch literal 123976 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 JJM)-1$N#-{jZ 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 literal 0 HcmV?d00001 diff --git a/docs/images/otel-jaeger-demo.png b/docs/images/otel-jaeger-demo.png new file mode 100644 index 0000000000000000000000000000000000000000..006b23c34de68375ed40377e14707493112ef2f4 GIT binary patch literal 120283 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

sKOYYw|>+j1GPSG8^N!ezs%p@wn-{X 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%0A(g?w1WZ7piIKNEaT2pXuohHH63 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⪪>-NPBFC5n+ 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Π28 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 literal 0 HcmV?d00001 diff --git a/docs/images/otel-zipkin-demo.png b/docs/images/otel-zipkin-demo.png new file mode 100644 index 0000000000000000000000000000000000000000..a3af04e466c8717c01ea4286ba360acedd76fe76 GIT binary patch literal 133964 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 |name: nginx| sb + sb --> |hello nginx!| sa + end + + subgraph otel + otc["Otel Collector"] + end + + subgraph observability + tempo["Tempo"] + grafana["Grafana"] + backend["Jaeger"] + zipkin["Zipkin"] + end + + subgraph ingress-nginx + ngx[nginx] + end + + subgraph ngx[nginx] + ng[nginx] + om[OpenTelemetry module] + end + + subgraph Node + app + otel + observability + ingress-nginx + om --> |otlp-gRPC| otc --> |jaeger| backend + otc --> |zipkin| zipkin + otc --> |otlp-gRPC| tempo --> grafana + sa --> |otlp-gRPC| otc + sb --> |otlp-gRPC| otc + start --> ng --> sa + end +``` + +To install the example and collectors run: + +1. Enable Ingress addon with: + + ```yaml + opentelemetry: + enabled: true + image: registry.k8s.io/ingress-nginx/opentelemetry:v20230107-helm-chart-4.4.2-2-g96b3d2165@sha256:331b9bebd6acfcd2d3048abbdd86555f5be76b7e3d0b5af4300b04235c6056c9 + containerSecurityContext: + allowPrivilegeEscalation: false + ``` + +2. Enable OpenTelemetry and set the otlp-collector-host: + + ```yaml + $ echo ' + apiVersion: v1 + kind: ConfigMap + data: + enable-opentelemetry: "true" + opentelemetry-config: "/etc/nginx/opentelemetry.toml" + opentelemetry-operation-name: "HTTP $request_method $service_name $uri" + opentelemetry-trust-incoming-span: "true" + otlp-collector-host: "otel-coll-collector.otel.svc" + otlp-collector-port: "4317" + otel-max-queuesize: "2048" + otel-schedule-delay-millis: "5000" + otel-max-export-batch-size: "512" + otel-service-name: "nginx-proxy" # Opentelemetry resource name + otel-sampler: "AlwaysOn" # Also: AlwaysOff, TraceIdRatioBased + otel-sampler-ratio: "1.0" + otel-sampler-parent-based: "false" + metadata: + name: ingress-nginx-controller + namespace: ingress-nginx + ' | kubectl replace -f - + ``` + +4. Deploy otel-collector, grafana and Jaeger backend: + + ```bash + # add helm charts needed for grafana and OpenTelemetry collector + helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts + helm repo add grafana https://grafana.github.io/helm-charts + helm repo update + # deply cert-manager needed for OpenTelemetry collector operator + kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml + # create observability namespace + kubectl apply -f https://raw.githubusercontent.com/esigo/nginx-example/main/observability/namespace.yaml + # install OpenTelemetry collector operator + helm upgrade --install otel-collector-operator -n otel --create-namespace open-telemetry/opentelemetry-operator + # deploy OpenTelemetry collector + kubectl apply -f https://raw.githubusercontent.com/esigo/nginx-example/main/observability/collector.yaml + # deploy Jaeger all-in-one + kubectl apply -f https://github.com/jaegertracing/jaeger-operator/releases/download/v1.37.0/jaeger-operator.yaml -n observability + kubectl apply -f https://raw.githubusercontent.com/esigo/nginx-example/main/observability/jaeger.yaml -n observability + # deploy zipkin + kubectl apply -f https://raw.githubusercontent.com/esigo/nginx-example/main/observability/zipkin.yaml -n observability + # deploy tempo and grafana + helm upgrade --install tempo grafana/tempo --create-namespace -n observability + helm upgrade -f https://raw.githubusercontent.com/esigo/nginx-example/main/observability/grafana/grafana-values.yaml --install grafana grafana/grafana --create-namespace -n observability + ``` + +3. Build and deploy demo app: + + ```bash + # build images + make images + + # deploy demo app: + make deploy-app + ``` + +5. Make a few requests to the Service: + + ```bash + kubectl port-forward --namespace=ingress-nginx service/ingress-nginx-controller 8090:80 + curl http://esigo.dev:8090/hello/nginx + + + StatusCode : 200 + StatusDescription : OK + Content : {"v":"hello nginx!"} + + RawContent : HTTP/1.1 200 OK + Connection: keep-alive + Content-Length: 21 + Content-Type: text/plain; charset=utf-8 + Date: Mon, 10 Oct 2022 17:43:33 GMT + + {"v":"hello nginx!"} + + Forms : {} + Headers : {[Connection, keep-alive], [Content-Length, 21], [Content-Type, text/plain; charset=utf-8], [Date, + Mon, 10 Oct 2022 17:43:33 GMT]} + Images : {} + InputFields : {} + Links : {} + ParsedHtml : System.__ComObject + RawContentLength : 21 + ``` + +6. View the Grafana UI: + + ```bash + kubectl port-forward --namespace=observability service/grafana 3000:80 + ``` + In the Grafana interface we can see the details: + ![grafana screenshot](../../images/otel-grafana-demo.png "grafana screenshot") + +7. View the Jaeger UI: + + ```bash + kubectl port-forward --namespace=observability service/jaeger-all-in-one-query 16686:16686 + ``` + In the Jaeger interface we can see the details: + ![Jaeger screenshot](../../images/otel-jaeger-demo.png "Jaeger screenshot") + +8. View the Zipkin UI: + + ```bash + kubectl port-forward --namespace=observability service/zipkin 9411:9411 + ``` + In the Zipkin interface we can see the details: + ![zipkin screenshot](../../images/otel-zipkin-demo.png "zipkin screenshot") diff --git a/internal/ingress/annotations/annotations.go b/internal/ingress/annotations/annotations.go index 14415a4f7..6a9e7367c 100644 --- a/internal/ingress/annotations/annotations.go +++ b/internal/ingress/annotations/annotations.go @@ -20,6 +20,7 @@ import ( "github.com/imdario/mergo" "k8s.io/ingress-nginx/internal/ingress/annotations/canary" "k8s.io/ingress-nginx/internal/ingress/annotations/modsecurity" + "k8s.io/ingress-nginx/internal/ingress/annotations/opentelemetry" "k8s.io/ingress-nginx/internal/ingress/annotations/proxyssl" "k8s.io/ingress-nginx/internal/ingress/annotations/sslcipher" "k8s.io/ingress-nginx/internal/ingress/annotations/streamsnippet" @@ -94,6 +95,7 @@ type Ingress struct { EnableGlobalAuth bool HTTP2PushPreload bool Opentracing opentracing.Config + Opentelemetry opentelemetry.Config Proxy proxy.Config ProxySSL proxyssl.Config RateLimit ratelimit.Config @@ -145,6 +147,7 @@ func NewAnnotationExtractor(cfg resolver.Resolver) Extractor { "EnableGlobalAuth": authreqglobal.NewParser(cfg), "HTTP2PushPreload": http2pushpreload.NewParser(cfg), "Opentracing": opentracing.NewParser(cfg), + "Opentelemetry": opentelemetry.NewParser(cfg), "Proxy": proxy.NewParser(cfg), "ProxySSL": proxyssl.NewParser(cfg), "RateLimit": ratelimit.NewParser(cfg), diff --git a/internal/ingress/annotations/opentelemetry/main.go b/internal/ingress/annotations/opentelemetry/main.go new file mode 100644 index 000000000..7dd292322 --- /dev/null +++ b/internal/ingress/annotations/opentelemetry/main.go @@ -0,0 +1,101 @@ +/* +Copyright 2022 The Kubernetes 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 opentelemetry + +import ( + networking "k8s.io/api/networking/v1" + + "k8s.io/ingress-nginx/internal/ingress/annotations/parser" + "k8s.io/ingress-nginx/internal/ingress/resolver" +) + +type opentelemetry struct { + r resolver.Resolver +} + +// Config contains the configuration to be used in the Ingress +type Config struct { + Enabled bool `json:"enabled"` + Set bool `json:"set"` + TrustEnabled bool `json:"trust-enabled"` + TrustSet bool `json:"trust-set"` + OperationName string `json:"operation-name"` +} + +// Equal tests for equality between two Config types +func (bd1 *Config) Equal(bd2 *Config) bool { + + if bd1.Set != bd2.Set { + return false + } + + if bd1.Enabled != bd2.Enabled { + return false + } + + if bd1.TrustSet != bd2.TrustSet { + return false + } + + if bd1.TrustEnabled != bd2.TrustEnabled { + return false + } + + if bd1.OperationName != bd2.OperationName { + return false + } + + return true +} + +// NewParser creates a new serviceUpstream annotation parser +func NewParser(r resolver.Resolver) parser.IngressAnnotation { + return opentelemetry{r} +} + +// Parse parses the annotations to look for opentelemetry configurations +func (c opentelemetry) Parse(ing *networking.Ingress) (interface{}, error) { + cfg := Config{} + enabled, err := parser.GetBoolAnnotation("enable-opentelemetry", ing) + if err != nil { + return &cfg, nil + } + cfg.Set = true + cfg.Enabled = enabled + if !enabled { + return &cfg, nil + } + + trustEnabled, err := parser.GetBoolAnnotation("opentelemetry-trust-incoming-span", ing) + if err != nil { + operationName, err := parser.GetStringAnnotation("opentelemetry-operation-name", ing) + if err != nil { + return &cfg, nil + } + cfg.OperationName = operationName + return &cfg, nil + } + + cfg.TrustSet = true + cfg.TrustEnabled = trustEnabled + operationName, err := parser.GetStringAnnotation("opentelemetry-operation-name", ing) + if err != nil { + return &cfg, nil + } + cfg.OperationName = operationName + return &cfg, nil +} diff --git a/internal/ingress/annotations/opentelemetry/main_test.go b/internal/ingress/annotations/opentelemetry/main_test.go new file mode 100644 index 000000000..619108fa6 --- /dev/null +++ b/internal/ingress/annotations/opentelemetry/main_test.go @@ -0,0 +1,170 @@ +/* +Copyright 2022 The Kubernetes 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 opentelemetry + +import ( + "testing" + + api "k8s.io/api/core/v1" + networking "k8s.io/api/networking/v1" + meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/ingress-nginx/internal/ingress/annotations/parser" + "k8s.io/ingress-nginx/internal/ingress/resolver" +) + +func buildIngress() *networking.Ingress { + defaultBackend := networking.IngressBackend{ + Service: &networking.IngressServiceBackend{ + Name: "default-backend", + Port: networking.ServiceBackendPort{ + Number: 80, + }, + }, + } + + return &networking.Ingress{ + ObjectMeta: meta_v1.ObjectMeta{ + Name: "foo", + Namespace: api.NamespaceDefault, + }, + Spec: networking.IngressSpec{ + DefaultBackend: &networking.IngressBackend{ + Service: &networking.IngressServiceBackend{ + Name: "default-backend", + Port: networking.ServiceBackendPort{ + Number: 80, + }, + }, + }, + Rules: []networking.IngressRule{ + { + Host: "foo.bar.com", + IngressRuleValue: networking.IngressRuleValue{ + HTTP: &networking.HTTPIngressRuleValue{ + Paths: []networking.HTTPIngressPath{ + { + Path: "/foo", + Backend: defaultBackend, + }, + }, + }, + }, + }, + }, + }, + } +} + +func TestIngressAnnotationOpentelemetrySetTrue(t *testing.T) { + ing := buildIngress() + + data := map[string]string{} + data[parser.GetAnnotationWithPrefix("enable-opentelemetry")] = "true" + ing.SetAnnotations(data) + + val, _ := NewParser(&resolver.Mock{}).Parse(ing) + openTelemetry, ok := val.(*Config) + if !ok { + t.Errorf("expected a Config type") + } + + if !openTelemetry.Enabled { + t.Errorf("expected annotation value to be true, got false") + } + + if !openTelemetry.Set { + t.Errorf("expected annotation value to be true, got false") + } + + if openTelemetry.TrustSet { + t.Errorf("expected annotation value to be false, got true") + } +} + +func TestIngressAnnotationOpentelemetrySetFalse(t *testing.T) { + ing := buildIngress() + + // Test with explicitly set to false + data := map[string]string{} + data[parser.GetAnnotationWithPrefix("enable-opentelemetry")] = "false" + ing.SetAnnotations(data) + + val, _ := NewParser(&resolver.Mock{}).Parse(ing) + openTelemetry, ok := val.(*Config) + if !ok { + t.Errorf("expected a Config type") + } + + if openTelemetry.Enabled { + t.Errorf("expected annotation value to be false, got true") + } + + if !openTelemetry.Set { + t.Errorf("expected annotation value to be true, got false") + } +} + +func TestIngressAnnotationOpentelemetryTrustSetTrue(t *testing.T) { + ing := buildIngress() + + data := map[string]string{} + opName := "foo-op" + data[parser.GetAnnotationWithPrefix("enable-opentelemetry")] = "true" + data[parser.GetAnnotationWithPrefix("opentelemetry-trust-incoming-span")] = "true" + data[parser.GetAnnotationWithPrefix("opentelemetry-operation-name")] = opName + ing.SetAnnotations(data) + + val, _ := NewParser(&resolver.Mock{}).Parse(ing) + openTelemetry, ok := val.(*Config) + if !ok { + t.Errorf("expected a Config type") + } + + if !openTelemetry.Enabled { + t.Errorf("expected annotation value to be true, got false") + } + + if !openTelemetry.Set { + t.Errorf("expected annotation value to be true, got false") + } + + if !openTelemetry.TrustEnabled { + t.Errorf("expected annotation value to be true, got false") + } + + if !openTelemetry.TrustSet { + t.Errorf("expected annotation value to be true, got false") + } + + if openTelemetry.OperationName != opName { + t.Errorf("expected annotation value to be %v, got %v", opName, openTelemetry.OperationName) + } +} + +func TestIngressAnnotationOpentelemetryUnset(t *testing.T) { + ing := buildIngress() + + // Test with no annotation specified + data := map[string]string{} + ing.SetAnnotations(data) + + val, _ := NewParser(&resolver.Mock{}).Parse(ing) + _, ok := val.(*Config) + if !ok { + t.Errorf("expected a Config type") + } +} diff --git a/internal/ingress/controller/config/config.go b/internal/ingress/controller/config/config.go index 5786b6776..da37ea3c9 100644 --- a/internal/ingress/controller/config/config.go +++ b/internal/ingress/controller/config/config.go @@ -568,6 +568,54 @@ type Configuration struct { // Default: true OpentracingTrustIncomingSpan bool `json:"opentracing-trust-incoming-span"` + // EnableOpentelemetry enables the nginx Opentelemetry extension + // By default this is disabled + EnableOpentelemetry bool `json:"enable-opentelemetry"` + + // OpentelemetryConfig sets the opentelemetry config file + // Default: /etc/nginx/opentelemetry.toml + OpentelemetryConfig string `json:"opentelemetry-config"` + + // OpentelemetryOperationName specifies a custom name for the server span + OpentelemetryOperationName string `json:"opentelemetry-operation-name"` + + // OpentelemetryTrustIncomingSpan sets whether or not to trust incoming trace spans + // If false, incoming span headers will be rejected + // Default: true + OpentelemetryTrustIncomingSpan bool `json:"opentelemetry-trust-incoming-span"` + + // OtlpCollectorHost specifies the host to use when uploading traces + OtlpCollectorHost string `json:"otlp-collector-host"` + + // OtlpCollectorPort specifies the port to use when uploading traces + // Default: 4317 + OtlpCollectorPort string `json:"otlp-collector-port"` + + // OtelServiceName specifies the service name to use for any traces created + // Default: nginx + OtelServiceName string `json:"otel-service-name"` + + // OtelSampler specifies the sampler to use for any traces created + // Default: AlwaysOff + OtelSampler string `json:"otel-sampler"` + + // OtelSamplerRatio specifies the sampler ratio to use for any traces created + // Default: 0.01 + OtelSamplerRatio float32 `json:"otel-sampler-ratio"` + + //OtelSamplerParentBased specifies the parent based sampler to be use for any traces created + // Default: false + OtelSamplerParentBased bool `json:"otel-sampler-parent-based"` + + // MaxQueueSize specifies the max queue size for uploading traces + OtelMaxQueueSize int32 `json:"otel-max-queuesize"` + + // ScheduleDelayMillis specifies the max delay between uploading traces + OtelScheduleDelayMillis int32 `json:"otel-schedule-delay-millis"` + + // MaxExportBatchSize specifies the max export batch size to used when uploading traces + OtelMaxExportBatchSize int32 `json:"otel-max-export-batch-size"` + // ZipkinCollectorHost specifies the host to use when uploading traces ZipkinCollectorHost string `json:"zipkin-collector-host"` @@ -917,6 +965,13 @@ func NewDefault() Configuration { BindAddressIpv4: defBindAddress, BindAddressIpv6: defBindAddress, OpentracingTrustIncomingSpan: true, + OpentelemetryTrustIncomingSpan: true, + OpentelemetryConfig: "/etc/nginx/opentelemetry.toml", + OtlpCollectorPort: "4317", + OtelServiceName: "nginx", + OtelSampler: "AlwaysOff", + OtelSamplerRatio: 0.01, + OtelSamplerParentBased: false, ZipkinCollectorPort: 9411, ZipkinServiceName: "nginx", ZipkinSampleRate: 1.0, diff --git a/internal/ingress/controller/controller.go b/internal/ingress/controller/controller.go index 20f8c8687..5d94605b5 100644 --- a/internal/ingress/controller/controller.go +++ b/internal/ingress/controller/controller.go @@ -1444,6 +1444,7 @@ func locationApplyAnnotations(loc *ingress.Location, anns *annotations.Ingress) loc.EnableGlobalAuth = anns.EnableGlobalAuth loc.HTTP2PushPreload = anns.HTTP2PushPreload loc.Opentracing = anns.Opentracing + loc.Opentelemetry = anns.Opentelemetry loc.Proxy = anns.Proxy loc.ProxySSL = anns.ProxySSL loc.RateLimit = anns.RateLimit diff --git a/internal/ingress/controller/nginx.go b/internal/ingress/controller/nginx.go index 5575009ea..80693db5c 100644 --- a/internal/ingress/controller/nginx.go +++ b/internal/ingress/controller/nginx.go @@ -673,6 +673,11 @@ func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) error { return err } + err = createOpentelemetryCfg(cfg) + if err != nil { + return err + } + err = n.testTemplate(content) if err != nil { return err @@ -1056,6 +1061,29 @@ const datadogTmpl = `{ "dd.priority.sampling": {{ .DatadogPrioritySampling }} }` +const otelTmpl = ` +exporter = "otlp" +processor = "batch" + +[exporters.otlp] +# Alternatively the OTEL_EXPORTER_OTLP_ENDPOINT environment variable can also be used. +host = "{{ .OtlpCollectorHost }}" +port = {{ .OtlpCollectorPort }} + +[processors.batch] +max_queue_size = {{ .OtelMaxQueueSize }} +schedule_delay_millis = {{ .OtelScheduleDelayMillis }} +max_export_batch_size = {{ .OtelMaxExportBatchSize }} + +[service] +name = "{{ .OtelServiceName }}" # Opentelemetry resource name + +[sampler] +name = "{{ .OtelSampler }}" # Also: AlwaysOff, TraceIdRatioBased +ratio = {{ .OtelSamplerRatio }} +parent_based = {{ .OtelSamplerParentBased }} +` + func createOpentracingCfg(cfg ngx_config.Configuration) error { var tmpl *template.Template var err error @@ -1091,6 +1119,21 @@ func createOpentracingCfg(cfg ngx_config.Configuration) error { return os.WriteFile("/etc/nginx/opentracing.json", []byte(expanded), file.ReadWriteByUser) } +func createOpentelemetryCfg(cfg ngx_config.Configuration) error { + + tmpl, err := template.New("otel").Parse(otelTmpl) + if err != nil { + return err + } + tmplBuf := bytes.NewBuffer(make([]byte, 0)) + err = tmpl.Execute(tmplBuf, cfg) + if err != nil { + return err + } + + return os.WriteFile(cfg.OpentelemetryConfig, tmplBuf.Bytes(), file.ReadWriteByUser) +} + func cleanTempNginxCfg() error { var files []string diff --git a/internal/ingress/controller/template/template.go b/internal/ingress/controller/template/template.go index f3283a782..9dc9fb3b8 100644 --- a/internal/ingress/controller/template/template.go +++ b/internal/ingress/controller/template/template.go @@ -265,6 +265,7 @@ var ( "buildAuthSignURL": buildAuthSignURL, "buildAuthSignURLLocation": buildAuthSignURLLocation, "buildOpentracing": buildOpentracing, + "buildOpentelemetry": buildOpentelemetry, "proxySetHeader": proxySetHeader, "buildInfluxDB": buildInfluxDB, "enforceRegexModifier": enforceRegexModifier, @@ -274,7 +275,9 @@ var ( "buildHTTPListener": buildHTTPListener, "buildHTTPSListener": buildHTTPSListener, "buildOpentracingForLocation": buildOpentracingForLocation, + "buildOpentelemetryForLocation": buildOpentelemetryForLocation, "shouldLoadOpentracingModule": shouldLoadOpentracingModule, + "shouldLoadOpentelemetryModule": shouldLoadOpentelemetryModule, "buildModSecurityForLocation": buildModSecurityForLocation, "buildMirrorLocations": buildMirrorLocations, "shouldLoadAuthDigestModule": shouldLoadAuthDigestModule, @@ -1239,6 +1242,33 @@ func buildOpentracing(c interface{}, s interface{}) string { return buf.String() } +func buildOpentelemetry(c interface{}, s interface{}) string { + cfg, ok := c.(config.Configuration) + if !ok { + klog.Errorf("expected a 'config.Configuration' type but %T was returned", c) + return "" + } + + servers, ok := s.([]*ingress.Server) + if !ok { + klog.Errorf("expected an '[]*ingress.Server' type but %T was returned", s) + return "" + } + + if !shouldLoadOpentelemetryModule(cfg, servers) { + return "" + } + + buf := bytes.NewBufferString("") + + buf.WriteString("\r\n") + + if cfg.OpentelemetryOperationName != "" { + buf.WriteString(fmt.Sprintf("opentelemetry_operation_name \"%s\";\n", cfg.OpentelemetryOperationName)) + } + return buf.String() +} + // buildInfluxDB produces the single line configuration // needed by the InfluxDB module to send request's metrics // for the current resource @@ -1360,6 +1390,13 @@ func opentracingPropagateContext(location *ingress.Location) string { return "opentracing_propagate_context;" } +func opentelemetryPropagateContext(location *ingress.Location) string { + if location == nil { + return "" + } + return "opentelemetry_propagate;" +} + // shouldLoadModSecurityModule determines whether or not the ModSecurity module needs to be loaded. // First, it checks if `enable-modsecurity` is set in the ConfigMap. If it is not, it iterates over all locations to // check if ModSecurity is enabled by the annotation `nginx.ingress.kubernetes.io/enable-modsecurity`. @@ -1575,6 +1612,36 @@ func buildOpentracingForLocation(isOTEnabled bool, isOTTrustSet bool, location * return opc } +func buildOpentelemetryForLocation(isOTEnabled bool, isOTTrustSet bool, location *ingress.Location) string { + isOTEnabledInLoc := location.Opentelemetry.Enabled + isOTSetInLoc := location.Opentelemetry.Set + + if isOTEnabled { + if isOTSetInLoc && !isOTEnabledInLoc { + return "opentelemetry off;" + } + } else if !isOTSetInLoc || !isOTEnabledInLoc { + return "" + } + + opc := opentelemetryPropagateContext(location) + if opc != "" { + opc = fmt.Sprintf("opentelemetry on;\n%v", opc) + } + + if location.Opentelemetry.OperationName != "" { + opc = opc + "\nopentelemetry_operation_name " + location.Opentelemetry.OperationName + ";" + } + + if (!isOTTrustSet && !location.Opentelemetry.TrustSet) || + (location.Opentelemetry.TrustSet && !location.Opentelemetry.TrustEnabled) { + opc = opc + "\nopentelemetry_trust_incoming_spans off;" + } else { + opc = opc + "\nopentelemetry_trust_incoming_spans on;" + } + return opc +} + // shouldLoadOpentracingModule determines whether or not the Opentracing module needs to be loaded. // First, it checks if `enable-opentracing` is set in the ConfigMap. If it is not, it iterates over all locations to // check if Opentracing is enabled by the annotation `nginx.ingress.kubernetes.io/enable-opentracing`. @@ -1606,6 +1673,35 @@ func shouldLoadOpentracingModule(c interface{}, s interface{}) bool { return false } +// shouldLoadOpentelemetryModule determines whether or not the Opentelemetry module needs to be loaded. +// It checks if `enable-opentelemetry` is set in the ConfigMap. +func shouldLoadOpentelemetryModule(c interface{}, s interface{}) bool { + cfg, ok := c.(config.Configuration) + if !ok { + klog.Errorf("expected a 'config.Configuration' type but %T was returned", c) + return false + } + + servers, ok := s.([]*ingress.Server) + if !ok { + klog.Errorf("expected an '[]*ingress.Server' type but %T was returned", s) + return false + } + + if cfg.EnableOpentelemetry { + return true + } + + for _, server := range servers { + for _, location := range server.Locations { + if location.Opentelemetry.Enabled { + return true + } + } + } + return false +} + func buildModSecurityForLocation(cfg config.Configuration, location *ingress.Location) string { isMSEnabledInLoc := location.ModSecurity.Enable isMSEnableSetInLoc := location.ModSecurity.EnableSet diff --git a/internal/ingress/controller/template/template_test.go b/internal/ingress/controller/template/template_test.go index cb1ebd1b7..343da506b 100644 --- a/internal/ingress/controller/template/template_test.go +++ b/internal/ingress/controller/template/template_test.go @@ -37,6 +37,7 @@ import ( "k8s.io/ingress-nginx/internal/ingress/annotations/authreq" "k8s.io/ingress-nginx/internal/ingress/annotations/influxdb" "k8s.io/ingress-nginx/internal/ingress/annotations/modsecurity" + "k8s.io/ingress-nginx/internal/ingress/annotations/opentelemetry" "k8s.io/ingress-nginx/internal/ingress/annotations/opentracing" "k8s.io/ingress-nginx/internal/ingress/annotations/ratelimit" "k8s.io/ingress-nginx/internal/ingress/annotations/rewrite" @@ -1150,6 +1151,26 @@ func TestOpentracingPropagateContext(t *testing.T) { } } +func TestOpentelemetryPropagateContext(t *testing.T) { + tests := map[*ingress.Location]string{ + {BackendProtocol: "HTTP"}: "opentelemetry_propagate;", + {BackendProtocol: "HTTPS"}: "opentelemetry_propagate;", + {BackendProtocol: "AUTO_HTTP"}: "opentelemetry_propagate;", + {BackendProtocol: "GRPC"}: "opentelemetry_propagate;", + {BackendProtocol: "GRPCS"}: "opentelemetry_propagate;", + {BackendProtocol: "AJP"}: "opentelemetry_propagate;", + {BackendProtocol: "FCGI"}: "opentelemetry_propagate;", + nil: "", + } + + for loc, expectedDirective := range tests { + actualDirective := opentelemetryPropagateContext(loc) + if actualDirective != expectedDirective { + t.Errorf("Expected %v but returned %v", expectedDirective, actualDirective) + } + } +} + func TestGetIngressInformation(t *testing.T) { testcases := map[string]struct { @@ -1723,6 +1744,37 @@ func TestBuildOpenTracing(t *testing.T) { } +func TestBuildOpenTelemetry(t *testing.T) { + invalidType := &ingress.Ingress{} + expected := "" + actual := buildOpentelemetry(invalidType, []*ingress.Server{}) + + if expected != actual { + t.Errorf("Expected '%v' but returned '%v'", expected, actual) + } + + cfgNoHost := config.Configuration{ + EnableOpentelemetry: true, + } + expected = "\r\n" + actual = buildOpentelemetry(cfgNoHost, []*ingress.Server{}) + + if expected != actual { + t.Errorf("Expected '%v' but returned '%v'", expected, actual) + } + + cfgOpenTelemetry := config.Configuration{ + EnableOpentelemetry: true, + OpentelemetryOperationName: "my-operation-name", + } + expected = "\r\n" + expected += "opentelemetry_operation_name \"my-operation-name\";\n" + actual = buildOpentelemetry(cfgOpenTelemetry, []*ingress.Server{}) + if expected != actual { + t.Errorf("Expected '%v' but returned '%v'", expected, actual) + } +} + func TestEnforceRegexModifier(t *testing.T) { invalidType := &ingress.Ingress{} expected := false @@ -1903,6 +1955,107 @@ func TestShouldLoadOpentracingModule(t *testing.T) { } } +func TestOpentelemetryForLocation(t *testing.T) { + trueVal := true + falseVal := false + + loadOT := `opentelemetry on; +opentelemetry_propagate; +opentelemetry_trust_incoming_spans on;` + loadOTUntrustedSpan := `opentelemetry on; +opentelemetry_propagate; +opentelemetry_trust_incoming_spans off;` + testCases := []struct { + description string + globalOT bool + isSetInLoc bool + isOTInLoc *bool + globalTrust bool + isTrustSetInLoc bool + isTrustInLoc *bool + expected string + }{ + {"globally enabled, without annotation", true, false, nil, true, false, nil, loadOT}, + {"globally enabled and enabled in location", true, true, &trueVal, true, false, nil, loadOT}, + {"globally disabled and not enabled in location", false, false, nil, true, false, nil, ""}, + {"globally disabled but enabled in location", false, true, &trueVal, true, false, nil, loadOT}, + {"globally trusted, not trusted in location", true, false, nil, true, true, &falseVal, loadOTUntrustedSpan}, + {"not globally trusted, trust set in location", true, false, nil, false, true, &trueVal, loadOT}, + {"not globally trusted, trust not set in location", true, false, nil, false, false, nil, loadOTUntrustedSpan}, + } + + for _, testCase := range testCases { + il := &ingress.Location{ + Opentelemetry: opentelemetry.Config{Set: testCase.isSetInLoc, TrustSet: testCase.isTrustSetInLoc}, + } + if il.Opentelemetry.Set { + il.Opentelemetry.Enabled = *testCase.isOTInLoc + } + if il.Opentelemetry.TrustSet { + il.Opentelemetry.TrustEnabled = *testCase.isTrustInLoc + } + + actual := buildOpentelemetryForLocation(testCase.globalOT, testCase.globalTrust, il) + + if testCase.expected != actual { + t.Errorf("%v: expected '%v' but returned '%v'", testCase.description, testCase.expected, actual) + } + } +} + +func TestShouldLoadOpentelemetryModule(t *testing.T) { + // ### Invalid argument type tests ### + // The first tests should return false. + expected := false + + invalidType := &ingress.Ingress{} + actual := shouldLoadOpentelemetryModule(config.Configuration{}, invalidType) + if expected != actual { + t.Errorf("Expected '%v' but returned '%v'", expected, actual) + } + + actual = shouldLoadOpentelemetryModule(invalidType, []*ingress.Server{}) + if expected != actual { + t.Errorf("Expected '%v' but returned '%v'", expected, actual) + } + + // ### Functional tests ### + actual = shouldLoadOpentelemetryModule(config.Configuration{}, []*ingress.Server{}) + if expected != actual { + t.Errorf("Expected '%v' but returned '%v'", expected, actual) + } + + // All further tests should return true. + expected = true + + configuration := config.Configuration{EnableOpentelemetry: true} + actual = shouldLoadOpentelemetryModule(configuration, []*ingress.Server{}) + if expected != actual { + t.Errorf("Expected '%v' but returned '%v'", expected, actual) + } + + servers := []*ingress.Server{ + { + Locations: []*ingress.Location{ + { + Opentelemetry: opentelemetry.Config{ + Enabled: true, + }, + }, + }, + }, + } + actual = shouldLoadOpentelemetryModule(config.Configuration{}, servers) + if expected != actual { + t.Errorf("Expected '%v' but returned '%v'", expected, actual) + } + + actual = shouldLoadOpentelemetryModule(configuration, servers) + if expected != actual { + t.Errorf("Expected '%v' but returned '%v'", expected, actual) + } +} + func TestModSecurityForLocation(t *testing.T) { loadModule := `modsecurity on; ` diff --git a/mkdocs.yml b/mkdocs.yml index c76a640f6..62c0ccf48 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -101,6 +101,7 @@ nav: - Third party addons: - ModSecurity Web Application Firewall: "user-guide/third-party-addons/modsecurity.md" - OpenTracing: "user-guide/third-party-addons/opentracing.md" + - OpenTelemetry: "user-guide/third-party-addons/opentelemetry.md" - Examples: - Introduction: "examples/index.md" - Prerequisites: "examples/PREREQUISITES.md" diff --git a/pkg/apis/ingress/types.go b/pkg/apis/ingress/types.go index 9395683ec..08a2f7575 100644 --- a/pkg/apis/ingress/types.go +++ b/pkg/apis/ingress/types.go @@ -35,6 +35,7 @@ import ( "k8s.io/ingress-nginx/internal/ingress/annotations/log" "k8s.io/ingress-nginx/internal/ingress/annotations/mirror" "k8s.io/ingress-nginx/internal/ingress/annotations/modsecurity" + "k8s.io/ingress-nginx/internal/ingress/annotations/opentelemetry" "k8s.io/ingress-nginx/internal/ingress/annotations/opentracing" "k8s.io/ingress-nginx/internal/ingress/annotations/proxy" "k8s.io/ingress-nginx/internal/ingress/annotations/proxyssl" @@ -360,6 +361,9 @@ type Location struct { // Opentracing allows the global opentracing setting to be overridden for a location // +optional Opentracing opentracing.Config `json:"opentracing"` + // Opentelemetry allows the global opentelemetry setting to be overridden for a location + // +optional + Opentelemetry opentelemetry.Config `json:"opentelemetry"` } // SSLPassthroughBackend describes a SSL upstream server configured diff --git a/pkg/apis/ingress/types_equals.go b/pkg/apis/ingress/types_equals.go index 2485f8a7b..8a54f3758 100644 --- a/pkg/apis/ingress/types_equals.go +++ b/pkg/apis/ingress/types_equals.go @@ -464,6 +464,10 @@ func (l1 *Location) Equal(l2 *Location) bool { return false } + if !l1.Opentelemetry.Equal(&l2.Opentelemetry) { + return false + } + if !l1.Mirror.Equal(&l2.Mirror) { return false } diff --git a/rootfs/etc/nginx/template/nginx.tmpl b/rootfs/etc/nginx/template/nginx.tmpl old mode 100755 new mode 100644 index 958397dd5..014c8cc2a --- a/rootfs/etc/nginx/template/nginx.tmpl +++ b/rootfs/etc/nginx/template/nginx.tmpl @@ -37,6 +37,10 @@ load_module /etc/nginx/modules/ngx_http_modsecurity_module.so; load_module /etc/nginx/modules/ngx_http_opentracing_module.so; {{ end }} +{{ if (shouldLoadOpentelemetryModule $cfg $servers) }} +load_module /modules_mount/etc/nginx/modules/otel/otel_ngx_module.so; +{{ end }} + daemon off; worker_processes {{ $cfg.WorkerProcesses }}; @@ -64,6 +68,10 @@ events { } http { + {{ if (shouldLoadOpentelemetryModule $cfg $servers) }} + opentelemetry_config {{ $cfg.OpentelemetryConfig }}; + {{ end }} + lua_package_path "/etc/nginx/lua/?.lua;;"; {{ buildLuaSharedDictionaries $cfg $servers }} @@ -322,6 +330,7 @@ http { limit_conn_status {{ $cfg.LimitConnStatusCode }}; {{ buildOpentracing $cfg $servers }} + {{ buildOpentelemetry $cfg $servers }} include /etc/nginx/mime.types; default_type {{ $cfg.DefaultType }}; @@ -695,6 +704,9 @@ http { opentracing off; {{ end }} + {{ if $cfg.EnableOpentelemetry }} + opentelemetry off; + {{ end }} location {{ $healthzURI }} { return 200; } @@ -1063,6 +1075,11 @@ stream { opentracing_propagate_context; {{ end }} + {{ if (or $all.Cfg.EnableOpentelemetry $location.Opentelemetry.Enabled) }} + opentelemetry on; + opentelemetry_propagate; + {{ end }} + access_log off; # Ensure that modsecurity will not run on an internal location as this is not accessible from outside @@ -1204,6 +1221,7 @@ stream { set $global_rate_limit_exceeding n; {{ buildOpentracingForLocation $all.Cfg.EnableOpentracing $all.Cfg.OpentracingTrustIncomingSpan $location }} + {{ buildOpentelemetryForLocation $all.Cfg.EnableOpentelemetry $all.Cfg.OpentelemetryTrustIncomingSpan $location }} {{ if $location.Mirror.Source }} mirror {{ $location.Mirror.Source }}; @@ -1520,6 +1538,10 @@ stream { opentracing off; {{ end }} + {{ if $all.Cfg.EnableOpentelemetry }} + opentelemetry off; + {{ end }} + access_log off; return 200; } @@ -1531,6 +1553,10 @@ stream { opentracing off; {{ end }} + {{ if $all.Cfg.EnableOpentelemetry }} + opentelemetry off; + {{ end }} + {{ range $v := $all.NginxStatusIpv4Whitelist }} allow {{ $v }}; {{ end }} diff --git a/test/e2e/framework/exec.go b/test/e2e/framework/exec.go index 0284e768c..d91d36551 100644 --- a/test/e2e/framework/exec.go +++ b/test/e2e/framework/exec.go @@ -21,6 +21,7 @@ import ( "encoding/json" "fmt" "io" + "os" "os/exec" "regexp" "strconv" @@ -111,7 +112,11 @@ func (f *Framework) NamespaceContent() (string, error) { // newIngressController deploys a new NGINX Ingress controller in a namespace func (f *Framework) newIngressController(namespace string, namespaceOverlay string) error { // Creates an nginx deployment - cmd := exec.Command("./wait-for-nginx.sh", namespace, namespaceOverlay) + isChroot, ok := os.LookupEnv("IS_CHROOT") + if !ok { + isChroot = "false" + } + cmd := exec.Command("./wait-for-nginx.sh", namespace, namespaceOverlay, isChroot) out, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("unexpected error waiting for ingress controller deployment: %v.\nLogs:\n%v", err, string(out)) diff --git a/test/e2e/run-e2e-suite.sh b/test/e2e/run-e2e-suite.sh index b1de8bf9a..a3bf589cd 100755 --- a/test/e2e/run-e2e-suite.sh +++ b/test/e2e/run-e2e-suite.sh @@ -76,6 +76,7 @@ kubectl run --rm \ --restart=Never \ --env="E2E_NODES=${E2E_NODES}" \ --env="FOCUS=${FOCUS}" \ + --env="IS_CHROOT=${IS_CHROOT:-false}"\ --env="E2E_CHECK_LEAKS=${E2E_CHECK_LEAKS}" \ --env="NGINX_BASE_IMAGE=${NGINX_BASE_IMAGE}" \ --overrides='{ "apiVersion": "v1", "spec":{"serviceAccountName": "ingress-nginx-e2e"}}' \ diff --git a/test/e2e/settings/opentelemetry.go b/test/e2e/settings/opentelemetry.go new file mode 100644 index 000000000..92d202cb3 --- /dev/null +++ b/test/e2e/settings/opentelemetry.go @@ -0,0 +1,119 @@ +/* +Copyright 2022 The Kubernetes 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 settings + +import ( + "strings" + + "github.com/onsi/ginkgo/v2" + + "k8s.io/ingress-nginx/test/e2e/framework" +) + +const ( + enableOpentelemetry = "enable-opentelemetry" + opentelemetryTrustIncomingSpan = "opentelemetry-trust-incoming-span" + + opentelemetryOperationName = "opentelemetry-operation-name" + opentelemetryLocationOperationName = "opentelemetry-location-operation-name" + opentelemetryConfig = "opentelemetry-config" + opentelemetryConfigPath = "/etc/nginx/opentelemetry.toml" +) + +var _ = framework.IngressNginxDescribe("Configure Opentelemetry", func() { + f := framework.NewDefaultFramework("enable-opentelemetry") + + ginkgo.BeforeEach(func() { + f.NewEchoDeployment() + }) + + ginkgo.AfterEach(func() { + }) + + ginkgo.It("should not exists opentelemetry directive", func() { + config := map[string]string{} + config[enableOpentelemetry] = "false" + f.SetNginxConfigMapData(config) + + f.EnsureIngress(framework.NewSingleIngress(enableOpentelemetry, "/", enableOpentelemetry, f.Namespace, "http-svc", 80, nil)) + + f.WaitForNginxConfiguration( + func(cfg string) bool { + return !strings.Contains(cfg, "opentelemetry on") + }) + }) + + ginkgo.It("should exists opentelemetry directive when is enabled", func() { + config := map[string]string{} + config[enableOpentelemetry] = "true" + config[opentelemetryConfig] = opentelemetryConfigPath + f.SetNginxConfigMapData(config) + + f.EnsureIngress(framework.NewSingleIngress(enableOpentelemetry, "/", enableOpentelemetry, f.Namespace, "http-svc", 80, nil)) + + f.WaitForNginxConfiguration( + func(cfg string) bool { + return strings.Contains(cfg, "opentelemetry on") + }) + }) + + ginkgo.It("should include opentelemetry_trust_incoming_spans on directive when enabled", func() { + config := map[string]string{} + config[enableOpentelemetry] = "true" + config[opentelemetryConfig] = opentelemetryConfigPath + config[opentelemetryTrustIncomingSpan] = "true" + f.SetNginxConfigMapData(config) + + f.EnsureIngress(framework.NewSingleIngress(enableOpentelemetry, "/", enableOpentelemetry, f.Namespace, "http-svc", 80, nil)) + + f.WaitForNginxConfiguration( + func(cfg string) bool { + return strings.Contains(cfg, "opentelemetry_trust_incoming_spans on") + }) + }) + + ginkgo.It("should not exists opentelemetry_operation_name directive when is empty", func() { + config := map[string]string{} + config[enableOpentelemetry] = "true" + config[opentelemetryConfig] = opentelemetryConfigPath + config[opentelemetryOperationName] = "" + f.SetNginxConfigMapData(config) + + f.EnsureIngress(framework.NewSingleIngress(enableOpentelemetry, "/", enableOpentelemetry, f.Namespace, "http-svc", 80, nil)) + + f.WaitForNginxConfiguration( + func(cfg string) bool { + return !strings.Contains(cfg, "opentelemetry_operation_name") + }) + }) + + ginkgo.It("should exists opentelemetry_operation_name directive when is configured", func() { + config := map[string]string{} + config[enableOpentelemetry] = "true" + config[opentelemetryConfig] = opentelemetryConfigPath + config[opentelemetryOperationName] = "HTTP $request_method $uri" + f.SetNginxConfigMapData(config) + + f.EnsureIngress(framework.NewSingleIngress(enableOpentelemetry, "/", enableOpentelemetry, f.Namespace, "http-svc", 80, nil)) + + f.WaitForNginxConfiguration( + func(cfg string) bool { + return strings.Contains(cfg, `opentelemetry_operation_name "HTTP $request_method $uri"`) + }) + }) + +}) diff --git a/test/e2e/wait-for-nginx.sh b/test/e2e/wait-for-nginx.sh index 190f71e6d..153d348c2 100755 --- a/test/e2e/wait-for-nginx.sh +++ b/test/e2e/wait-for-nginx.sh @@ -23,6 +23,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" export NAMESPACE=$1 export NAMESPACE_OVERLAY=$2 +export IS_CHROOT=$3 echo "deploying NGINX Ingress controller in namespace $NAMESPACE" @@ -46,6 +47,16 @@ metadata: EOF +OTEL_MODULE=$(cat < Date: Wed, 22 Mar 2023 18:50:22 -0700 Subject: [PATCH 68/69] Update exposing-tcp-udp-services.md (#9777) --- docs/user-guide/exposing-tcp-udp-services.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/user-guide/exposing-tcp-udp-services.md b/docs/user-guide/exposing-tcp-udp-services.md index 6b595ffae..63293f0e5 100644 --- a/docs/user-guide/exposing-tcp-udp-services.md +++ b/docs/user-guide/exposing-tcp-udp-services.md @@ -63,3 +63,9 @@ spec: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx ``` +Then, the configmap should be added into ingress controller's deployment args. +``` + args: + - /nginx-ingress-controller + - --tcp-services-configmap=ingress-nginx/tcp-services +``` From 72ff21ed9e26cb969052c753633049ba8a87ecf9 Mon Sep 17 00:00:00 2001 From: James Strong Date: Wed, 22 Mar 2023 23:26:22 -0400 Subject: [PATCH 69/69] kick off 1.7.0 build (#9775) Signed-off-by: James Strong --- TAG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TAG b/TAG index 9dc820555..b13f0e3bc 100644 --- a/TAG +++ b/TAG @@ -1,2 +1,2 @@ -v1.6.4 +v1.7.0