From e77a66c2ac99c5ff9754dcaa6df5008df77a27b3 Mon Sep 17 00:00:00 2001 From: Suyash Choudhary <57896905+sssash18@users.noreply.github.com> Date: Wed, 6 Dec 2023 19:06:05 +0530 Subject: [PATCH 01/21] Fixed datadog logs json format issue --- pkg/log/datadog.go | 13 +++++++++++++ pkg/tracing/datadog/datadog.go | 4 ++++ 2 files changed, 17 insertions(+) create mode 100644 pkg/log/datadog.go diff --git a/pkg/log/datadog.go b/pkg/log/datadog.go new file mode 100644 index 000000000..dda0fed5d --- /dev/null +++ b/pkg/log/datadog.go @@ -0,0 +1,13 @@ +package log + +type DatadogLogger struct { + logger Logger +} + +func NewDatadogLogger(logger Logger) *DatadogLogger { + return &DatadogLogger{logger: logger} +} + +func (d DatadogLogger) Log(msg string) { + d.logger.Debug(msg) +} diff --git a/pkg/tracing/datadog/datadog.go b/pkg/tracing/datadog/datadog.go index b0c32643f..30e99fcda 100644 --- a/pkg/tracing/datadog/datadog.go +++ b/pkg/tracing/datadog/datadog.go @@ -1,6 +1,7 @@ package datadog import ( + "context" "io" "net" "os" @@ -47,6 +48,8 @@ func (c *Config) SetDefaults() { // Setup sets up the tracer. func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error) { + ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "datadog")) + opts := []datadog.StartOption{ datadog.WithService(serviceName), datadog.WithDebugMode(c.Debug), @@ -56,6 +59,7 @@ func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error PriorityHeader: c.SamplingPriorityHeaderName, BaggagePrefix: c.BagagePrefixHeaderName, })), + datadog.WithLogger(log.NewDatadogLogger(log.FromContext(ctx))), } if c.LocalAgentSocket != "" { From 0a7964300166d167f68d5502bc245b3b9c8842b4 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Wed, 6 Dec 2023 16:42:09 +0100 Subject: [PATCH 02/21] Prepare release v2.10.7 --- CHANGELOG.md | 6 ++++++ script/gcg/traefik-bugfix.toml | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49f19bedb..4d40ab83e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [v2.10.7](https://github.com/traefik/traefik/tree/v2.10.7) (2023-12-06) +[All Commits](https://github.com/traefik/traefik/compare/v2.10.6...v2.10.7) + +**Bug fixes:** +- **[logs]** Fixed datadog logs json format issue ([#10233](https://github.com/traefik/traefik/pull/10233) by [sssash18](https://github.com/sssash18)) + ## [v2.10.6](https://github.com/traefik/traefik/tree/v2.10.6) (2023-11-28) [All Commits](https://github.com/traefik/traefik/compare/v2.10.5...v2.10.6) diff --git a/script/gcg/traefik-bugfix.toml b/script/gcg/traefik-bugfix.toml index fb6f9ccde..d1f7eed10 100644 --- a/script/gcg/traefik-bugfix.toml +++ b/script/gcg/traefik-bugfix.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example new bugfix v2.10.6 +# example new bugfix v2.10.7 CurrentRef = "v2.10" -PreviousRef = "v2.10.5" +PreviousRef = "v2.10.6" BaseBranch = "v2.10" -FutureCurrentRefName = "v2.10.6" +FutureCurrentRefName = "v2.10.7" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10 From 2a7b2ef772b31844141da8d1cf85bec82456a052 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 2 Jan 2024 15:28:09 +0100 Subject: [PATCH 03/21] chore: happy new year 2024 --- LICENSE.md | 2 +- docs/mkdocs.yml | 2 +- pkg/config/dynamic/zz_generated.deepcopy.go | 2 +- .../kubernetes/crd/generated/clientset/versioned/clientset.go | 2 +- .../generated/clientset/versioned/fake/clientset_generated.go | 2 +- .../kubernetes/crd/generated/clientset/versioned/fake/doc.go | 2 +- .../crd/generated/clientset/versioned/fake/register.go | 2 +- .../kubernetes/crd/generated/clientset/versioned/scheme/doc.go | 2 +- .../crd/generated/clientset/versioned/scheme/register.go | 2 +- .../clientset/versioned/typed/traefikcontainous/v1alpha1/doc.go | 2 +- .../versioned/typed/traefikcontainous/v1alpha1/fake/doc.go | 2 +- .../typed/traefikcontainous/v1alpha1/fake/fake_ingressroute.go | 2 +- .../traefikcontainous/v1alpha1/fake/fake_ingressroutetcp.go | 2 +- .../traefikcontainous/v1alpha1/fake/fake_ingressrouteudp.go | 2 +- .../typed/traefikcontainous/v1alpha1/fake/fake_middleware.go | 2 +- .../typed/traefikcontainous/v1alpha1/fake/fake_middlewaretcp.go | 2 +- .../traefikcontainous/v1alpha1/fake/fake_serverstransport.go | 2 +- .../typed/traefikcontainous/v1alpha1/fake/fake_tlsoption.go | 2 +- .../typed/traefikcontainous/v1alpha1/fake/fake_tlsstore.go | 2 +- .../v1alpha1/fake/fake_traefikcontainous_client.go | 2 +- .../traefikcontainous/v1alpha1/fake/fake_traefikservice.go | 2 +- .../typed/traefikcontainous/v1alpha1/generated_expansion.go | 2 +- .../versioned/typed/traefikcontainous/v1alpha1/ingressroute.go | 2 +- .../typed/traefikcontainous/v1alpha1/ingressroutetcp.go | 2 +- .../typed/traefikcontainous/v1alpha1/ingressrouteudp.go | 2 +- .../versioned/typed/traefikcontainous/v1alpha1/middleware.go | 2 +- .../versioned/typed/traefikcontainous/v1alpha1/middlewaretcp.go | 2 +- .../typed/traefikcontainous/v1alpha1/serverstransport.go | 2 +- .../versioned/typed/traefikcontainous/v1alpha1/tlsoption.go | 2 +- .../versioned/typed/traefikcontainous/v1alpha1/tlsstore.go | 2 +- .../traefikcontainous/v1alpha1/traefikcontainous_client.go | 2 +- .../typed/traefikcontainous/v1alpha1/traefikservice.go | 2 +- .../clientset/versioned/typed/traefikio/v1alpha1/doc.go | 2 +- .../clientset/versioned/typed/traefikio/v1alpha1/fake/doc.go | 2 +- .../typed/traefikio/v1alpha1/fake/fake_ingressroute.go | 2 +- .../typed/traefikio/v1alpha1/fake/fake_ingressroutetcp.go | 2 +- .../typed/traefikio/v1alpha1/fake/fake_ingressrouteudp.go | 2 +- .../versioned/typed/traefikio/v1alpha1/fake/fake_middleware.go | 2 +- .../typed/traefikio/v1alpha1/fake/fake_middlewaretcp.go | 2 +- .../typed/traefikio/v1alpha1/fake/fake_serverstransport.go | 2 +- .../versioned/typed/traefikio/v1alpha1/fake/fake_tlsoption.go | 2 +- .../versioned/typed/traefikio/v1alpha1/fake/fake_tlsstore.go | 2 +- .../typed/traefikio/v1alpha1/fake/fake_traefikio_client.go | 2 +- .../typed/traefikio/v1alpha1/fake/fake_traefikservice.go | 2 +- .../versioned/typed/traefikio/v1alpha1/generated_expansion.go | 2 +- .../versioned/typed/traefikio/v1alpha1/ingressroute.go | 2 +- .../versioned/typed/traefikio/v1alpha1/ingressroutetcp.go | 2 +- .../versioned/typed/traefikio/v1alpha1/ingressrouteudp.go | 2 +- .../clientset/versioned/typed/traefikio/v1alpha1/middleware.go | 2 +- .../versioned/typed/traefikio/v1alpha1/middlewaretcp.go | 2 +- .../versioned/typed/traefikio/v1alpha1/serverstransport.go | 2 +- .../clientset/versioned/typed/traefikio/v1alpha1/tlsoption.go | 2 +- .../clientset/versioned/typed/traefikio/v1alpha1/tlsstore.go | 2 +- .../versioned/typed/traefikio/v1alpha1/traefikio_client.go | 2 +- .../versioned/typed/traefikio/v1alpha1/traefikservice.go | 2 +- .../crd/generated/informers/externalversions/factory.go | 2 +- .../crd/generated/informers/externalversions/generic.go | 2 +- .../externalversions/internalinterfaces/factory_interfaces.go | 2 +- .../informers/externalversions/traefikcontainous/interface.go | 2 +- .../externalversions/traefikcontainous/v1alpha1/ingressroute.go | 2 +- .../traefikcontainous/v1alpha1/ingressroutetcp.go | 2 +- .../traefikcontainous/v1alpha1/ingressrouteudp.go | 2 +- .../externalversions/traefikcontainous/v1alpha1/interface.go | 2 +- .../externalversions/traefikcontainous/v1alpha1/middleware.go | 2 +- .../traefikcontainous/v1alpha1/middlewaretcp.go | 2 +- .../traefikcontainous/v1alpha1/serverstransport.go | 2 +- .../externalversions/traefikcontainous/v1alpha1/tlsoption.go | 2 +- .../externalversions/traefikcontainous/v1alpha1/tlsstore.go | 2 +- .../traefikcontainous/v1alpha1/traefikservice.go | 2 +- .../generated/informers/externalversions/traefikio/interface.go | 2 +- .../externalversions/traefikio/v1alpha1/ingressroute.go | 2 +- .../externalversions/traefikio/v1alpha1/ingressroutetcp.go | 2 +- .../externalversions/traefikio/v1alpha1/ingressrouteudp.go | 2 +- .../informers/externalversions/traefikio/v1alpha1/interface.go | 2 +- .../informers/externalversions/traefikio/v1alpha1/middleware.go | 2 +- .../externalversions/traefikio/v1alpha1/middlewaretcp.go | 2 +- .../externalversions/traefikio/v1alpha1/serverstransport.go | 2 +- .../informers/externalversions/traefikio/v1alpha1/tlsoption.go | 2 +- .../informers/externalversions/traefikio/v1alpha1/tlsstore.go | 2 +- .../externalversions/traefikio/v1alpha1/traefikservice.go | 2 +- .../listers/traefikcontainous/v1alpha1/expansion_generated.go | 2 +- .../listers/traefikcontainous/v1alpha1/ingressroute.go | 2 +- .../listers/traefikcontainous/v1alpha1/ingressroutetcp.go | 2 +- .../listers/traefikcontainous/v1alpha1/ingressrouteudp.go | 2 +- .../generated/listers/traefikcontainous/v1alpha1/middleware.go | 2 +- .../listers/traefikcontainous/v1alpha1/middlewaretcp.go | 2 +- .../listers/traefikcontainous/v1alpha1/serverstransport.go | 2 +- .../generated/listers/traefikcontainous/v1alpha1/tlsoption.go | 2 +- .../generated/listers/traefikcontainous/v1alpha1/tlsstore.go | 2 +- .../listers/traefikcontainous/v1alpha1/traefikservice.go | 2 +- .../generated/listers/traefikio/v1alpha1/expansion_generated.go | 2 +- .../crd/generated/listers/traefikio/v1alpha1/ingressroute.go | 2 +- .../crd/generated/listers/traefikio/v1alpha1/ingressroutetcp.go | 2 +- .../crd/generated/listers/traefikio/v1alpha1/ingressrouteudp.go | 2 +- .../crd/generated/listers/traefikio/v1alpha1/middleware.go | 2 +- .../crd/generated/listers/traefikio/v1alpha1/middlewaretcp.go | 2 +- .../generated/listers/traefikio/v1alpha1/serverstransport.go | 2 +- .../crd/generated/listers/traefikio/v1alpha1/tlsoption.go | 2 +- .../crd/generated/listers/traefikio/v1alpha1/tlsstore.go | 2 +- .../crd/generated/listers/traefikio/v1alpha1/traefikservice.go | 2 +- .../crd/traefikcontainous/v1alpha1/zz_generated.deepcopy.go | 2 +- .../kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go | 2 +- pkg/tls/zz_generated.deepcopy.go | 2 +- pkg/types/zz_generated.deepcopy.go | 2 +- 104 files changed, 104 insertions(+), 104 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index d56287566..fda9f5084 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 7432a44a0..f588c1d80 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -27,7 +27,7 @@ theme: prev: 'Previous' next: 'Next' -copyright: 'Traefik Labs • Copyright © 2016-2023' +copyright: 'Traefik Labs • Copyright © 2016-2024' extra_javascript: - assets/js/hljs/highlight.pack.js # Download from https://highlightjs.org/download/ and enable YAML, TOML and Dockerfile diff --git a/pkg/config/dynamic/zz_generated.deepcopy.go b/pkg/config/dynamic/zz_generated.deepcopy.go index 7b51c92c7..f897f6f31 100644 --- a/pkg/config/dynamic/zz_generated.deepcopy.go +++ b/pkg/config/dynamic/zz_generated.deepcopy.go @@ -4,7 +4,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/clientset.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/clientset.go index 6f1dbe043..f204dbe07 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/clientset.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/clientset.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/clientset_generated.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/clientset_generated.go index b2f1ea211..db9c67cb2 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/clientset_generated.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/clientset_generated.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/doc.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/doc.go index 081d07edb..ae4bdb20e 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/doc.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/doc.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/register.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/register.go index 12677f64b..99758be01 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/register.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/fake/register.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme/doc.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme/doc.go index 87af68273..ba3753967 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme/doc.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme/doc.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme/register.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme/register.go index f8a30576c..f008f0e20 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme/register.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme/register.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/doc.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/doc.go index e39212eab..91c1c1d8a 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/doc.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/doc.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/doc.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/doc.go index 24ecc2be0..1964e2084 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/doc.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/doc.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_ingressroute.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_ingressroute.go index cedfa74a2..2c0a1494b 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_ingressroute.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_ingressroute.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_ingressroutetcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_ingressroutetcp.go index 841e394ae..623fd5985 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_ingressroutetcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_ingressrouteudp.go index bf60f14d8..0b9913d47 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_ingressrouteudp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_middleware.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_middleware.go index 5b126d564..ef909746c 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_middleware.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_middleware.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_middlewaretcp.go index 475b7279e..23d4e6703 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_middlewaretcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_serverstransport.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_serverstransport.go index 4a711e791..289081537 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_serverstransport.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_serverstransport.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_tlsoption.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_tlsoption.go index 8d884f993..2dc3fa3ab 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_tlsoption.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_tlsoption.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_tlsstore.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_tlsstore.go index 15bf1e1e5..1d20311c1 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_tlsstore.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_tlsstore.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_traefikcontainous_client.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_traefikcontainous_client.go index 0ccf55f19..05cbeee51 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_traefikcontainous_client.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_traefikcontainous_client.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_traefikservice.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_traefikservice.go index 5a1a390c7..6e5f5b2ed 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_traefikservice.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/fake/fake_traefikservice.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/generated_expansion.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/generated_expansion.go index aeaaec294..59b56c32f 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/generated_expansion.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/generated_expansion.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/ingressroute.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/ingressroute.go index 9ae05fd02..1ad1af049 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/ingressroute.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/ingressroute.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/ingressroutetcp.go index f75f54834..ec4814207 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/ingressroutetcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/ingressrouteudp.go index ad4f3b150..d7a7ebbb8 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/ingressrouteudp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/middleware.go index dd2694341..b23e8df36 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/middleware.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/middlewaretcp.go index 32a478b35..9cf0fd2f9 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/middlewaretcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/serverstransport.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/serverstransport.go index ada49856c..ed9ea93ea 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/serverstransport.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/serverstransport.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/tlsoption.go index c340d8b64..f1d66a882 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/tlsoption.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/tlsoption.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/tlsstore.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/tlsstore.go index 91d86684e..74b2f4045 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/tlsstore.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/tlsstore.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/traefikcontainous_client.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/traefikcontainous_client.go index 237a5f48f..c24b091eb 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/traefikcontainous_client.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/traefikcontainous_client.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/traefikservice.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/traefikservice.go index 344f26651..f52ff7aab 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/traefikservice.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikcontainous/v1alpha1/traefikservice.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/doc.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/doc.go index e39212eab..91c1c1d8a 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/doc.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/doc.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/doc.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/doc.go index 24ecc2be0..1964e2084 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/doc.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/doc.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_ingressroute.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_ingressroute.go index 364113084..2f0bb8d60 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_ingressroute.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_ingressroute.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_ingressroutetcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_ingressroutetcp.go index dcca789ae..c7dd8fbf7 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_ingressroutetcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_ingressrouteudp.go index 815811762..ed0c3a23c 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_ingressrouteudp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_middleware.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_middleware.go index d2ce41e27..7385b7985 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_middleware.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_middleware.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_middlewaretcp.go index d026a2a81..8c90d221c 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_middlewaretcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_serverstransport.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_serverstransport.go index 8c04de8bd..08d1f6a1c 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_serverstransport.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_serverstransport.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_tlsoption.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_tlsoption.go index ba23bef83..99132f297 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_tlsoption.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_tlsoption.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_tlsstore.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_tlsstore.go index 9dd04322c..2868030e7 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_tlsstore.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_tlsstore.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_traefikio_client.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_traefikio_client.go index 1b5d8233a..e2c81f799 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_traefikio_client.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_traefikio_client.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_traefikservice.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_traefikservice.go index 50a18e86d..fdb18b474 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_traefikservice.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/fake/fake_traefikservice.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/generated_expansion.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/generated_expansion.go index aeaaec294..59b56c32f 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/generated_expansion.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/generated_expansion.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressroute.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressroute.go index 710c59a37..2c8ed2ce1 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressroute.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressroute.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressroutetcp.go index 1d24bbc61..a8a5407f6 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressroutetcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressrouteudp.go index c98226d1a..e1adfe4e7 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/ingressrouteudp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/middleware.go index c9cc8d4a1..6282b8d35 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/middleware.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/middlewaretcp.go index 86d4af855..2d61da310 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/middlewaretcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/serverstransport.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/serverstransport.go index a9a824e90..a9dd020c2 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/serverstransport.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/serverstransport.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/tlsoption.go index e782549be..e7404ad46 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/tlsoption.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/tlsoption.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/tlsstore.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/tlsstore.go index 401559371..14cb0f0c7 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/tlsstore.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/tlsstore.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/traefikio_client.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/traefikio_client.go index 20ec249fa..96e6e9e05 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/traefikio_client.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/traefikio_client.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/traefikservice.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/traefikservice.go index cf1503d1d..47682e416 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/traefikservice.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefikio/v1alpha1/traefikservice.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/factory.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/factory.go index 0b9aebf6e..5c2375b97 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/factory.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/factory.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go index 553bf72db..dfbcf0bfd 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces/factory_interfaces.go index 5abe4a64d..f37301acc 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/interface.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/interface.go index e462260b5..115a745a0 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/interface.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/interface.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/ingressroute.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/ingressroute.go index 500091592..ecfaf25f6 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/ingressroute.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/ingressroute.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/ingressroutetcp.go index b8382e1c2..f80a1b76a 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/ingressroutetcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/ingressrouteudp.go index 69bdd520c..1fee049a8 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/ingressrouteudp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/interface.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/interface.go index 9edba3953..83653f484 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/interface.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/interface.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/middleware.go index 71c08243e..84343dc6c 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/middleware.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/middlewaretcp.go index f80484e92..3c4a85a82 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/middlewaretcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/serverstransport.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/serverstransport.go index 29ae57c7e..64b342142 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/serverstransport.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/serverstransport.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/tlsoption.go index 3fe6f8dc7..11b3dd710 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/tlsoption.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/tlsoption.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/tlsstore.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/tlsstore.go index b27961285..36df0adb8 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/tlsstore.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/tlsstore.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/traefikservice.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/traefikservice.go index 501710f13..851b664bd 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/traefikservice.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikcontainous/v1alpha1/traefikservice.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/interface.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/interface.go index 726ceb16f..0c0321cbb 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/interface.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/interface.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressroute.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressroute.go index ac1ece6b0..cd67e24df 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressroute.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressroute.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressroutetcp.go index d86c7ca9d..71c54cb62 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressroutetcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressrouteudp.go index fb2b8a9ae..28a28f0d5 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/ingressrouteudp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/interface.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/interface.go index 9edba3953..83653f484 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/interface.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/interface.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/middleware.go index 11de7184c..7d3573441 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/middleware.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/middlewaretcp.go index db9c5e47b..1ee175d6a 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/middlewaretcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/serverstransport.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/serverstransport.go index 90f2dfbcd..c4cb27940 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/serverstransport.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/serverstransport.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/tlsoption.go index f81a0a265..0da9e2b2d 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/tlsoption.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/tlsoption.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/tlsstore.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/tlsstore.go index 338a72501..93685d299 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/tlsstore.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/tlsstore.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/traefikservice.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/traefikservice.go index e24a89fb8..9c63a8cba 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/traefikservice.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefikio/v1alpha1/traefikservice.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/expansion_generated.go b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/expansion_generated.go index 341744ace..e2badc3a1 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/expansion_generated.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/expansion_generated.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/ingressroute.go b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/ingressroute.go index 6b0238b9c..f9bf671aa 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/ingressroute.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/ingressroute.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/ingressroutetcp.go index 84907b741..773c31f32 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/ingressroutetcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/ingressrouteudp.go index e6a14e6fa..b791006ee 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/ingressrouteudp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/middleware.go index 4905d7741..d00224c93 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/middleware.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/middlewaretcp.go index b556c030e..e7f0caa75 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/middlewaretcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/serverstransport.go b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/serverstransport.go index b29ee49ae..b357654ea 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/serverstransport.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/serverstransport.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/tlsoption.go index 4ff720db9..aa10d4c13 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/tlsoption.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/tlsoption.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/tlsstore.go b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/tlsstore.go index 4964646a6..545ec82a6 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/tlsstore.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/tlsstore.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/traefikservice.go b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/traefikservice.go index cc9d26831..f01f936bf 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/traefikservice.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikcontainous/v1alpha1/traefikservice.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/expansion_generated.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/expansion_generated.go index 341744ace..e2badc3a1 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/expansion_generated.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/expansion_generated.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressroute.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressroute.go index 2a853bea1..762ad5fe3 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressroute.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressroute.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressroutetcp.go index a6c69a805..932d48713 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressroutetcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressrouteudp.go index 5b5df603d..56ea4d6e1 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/ingressrouteudp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/middleware.go index ab6a8d0e9..712ba96f3 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/middleware.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/middlewaretcp.go index 192a0c682..a4a0ccfa4 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/middlewaretcp.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/serverstransport.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/serverstransport.go index 5784d0ae6..9b7f60371 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/serverstransport.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/serverstransport.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/tlsoption.go index 3d1145b91..e32c107b1 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/tlsoption.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/tlsoption.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/tlsstore.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/tlsstore.go index 2af005be1..f8922e437 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/tlsstore.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/tlsstore.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/traefikservice.go b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/traefikservice.go index 2ebc6533d..686ac967a 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/traefikservice.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefikio/v1alpha1/traefikservice.go @@ -1,7 +1,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/zz_generated.deepcopy.go index 03ddabec3..a91c5cfc1 100644 --- a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/zz_generated.deepcopy.go @@ -4,7 +4,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go index 03ddabec3..a91c5cfc1 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go @@ -4,7 +4,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/tls/zz_generated.deepcopy.go b/pkg/tls/zz_generated.deepcopy.go index 95438c468..6050777a6 100644 --- a/pkg/tls/zz_generated.deepcopy.go +++ b/pkg/tls/zz_generated.deepcopy.go @@ -4,7 +4,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/pkg/types/zz_generated.deepcopy.go b/pkg/types/zz_generated.deepcopy.go index 8c55ace87..f2853fdfc 100644 --- a/pkg/types/zz_generated.deepcopy.go +++ b/pkg/types/zz_generated.deepcopy.go @@ -4,7 +4,7 @@ /* The MIT License (MIT) -Copyright (c) 2016-2020 Containous SAS; 2020-2023 Traefik Labs +Copyright (c) 2016-2020 Containous SAS; 2020-2024 Traefik Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 60123a8f3ff380b4dfde89877c329464607980a2 Mon Sep 17 00:00:00 2001 From: Baptiste Mayelle Date: Tue, 2 Jan 2024 15:52:05 +0100 Subject: [PATCH 04/21] Hash WRR sticky cookies Co-authored-by: Romain --- pkg/server/service/loadbalancer/wrr/wrr.go | 55 +++++++++++-------- .../service/loadbalancer/wrr/wrr_test.go | 31 +++++++++++ 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/pkg/server/service/loadbalancer/wrr/wrr.go b/pkg/server/service/loadbalancer/wrr/wrr.go index d7261d95b..95c374842 100644 --- a/pkg/server/service/loadbalancer/wrr/wrr.go +++ b/pkg/server/service/loadbalancer/wrr/wrr.go @@ -5,6 +5,7 @@ import ( "context" "errors" "fmt" + "hash/fnv" "net/http" "sync" @@ -34,7 +35,9 @@ type Balancer struct { stickyCookie *stickyCookie wantsHealthCheck bool - mutex sync.RWMutex + handlersMu sync.RWMutex + // References all the handlers by name and also by the hashed value of the name. + handlerMap map[string]*namedHandler handlers []*namedHandler curDeadline float64 // status is a record of which child services of the Balancer are healthy, keyed @@ -51,6 +54,7 @@ type Balancer struct { func New(sticky *dynamic.Sticky, hc *dynamic.HealthCheck) *Balancer { balancer := &Balancer{ status: make(map[string]struct{}), + handlerMap: make(map[string]*namedHandler), wantsHealthCheck: hc != nil, } if sticky != nil && sticky.Cookie != nil { @@ -60,6 +64,7 @@ func New(sticky *dynamic.Sticky, hc *dynamic.HealthCheck) *Balancer { httpOnly: sticky.Cookie.HTTPOnly, } } + return balancer } @@ -97,8 +102,8 @@ func (b *Balancer) Pop() interface{} { // SetStatus sets on the balancer that its given child is now of the given // status. balancerName is only needed for logging purposes. func (b *Balancer) SetStatus(ctx context.Context, childName string, up bool) { - b.mutex.Lock() - defer b.mutex.Unlock() + b.handlersMu.Lock() + defer b.handlersMu.Unlock() upBefore := len(b.status) > 0 @@ -147,8 +152,8 @@ func (b *Balancer) RegisterStatusUpdater(fn func(up bool)) error { var errNoAvailableServer = errors.New("no available server") func (b *Balancer) nextServer() (*namedHandler, error) { - b.mutex.Lock() - defer b.mutex.Unlock() + b.handlersMu.Lock() + defer b.handlersMu.Unlock() if len(b.handlers) == 0 { return nil, fmt.Errorf("no servers in the pool") @@ -185,22 +190,18 @@ func (b *Balancer) ServeHTTP(w http.ResponseWriter, req *http.Request) { } if err == nil && cookie != nil { - for _, handler := range b.handlers { - if handler.name != cookie.Value { - continue - } + b.handlersMu.RLock() + handler, ok := b.handlerMap[cookie.Value] + b.handlersMu.RUnlock() - b.mutex.RLock() - _, ok := b.status[handler.name] - b.mutex.RUnlock() - if !ok { - // because we already are in the only iteration that matches the cookie, so none - // of the following iterations are going to be a match for the cookie anyway. - break + if ok && handler != nil { + b.handlersMu.RLock() + _, isHealthy := b.status[handler.name] + b.handlersMu.RUnlock() + if isHealthy { + handler.ServeHTTP(w, req) + return } - - handler.ServeHTTP(w, req) - return } } } @@ -216,7 +217,7 @@ func (b *Balancer) ServeHTTP(w http.ResponseWriter, req *http.Request) { } if b.stickyCookie != nil { - cookie := &http.Cookie{Name: b.stickyCookie.name, Value: server.name, Path: "/", HttpOnly: b.stickyCookie.httpOnly, Secure: b.stickyCookie.secure} + cookie := &http.Cookie{Name: b.stickyCookie.name, Value: hash(server.name), Path: "/", HttpOnly: b.stickyCookie.httpOnly, Secure: b.stickyCookie.secure} http.SetCookie(w, cookie) } @@ -237,9 +238,19 @@ func (b *Balancer) AddService(name string, handler http.Handler, weight *int) { h := &namedHandler{Handler: handler, name: name, weight: float64(w)} - b.mutex.Lock() + b.handlersMu.Lock() h.deadline = b.curDeadline + 1/h.weight heap.Push(b, h) b.status[name] = struct{}{} - b.mutex.Unlock() + b.handlerMap[name] = h + b.handlerMap[hash(name)] = h + b.handlersMu.Unlock() +} + +func hash(input string) string { + hasher := fnv.New64() + // We purposely ignore the error because the implementation always returns nil. + _, _ = hasher.Write([]byte(input)) + + return fmt.Sprintf("%x", hasher.Sum64()) } diff --git a/pkg/server/service/loadbalancer/wrr/wrr_test.go b/pkg/server/service/loadbalancer/wrr/wrr_test.go index ac5f7e15b..7328fd98d 100644 --- a/pkg/server/service/loadbalancer/wrr/wrr_test.go +++ b/pkg/server/service/loadbalancer/wrr/wrr_test.go @@ -254,6 +254,8 @@ func TestSticky(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/", nil) for i := 0; i < 3; i++ { for _, cookie := range recorder.Result().Cookies() { + assert.NotContains(t, "test=first", cookie.Value) + assert.NotContains(t, "test=second", cookie.Value) req.AddCookie(cookie) } recorder.ResponseRecorder = httptest.NewRecorder() @@ -265,6 +267,35 @@ func TestSticky(t *testing.T) { assert.Equal(t, 3, recorder.save["second"]) } +func TestSticky_FallBack(t *testing.T) { + balancer := New(&dynamic.Sticky{ + Cookie: &dynamic.Cookie{Name: "test"}, + }, nil) + + balancer.AddService("first", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.Header().Set("server", "first") + rw.WriteHeader(http.StatusOK) + }), Int(1)) + + balancer.AddService("second", http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.Header().Set("server", "second") + rw.WriteHeader(http.StatusOK) + }), Int(2)) + + recorder := &responseRecorder{ResponseRecorder: httptest.NewRecorder(), save: map[string]int{}} + + req := httptest.NewRequest(http.MethodGet, "/", nil) + req.AddCookie(&http.Cookie{Name: "test", Value: "second"}) + for i := 0; i < 3; i++ { + recorder.ResponseRecorder = httptest.NewRecorder() + + balancer.ServeHTTP(recorder, req) + } + + assert.Equal(t, 0, recorder.save["first"]) + assert.Equal(t, 3, recorder.save["second"]) +} + // TestBalancerBias makes sure that the WRR algorithm spreads elements evenly right from the start, // and that it does not "over-favor" the high-weighted ones with a biased start-up regime. func TestBalancerBias(t *testing.T) { From 3dfaa3d5fa3d18d3db2a9e2b538237460bc409d9 Mon Sep 17 00:00:00 2001 From: Baptiste Mayelle Date: Tue, 2 Jan 2024 16:16:05 +0100 Subject: [PATCH 05/21] Add Redis Sentinel support Co-authored-by: Romain --- docs/content/providers/redis.md | 163 +++++++++++++++ .../reference/static-configuration/cli-ref.md | 21 ++ .../reference/static-configuration/env-ref.md | 21 ++ .../reference/static-configuration/file.toml | 8 + .../reference/static-configuration/file.yaml | 8 + go.mod | 5 +- go.sum | 12 +- integration/fixtures/redis/sentinel.toml | 19 ++ integration/redis_test.go | 196 +++++++++++++++++- .../compose/config/sentinel_template.conf | 5 + .../resources/compose/redis_sentinel.yml | 61 ++++++ pkg/provider/kv/redis/redis.go | 36 ++++ 12 files changed, 543 insertions(+), 12 deletions(-) create mode 100644 integration/fixtures/redis/sentinel.toml create mode 100644 integration/resources/compose/config/sentinel_template.conf create mode 100644 integration/resources/compose/redis_sentinel.yml diff --git a/docs/content/providers/redis.md b/docs/content/providers/redis.md index bd61e103c..309531423 100644 --- a/docs/content/providers/redis.md +++ b/docs/content/providers/redis.md @@ -229,3 +229,166 @@ providers: ```bash tab="CLI" --providers.redis.tls.insecureSkipVerify=true ``` + +### `sentinel` + +_Optional_ + +Defines the Sentinel configuration used to interact with Redis Sentinel. + +#### `masterName` + +_Required_ + +`masterName` is the name of the Sentinel master. + +```yaml tab="File (YAML)" +providers: + redis: + sentinel: + masterName: my-master +``` + +```toml tab="File (TOML)" +[providers.redis.sentinel] + masterName = "my-master" +``` + +```bash tab="CLI" +--providers.redis.sentinel.masterName=my-master +``` + +#### `username` + +_Optional_ + +`username` is the username for Sentinel authentication. + +```yaml tab="File (YAML)" +providers: + redis: + sentinel: + username: user +``` + +```toml tab="File (TOML)" +[providers.redis.sentinel] + username = "user" +``` + +```bash tab="CLI" +--providers.redis.sentinel.username=user +``` + +#### `password` + +_Optional_ + +`password` is the password for Sentinel authentication. + +```yaml tab="File (YAML)" +providers: + redis: + sentinel: + password: password +``` + +```toml tab="File (TOML)" +[providers.redis.sentinel] + password = "password" +``` + +```bash tab="CLI" +--providers.redis.sentinel.password=password +``` + +#### `latencyStrategy` + +_Optional, Default=false_ + +`latencyStrategy` defines whether to route commands to the closest master or replica nodes +(mutually exclusive with RandomStrategy and ReplicaStrategy). + +```yaml tab="File (YAML)" +providers: + redis: + sentinel: + latencyStrategy: true +``` + +```toml tab="File (TOML)" +[providers.redis.sentinel] +latencyStrategy = true +``` + +```bash tab="CLI" +--providers.redis.sentinel.latencyStrategy=true +``` + +#### `randomStrategy` + +_Optional, Default=false_ + +`randomStrategy` defines whether to route commands randomly to master or replica nodes +(mutually exclusive with LatencyStrategy and ReplicaStrategy). + +```yaml tab="File (YAML)" +providers: + redis: + sentinel: + randomStrategy: true +``` + +```toml tab="File (TOML)" +[providers.redis.sentinel] +randomStrategy = true +``` + +```bash tab="CLI" +--providers.redis.sentinel.randomStrategy=true +``` + +#### `replicaStrategy` + +_Optional, Default=false_ + +`replicaStrategy` Defines whether to route all commands to replica nodes +(mutually exclusive with LatencyStrategy and RandomStrategy). + +```yaml tab="File (YAML)" +providers: + redis: + sentinel: + replicaStrategy: true +``` + +```toml tab="File (TOML)" +[providers.redis.sentinel] +replicaStrategy = true +``` + +```bash tab="CLI" +--providers.redis.sentinel.replicaStrategy=true +``` + +#### `useDisconnectedReplicas` + +_Optional, Default=false_ + +`useDisconnectedReplicas` defines whether to use replicas disconnected with master when cannot get connected replicas. + +```yaml tab="File (YAML)" +providers: + redis: + sentinel: + useDisconnectedReplicas: true +``` + +```toml tab="File (TOML)" +[providers.redis.sentinel] +useDisconnectedReplicas = true +``` + +```bash tab="CLI" +--providers.redis.sentinel.useDisconnectedReplicas=true +``` diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index fbc3eb389..a0415e1b4 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -906,6 +906,27 @@ Password for authentication. `--providers.redis.rootkey`: Root key used for KV store. (Default: ```traefik```) +`--providers.redis.sentinel.latencystrategy`: +Defines whether to route commands to the closest master or replica nodes (mutually exclusive with RandomStrategy and ReplicaStrategy). (Default: ```false```) + +`--providers.redis.sentinel.mastername`: +Name of the master. + +`--providers.redis.sentinel.password`: +Password for Sentinel authentication. + +`--providers.redis.sentinel.randomstrategy`: +Defines whether to route commands randomly to master or replica nodes (mutually exclusive with LatencyStrategy and ReplicaStrategy). (Default: ```false```) + +`--providers.redis.sentinel.replicastrategy`: +Defines whether to route all commands to replica nodes (mutually exclusive with LatencyStrategy and RandomStrategy). (Default: ```false```) + +`--providers.redis.sentinel.usedisconnectedreplicas`: +Use replicas disconnected with master when cannot get connected replicas. (Default: ```false```) + +`--providers.redis.sentinel.username`: +Username for Sentinel authentication. + `--providers.redis.tls.ca`: TLS CA diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 9f59741ce..a7b3ace47 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -906,6 +906,27 @@ Password for authentication. `TRAEFIK_PROVIDERS_REDIS_ROOTKEY`: Root key used for KV store. (Default: ```traefik```) +`TRAEFIK_PROVIDERS_REDIS_SENTINEL_LATENCYSTRATEGY`: +Defines whether to route commands to the closest master or replica nodes (mutually exclusive with RandomStrategy and ReplicaStrategy). (Default: ```false```) + +`TRAEFIK_PROVIDERS_REDIS_SENTINEL_MASTERNAME`: +Name of the master. + +`TRAEFIK_PROVIDERS_REDIS_SENTINEL_PASSWORD`: +Password for Sentinel authentication. + +`TRAEFIK_PROVIDERS_REDIS_SENTINEL_RANDOMSTRATEGY`: +Defines whether to route commands randomly to master or replica nodes (mutually exclusive with LatencyStrategy and ReplicaStrategy). (Default: ```false```) + +`TRAEFIK_PROVIDERS_REDIS_SENTINEL_REPLICASTRATEGY`: +Defines whether to route all commands to replica nodes (mutually exclusive with LatencyStrategy and RandomStrategy). (Default: ```false```) + +`TRAEFIK_PROVIDERS_REDIS_SENTINEL_USEDISCONNECTEDREPLICAS`: +Use replicas disconnected with master when cannot get connected replicas. (Default: ```false```) + +`TRAEFIK_PROVIDERS_REDIS_SENTINEL_USERNAME`: +Username for Sentinel authentication. + `TRAEFIK_PROVIDERS_REDIS_TLS_CA`: TLS CA diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index c33fbf309..42dda1fbf 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -247,6 +247,14 @@ cert = "foobar" key = "foobar" insecureSkipVerify = true + [providers.redis.sentinel] + masterName = "foobar" + username = "foobar" + password = "foobar" + latencyStrategy = true + randomStrategy = true + replicaStrategy = true + useDisconnectedReplicas = true [providers.http] endpoint = "foobar" pollInterval = "42s" diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index 67cf11398..1497f57e5 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -275,6 +275,14 @@ providers: cert: foobar key: foobar insecureSkipVerify: true + sentinel: + masterName: foobar + username: foobar + password: foobar + latencyStrategy: true + randomStrategy: true + replicaStrategy: true + useDisconnectedReplicas: true http: endpoint: foobar pollInterval: 42s diff --git a/go.mod b/go.mod index 22eb59b22..62ac8306b 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( github.com/klauspost/compress v1.17.1 github.com/kvtools/consul v1.0.2 github.com/kvtools/etcdv3 v1.0.2 - github.com/kvtools/redis v1.0.2 + github.com/kvtools/redis v1.1.0 github.com/kvtools/valkeyrie v1.0.0 github.com/kvtools/zookeeper v1.0.2 github.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f @@ -189,7 +189,6 @@ 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-redis/redis/v8 v8.11.5 // indirect github.com/go-resty/resty/v2 v2.7.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/go-zookeeper/zk v1.0.3 // indirect @@ -278,6 +277,7 @@ require ( github.com/nrdcg/nodion v0.1.0 // indirect github.com/nrdcg/porkbun v0.2.0 // indirect github.com/nzdjb/go-metaname v1.0.0 // indirect + github.com/onsi/ginkgo v1.16.5 // indirect github.com/onsi/ginkgo/v2 v2.9.5 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect @@ -294,6 +294,7 @@ require ( github.com/prometheus/procfs v0.8.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-20 v0.3.4 // indirect + github.com/redis/go-redis/v9 v9.2.1 // indirect github.com/sacloud/api-client-go v0.2.8 // indirect github.com/sacloud/go-http v0.1.6 // indirect github.com/sacloud/iaas-api-go v1.11.1 // indirect diff --git a/go.sum b/go.sum index b4a954782..ea218e429 100644 --- a/go.sum +++ b/go.sum @@ -287,6 +287,10 @@ github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8 github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/buger/goterm v1.0.0 h1:ZB6uUlY8+sjJyFGzz2WpRqX2XYPeXVgtZAOJMwOsTWM= github.com/buger/goterm v1.0.0/go.mod h1:16STi3LquiscTIHA8SXUNKEa/Cnu4ZHBH8NsCaWgso0= github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= @@ -741,8 +745,6 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= -github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= -github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= @@ -1169,8 +1171,8 @@ github.com/kvtools/consul v1.0.2 h1:ltPgs4Ld09Xaa7zrOJ/TewBYKAsr11/LRFpErdkb8AA= github.com/kvtools/consul v1.0.2/go.mod h1:bFnzfGJ5ZIRRXCBGBmwhJlLdEWOlrjOcS1WjyAQzaJA= github.com/kvtools/etcdv3 v1.0.2 h1:EB0mAtzqe1folE7m7Q6wnCXcGwaOmrYmsVmF3hNsTKI= github.com/kvtools/etcdv3 v1.0.2/go.mod h1:Xr6DbwqjuCEcXAIWmXxw0DX+N5BhuvablXgN90XeqMM= -github.com/kvtools/redis v1.0.2 h1:D3GjGGtssJF2w8mniWtIxcT/YX9YnRc4jNCm0hrVygQ= -github.com/kvtools/redis v1.0.2/go.mod h1:wuUNwwKOHi2TYxDxj1sGF74Jdg0jywydnatXtnOR3hA= +github.com/kvtools/redis v1.1.0 h1:nXRAyh2nsaWiJyrX449/qHMc3SvGUqRqRXcrA/MplEo= +github.com/kvtools/redis v1.1.0/go.mod h1:cqg3esJOIYMQ1qy5LVIbPZz9kuiBBcFREP2N5b9+Dn0= github.com/kvtools/valkeyrie v1.0.0 h1:LAITop2wPoYCMitR24GZZsW0b57hmI+ePD18VRTtOf0= github.com/kvtools/valkeyrie v1.0.0/go.mod h1:bDi/OdhJCSbGPMsCgUQl881yuEweKCSItAtTBI+ZjpU= github.com/kvtools/zookeeper v1.0.2 h1:uK0CzQa+mtKGxDDH+DeqXo2HC1Kx4hWXZ7pX/zS4aTo= @@ -1586,6 +1588,8 @@ github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac/go.mod github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= +github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052 h1:Qp27Idfgi6ACvFQat5+VJvlYToylpM/hcyLBI3WaKPA= github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052/go.mod h1:uvX/8buq8uVeiZiFht+0lqSLBHF+uGV8BrTv8W/SIwk= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= diff --git a/integration/fixtures/redis/sentinel.toml b/integration/fixtures/redis/sentinel.toml new file mode 100644 index 000000000..3d5a59ec4 --- /dev/null +++ b/integration/fixtures/redis/sentinel.toml @@ -0,0 +1,19 @@ +[global] + checkNewVersion = false + sendAnonymousUsage = false + +[log] + level = "DEBUG" + +[entryPoints.web] + address = ":8000" + +[api] + insecure = true + +[providers.redis] + rootKey = "traefik" + endpoints = ["{{ .RedisAddress }}"] + +[providers.redis.sentinel] + masterName = "mymaster" diff --git a/integration/redis_test.go b/integration/redis_test.go index b642691c4..6407a3a35 100644 --- a/integration/redis_test.go +++ b/integration/redis_test.go @@ -4,12 +4,18 @@ import ( "bytes" "context" "encoding/json" + "errors" + "fmt" + "io/fs" "net" "net/http" "os" "path/filepath" + "strings" + "text/template" "time" + "github.com/fatih/structs" "github.com/go-check/check" "github.com/kvtools/redis" "github.com/kvtools/valkeyrie" @@ -23,24 +29,36 @@ import ( // Redis test suites. type RedisSuite struct { BaseSuite - kvClient store.Store - redisAddr string + kvClient store.Store + redisEndpoints []string +} + +func (s *RedisSuite) TearDownSuite(c *check.C) { + s.composeDown(c) + + for _, filename := range []string{"sentinel1.conf", "sentinel2.conf", "sentinel3.conf"} { + err := os.Remove(filepath.Join(".", "resources", "compose", "config", filename)) + if err != nil && !errors.Is(err, fs.ErrNotExist) { + c.Fatal("unable to clean configuration file for sentinel: ", err) + } + } } func (s *RedisSuite) setupStore(c *check.C) { s.createComposeProject(c, "redis") s.composeUp(c) - s.redisAddr = net.JoinHostPort(s.getComposeServiceIP(c, "redis"), "6379") + s.redisEndpoints = []string{} + s.redisEndpoints = append(s.redisEndpoints, net.JoinHostPort(s.getComposeServiceIP(c, "redis"), "6379")) kv, err := valkeyrie.NewStore( context.Background(), redis.StoreName, - []string{s.redisAddr}, + s.redisEndpoints, &redis.Config{}, ) if err != nil { - c.Fatal("Cannot create store redis") + c.Fatal("Cannot create store redis: ", err) } s.kvClient = kv @@ -52,7 +70,173 @@ func (s *RedisSuite) setupStore(c *check.C) { func (s *RedisSuite) TestSimpleConfiguration(c *check.C) { s.setupStore(c) - file := s.adaptFile(c, "fixtures/redis/simple.toml", struct{ RedisAddress string }{s.redisAddr}) + file := s.adaptFile(c, "fixtures/redis/simple.toml", struct{ RedisAddress string }{ + RedisAddress: strings.Join(s.redisEndpoints, ","), + }) + defer os.Remove(file) + + data := map[string]string{ + "traefik/http/routers/Router0/entryPoints/0": "web", + "traefik/http/routers/Router0/middlewares/0": "compressor", + "traefik/http/routers/Router0/middlewares/1": "striper", + "traefik/http/routers/Router0/service": "simplesvc", + "traefik/http/routers/Router0/rule": "Host(`kv1.localhost`)", + "traefik/http/routers/Router0/priority": "42", + "traefik/http/routers/Router0/tls": "true", + + "traefik/http/routers/Router1/rule": "Host(`kv2.localhost`)", + "traefik/http/routers/Router1/priority": "42", + "traefik/http/routers/Router1/tls/domains/0/main": "aaa.localhost", + "traefik/http/routers/Router1/tls/domains/0/sans/0": "aaa.aaa.localhost", + "traefik/http/routers/Router1/tls/domains/0/sans/1": "bbb.aaa.localhost", + "traefik/http/routers/Router1/tls/domains/1/main": "bbb.localhost", + "traefik/http/routers/Router1/tls/domains/1/sans/0": "aaa.bbb.localhost", + "traefik/http/routers/Router1/tls/domains/1/sans/1": "bbb.bbb.localhost", + "traefik/http/routers/Router1/entryPoints/0": "web", + "traefik/http/routers/Router1/service": "simplesvc", + + "traefik/http/services/simplesvc/loadBalancer/servers/0/url": "http://10.0.1.1:8888", + "traefik/http/services/simplesvc/loadBalancer/servers/1/url": "http://10.0.1.1:8889", + + "traefik/http/services/srvcA/loadBalancer/servers/0/url": "http://10.0.1.2:8888", + "traefik/http/services/srvcA/loadBalancer/servers/1/url": "http://10.0.1.2:8889", + + "traefik/http/services/srvcB/loadBalancer/servers/0/url": "http://10.0.1.3:8888", + "traefik/http/services/srvcB/loadBalancer/servers/1/url": "http://10.0.1.3:8889", + + "traefik/http/services/mirror/mirroring/service": "simplesvc", + "traefik/http/services/mirror/mirroring/mirrors/0/name": "srvcA", + "traefik/http/services/mirror/mirroring/mirrors/0/percent": "42", + "traefik/http/services/mirror/mirroring/mirrors/1/name": "srvcB", + "traefik/http/services/mirror/mirroring/mirrors/1/percent": "42", + + "traefik/http/services/Service03/weighted/services/0/name": "srvcA", + "traefik/http/services/Service03/weighted/services/0/weight": "42", + "traefik/http/services/Service03/weighted/services/1/name": "srvcB", + "traefik/http/services/Service03/weighted/services/1/weight": "42", + + "traefik/http/middlewares/compressor/compress": "true", + "traefik/http/middlewares/striper/stripPrefix/prefixes/0": "foo", + "traefik/http/middlewares/striper/stripPrefix/prefixes/1": "bar", + "traefik/http/middlewares/striper/stripPrefix/forceSlash": "true", + } + + for k, v := range data { + err := s.kvClient.Put(context.Background(), k, []byte(v), nil) + c.Assert(err, checker.IsNil) + } + + cmd, display := s.traefikCmd(withConfigFile(file)) + defer display(c) + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer s.killCmd(cmd) + + // wait for traefik + err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second, + try.BodyContains(`"striper@redis":`, `"compressor@redis":`, `"srvcA@redis":`, `"srvcB@redis":`), + ) + c.Assert(err, checker.IsNil) + + resp, err := http.Get("http://127.0.0.1:8080/api/rawdata") + c.Assert(err, checker.IsNil) + + var obtained api.RunTimeRepresentation + err = json.NewDecoder(resp.Body).Decode(&obtained) + c.Assert(err, checker.IsNil) + got, err := json.MarshalIndent(obtained, "", " ") + c.Assert(err, checker.IsNil) + + expectedJSON := filepath.FromSlash("testdata/rawdata-redis.json") + + if *updateExpected { + err = os.WriteFile(expectedJSON, got, 0o666) + c.Assert(err, checker.IsNil) + } + + expected, err := os.ReadFile(expectedJSON) + c.Assert(err, checker.IsNil) + + if !bytes.Equal(expected, got) { + diff := difflib.UnifiedDiff{ + FromFile: "Expected", + A: difflib.SplitLines(string(expected)), + ToFile: "Got", + B: difflib.SplitLines(string(got)), + Context: 3, + } + + text, err := difflib.GetUnifiedDiffString(diff) + c.Assert(err, checker.IsNil) + c.Error(text) + } +} + +func (s *RedisSuite) setupSentinelStore(c *check.C) { + s.setupSentinelConfiguration(c, []string{"26379", "36379", "46379"}) + + s.createComposeProject(c, "redis_sentinel") + s.composeUp(c) + + s.redisEndpoints = []string{ + net.JoinHostPort(s.getComposeServiceIP(c, "sentinel1"), "26379"), + net.JoinHostPort(s.getComposeServiceIP(c, "sentinel2"), "36379"), + net.JoinHostPort(s.getComposeServiceIP(c, "sentinel3"), "46379"), + } + + kv, err := valkeyrie.NewStore( + context.Background(), + redis.StoreName, + s.redisEndpoints, + &redis.Config{ + Sentinel: &redis.Sentinel{ + MasterName: "mymaster", + }, + }, + ) + if err != nil { + c.Fatal("Cannot create store redis sentinel") + } + s.kvClient = kv + + // wait for redis + err = try.Do(60*time.Second, try.KVExists(kv, "test")) + c.Assert(err, checker.IsNil) +} + +func (s *RedisSuite) setupSentinelConfiguration(c *check.C, ports []string) { + for i, port := range ports { + templateValue := struct{ SentinelPort string }{SentinelPort: port} + + // Load file + templateFile := "resources/compose/config/sentinel_template.conf" + tmpl, err := template.ParseFiles(templateFile) + c.Assert(err, checker.IsNil) + + folder, prefix := filepath.Split(templateFile) + + fileName := fmt.Sprintf("%s/sentinel%d.conf", folder, i+1) + tmpFile, err := os.Create(fileName) + c.Assert(err, checker.IsNil) + defer tmpFile.Close() + + model := structs.Map(templateValue) + model["SelfFilename"] = tmpFile.Name() + + err = tmpl.ExecuteTemplate(tmpFile, prefix, model) + c.Assert(err, checker.IsNil) + + err = tmpFile.Sync() + c.Assert(err, checker.IsNil) + } +} + +func (s *RedisSuite) TestSentinelConfiguration(c *check.C) { + s.setupSentinelStore(c) + + file := s.adaptFile(c, "fixtures/redis/sentinel.toml", struct{ RedisAddress string }{ + RedisAddress: strings.Join(s.redisEndpoints, `","`), + }) defer os.Remove(file) data := map[string]string{ diff --git a/integration/resources/compose/config/sentinel_template.conf b/integration/resources/compose/config/sentinel_template.conf new file mode 100644 index 000000000..c9f5acf6d --- /dev/null +++ b/integration/resources/compose/config/sentinel_template.conf @@ -0,0 +1,5 @@ +port {{ .SentinelPort }} +dir "/tmp" +sentinel resolve-hostnames yes +sentinel monitor mymaster master 6380 2 +sentinel deny-scripts-reconfig yes diff --git a/integration/resources/compose/redis_sentinel.yml b/integration/resources/compose/redis_sentinel.yml new file mode 100644 index 000000000..261e694e5 --- /dev/null +++ b/integration/resources/compose/redis_sentinel.yml @@ -0,0 +1,61 @@ +version: "3.8" +services: + master: + image: redis + container_name: redis-master + command: redis-server --port 6380 + ports: + - 6380:6380 + healthcheck: + test: redis-cli -p 6380 ping + node1: + image: redis + container_name: redis-node-1 + ports: + - 6381:6381 + command: redis-server --port 6381 --slaveof redis-master 6380 + healthcheck: + test: redis-cli -p 6381 ping + node2: + image: redis + container_name: redis-node-2 + ports: + - 6382:6382 + command: redis-server --port 6382 --slaveof redis-master 6380 + healthcheck: + test: redis-cli -p 6382 ping + sentinel1: + image: redis + container_name: redis-sentinel-1 + ports: + - 26379:26379 + command: redis-sentinel /usr/local/etc/redis/conf/sentinel1.conf + healthcheck: + test: redis-cli -p 26379 ping + volumes: + - ./resources/compose/config:/usr/local/etc/redis/conf + sentinel2: + image: redis + container_name: redis-sentinel-2 + ports: + - 36379:26379 + command: redis-sentinel /usr/local/etc/redis/conf/sentinel2.conf + healthcheck: + test: redis-cli -p 36379 ping + volumes: + - ./resources/compose/config:/usr/local/etc/redis/conf + sentinel3: + image: redis + container_name: redis-sentinel-3 + ports: + - 46379:26379 + command: redis-sentinel /usr/local/etc/redis/conf/sentinel3.conf + healthcheck: + test: redis-cli -p 46379 ping + volumes: + - ./resources/compose/config:/usr/local/etc/redis/conf + +networks: + default: + name: traefik-test-network + external: true diff --git a/pkg/provider/kv/redis/redis.go b/pkg/provider/kv/redis/redis.go index 23f432bb1..3005c8f2d 100644 --- a/pkg/provider/kv/redis/redis.go +++ b/pkg/provider/kv/redis/redis.go @@ -2,6 +2,7 @@ package redis import ( "context" + "errors" "fmt" "github.com/kvtools/redis" @@ -20,6 +21,20 @@ type Provider struct { Username string `description:"Username for authentication." json:"username,omitempty" toml:"username,omitempty" yaml:"username,omitempty" loggable:"false"` Password string `description:"Password for authentication." json:"password,omitempty" toml:"password,omitempty" yaml:"password,omitempty" loggable:"false"` DB int `description:"Database to be selected after connecting to the server." json:"db,omitempty" toml:"db,omitempty" yaml:"db,omitempty"` + Sentinel *Sentinel `description:"Enable Sentinel support." json:"sentinel,omitempty" toml:"sentinel,omitempty" yaml:"sentinel,omitempty"` +} + +// Sentinel holds the Redis Sentinel configuration. +type Sentinel struct { + MasterName string `description:"Name of the master." json:"masterName,omitempty" toml:"masterName,omitempty" yaml:"masterName,omitempty" export:"true"` + Username string `description:"Username for Sentinel authentication." json:"username,omitempty" toml:"username,omitempty" yaml:"username,omitempty" export:"true"` + Password string `description:"Password for Sentinel authentication." json:"password,omitempty" toml:"password,omitempty" yaml:"password,omitempty" export:"true"` + + LatencyStrategy bool `description:"Defines whether to route commands to the closest master or replica nodes (mutually exclusive with RandomStrategy and ReplicaStrategy)." json:"latencyStrategy,omitempty" toml:"latencyStrategy,omitempty" yaml:"latencyStrategy,omitempty" export:"true"` + RandomStrategy bool `description:"Defines whether to route commands randomly to master or replica nodes (mutually exclusive with LatencyStrategy and ReplicaStrategy)." json:"randomStrategy,omitempty" toml:"randomStrategy,omitempty" yaml:"randomStrategy,omitempty" export:"true"` + ReplicaStrategy bool `description:"Defines whether to route all commands to replica nodes (mutually exclusive with LatencyStrategy and RandomStrategy)." json:"replicaStrategy,omitempty" toml:"replicaStrategy,omitempty" yaml:"replicaStrategy,omitempty" export:"true"` + + UseDisconnectedReplicas bool `description:"Use replicas disconnected with master when cannot get connected replicas." json:"useDisconnectedReplicas,omitempty" toml:"useDisconnectedReplicas,omitempty" yaml:"useDisconnectedReplicas,omitempty" export:"true"` } // SetDefaults sets the default values. @@ -44,5 +59,26 @@ func (p *Provider) Init() error { } } + if p.Sentinel != nil { + switch { + case p.Sentinel.LatencyStrategy && !(p.Sentinel.RandomStrategy || p.Sentinel.ReplicaStrategy): + case p.Sentinel.RandomStrategy && !(p.Sentinel.LatencyStrategy || p.Sentinel.ReplicaStrategy): + case p.Sentinel.ReplicaStrategy && !(p.Sentinel.RandomStrategy || p.Sentinel.LatencyStrategy): + return errors.New("latencyStrategy, randomStrategy and replicaStrategy options are mutually exclusive, please use only one of those options") + } + + clusterClient := p.Sentinel.LatencyStrategy || p.Sentinel.RandomStrategy + config.Sentinel = &redis.Sentinel{ + MasterName: p.Sentinel.MasterName, + Username: p.Sentinel.Username, + Password: p.Sentinel.Password, + ClusterClient: clusterClient, + RouteByLatency: p.Sentinel.LatencyStrategy, + RouteRandomly: p.Sentinel.RandomStrategy, + ReplicaOnly: p.Sentinel.ReplicaStrategy, + UseDisconnectedReplicas: p.Sentinel.UseDisconnectedReplicas, + } + } + return p.Provider.Init(redis.StoreName, "redis", config) } From 9662cdca648fd2c7e7002e18cc73a29769d3901f Mon Sep 17 00:00:00 2001 From: Julien Salleyron Date: Tue, 2 Jan 2024 16:40:06 +0100 Subject: [PATCH 06/21] Add KeepAliveMaxTime and KeepAliveMaxRequests features to entrypoints --- .../reference/static-configuration/cli-ref.md | 6 ++ .../reference/static-configuration/env-ref.md | 6 ++ .../reference/static-configuration/file.toml | 2 + .../reference/static-configuration/file.yaml | 2 + docs/content/routing/entrypoints.md | 70 +++++++++++++-- pkg/config/static/entrypoints.go | 6 +- pkg/server/keep_alive_middleware.go | 29 ++++++ pkg/server/server_entrypoint_tcp.go | 56 ++++++++++++ pkg/server/server_entrypoint_tcp_test.go | 88 +++++++++++++++++++ 9 files changed, 258 insertions(+), 7 deletions(-) create mode 100644 pkg/server/keep_alive_middleware.go diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index a0415e1b4..03409a1c3 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -171,6 +171,12 @@ Trust all. (Default: ```false```) `--entrypoints..proxyprotocol.trustedips`: Trust only selected IPs. +`--entrypoints..transport.keepalivemaxrequests`: +Maximum number of requests before closing a keep-alive connection. (Default: ```0```) + +`--entrypoints..transport.keepalivemaxtime`: +Maximum duration before closing a keep-alive connection. (Default: ```0```) + `--entrypoints..transport.lifecycle.gracetimeout`: Duration to give active requests a chance to finish before Traefik stops. (Default: ```10```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index a7b3ace47..d3de13a66 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -171,6 +171,12 @@ Trust all. (Default: ```false```) `TRAEFIK_ENTRYPOINTS__PROXYPROTOCOL_TRUSTEDIPS`: Trust only selected IPs. +`TRAEFIK_ENTRYPOINTS__TRANSPORT_KEEPALIVEMAXREQUESTS`: +Maximum number of requests before closing a keep-alive connection. (Default: ```0```) + +`TRAEFIK_ENTRYPOINTS__TRANSPORT_KEEPALIVEMAXTIME`: +Maximum duration before closing a keep-alive connection. (Default: ```0```) + `TRAEFIK_ENTRYPOINTS__TRANSPORT_LIFECYCLE_GRACETIMEOUT`: Duration to give active requests a chance to finish before Traefik stops. (Default: ```10```) diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index 42dda1fbf..dc38a2cea 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -15,6 +15,8 @@ [entryPoints.EntryPoint0] address = "foobar" [entryPoints.EntryPoint0.transport] + keepAliveMaxRequests = 42 + keepAliveMaxTime = "42s" [entryPoints.EntryPoint0.transport.lifeCycle] requestAcceptGraceTimeout = "42s" graceTimeOut = "42s" diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index 1497f57e5..6a0cb264b 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -15,6 +15,8 @@ entryPoints: EntryPoint0: address: foobar transport: + keepAliveMaxRequests: 42 + keepAliveMaxTime: 42s lifeCycle: requestAcceptGraceTimeout: 42s graceTimeOut: 42s diff --git a/docs/content/routing/entrypoints.md b/docs/content/routing/entrypoints.md index 305e69cd1..c77c8e406 100644 --- a/docs/content/routing/entrypoints.md +++ b/docs/content/routing/entrypoints.md @@ -589,17 +589,77 @@ Controls the behavior of Traefik during the shutdown phase. --entryPoints.name.transport.lifeCycle.graceTimeOut=42 ``` +#### `keepAliveMaxRequests` + +_Optional, Default=0_ + +The maximum number of requests Traefik can handle before sending a `Connection: Close` header to the client (for HTTP2, Traefik sends a GOAWAY). Zero means no limit. + + ```yaml tab="File (YAML)" + ## Static configuration + entryPoints: + name: + address: ":8888" + transport: + keepAliveMaxRequests: 42 + ``` + + ```toml tab="File (TOML)" + ## Static configuration + [entryPoints] + [entryPoints.name] + address = ":8888" + [entryPoints.name.transport] + keepAliveMaxRequests = 42 + ``` + + ```bash tab="CLI" + ## Static configuration + --entryPoints.name.address=:8888 + --entryPoints.name.transport.keepAliveRequests=42 + ``` + +#### `keepAliveMaxTime` + +_Optional, Default=0s_ + +The maximum duration Traefik can handle requests before sending a `Connection: Close` header to the client (for HTTP2, Traefik sends a GOAWAY). Zero means no limit. + + ```yaml tab="File (YAML)" + ## Static configuration + entryPoints: + name: + address: ":8888" + transport: + keepAliveMaxTime: 42s + ``` + + ```toml tab="File (TOML)" + ## Static configuration + [entryPoints] + [entryPoints.name] + address = ":8888" + [entryPoints.name.transport] + keepAliveMaxTime = 42s + ``` + + ```bash tab="CLI" + ## Static configuration + --entryPoints.name.address=:8888 + --entryPoints.name.transport.keepAliveTime=42s + ``` + ### ProxyProtocol -Traefik supports [ProxyProtocol](https://www.haproxy.org/download/2.0/doc/proxy-protocol.txt) version 1 and 2. +Traefik supports [PROXY protocol](https://www.haproxy.org/download/2.0/doc/proxy-protocol.txt) version 1 and 2. -If Proxy Protocol header parsing is enabled for the entry point, this entry point can accept connections with or without Proxy Protocol headers. +If PROXY protocol header parsing is enabled for the entry point, this entry point can accept connections with or without PROXY protocol headers. -If the Proxy Protocol header is passed, then the version is determined automatically. +If the PROXY protocol header is passed, then the version is determined automatically. ??? info "`proxyProtocol.trustedIPs`" - Enabling Proxy Protocol with Trusted IPs. + Enabling PROXY protocol with Trusted IPs. ```yaml tab="File (YAML)" ## Static configuration @@ -662,7 +722,7 @@ If the Proxy Protocol header is passed, then the version is determined automatic !!! warning "Queuing Traefik behind Another Load Balancer" - When queuing Traefik behind another load-balancer, make sure to configure Proxy Protocol on both sides. + When queuing Traefik behind another load-balancer, make sure to configure PROXY protocol on both sides. Not doing so could introduce a security risk in your system (enabling request forgery). ## HTTP Options diff --git a/pkg/config/static/entrypoints.go b/pkg/config/static/entrypoints.go index 68ac9285e..b2243aa3f 100644 --- a/pkg/config/static/entrypoints.go +++ b/pkg/config/static/entrypoints.go @@ -122,8 +122,10 @@ type EntryPoints map[string]*EntryPoint // EntryPointsTransport configures communication between clients and Traefik. type EntryPointsTransport struct { - LifeCycle *LifeCycle `description:"Timeouts influencing the server life cycle." json:"lifeCycle,omitempty" toml:"lifeCycle,omitempty" yaml:"lifeCycle,omitempty" export:"true"` - RespondingTimeouts *RespondingTimeouts `description:"Timeouts for incoming requests to the Traefik instance." json:"respondingTimeouts,omitempty" toml:"respondingTimeouts,omitempty" yaml:"respondingTimeouts,omitempty" export:"true"` + LifeCycle *LifeCycle `description:"Timeouts influencing the server life cycle." json:"lifeCycle,omitempty" toml:"lifeCycle,omitempty" yaml:"lifeCycle,omitempty" export:"true"` + RespondingTimeouts *RespondingTimeouts `description:"Timeouts for incoming requests to the Traefik instance." json:"respondingTimeouts,omitempty" toml:"respondingTimeouts,omitempty" yaml:"respondingTimeouts,omitempty" export:"true"` + KeepAliveMaxTime ptypes.Duration `description:"Maximum duration before closing a keep-alive connection." json:"keepAliveMaxTime,omitempty" toml:"keepAliveMaxTime,omitempty" yaml:"keepAliveMaxTime,omitempty" export:"true"` + KeepAliveMaxRequests int `description:"Maximum number of requests before closing a keep-alive connection." json:"keepAliveMaxRequests,omitempty" toml:"keepAliveMaxRequests,omitempty" yaml:"keepAliveMaxRequests,omitempty" export:"true"` } // SetDefaults sets the default values. diff --git a/pkg/server/keep_alive_middleware.go b/pkg/server/keep_alive_middleware.go new file mode 100644 index 000000000..73b2159b1 --- /dev/null +++ b/pkg/server/keep_alive_middleware.go @@ -0,0 +1,29 @@ +package server + +import ( + "net/http" + "time" + + ptypes "github.com/traefik/paerser/types" + "github.com/traefik/traefik/v2/pkg/log" +) + +func newKeepAliveMiddleware(next http.Handler, maxRequests int, maxTime ptypes.Duration) http.Handler { + return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + state, ok := req.Context().Value(connStateKey).(*connState) + if ok { + state.HTTPRequestCount++ + if maxRequests > 0 && state.HTTPRequestCount >= maxRequests { + log.WithoutContext().Debug("Close because of too many requests") + state.KeepAliveState = "Close because of too many requests" + rw.Header().Set("Connection", "close") + } + if maxTime > 0 && time.Now().After(state.Start.Add(time.Duration(maxTime))) { + log.WithoutContext().Debug("Close because of too long connection") + state.KeepAliveState = "Close because of too long connection" + rw.Header().Set("Connection", "close") + } + } + next.ServeHTTP(rw, req) + }) +} diff --git a/pkg/server/server_entrypoint_tcp.go b/pkg/server/server_entrypoint_tcp.go index b33c955ee..e3e22998e 100644 --- a/pkg/server/server_entrypoint_tcp.go +++ b/pkg/server/server_entrypoint_tcp.go @@ -3,6 +3,7 @@ package server import ( "context" "errors" + "expvar" "fmt" stdlog "log" "net" @@ -34,6 +35,25 @@ import ( var httpServerLogger = stdlog.New(log.WithoutContext().WriterLevel(logrus.DebugLevel), "", 0) +type key string + +const ( + connStateKey key = "connState" + debugConnectionEnv string = "DEBUG_CONNECTION" +) + +var ( + clientConnectionStates = map[string]*connState{} + clientConnectionStatesMu = sync.RWMutex{} +) + +type connState struct { + State string + KeepAliveState string + Start time.Time + HTTPRequestCount int +} + type httpForwarder struct { net.Listener connChan chan net.Conn @@ -68,6 +88,12 @@ type TCPEntryPoints map[string]*TCPEntryPoint // NewTCPEntryPoints creates a new TCPEntryPoints. func NewTCPEntryPoints(entryPointsConfig static.EntryPoints, hostResolverConfig *types.HostResolverConfig) (TCPEntryPoints, error) { + if os.Getenv(debugConnectionEnv) != "" { + expvar.Publish("clientConnectionStates", expvar.Func(func() any { + return clientConnectionStates + })) + } + serverEntryPointsTCP := make(TCPEntryPoints) for entryPointName, config := range entryPointsConfig { protocol, err := config.GetProtocol() @@ -548,6 +574,11 @@ func createHTTPServer(ctx context.Context, ln net.Listener, configuration *stati }) } + debugConnection := os.Getenv(debugConnectionEnv) != "" + if debugConnection || (configuration.Transport != nil && (configuration.Transport.KeepAliveMaxTime > 0 || configuration.Transport.KeepAliveMaxRequests > 0)) { + handler = newKeepAliveMiddleware(handler, configuration.Transport.KeepAliveMaxRequests, configuration.Transport.KeepAliveMaxTime) + } + serverHTTP := &http.Server{ Handler: handler, ErrorLog: httpServerLogger, @@ -555,6 +586,27 @@ func createHTTPServer(ctx context.Context, ln net.Listener, configuration *stati WriteTimeout: time.Duration(configuration.Transport.RespondingTimeouts.WriteTimeout), IdleTimeout: time.Duration(configuration.Transport.RespondingTimeouts.IdleTimeout), } + if debugConnection || (configuration.Transport != nil && (configuration.Transport.KeepAliveMaxTime > 0 || configuration.Transport.KeepAliveMaxRequests > 0)) { + serverHTTP.ConnContext = func(ctx context.Context, c net.Conn) context.Context { + cState := &connState{Start: time.Now()} + if debugConnection { + clientConnectionStatesMu.Lock() + clientConnectionStates[getConnKey(c)] = cState + clientConnectionStatesMu.Unlock() + } + return context.WithValue(ctx, connStateKey, cState) + } + + if debugConnection { + serverHTTP.ConnState = func(c net.Conn, state http.ConnState) { + clientConnectionStatesMu.Lock() + if clientConnectionStates[getConnKey(c)] != nil { + clientConnectionStates[getConnKey(c)].State = state.String() + } + clientConnectionStatesMu.Unlock() + } + } + } // ConfigureServer configures HTTP/2 with the MaxConcurrentStreams option for the given server. // Also keeping behavior the same as @@ -584,6 +636,10 @@ func createHTTPServer(ctx context.Context, ln net.Listener, configuration *stati }, nil } +func getConnKey(conn net.Conn) string { + return fmt.Sprintf("%s => %s", conn.RemoteAddr(), conn.LocalAddr()) +} + func newTrackedConnection(conn tcp.WriteCloser, tracker *connectionTracker) *trackedConnection { tracker.AddConnection(conn) return &trackedConnection{ diff --git a/pkg/server/server_entrypoint_tcp_test.go b/pkg/server/server_entrypoint_tcp_test.go index 342d7d9fa..9d66c44e0 100644 --- a/pkg/server/server_entrypoint_tcp_test.go +++ b/pkg/server/server_entrypoint_tcp_test.go @@ -230,3 +230,91 @@ func TestReadTimeoutWithFirstByte(t *testing.T) { t.Error("Timeout while read") } } + +func TestKeepAliveMaxRequests(t *testing.T) { + epConfig := &static.EntryPointsTransport{} + epConfig.SetDefaults() + epConfig.KeepAliveMaxRequests = 3 + + entryPoint, err := NewTCPEntryPoint(context.Background(), &static.EntryPoint{ + Address: ":0", + Transport: epConfig, + ForwardedHeaders: &static.ForwardedHeaders{}, + HTTP2: &static.HTTP2Config{}, + }, nil) + require.NoError(t, err) + + router := &tcprouter.Router{} + router.SetHTTPHandler(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.WriteHeader(http.StatusOK) + })) + + conn, err := startEntrypoint(entryPoint, router) + require.NoError(t, err) + + http.DefaultClient.Transport = &http.Transport{ + DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + return conn, nil + }, + } + + resp, err := http.Get("http://" + entryPoint.listener.Addr().String()) + require.NoError(t, err) + require.False(t, resp.Close) + err = resp.Body.Close() + require.NoError(t, err) + + resp, err = http.Get("http://" + entryPoint.listener.Addr().String()) + require.NoError(t, err) + require.False(t, resp.Close) + err = resp.Body.Close() + require.NoError(t, err) + + resp, err = http.Get("http://" + entryPoint.listener.Addr().String()) + require.NoError(t, err) + require.True(t, resp.Close) + err = resp.Body.Close() + require.NoError(t, err) +} + +func TestKeepAliveMaxTime(t *testing.T) { + epConfig := &static.EntryPointsTransport{} + epConfig.SetDefaults() + epConfig.KeepAliveMaxTime = ptypes.Duration(time.Millisecond) + + entryPoint, err := NewTCPEntryPoint(context.Background(), &static.EntryPoint{ + Address: ":0", + Transport: epConfig, + ForwardedHeaders: &static.ForwardedHeaders{}, + HTTP2: &static.HTTP2Config{}, + }, nil) + require.NoError(t, err) + + router := &tcprouter.Router{} + router.SetHTTPHandler(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.WriteHeader(http.StatusOK) + })) + + conn, err := startEntrypoint(entryPoint, router) + require.NoError(t, err) + + http.DefaultClient.Transport = &http.Transport{ + DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + return conn, nil + }, + } + + resp, err := http.Get("http://" + entryPoint.listener.Addr().String()) + require.NoError(t, err) + require.False(t, resp.Close) + err = resp.Body.Close() + require.NoError(t, err) + + time.Sleep(time.Millisecond) + + resp, err = http.Get("http://" + entryPoint.listener.Addr().String()) + require.NoError(t, err) + require.True(t, resp.Close) + err = resp.Body.Close() + require.NoError(t, err) +} From 0e92b0247415c00dccdd5634ac20ea61fa4af869 Mon Sep 17 00:00:00 2001 From: Landry Benguigui Date: Tue, 2 Jan 2024 17:04:06 +0100 Subject: [PATCH 07/21] Deprecate IPWhiteList middleware in favor of IPAllowList Co-authored-by: Kevin Pollet --- docs/content/middlewares/http/ipallowlist.md | 195 ++++++++++++++++++ docs/content/middlewares/http/ipwhitelist.md | 8 +- docs/content/middlewares/tcp/ipallowlist.md | 60 ++++++ docs/content/middlewares/tcp/ipwhitelist.md | 6 +- docs/content/migration/v2.md | 10 + .../dynamic-configuration/docker-labels.yml | 4 + .../reference/dynamic-configuration/file.toml | 6 + .../reference/dynamic-configuration/file.yaml | 15 ++ .../kubernetes-crd-definition-v1.yml | 114 ++++++++-- .../kubernetes-crd-resource.yml | 2 +- .../reference/dynamic-configuration/kv-ref.md | 5 + .../marathon-labels.json | 4 + .../traefik.containo.us_middlewares.yaml | 41 +++- .../traefik.containo.us_middlewaretcps.yaml | 16 +- .../traefik.io_middlewares.yaml | 41 +++- .../traefik.io_middlewaretcps.yaml | 16 +- docs/mkdocs.yml | 6 +- integration/fixtures/k8s/01-traefik-crd.yml | 114 ++++++++-- integration/fixtures/simple_allowlist.toml | 18 ++ integration/resources/compose/allowlist.yml | 41 ++++ integration/simple_test.go | 70 +++++++ pkg/config/dynamic/middlewares.go | 15 +- pkg/config/dynamic/tcp_middlewares.go | 10 +- pkg/config/dynamic/zz_generated.deepcopy.go | 57 +++++ pkg/middlewares/ipallowlist/ip_allowlist.go | 88 ++++++++ .../ipallowlist/ip_allowlist_test.go | 100 +++++++++ .../tcp/ipallowlist/ip_allowlist.go | 65 ++++++ .../tcp/ipallowlist/ip_allowlist_test.go | 139 +++++++++++++ pkg/provider/kubernetes/crd/kubernetes.go | 2 + .../traefikcontainous/v1alpha1/middleware.go | 1 + .../v1alpha1/middlewaretcp.go | 7 + .../v1alpha1/zz_generated.deepcopy.go | 10 + .../crd/traefikio/v1alpha1/middleware.go | 1 + .../crd/traefikio/v1alpha1/middlewaretcp.go | 7 + .../v1alpha1/zz_generated.deepcopy.go | 10 + pkg/server/middleware/middlewares.go | 14 ++ 36 files changed, 1268 insertions(+), 50 deletions(-) create mode 100644 docs/content/middlewares/http/ipallowlist.md create mode 100644 docs/content/middlewares/tcp/ipallowlist.md create mode 100644 integration/fixtures/simple_allowlist.toml create mode 100644 integration/resources/compose/allowlist.yml create mode 100644 pkg/middlewares/ipallowlist/ip_allowlist.go create mode 100644 pkg/middlewares/ipallowlist/ip_allowlist_test.go create mode 100644 pkg/middlewares/tcp/ipallowlist/ip_allowlist.go create mode 100644 pkg/middlewares/tcp/ipallowlist/ip_allowlist_test.go diff --git a/docs/content/middlewares/http/ipallowlist.md b/docs/content/middlewares/http/ipallowlist.md new file mode 100644 index 000000000..d62e253bb --- /dev/null +++ b/docs/content/middlewares/http/ipallowlist.md @@ -0,0 +1,195 @@ +--- +title: "Traefik HTTP Middlewares IPAllowList" +description: "Learn how to use IPAllowList in HTTP middleware for limiting clients to specific IPs in Traefik Proxy. Read the technical documentation." +--- + +# IPAllowList + +Limiting Clients to Specific IPs +{: .subtitle } + +IPAllowList accepts / refuses requests based on the client IP. + +## Configuration Examples + +```yaml tab="Docker & Swarm" +# Accepts request from defined IP +labels: + - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: test-ipallowlist +spec: + ipAllowList: + sourceRange: + - 127.0.0.1/32 + - 192.168.1.7 +``` + +```yaml tab="Consul Catalog" +# Accepts request from defined IP +- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" +``` + +```yaml tab="File (YAML)" +# Accepts request from defined IP +http: + middlewares: + test-ipallowlist: + ipAllowList: + sourceRange: + - "127.0.0.1/32" + - "192.168.1.7" +``` + +```toml tab="File (TOML)" +# Accepts request from defined IP +[http.middlewares] + [http.middlewares.test-ipallowlist.ipAllowList] + sourceRange = ["127.0.0.1/32", "192.168.1.7"] +``` + +## Configuration Options + +### `sourceRange` + +The `sourceRange` option sets the allowed IPs (or ranges of allowed IPs by using CIDR notation). + +### `ipStrategy` + +The `ipStrategy` option defines two parameters that set how Traefik determines the client IP: `depth`, and `excludedIPs`. +If no strategy is set, the default behavior is to match `sourceRange` against the Remote address found in the request. + +!!! important "As a middleware, whitelisting happens before the actual proxying to the backend takes place. In addition, the previous network hop only gets appended to `X-Forwarded-For` during the last stages of proxying, i.e. after it has already passed through whitelisting. Therefore, during whitelisting, as the previous network hop is not yet present in `X-Forwarded-For`, it cannot be matched against `sourceRange`." + +#### `ipStrategy.depth` + +The `depth` option tells Traefik to use the `X-Forwarded-For` header and take the IP located at the `depth` position (starting from the right). + +- If `depth` is greater than the total number of IPs in `X-Forwarded-For`, then the client IP will be empty. +- `depth` is ignored if its value is less than or equal to 0. + +!!! example "Examples of Depth & X-Forwarded-For" + + If `depth` is set to 2, and the request `X-Forwarded-For` header is `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` then the "real" client IP is `"10.0.0.1"` (at depth 4) but the IP used is `"12.0.0.1"` (`depth=2`). + + | `X-Forwarded-For` | `depth` | clientIP | + |-----------------------------------------|---------|--------------| + | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `1` | `"13.0.0.1"` | + | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `3` | `"11.0.0.1"` | + | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `5` | `""` | + +```yaml tab="Docker & Swarm" +# Allowlisting Based on `X-Forwarded-For` with `depth=2` +labels: + - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" + - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth=2" +``` + +```yaml tab="Kubernetes" +# Allowlisting Based on `X-Forwarded-For` with `depth=2` +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: test-ipallowlist +spec: + ipAllowList: + sourceRange: + - 127.0.0.1/32 + - 192.168.1.7 + ipStrategy: + depth: 2 +``` + +```yaml tab="Consul Catalog" +# Allowlisting Based on `X-Forwarded-For` with `depth=2` +- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" +- "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth=2" +``` + +```yaml tab="File (YAML)" +# Allowlisting Based on `X-Forwarded-For` with `depth=2` +http: + middlewares: + test-ipallowlist: + ipAllowList: + sourceRange: + - "127.0.0.1/32" + - "192.168.1.7" + ipStrategy: + depth: 2 +``` + +```toml tab="File (TOML)" +# Allowlisting Based on `X-Forwarded-For` with `depth=2` +[http.middlewares] + [http.middlewares.test-ipallowlist.ipAllowList] + sourceRange = ["127.0.0.1/32", "192.168.1.7"] + [http.middlewares.test-ipallowlist.ipAllowList.ipStrategy] + depth = 2 +``` + +#### `ipStrategy.excludedIPs` + +`excludedIPs` configures Traefik to scan the `X-Forwarded-For` header and select the first IP not in the list. + +!!! important "If `depth` is specified, `excludedIPs` is ignored." + +!!! example "Example of ExcludedIPs & X-Forwarded-For" + + | `X-Forwarded-For` | `excludedIPs` | clientIP | + |-----------------------------------------|-----------------------|--------------| + | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `"12.0.0.1,13.0.0.1"` | `"11.0.0.1"` | + | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `"15.0.0.1,13.0.0.1"` | `"12.0.0.1"` | + | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `"10.0.0.1,13.0.0.1"` | `"12.0.0.1"` | + | `"10.0.0.1,11.0.0.1,12.0.0.1,13.0.0.1"` | `"15.0.0.1,16.0.0.1"` | `"13.0.0.1"` | + | `"10.0.0.1,11.0.0.1"` | `"10.0.0.1,11.0.0.1"` | `""` | + +```yaml tab="Docker & Swarm" +# Exclude from `X-Forwarded-For` +labels: + - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" +``` + +```yaml tab="Kubernetes" +# Exclude from `X-Forwarded-For` +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: test-ipallowlist +spec: + ipAllowList: + ipStrategy: + excludedIPs: + - 127.0.0.1/32 + - 192.168.1.7 +``` + +```yaml tab="Consul Catalog" +# Exclude from `X-Forwarded-For` +- "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" +``` + +```yaml tab="File (YAML)" +# Exclude from `X-Forwarded-For` +http: + middlewares: + test-ipallowlist: + ipAllowList: + ipStrategy: + excludedIPs: + - "127.0.0.1/32" + - "192.168.1.7" +``` + +```toml tab="File (TOML)" +# Exclude from `X-Forwarded-For` +[http.middlewares] + [http.middlewares.test-ipallowlist.ipAllowList] + [http.middlewares.test-ipallowlist.ipAllowList.ipStrategy] + excludedIPs = ["127.0.0.1/32", "192.168.1.7"] +``` diff --git a/docs/content/middlewares/http/ipwhitelist.md b/docs/content/middlewares/http/ipwhitelist.md index 979791de0..eaf761541 100644 --- a/docs/content/middlewares/http/ipwhitelist.md +++ b/docs/content/middlewares/http/ipwhitelist.md @@ -8,9 +8,13 @@ description: "Learn how to use IPWhiteList in HTTP middleware for limiting clien Limiting Clients to Specific IPs {: .subtitle } -![IpWhiteList](../../assets/img/middleware/ipwhitelist.png) +![IPWhiteList](../../assets/img/middleware/ipwhitelist.png) -IPWhitelist accepts / refuses requests based on the client IP. +IPWhiteList accepts / refuses requests based on the client IP. + +!!! warning + + This middleware is deprecated, please use the [IPAllowList](./ipallowlist.md) middleware instead. ## Configuration Examples diff --git a/docs/content/middlewares/tcp/ipallowlist.md b/docs/content/middlewares/tcp/ipallowlist.md new file mode 100644 index 000000000..e8466b94e --- /dev/null +++ b/docs/content/middlewares/tcp/ipallowlist.md @@ -0,0 +1,60 @@ +--- +title: "Traefik TCP Middlewares IPAllowList" +description: "Learn how to use IPAllowList in TCP middleware for limiting clients to specific IPs in Traefik Proxy. Read the technical documentation." +--- + +# IPAllowList + +Limiting Clients to Specific IPs +{: .subtitle } + +IPAllowList accepts / refuses connections based on the client IP. + +## Configuration Examples + +```yaml tab="Docker & Swarm" +# Accepts connections from defined IP +labels: + - "traefik.tcp.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.io/v1alpha1 +kind: MiddlewareTCP +metadata: + name: test-ipallowlist +spec: + ipAllowList: + sourceRange: + - 127.0.0.1/32 + - 192.168.1.7 +``` + +```yaml tab="Consul Catalog" +# Accepts request from defined IP +- "traefik.tcp.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" +``` + +```toml tab="File (TOML)" +# Accepts request from defined IP +[tcp.middlewares] + [tcp.middlewares.test-ipallowlist.ipAllowList] + sourceRange = ["127.0.0.1/32", "192.168.1.7"] +``` + +```yaml tab="File (YAML)" +# Accepts request from defined IP +tcp: + middlewares: + test-ipallowlist: + ipAllowList: + sourceRange: + - "127.0.0.1/32" + - "192.168.1.7" +``` + +## Configuration Options + +### `sourceRange` + +The `sourceRange` option sets the allowed IPs (or ranges of allowed IPs by using CIDR notation). diff --git a/docs/content/middlewares/tcp/ipwhitelist.md b/docs/content/middlewares/tcp/ipwhitelist.md index 5926cc65a..9133c5f37 100644 --- a/docs/content/middlewares/tcp/ipwhitelist.md +++ b/docs/content/middlewares/tcp/ipwhitelist.md @@ -8,7 +8,11 @@ description: "Learn how to use IPWhiteList in TCP middleware for limiting client Limiting Clients to Specific IPs {: .subtitle } -IPWhitelist accepts / refuses connections based on the client IP. +IPWhiteList accepts / refuses connections based on the client IP. + +!!! warning + + This middleware is deprecated, please use the [IPAllowList](./ipallowlist.md) middleware instead. ## Configuration Examples diff --git a/docs/content/migration/v2.md b/docs/content/migration/v2.md index fdf1f6aa2..9fc05c38f 100644 --- a/docs/content/migration/v2.md +++ b/docs/content/migration/v2.md @@ -523,3 +523,13 @@ kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/co ### Traefik Hub In `v2.10`, Traefik Hub configuration has been removed because Traefik Hub v2 doesn't require this configuration. + +## v2.11 + +### IPWhiteList (HTTP) + +In `v2.11`, the `IPWhiteList` middleware is deprecated, please use the [IPAllowList](../middlewares/http/ipallowlist.md) middleware instead. + +### IPWhiteList (TCP) + +In `v2.11`, the `IPWhiteList` middleware is deprecated, please use the [IPAllowList](../middlewares/tcp/ipallowlist.md) middleware instead. diff --git a/docs/content/reference/dynamic-configuration/docker-labels.yml b/docs/content/reference/dynamic-configuration/docker-labels.yml index c413f27bd..723d4b049 100644 --- a/docs/content/reference/dynamic-configuration/docker-labels.yml +++ b/docs/content/reference/dynamic-configuration/docker-labels.yml @@ -121,6 +121,9 @@ - "traefik.http.middlewares.middleware21.stripprefix.forceslash=true" - "traefik.http.middlewares.middleware21.stripprefix.prefixes=foobar, foobar" - "traefik.http.middlewares.middleware22.stripprefixregex.regex=foobar, foobar" +- "traefik.http.middlewares.middleware23.ipallowlist.ipstrategy.depth=42" +- "traefik.http.middlewares.middleware23.ipallowlist.ipstrategy.excludedips=foobar, foobar" +- "traefik.http.middlewares.middleware23.ipallowlist.sourcerange=foobar, foobar" - "traefik.http.routers.router0.entrypoints=foobar, foobar" - "traefik.http.routers.router0.middlewares=foobar, foobar" - "traefik.http.routers.router0.priority=42" @@ -167,6 +170,7 @@ - "traefik.http.services.service01.loadbalancer.server.scheme=foobar" - "traefik.tcp.middlewares.tcpmiddleware00.ipwhitelist.sourcerange=foobar, foobar" - "traefik.tcp.middlewares.tcpmiddleware01.inflightconn.amount=42" +- "traefik.tcp.middlewares.tcpmiddleware02.ipallowlist.sourcerange=foobar, foobar" - "traefik.tcp.routers.tcprouter0.entrypoints=foobar, foobar" - "traefik.tcp.routers.tcprouter0.middlewares=foobar, foobar" - "traefik.tcp.routers.tcprouter0.rule=foobar" diff --git a/docs/content/reference/dynamic-configuration/file.toml b/docs/content/reference/dynamic-configuration/file.toml index 895a1f97f..7b00cffa2 100644 --- a/docs/content/reference/dynamic-configuration/file.toml +++ b/docs/content/reference/dynamic-configuration/file.toml @@ -284,6 +284,12 @@ [http.middlewares.Middleware22] [http.middlewares.Middleware22.stripPrefixRegex] regex = ["foobar", "foobar"] + [http.middlewares.Middleware23] + [http.middlewares.Middleware23.ipAllowList] + sourceRange = ["foobar", "foobar"] + [http.middlewares.Middleware23.ipAllowList.ipStrategy] + depth = 42 + excludedIPs = ["foobar", "foobar"] [http.serversTransports] [http.serversTransports.ServersTransport0] serverName = "foobar" diff --git a/docs/content/reference/dynamic-configuration/file.yaml b/docs/content/reference/dynamic-configuration/file.yaml index ec3081778..a19859e0b 100644 --- a/docs/content/reference/dynamic-configuration/file.yaml +++ b/docs/content/reference/dynamic-configuration/file.yaml @@ -323,6 +323,16 @@ http: regex: - foobar - foobar + Middleware23: + ipAllowList: + sourceRange: + - foobar + - foobar + ipStrategy: + depth: 42 + excludedIPs: + - foobar + - foobar serversTransports: ServersTransport0: serverName: foobar @@ -437,6 +447,11 @@ tcp: TCPMiddleware01: inFlightConn: amount: 42 + TCPMiddleware02: + ipAllowList: + sourceRange: + - foobar + - foobar udp: routers: UDPRouter0: diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml index 07b7eb3da..960f98fe7 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml @@ -1151,7 +1151,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1176,14 +1176,43 @@ spec: type: boolean type: object type: object - ipWhiteList: - description: 'IPWhiteList holds the IP whitelist middleware configuration. + ipAllowList: + description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/' + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position (starting + from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the X-Forwarded-For + header and select the first IP not in the list. + items: + type: string + type: array + type: object + sourceRange: + description: SourceRange defines the set of allowed IPs (or ranges + of allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + ipWhiteList: + description: 'IPWhiteList holds the IP whitelist middleware configuration. + This middleware accepts / refuses requests based on the client IP. + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + Deprecated: please use IPAllowList instead.' + properties: + ipStrategy: + description: 'IPStrategy holds the IP strategy configuration used + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1347,7 +1376,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1535,8 +1564,22 @@ spec: format: int64 type: integer type: object + ipAllowList: + description: 'IPAllowList defines the IPAllowList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + properties: + sourceRange: + description: SourceRange defines the allowed IPs (or ranges of + allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object ipWhiteList: - description: IPWhiteList defines the IPWhiteList middleware configuration. + description: 'IPWhiteList defines the IPWhiteList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of @@ -3415,7 +3458,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3440,14 +3483,43 @@ spec: type: boolean type: object type: object - ipWhiteList: - description: 'IPWhiteList holds the IP whitelist middleware configuration. + ipAllowList: + description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/' + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position (starting + from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the X-Forwarded-For + header and select the first IP not in the list. + items: + type: string + type: array + type: object + sourceRange: + description: SourceRange defines the set of allowed IPs (or ranges + of allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + ipWhiteList: + description: 'IPWhiteList holds the IP whitelist middleware configuration. + This middleware accepts / refuses requests based on the client IP. + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + Deprecated: please use IPAllowList instead.' + properties: + ipStrategy: + description: 'IPStrategy holds the IP strategy configuration used + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3611,7 +3683,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3799,8 +3871,22 @@ spec: format: int64 type: integer type: object + ipAllowList: + description: 'IPAllowList defines the IPAllowList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + properties: + sourceRange: + description: SourceRange defines the allowed IPs (or ranges of + allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object ipWhiteList: - description: IPWhiteList defines the IPWhiteList middleware configuration. + description: 'IPWhiteList defines the IPWhiteList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml index a7fccce89..b1385cda2 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml @@ -148,7 +148,7 @@ spec: - name: whoamitcp port: 8080 middlewares: - - name: ipwhitelist + - name: ipallowlist tls: secretName: foosecret passthrough: false diff --git a/docs/content/reference/dynamic-configuration/kv-ref.md b/docs/content/reference/dynamic-configuration/kv-ref.md index c12162ccc..13029dd50 100644 --- a/docs/content/reference/dynamic-configuration/kv-ref.md +++ b/docs/content/reference/dynamic-configuration/kv-ref.md @@ -140,6 +140,11 @@ | `traefik/http/middlewares/Middleware21/stripPrefix/prefixes/1` | `foobar` | | `traefik/http/middlewares/Middleware22/stripPrefixRegex/regex/0` | `foobar` | | `traefik/http/middlewares/Middleware22/stripPrefixRegex/regex/1` | `foobar` | +| `traefik/http/middlewares/Middleware23/ipAllowList/ipStrategy/depth` | `42` | +| `traefik/http/middlewares/Middleware23/ipAllowList/ipStrategy/excludedIPs/0` | `foobar` | +| `traefik/http/middlewares/Middleware23/ipAllowList/ipStrategy/excludedIPs/1` | `foobar` | +| `traefik/http/middlewares/Middleware23/ipAllowList/sourceRange/0` | `foobar` | +| `traefik/http/middlewares/Middleware23/ipAllowList/sourceRange/1` | `foobar` | | `traefik/http/routers/Router0/entryPoints/0` | `foobar` | | `traefik/http/routers/Router0/entryPoints/1` | `foobar` | | `traefik/http/routers/Router0/middlewares/0` | `foobar` | diff --git a/docs/content/reference/dynamic-configuration/marathon-labels.json b/docs/content/reference/dynamic-configuration/marathon-labels.json index 5da004819..8d4768f8f 100644 --- a/docs/content/reference/dynamic-configuration/marathon-labels.json +++ b/docs/content/reference/dynamic-configuration/marathon-labels.json @@ -121,6 +121,9 @@ "traefik.http.middlewares.middleware21.stripprefix.forceslash": "true", "traefik.http.middlewares.middleware21.stripprefix.prefixes": "foobar, foobar", "traefik.http.middlewares.middleware22.stripprefixregex.regex": "foobar, foobar", +"traefik.http.middlewares.middleware23.ipallowlist.ipstrategy.depth": "42", +"traefik.http.middlewares.middleware23.ipallowlist.ipstrategy.excludedips": "foobar, foobar", +"traefik.http.middlewares.middleware23.ipallowlist.sourcerange": "foobar, foobar", "traefik.http.routers.router0.entrypoints": "foobar, foobar", "traefik.http.routers.router0.middlewares": "foobar, foobar", "traefik.http.routers.router0.priority": "42", @@ -167,6 +170,7 @@ "traefik.http.services.service01.loadbalancer.server.scheme": "foobar", "traefik.tcp.middlewares.tcpmiddleware00.ipwhitelist.sourcerange": "foobar, foobar", "traefik.tcp.middlewares.tcpmiddleware01.inflightconn.amount": "42", +"traefik.tcp.middlewares.tcpmiddleware02.ipallowlist.sourcerange": "foobar, foobar", "traefik.tcp.routers.tcprouter0.entrypoints": "foobar, foobar", "traefik.tcp.routers.tcprouter0.middlewares": "foobar, foobar", "traefik.tcp.routers.tcprouter0.rule": "foobar", diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml index f96dafdc9..ad53a5e9a 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml @@ -577,7 +577,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -602,14 +602,43 @@ spec: type: boolean type: object type: object - ipWhiteList: - description: 'IPWhiteList holds the IP whitelist middleware configuration. + ipAllowList: + description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/' + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position (starting + from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the X-Forwarded-For + header and select the first IP not in the list. + items: + type: string + type: array + type: object + sourceRange: + description: SourceRange defines the set of allowed IPs (or ranges + of allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + ipWhiteList: + description: 'IPWhiteList holds the IP whitelist middleware configuration. + This middleware accepts / refuses requests based on the client IP. + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + Deprecated: please use IPAllowList instead.' + properties: + ipStrategy: + description: 'IPStrategy holds the IP strategy configuration used + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -773,7 +802,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml index 45ac8aee2..025dd2f7b 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml @@ -45,8 +45,22 @@ spec: format: int64 type: integer type: object + ipAllowList: + description: 'IPAllowList defines the IPAllowList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + properties: + sourceRange: + description: SourceRange defines the allowed IPs (or ranges of + allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object ipWhiteList: - description: IPWhiteList defines the IPWhiteList middleware configuration. + description: 'IPWhiteList defines the IPWhiteList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of diff --git a/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml b/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml index 0ba7bb31b..868a8f3ac 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml @@ -577,7 +577,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -602,14 +602,43 @@ spec: type: boolean type: object type: object - ipWhiteList: - description: 'IPWhiteList holds the IP whitelist middleware configuration. + ipAllowList: + description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/' + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position (starting + from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the X-Forwarded-For + header and select the first IP not in the list. + items: + type: string + type: array + type: object + sourceRange: + description: SourceRange defines the set of allowed IPs (or ranges + of allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + ipWhiteList: + description: 'IPWhiteList holds the IP whitelist middleware configuration. + This middleware accepts / refuses requests based on the client IP. + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + Deprecated: please use IPAllowList instead.' + properties: + ipStrategy: + description: 'IPStrategy holds the IP strategy configuration used + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -773,7 +802,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For diff --git a/docs/content/reference/dynamic-configuration/traefik.io_middlewaretcps.yaml b/docs/content/reference/dynamic-configuration/traefik.io_middlewaretcps.yaml index cd2988194..3439ea445 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_middlewaretcps.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_middlewaretcps.yaml @@ -45,8 +45,22 @@ spec: format: int64 type: integer type: object + ipAllowList: + description: 'IPAllowList defines the IPAllowList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + properties: + sourceRange: + description: SourceRange defines the allowed IPs (or ranges of + allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object ipWhiteList: - description: IPWhiteList defines the IPWhiteList middleware configuration. + description: 'IPWhiteList defines the IPWhiteList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index f588c1d80..05e913a2b 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -124,7 +124,8 @@ nav: - 'Errors': 'middlewares/http/errorpages.md' - 'ForwardAuth': 'middlewares/http/forwardauth.md' - 'Headers': 'middlewares/http/headers.md' - - 'IpWhitelist': 'middlewares/http/ipwhitelist.md' + - 'IPWhiteList': 'middlewares/http/ipwhitelist.md' + - 'IPAllowList': 'middlewares/http/ipallowlist.md' - 'InFlightReq': 'middlewares/http/inflightreq.md' - 'PassTLSClientCert': 'middlewares/http/passtlsclientcert.md' - 'RateLimit': 'middlewares/http/ratelimit.md' @@ -138,7 +139,8 @@ nav: - 'TCP': - 'Overview': 'middlewares/tcp/overview.md' - 'InFlightConn': 'middlewares/tcp/inflightconn.md' - - 'IpWhitelist': 'middlewares/tcp/ipwhitelist.md' + - 'IPWhiteList': 'middlewares/tcp/ipwhitelist.md' + - 'IPAllowList': 'middlewares/tcp/ipallowlist.md' - 'Plugins & Plugin Catalog': 'plugins/index.md' - 'Operations': - 'CLI': 'operations/cli.md' diff --git a/integration/fixtures/k8s/01-traefik-crd.yml b/integration/fixtures/k8s/01-traefik-crd.yml index 07b7eb3da..960f98fe7 100644 --- a/integration/fixtures/k8s/01-traefik-crd.yml +++ b/integration/fixtures/k8s/01-traefik-crd.yml @@ -1151,7 +1151,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1176,14 +1176,43 @@ spec: type: boolean type: object type: object - ipWhiteList: - description: 'IPWhiteList holds the IP whitelist middleware configuration. + ipAllowList: + description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/' + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position (starting + from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the X-Forwarded-For + header and select the first IP not in the list. + items: + type: string + type: array + type: object + sourceRange: + description: SourceRange defines the set of allowed IPs (or ranges + of allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + ipWhiteList: + description: 'IPWhiteList holds the IP whitelist middleware configuration. + This middleware accepts / refuses requests based on the client IP. + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + Deprecated: please use IPAllowList instead.' + properties: + ipStrategy: + description: 'IPStrategy holds the IP strategy configuration used + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1347,7 +1376,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1535,8 +1564,22 @@ spec: format: int64 type: integer type: object + ipAllowList: + description: 'IPAllowList defines the IPAllowList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + properties: + sourceRange: + description: SourceRange defines the allowed IPs (or ranges of + allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object ipWhiteList: - description: IPWhiteList defines the IPWhiteList middleware configuration. + description: 'IPWhiteList defines the IPWhiteList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of @@ -3415,7 +3458,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3440,14 +3483,43 @@ spec: type: boolean type: object type: object - ipWhiteList: - description: 'IPWhiteList holds the IP whitelist middleware configuration. + ipAllowList: + description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/' + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + properties: + depth: + description: Depth tells Traefik to use the X-Forwarded-For + header and take the IP located at the depth position (starting + from the right). + type: integer + excludedIPs: + description: ExcludedIPs configures Traefik to scan the X-Forwarded-For + header and select the first IP not in the list. + items: + type: string + type: array + type: object + sourceRange: + description: SourceRange defines the set of allowed IPs (or ranges + of allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object + ipWhiteList: + description: 'IPWhiteList holds the IP whitelist middleware configuration. + This middleware accepts / refuses requests based on the client IP. + More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + Deprecated: please use IPAllowList instead.' + properties: + ipStrategy: + description: 'IPStrategy holds the IP strategy configuration used + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3611,7 +3683,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3799,8 +3871,22 @@ spec: format: int64 type: integer type: object + ipAllowList: + description: 'IPAllowList defines the IPAllowList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + properties: + sourceRange: + description: SourceRange defines the allowed IPs (or ranges of + allowed IPs by using CIDR notation). + items: + type: string + type: array + type: object ipWhiteList: - description: IPWhiteList defines the IPWhiteList middleware configuration. + description: 'IPWhiteList defines the IPWhiteList middleware configuration. + This middleware accepts/refuses connections based on the client + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of diff --git a/integration/fixtures/simple_allowlist.toml b/integration/fixtures/simple_allowlist.toml new file mode 100644 index 000000000..03fa451e4 --- /dev/null +++ b/integration/fixtures/simple_allowlist.toml @@ -0,0 +1,18 @@ +[global] + checkNewVersion = false + sendAnonymousUsage = false + +[log] + level = "DEBUG" + +[entryPoints] + [entryPoints.web] + address = ":8000" + [entryPoints.web.ForwardedHeaders] + insecure = true + +[api] + insecure = true + +[providers] + [providers.docker] diff --git a/integration/resources/compose/allowlist.yml b/integration/resources/compose/allowlist.yml new file mode 100644 index 000000000..02e3761ca --- /dev/null +++ b/integration/resources/compose/allowlist.yml @@ -0,0 +1,41 @@ +version: "3.8" +services: + noOverrideAllowlist: + image: traefik/whoami + labels: + traefik.enable: true + traefik.http.routers.rt1.rule: Host(`no.override.allowlist.docker.local`) + traefik.http.routers.rt1.middlewares: wl1 + traefik.http.middlewares.wl1.ipallowlist.sourceRange: 8.8.8.8 + + overrideIPStrategyRemoteAddrAllowlist: + image: traefik/whoami + labels: + traefik.enable: true + traefik.http.routers.rt2.rule: Host(`override.remoteaddr.allowlist.docker.local`) + traefik.http.routers.rt2.middlewares: wl2 + traefik.http.middlewares.wl2.ipallowlist.sourceRange: 8.8.8.8 + traefik.http.middlewares.wl2.ipallowlist.ipStrategy: true + + overrideIPStrategyDepthAllowlist: + image: traefik/whoami + labels: + traefik.enable: true + traefik.http.routers.rt3.rule: Host(`override.depth.allowlist.docker.local`) + traefik.http.routers.rt3.middlewares: wl3 + traefik.http.middlewares.wl3.ipallowlist.sourceRange: 8.8.8.8 + traefik.http.middlewares.wl3.ipallowlist.ipStrategy.depth: 3 + + overrideIPStrategyExcludedIPsAllowlist: + image: traefik/whoami + labels: + traefik.enable: true + traefik.http.routers.rt4.rule: Host(`override.excludedips.allowlist.docker.local`) + traefik.http.routers.rt4.middlewares: wl4 + traefik.http.middlewares.wl4.ipallowlist.sourceRange: 8.8.8.8 + traefik.http.middlewares.wl4.ipallowlist.ipStrategy.excludedIPs: 10.0.0.1,10.0.0.2 + +networks: + default: + name: traefik-test-network + external: true diff --git a/integration/simple_test.go b/integration/simple_test.go index f88afb9e4..3284a5a81 100644 --- a/integration/simple_test.go +++ b/integration/simple_test.go @@ -546,6 +546,76 @@ func (s *SimpleSuite) TestIPStrategyWhitelist(c *check.C) { } } +func (s *SimpleSuite) TestIPStrategyAllowlist(c *check.C) { + s.createComposeProject(c, "allowlist") + + s.composeUp(c) + defer s.composeDown(c) + + cmd, output := s.traefikCmd(withConfigFile("fixtures/simple_allowlist.toml")) + defer output(c) + + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer s.killCmd(cmd) + + err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second, try.BodyContains("override")) + c.Assert(err, checker.IsNil) + + err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2*time.Second, try.BodyContains("override.remoteaddr.allowlist.docker.local")) + c.Assert(err, checker.IsNil) + + testCases := []struct { + desc string + xForwardedFor string + host string + expectedStatusCode int + }{ + { + desc: "override remote addr reject", + xForwardedFor: "8.8.8.8,8.8.8.8", + host: "override.remoteaddr.allowlist.docker.local", + expectedStatusCode: 403, + }, + { + desc: "override depth accept", + xForwardedFor: "8.8.8.8,10.0.0.1,127.0.0.1", + host: "override.depth.allowlist.docker.local", + expectedStatusCode: 200, + }, + { + desc: "override depth reject", + xForwardedFor: "10.0.0.1,8.8.8.8,127.0.0.1", + host: "override.depth.allowlist.docker.local", + expectedStatusCode: 403, + }, + { + desc: "override excludedIPs reject", + xForwardedFor: "10.0.0.3,10.0.0.1,10.0.0.2", + host: "override.excludedips.allowlist.docker.local", + expectedStatusCode: 403, + }, + { + desc: "override excludedIPs accept", + xForwardedFor: "8.8.8.8,10.0.0.1,10.0.0.2", + host: "override.excludedips.allowlist.docker.local", + expectedStatusCode: 200, + }, + } + + for _, test := range testCases { + req := httptest.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil) + req.Header.Set("X-Forwarded-For", test.xForwardedFor) + req.Host = test.host + req.RequestURI = "" + + err = try.Request(req, 1*time.Second, try.StatusCodeIs(test.expectedStatusCode)) + if err != nil { + c.Fatalf("Error while %s: %v", test.desc, err) + } + } +} + func (s *SimpleSuite) TestXForwardedHeaders(c *check.C) { s.createComposeProject(c, "whitelist") diff --git a/pkg/config/dynamic/middlewares.go b/pkg/config/dynamic/middlewares.go index c2ec1ba44..714c459a6 100644 --- a/pkg/config/dynamic/middlewares.go +++ b/pkg/config/dynamic/middlewares.go @@ -19,6 +19,7 @@ type Middleware struct { ReplacePathRegex *ReplacePathRegex `json:"replacePathRegex,omitempty" toml:"replacePathRegex,omitempty" yaml:"replacePathRegex,omitempty" export:"true"` Chain *Chain `json:"chain,omitempty" toml:"chain,omitempty" yaml:"chain,omitempty" export:"true"` IPWhiteList *IPWhiteList `json:"ipWhiteList,omitempty" toml:"ipWhiteList,omitempty" yaml:"ipWhiteList,omitempty" export:"true"` + IPAllowList *IPAllowList `json:"ipAllowList,omitempty" toml:"ipAllowList,omitempty" yaml:"ipAllowList,omitempty" export:"true"` Headers *Headers `json:"headers,omitempty" toml:"headers,omitempty" yaml:"headers,omitempty" export:"true"` Errors *ErrorPage `json:"errors,omitempty" toml:"errors,omitempty" yaml:"errors,omitempty" export:"true"` RateLimit *RateLimit `json:"rateLimit,omitempty" toml:"rateLimit,omitempty" yaml:"rateLimit,omitempty" export:"true"` @@ -346,7 +347,7 @@ func (h *Headers) HasSecureHeadersDefined() bool { // +k8s:deepcopy-gen=true // IPStrategy holds the IP strategy configuration used by Traefik to determine the client IP. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/#ipstrategy +// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy type IPStrategy struct { // Depth tells Traefik to use the X-Forwarded-For header and take the IP located at the depth position (starting from the right). Depth int `json:"depth,omitempty" toml:"depth,omitempty" yaml:"depth,omitempty" export:"true"` @@ -388,6 +389,7 @@ func (s *IPStrategy) Get() (ip.Strategy, error) { // IPWhiteList holds the IP whitelist middleware configuration. // This middleware accepts / refuses requests based on the client IP. // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ +// Deprecated: please use IPAllowList instead. type IPWhiteList struct { // SourceRange defines the set of allowed IPs (or ranges of allowed IPs by using CIDR notation). SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"` @@ -396,6 +398,17 @@ type IPWhiteList struct { // +k8s:deepcopy-gen=true +// IPAllowList holds the IP allowlist middleware configuration. +// This middleware accepts / refuses requests based on the client IP. +// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/ +type IPAllowList struct { + // SourceRange defines the set of allowed IPs (or ranges of allowed IPs by using CIDR notation). + SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"` + IPStrategy *IPStrategy `json:"ipStrategy,omitempty" toml:"ipStrategy,omitempty" yaml:"ipStrategy,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"` +} + +// +k8s:deepcopy-gen=true + // InFlightReq holds the in-flight request middleware configuration. // This middleware limits the number of requests being processed and served concurrently. // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/inflightreq/ diff --git a/pkg/config/dynamic/tcp_middlewares.go b/pkg/config/dynamic/tcp_middlewares.go index e0cf31919..f4052cd82 100644 --- a/pkg/config/dynamic/tcp_middlewares.go +++ b/pkg/config/dynamic/tcp_middlewares.go @@ -6,6 +6,7 @@ package dynamic type TCPMiddleware struct { InFlightConn *TCPInFlightConn `json:"inFlightConn,omitempty" toml:"inFlightConn,omitempty" yaml:"inFlightConn,omitempty" export:"true"` IPWhiteList *TCPIPWhiteList `json:"ipWhiteList,omitempty" toml:"ipWhiteList,omitempty" yaml:"ipWhiteList,omitempty" export:"true"` + IPAllowList *TCPIPAllowList `json:"ipAllowList,omitempty" toml:"ipAllowList,omitempty" yaml:"ipAllowList,omitempty" export:"true"` } // +k8s:deepcopy-gen=true @@ -23,8 +24,15 @@ type TCPInFlightConn struct { // +k8s:deepcopy-gen=true // TCPIPWhiteList holds the TCP IPWhiteList middleware configuration. -// This middleware accepts/refuses connections based on the client IP. type TCPIPWhiteList struct { // SourceRange defines the allowed IPs (or ranges of allowed IPs by using CIDR notation). SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"` } + +// +k8s:deepcopy-gen=true + +// TCPIPAllowList holds the TCP IPAllowList middleware configuration. +type TCPIPAllowList struct { + // SourceRange defines the allowed IPs (or ranges of allowed IPs by using CIDR notation). + SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"` +} diff --git a/pkg/config/dynamic/zz_generated.deepcopy.go b/pkg/config/dynamic/zz_generated.deepcopy.go index f897f6f31..fee40799c 100644 --- a/pkg/config/dynamic/zz_generated.deepcopy.go +++ b/pkg/config/dynamic/zz_generated.deepcopy.go @@ -532,6 +532,32 @@ func (in *HealthCheck) DeepCopy() *HealthCheck { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPAllowList) DeepCopyInto(out *IPAllowList) { + *out = *in + if in.SourceRange != nil { + in, out := &in.SourceRange, &out.SourceRange + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.IPStrategy != nil { + in, out := &in.IPStrategy, &out.IPStrategy + *out = new(IPStrategy) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPAllowList. +func (in *IPAllowList) DeepCopy() *IPAllowList { + if in == nil { + return nil + } + out := new(IPAllowList) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IPStrategy) DeepCopyInto(out *IPStrategy) { *out = *in @@ -659,6 +685,11 @@ func (in *Middleware) DeepCopyInto(out *Middleware) { *out = new(IPWhiteList) (*in).DeepCopyInto(*out) } + if in.IPAllowList != nil { + in, out := &in.IPAllowList, &out.IPAllowList + *out = new(IPAllowList) + (*in).DeepCopyInto(*out) + } if in.Headers != nil { in, out := &in.Headers, &out.Headers *out = new(Headers) @@ -1355,6 +1386,27 @@ func (in *TCPConfiguration) DeepCopy() *TCPConfiguration { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TCPIPAllowList) DeepCopyInto(out *TCPIPAllowList) { + *out = *in + if in.SourceRange != nil { + in, out := &in.SourceRange, &out.SourceRange + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPIPAllowList. +func (in *TCPIPAllowList) DeepCopy() *TCPIPAllowList { + if in == nil { + return nil + } + out := new(TCPIPAllowList) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TCPIPWhiteList) DeepCopyInto(out *TCPIPWhiteList) { *out = *in @@ -1405,6 +1457,11 @@ func (in *TCPMiddleware) DeepCopyInto(out *TCPMiddleware) { *out = new(TCPIPWhiteList) (*in).DeepCopyInto(*out) } + if in.IPAllowList != nil { + in, out := &in.IPAllowList, &out.IPAllowList + *out = new(TCPIPAllowList) + (*in).DeepCopyInto(*out) + } return } diff --git a/pkg/middlewares/ipallowlist/ip_allowlist.go b/pkg/middlewares/ipallowlist/ip_allowlist.go new file mode 100644 index 000000000..d700a9279 --- /dev/null +++ b/pkg/middlewares/ipallowlist/ip_allowlist.go @@ -0,0 +1,88 @@ +package ipallowlist + +import ( + "context" + "errors" + "fmt" + "net/http" + + "github.com/opentracing/opentracing-go/ext" + "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v2/pkg/ip" + "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/middlewares" + "github.com/traefik/traefik/v2/pkg/tracing" +) + +const ( + typeName = "IPAllowLister" +) + +// ipAllowLister is a middleware that provides Checks of the Requesting IP against a set of Allowlists. +type ipAllowLister struct { + next http.Handler + allowLister *ip.Checker + strategy ip.Strategy + name string +} + +// New builds a new IPAllowLister given a list of CIDR-Strings to allow. +func New(ctx context.Context, next http.Handler, config dynamic.IPAllowList, name string) (http.Handler, error) { + logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)) + logger.Debug("Creating middleware") + + if len(config.SourceRange) == 0 { + return nil, errors.New("sourceRange is empty, IPAllowLister not created") + } + + checker, err := ip.NewChecker(config.SourceRange) + if err != nil { + return nil, fmt.Errorf("cannot parse CIDRs %s: %w", config.SourceRange, err) + } + + strategy, err := config.IPStrategy.Get() + if err != nil { + return nil, err + } + + logger.Debugf("Setting up IPAllowLister with sourceRange: %s", config.SourceRange) + + return &ipAllowLister{ + strategy: strategy, + allowLister: checker, + next: next, + name: name, + }, nil +} + +func (al *ipAllowLister) GetTracingInformation() (string, ext.SpanKindEnum) { + return al.name, tracing.SpanKindNoneEnum +} + +func (al *ipAllowLister) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + ctx := middlewares.GetLoggerCtx(req.Context(), al.name, typeName) + logger := log.FromContext(ctx) + + clientIP := al.strategy.GetIP(req) + err := al.allowLister.IsAuthorized(clientIP) + if err != nil { + msg := fmt.Sprintf("Rejecting IP %s: %v", clientIP, err) + logger.Debug(msg) + tracing.SetErrorWithEvent(req, msg) + reject(ctx, rw) + return + } + logger.Debugf("Accepting IP %s", clientIP) + + al.next.ServeHTTP(rw, req) +} + +func reject(ctx context.Context, rw http.ResponseWriter) { + statusCode := http.StatusForbidden + + rw.WriteHeader(statusCode) + _, err := rw.Write([]byte(http.StatusText(statusCode))) + if err != nil { + log.FromContext(ctx).Error(err) + } +} diff --git a/pkg/middlewares/ipallowlist/ip_allowlist_test.go b/pkg/middlewares/ipallowlist/ip_allowlist_test.go new file mode 100644 index 000000000..df2e49835 --- /dev/null +++ b/pkg/middlewares/ipallowlist/ip_allowlist_test.go @@ -0,0 +1,100 @@ +package ipallowlist + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/traefik/traefik/v2/pkg/config/dynamic" +) + +func TestNewIPAllowLister(t *testing.T) { + testCases := []struct { + desc string + allowList dynamic.IPAllowList + expectedError bool + }{ + { + desc: "invalid IP", + allowList: dynamic.IPAllowList{ + SourceRange: []string{"foo"}, + }, + expectedError: true, + }, + { + desc: "valid IP", + allowList: dynamic.IPAllowList{ + SourceRange: []string{"10.10.10.10"}, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + allowLister, err := New(context.Background(), next, test.allowList, "traefikTest") + + if test.expectedError { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.NotNil(t, allowLister) + } + }) + } +} + +func TestIPAllowLister_ServeHTTP(t *testing.T) { + testCases := []struct { + desc string + allowList dynamic.IPAllowList + remoteAddr string + expected int + }{ + { + desc: "authorized with remote address", + allowList: dynamic.IPAllowList{ + SourceRange: []string{"20.20.20.20"}, + }, + remoteAddr: "20.20.20.20:1234", + expected: 200, + }, + { + desc: "non authorized with remote address", + allowList: dynamic.IPAllowList{ + SourceRange: []string{"20.20.20.20"}, + }, + remoteAddr: "20.20.20.21:1234", + expected: 403, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}) + allowLister, err := New(context.Background(), next, test.allowList, "traefikTest") + require.NoError(t, err) + + recorder := httptest.NewRecorder() + + req := httptest.NewRequest(http.MethodGet, "http://10.10.10.10", nil) + + if len(test.remoteAddr) > 0 { + req.RemoteAddr = test.remoteAddr + } + + allowLister.ServeHTTP(recorder, req) + + assert.Equal(t, test.expected, recorder.Code) + }) + } +} diff --git a/pkg/middlewares/tcp/ipallowlist/ip_allowlist.go b/pkg/middlewares/tcp/ipallowlist/ip_allowlist.go new file mode 100644 index 000000000..dd5d14d43 --- /dev/null +++ b/pkg/middlewares/tcp/ipallowlist/ip_allowlist.go @@ -0,0 +1,65 @@ +package ipallowlist + +import ( + "context" + "errors" + "fmt" + + "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v2/pkg/ip" + "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/middlewares" + "github.com/traefik/traefik/v2/pkg/tcp" +) + +const ( + typeName = "IPAllowListerTCP" +) + +// ipAllowLister is a middleware that provides Checks of the Requesting IP against a set of Allowlists. +type ipAllowLister struct { + next tcp.Handler + allowLister *ip.Checker + name string +} + +// New builds a new TCP IPAllowLister given a list of CIDR-Strings to allow. +func New(ctx context.Context, next tcp.Handler, config dynamic.TCPIPAllowList, name string) (tcp.Handler, error) { + logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)) + logger.Debug("Creating middleware") + + if len(config.SourceRange) == 0 { + return nil, errors.New("sourceRange is empty, IPAllowLister not created") + } + + checker, err := ip.NewChecker(config.SourceRange) + if err != nil { + return nil, fmt.Errorf("cannot parse CIDRs %s: %w", config.SourceRange, err) + } + + logger.Debugf("Setting up IPAllowLister with sourceRange: %s", config.SourceRange) + + return &ipAllowLister{ + allowLister: checker, + next: next, + name: name, + }, nil +} + +func (al *ipAllowLister) ServeTCP(conn tcp.WriteCloser) { + ctx := middlewares.GetLoggerCtx(context.Background(), al.name, typeName) + logger := log.FromContext(ctx) + + addr := conn.RemoteAddr().String() + + err := al.allowLister.IsAuthorized(addr) + if err != nil { + logger.Errorf("Connection from %s rejected: %v", addr, err) + conn.Close() + return + } + + logger.Debugf("Connection from %s accepted", addr) + + al.next.ServeTCP(conn) +} diff --git a/pkg/middlewares/tcp/ipallowlist/ip_allowlist_test.go b/pkg/middlewares/tcp/ipallowlist/ip_allowlist_test.go new file mode 100644 index 000000000..4f3b59e15 --- /dev/null +++ b/pkg/middlewares/tcp/ipallowlist/ip_allowlist_test.go @@ -0,0 +1,139 @@ +package ipallowlist + +import ( + "context" + "io" + "net" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v2/pkg/tcp" +) + +func TestNewIPAllowLister(t *testing.T) { + testCases := []struct { + desc string + allowList dynamic.TCPIPAllowList + expectedError bool + }{ + { + desc: "Empty config", + allowList: dynamic.TCPIPAllowList{}, + expectedError: true, + }, + { + desc: "invalid IP", + allowList: dynamic.TCPIPAllowList{ + SourceRange: []string{"foo"}, + }, + expectedError: true, + }, + { + desc: "valid IP", + allowList: dynamic.TCPIPAllowList{ + SourceRange: []string{"10.10.10.10"}, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + next := tcp.HandlerFunc(func(conn tcp.WriteCloser) {}) + allowLister, err := New(context.Background(), next, test.allowList, "traefikTest") + + if test.expectedError { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.NotNil(t, allowLister) + } + }) + } +} + +func TestIPAllowLister_ServeHTTP(t *testing.T) { + testCases := []struct { + desc string + allowList dynamic.TCPIPAllowList + remoteAddr string + expected string + }{ + { + desc: "authorized with remote address", + allowList: dynamic.TCPIPAllowList{ + SourceRange: []string{"20.20.20.20"}, + }, + remoteAddr: "20.20.20.20:1234", + expected: "OK", + }, + { + desc: "non authorized with remote address", + allowList: dynamic.TCPIPAllowList{ + SourceRange: []string{"20.20.20.20"}, + }, + remoteAddr: "20.20.20.21:1234", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + next := tcp.HandlerFunc(func(conn tcp.WriteCloser) { + write, err := conn.Write([]byte("OK")) + require.NoError(t, err) + assert.Equal(t, 2, write) + + err = conn.Close() + require.NoError(t, err) + }) + + allowLister, err := New(context.Background(), next, test.allowList, "traefikTest") + require.NoError(t, err) + + server, client := net.Pipe() + + go func() { + allowLister.ServeTCP(&contextWriteCloser{client, addr{test.remoteAddr}}) + }() + + read, err := io.ReadAll(server) + require.NoError(t, err) + + assert.Equal(t, test.expected, string(read)) + }) + } +} + +type contextWriteCloser struct { + net.Conn + addr +} + +type addr struct { + remoteAddr string +} + +func (a addr) Network() string { + panic("implement me") +} + +func (a addr) String() string { + return a.remoteAddr +} + +func (c contextWriteCloser) CloseWrite() error { + panic("implement me") +} + +func (c contextWriteCloser) RemoteAddr() net.Addr { return c.addr } + +func (c contextWriteCloser) Context() context.Context { + return context.Background() +} diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index 2759055ef..03807ac9c 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -288,6 +288,7 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) ReplacePathRegex: middleware.Spec.ReplacePathRegex, Chain: createChainMiddleware(ctxMid, middleware.Namespace, middleware.Spec.Chain), IPWhiteList: middleware.Spec.IPWhiteList, + IPAllowList: middleware.Spec.IPAllowList, Headers: middleware.Spec.Headers, Errors: errorPage, RateLimit: rateLimit, @@ -313,6 +314,7 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) conf.TCP.Middlewares[id] = &dynamic.TCPMiddleware{ InFlightConn: middlewareTCP.Spec.InFlightConn, IPWhiteList: middlewareTCP.Spec.IPWhiteList, + IPAllowList: middlewareTCP.Spec.IPAllowList, } } diff --git a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middleware.go index 54dbe07e6..65b969540 100644 --- a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middleware.go @@ -33,6 +33,7 @@ type MiddlewareSpec struct { ReplacePathRegex *dynamic.ReplacePathRegex `json:"replacePathRegex,omitempty"` Chain *Chain `json:"chain,omitempty"` IPWhiteList *dynamic.IPWhiteList `json:"ipWhiteList,omitempty"` + IPAllowList *dynamic.IPAllowList `json:"ipAllowList,omitempty"` Headers *dynamic.Headers `json:"headers,omitempty"` Errors *ErrorPage `json:"errors,omitempty"` RateLimit *RateLimit `json:"rateLimit,omitempty"` diff --git a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middlewaretcp.go index c903a8ca7..923c3d404 100644 --- a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middlewaretcp.go @@ -26,7 +26,14 @@ type MiddlewareTCPSpec struct { // InFlightConn defines the InFlightConn middleware configuration. InFlightConn *dynamic.TCPInFlightConn `json:"inFlightConn,omitempty"` // IPWhiteList defines the IPWhiteList middleware configuration. + // This middleware accepts/refuses connections based on the client IP. + // Deprecated: please use IPAllowList instead. + // More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/ IPWhiteList *dynamic.TCPIPWhiteList `json:"ipWhiteList,omitempty"` + // IPAllowList defines the IPAllowList middleware configuration. + // This middleware accepts/refuses connections based on the client IP. + // More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/ + IPAllowList *dynamic.TCPIPAllowList `json:"ipAllowList,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/zz_generated.deepcopy.go index a91c5cfc1..0b0126432 100644 --- a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/zz_generated.deepcopy.go @@ -694,6 +694,11 @@ func (in *MiddlewareSpec) DeepCopyInto(out *MiddlewareSpec) { *out = new(dynamic.IPWhiteList) (*in).DeepCopyInto(*out) } + if in.IPAllowList != nil { + in, out := &in.IPAllowList, &out.IPAllowList + *out = new(dynamic.IPAllowList) + (*in).DeepCopyInto(*out) + } if in.Headers != nil { in, out := &in.Headers, &out.Headers *out = new(dynamic.Headers) @@ -862,6 +867,11 @@ func (in *MiddlewareTCPSpec) DeepCopyInto(out *MiddlewareTCPSpec) { *out = new(dynamic.TCPIPWhiteList) (*in).DeepCopyInto(*out) } + if in.IPAllowList != nil { + in, out := &in.IPAllowList, &out.IPAllowList + *out = new(dynamic.TCPIPAllowList) + (*in).DeepCopyInto(*out) + } return } diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go index 54dbe07e6..65b969540 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go @@ -33,6 +33,7 @@ type MiddlewareSpec struct { ReplacePathRegex *dynamic.ReplacePathRegex `json:"replacePathRegex,omitempty"` Chain *Chain `json:"chain,omitempty"` IPWhiteList *dynamic.IPWhiteList `json:"ipWhiteList,omitempty"` + IPAllowList *dynamic.IPAllowList `json:"ipAllowList,omitempty"` Headers *dynamic.Headers `json:"headers,omitempty"` Errors *ErrorPage `json:"errors,omitempty"` RateLimit *RateLimit `json:"rateLimit,omitempty"` diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middlewaretcp.go index c903a8ca7..923c3d404 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middlewaretcp.go @@ -26,7 +26,14 @@ type MiddlewareTCPSpec struct { // InFlightConn defines the InFlightConn middleware configuration. InFlightConn *dynamic.TCPInFlightConn `json:"inFlightConn,omitempty"` // IPWhiteList defines the IPWhiteList middleware configuration. + // This middleware accepts/refuses connections based on the client IP. + // Deprecated: please use IPAllowList instead. + // More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/ IPWhiteList *dynamic.TCPIPWhiteList `json:"ipWhiteList,omitempty"` + // IPAllowList defines the IPAllowList middleware configuration. + // This middleware accepts/refuses connections based on the client IP. + // More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/ + IPAllowList *dynamic.TCPIPAllowList `json:"ipAllowList,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go index a91c5cfc1..0b0126432 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go @@ -694,6 +694,11 @@ func (in *MiddlewareSpec) DeepCopyInto(out *MiddlewareSpec) { *out = new(dynamic.IPWhiteList) (*in).DeepCopyInto(*out) } + if in.IPAllowList != nil { + in, out := &in.IPAllowList, &out.IPAllowList + *out = new(dynamic.IPAllowList) + (*in).DeepCopyInto(*out) + } if in.Headers != nil { in, out := &in.Headers, &out.Headers *out = new(dynamic.Headers) @@ -862,6 +867,11 @@ func (in *MiddlewareTCPSpec) DeepCopyInto(out *MiddlewareTCPSpec) { *out = new(dynamic.TCPIPWhiteList) (*in).DeepCopyInto(*out) } + if in.IPAllowList != nil { + in, out := &in.IPAllowList, &out.IPAllowList + *out = new(dynamic.TCPIPAllowList) + (*in).DeepCopyInto(*out) + } return } diff --git a/pkg/server/middleware/middlewares.go b/pkg/server/middleware/middlewares.go index 0f666c996..073843472 100644 --- a/pkg/server/middleware/middlewares.go +++ b/pkg/server/middleware/middlewares.go @@ -10,6 +10,7 @@ import ( "github.com/containous/alice" "github.com/traefik/traefik/v2/pkg/config/runtime" + "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/middlewares/addprefix" "github.com/traefik/traefik/v2/pkg/middlewares/auth" "github.com/traefik/traefik/v2/pkg/middlewares/buffering" @@ -19,6 +20,7 @@ import ( "github.com/traefik/traefik/v2/pkg/middlewares/customerrors" "github.com/traefik/traefik/v2/pkg/middlewares/headers" "github.com/traefik/traefik/v2/pkg/middlewares/inflightreq" + "github.com/traefik/traefik/v2/pkg/middlewares/ipallowlist" "github.com/traefik/traefik/v2/pkg/middlewares/ipwhitelist" "github.com/traefik/traefik/v2/pkg/middlewares/passtlsclientcert" "github.com/traefik/traefik/v2/pkg/middlewares/ratelimiter" @@ -231,6 +233,8 @@ func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) ( // IPWhiteList if config.IPWhiteList != nil { + log.FromContext(ctx).Warn("IPWhiteList is deprecated, please use IPAllowList instead.") + if middleware != nil { return nil, badConf } @@ -239,6 +243,16 @@ func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) ( } } + // IPAllowList + if config.IPAllowList != nil { + if middleware != nil { + return nil, badConf + } + middleware = func(next http.Handler) (http.Handler, error) { + return ipallowlist.New(ctx, next, *config.IPAllowList, middlewareName) + } + } + // InFlightReq if config.InFlightReq != nil { if middleware != nil { From cd7d324295e45627a586c4ed7ef074e93e4d9193 Mon Sep 17 00:00:00 2001 From: sven Date: Tue, 2 Jan 2024 17:30:06 +0100 Subject: [PATCH 08/21] Documentation enhancements --- .../getting-started/configuration-overview.md | 4 +-- docs/content/getting-started/faq.md | 16 ++++----- .../getting-started/install-traefik.md | 8 ++--- .../quick-start-with-kubernetes.md | 36 +++++++++---------- docs/content/getting-started/quick-start.md | 14 ++++---- docs/content/index.md | 2 +- docs/content/operations/dashboard.md | 6 ++-- docs/content/operations/ping.md | 9 ++--- 8 files changed, 48 insertions(+), 47 deletions(-) diff --git a/docs/content/getting-started/configuration-overview.md b/docs/content/getting-started/configuration-overview.md index 2ecf93b74..2e5e10c50 100644 --- a/docs/content/getting-started/configuration-overview.md +++ b/docs/content/getting-started/configuration-overview.md @@ -82,11 +82,11 @@ docker run traefik[:version] --help # ex: docker run traefik:v2.10 --help ``` -All available arguments can also be found [here](../reference/static-configuration/cli.md). +Check the [CLI reference](../reference/static-configuration/cli.md "Link to CLI reference overview") for an overview about all available arguments. ### Environment Variables -All available environment variables can be found [here](../reference/static-configuration/env.md) +All available environment variables can be found in the [static configuration environment overview](../reference/static-configuration/env.md). ## Available Configuration Options diff --git a/docs/content/getting-started/faq.md b/docs/content/getting-started/faq.md index caa82058f..761e8d3a7 100644 --- a/docs/content/getting-started/faq.md +++ b/docs/content/getting-started/faq.md @@ -29,7 +29,7 @@ Not to mention that dynamic configuration changes potentially make that kind of Therefore, in this dynamic context, the static configuration of an `entryPoint` does not give any hint whatsoever about how the traffic going through that `entryPoint` is going to be routed. Or whether it's even going to be routed at all, -i.e. whether there is a Router matching the kind of traffic going through it. +that is whether there is a Router matching the kind of traffic going through it. ### `404 Not found` @@ -71,7 +71,7 @@ Traefik returns a `502` response code when an error happens while contacting the ### `503 Service Unavailable` -Traefik returns a `503` response code when a Router has been matched +Traefik returns a `503` response code when a Router has been matched, but there are no servers ready to handle the request. This situation is encountered when a service has been explicitly configured without servers, @@ -84,7 +84,7 @@ Sometimes, the `404` response code doesn't play well with other parties or servi In these situations, you may want Traefik to always reply with a `503` response code, instead of a `404` response code. -To achieve this behavior, a simple catchall router, +To achieve this behavior, a catchall router, with the lowest possible priority and routing to a service without servers, can handle all the requests when no other router has been matched. @@ -130,7 +130,7 @@ http: the principle of the above example above (a catchall router) still stands, but the `unavailable` service should be adapted to fit such a need. -## Why Is My TLS Certificate Not Reloaded When Its Contents Change? +## Why Is My TLS Certificate Not Reloaded When Its Contents Change? With the file provider, a configuration update is only triggered when one of the [watched](../providers/file.md#provider-configuration) configuration files is modified. @@ -216,7 +216,7 @@ error: field not found, node: -badField- The "field not found" error occurs, when an unknown property is encountered in the dynamic or static configuration. -One easy way to check whether a configuration file is well-formed, is to validate it with: +One way to check whether a configuration file is well-formed, is to validate it with: - [JSON Schema of the static configuration](https://json.schemastore.org/traefik-v2.json) - [JSON Schema of the dynamic configuration](https://json.schemastore.org/traefik-v2-file-provider.json) @@ -226,11 +226,11 @@ One easy way to check whether a configuration file is well-formed, is to validat As a common tip, if a resource is dropped/not created by Traefik after the dynamic configuration was evaluated, one should look for an error in the logs. -If found, the error obviously confirms that something went wrong while creating the resource, +If found, the error confirms that something went wrong while creating the resource, and the message should help in figuring out the mistake(s) in the configuration, and how to fix it. When using the file provider, -one easy way to check if the dynamic configuration is well-formed is to validate it with the [JSON Schema of the dynamic configuration](https://json.schemastore.org/traefik-v2-file-provider.json). +one way to check if the dynamic configuration is well-formed is to validate it with the [JSON Schema of the dynamic configuration](https://json.schemastore.org/traefik-v2-file-provider.json). ## Why does Let's Encrypt wildcard certificate renewal/generation with DNS challenge fail? @@ -248,6 +248,6 @@ then it could be due to `CNAME` support. In which case, you should make sure your infrastructure is properly set up for a `DNS` challenge that does not rely on `CNAME`, and you should try disabling `CNAME` support with: -```bash +```shell LEGO_DISABLE_CNAME_SUPPORT=true ``` diff --git a/docs/content/getting-started/install-traefik.md b/docs/content/getting-started/install-traefik.md index 007d609c6..57dea428c 100644 --- a/docs/content/getting-started/install-traefik.md +++ b/docs/content/getting-started/install-traefik.md @@ -19,7 +19,7 @@ Choose one of the [official Docker images](https://hub.docker.com/_/traefik) and * [YAML](https://raw.githubusercontent.com/traefik/traefik/v2.10/traefik.sample.yml) * [TOML](https://raw.githubusercontent.com/traefik/traefik/v2.10/traefik.sample.toml) -```bash +```shell docker run -d -p 8080:8080 -p 80:80 \ -v $PWD/traefik.yml:/etc/traefik/traefik.yml traefik:v2.10 ``` @@ -59,7 +59,7 @@ You can update the chart repository by running: helm repo update ``` -And install it with the `helm` command line: +And install it with the Helm command line: ```bash helm install traefik traefik/traefik @@ -69,7 +69,7 @@ helm install traefik traefik/traefik All [Helm features](https://helm.sh/docs/intro/using_helm/) are supported. - Examples are provided [here](https://github.com/traefik/traefik-helm-chart/blob/master/EXAMPLES.md). + Examples are provided [here](https://github.com/traefik/traefik-helm-chart/blob/master/EXAMPLES.md). For instance, installing the chart in a dedicated namespace: @@ -106,7 +106,7 @@ helm install traefik traefik/traefik ### Exposing the Traefik dashboard -This HelmChart does not expose the Traefik dashboard by default, for security concerns. +This Helm chart does not expose the Traefik dashboard by default, for security concerns. Thus, there are multiple ways to expose the dashboard. For instance, the dashboard access could be achieved through a port-forward: diff --git a/docs/content/getting-started/quick-start-with-kubernetes.md b/docs/content/getting-started/quick-start-with-kubernetes.md index d1920690d..8359bc6ef 100644 --- a/docs/content/getting-started/quick-start-with-kubernetes.md +++ b/docs/content/getting-started/quick-start-with-kubernetes.md @@ -1,23 +1,23 @@ --- title: "Traefik Getting Started With Kubernetes" -description: "Looking to get started with Traefik Proxy? Read the technical documentation to learn a simple use case that leverages Kubernetes." +description: "Get started with Traefik Proxy and Kubernetes." --- # Quick Start -A Simple Use Case of Traefik Proxy and Kubernetes +A Use Case of Traefik Proxy and Kubernetes {: .subtitle } -This guide is an introduction to using Traefik Proxy in a Kubernetes environment. -The objective is to learn how to run an application behind a Traefik reverse proxy in Kubernetes. +This guide is an introduction to using Traefik Proxy in a Kubernetes environment. +The objective is to learn how to run an application behind a Traefik reverse proxy in Kubernetes. It presents and explains the basic blocks required to start with Traefik such as Ingress Controller, Ingresses, Deployments, static, and dynamic configuration. ## Permissions and Accesses Traefik uses the Kubernetes API to discover running services. -In order to use the Kubernetes API, Traefik needs some permissions. -This [permission mechanism](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) is based on roles defined by the cluster administrator. +To use the Kubernetes API, Traefik needs some permissions. +This [permission mechanism](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) is based on roles defined by the cluster administrator. The role is then bound to an account used by an application, in this case, Traefik Proxy. The first step is to create the role. @@ -88,7 +88,7 @@ roleRef: subjects: - kind: ServiceAccount name: traefik-account - namespace: default # Using "default" because we did not specify a namespace when creating the ClusterAccount. + namespace: default # This tutorial uses the "default" K8s namespace. ``` !!! info "`roleRef` is the Kubernetes reference to the role created in `00-role.yml`." @@ -102,7 +102,7 @@ subjects: !!! info "This section can be managed with the help of the [Traefik Helm chart](../install-traefik/#use-the-helm-chart)." The [ingress controller](https://traefik.io/glossary/kubernetes-ingress-and-ingress-controller-101/#what-is-a-kubernetes-ingress-controller) -is a software that runs in the same way as any other application on a cluster. +is a software that runs in the same way as any other application on a cluster. To start Traefik on the Kubernetes cluster, a [`Deployment`](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/deployment-v1/) resource must exist to describe how to configure and scale containers horizontally to support larger workloads. @@ -141,12 +141,12 @@ spec: containerPort: 8080 ``` -The deployment contains an important attribute for customizing Traefik: `args`. -These arguments are the static configuration for Traefik. +The deployment contains an important attribute for customizing Traefik: `args`. +These arguments are the static configuration for Traefik. From here, it is possible to enable the dashboard, configure entry points, select dynamic configuration providers, -and [more](../reference/static-configuration/cli.md)... +and [more](../reference/static-configuration/cli.md). In this deployment, the static configuration enables the Traefik dashboard, @@ -159,10 +159,10 @@ and uses Kubernetes native Ingress resources as router definitions to route inco !!! info "When enabling the [`api.insecure`](../../operations/api/#insecure) mode, Traefik exposes the dashboard on the port `8080`." A deployment manages scaling and then can create lots of containers, called [Pods](https://kubernetes.io/docs/concepts/workloads/pods/). -Each Pod is configured following the `spec` field in the deployment. +Each Pod is configured following the `spec` field in the deployment. Given that, a Deployment can run multiple Traefik Proxy Pods, a piece is required to forward the traffic to any of the instance: -namely a [`Service`](https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/#Service). +namely a [`Service`](https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/#Service). Create a file called `02-traefik-services.yml` and insert the two `Service` resources: ```yaml tab="02-traefik-services.yml" @@ -195,7 +195,7 @@ spec: !!! warning "It is possible to expose a service in different ways." - Depending on your working environment and use case, the `spec.type` might change. + Depending on your working environment and use case, the `spec.type` might change. It is strongly recommended to understand the available [service types](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) before proceeding to the next step. It is now time to apply those files on your cluster to start Traefik. @@ -210,11 +210,11 @@ kubectl apply -f 00-role.yml \ ## Proxying applications -The only part still missing is the business application behind the reverse proxy. +The only part still missing is the business application behind the reverse proxy. For this guide, we use the example application [traefik/whoami](https://github.com/traefik/whoami), but the principles are applicable to any other application. -The `whoami` application is a simple HTTP server running on port 80 which answers host-related information to the incoming requests. +The `whoami` application is an HTTP server running on port 80 which answers host-related information to the incoming requests. As usual, start by creating a file called `03-whoami.yml` and paste the following `Deployment` resource: ```yaml tab="03-whoami.yml" @@ -262,8 +262,8 @@ spec: ``` Thanks to the Kubernetes API, -Traefik is notified when an Ingress resource is created, updated, or deleted. -This makes the process dynamic. +Traefik is notified when an Ingress resource is created, updated, or deleted. +This makes the process dynamic. The ingresses are, in a way, the [dynamic configuration](../../providers/kubernetes-ingress/) for Traefik. !!! tip diff --git a/docs/content/getting-started/quick-start.md b/docs/content/getting-started/quick-start.md index 4c1a59eae..08e173011 100644 --- a/docs/content/getting-started/quick-start.md +++ b/docs/content/getting-started/quick-start.md @@ -1,11 +1,11 @@ --- title: "Traefik Getting Started Quickly" -description: "Looking to get started with Traefik Proxy quickly? Read the technical documentation to learn a simple use case that leverages Docker." +description: "Get started with Traefik Proxy and Docker." --- # Quick Start -A Simple Use Case Using Docker +A Use Case Using Docker {: .subtitle } ![quickstart-diagram](../assets/img/quickstart-diagram.png) @@ -41,11 +41,11 @@ Start your `reverse-proxy` with the following command: docker-compose up -d reverse-proxy ``` -You can open a browser and go to `http://localhost:8080/api/rawdata` to see Traefik's API rawdata (we'll go back there once we have launched a service in step 2). +You can open a browser and go to `http://localhost:8080/api/rawdata` to see Traefik's API rawdata (you'll go back there once you have launched a service in step 2). ## Traefik Detects New Services and Creates the Route for You -Now that we have a Traefik instance up and running, we will deploy new services. +Now that you have a Traefik instance up and running, you will deploy new services. Edit your `docker-compose.yml` file and add the following at the end of your file. @@ -63,7 +63,7 @@ services: - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)" ``` -The above defines `whoami`: a simple web service that outputs information about the machine it is deployed on (its IP address, host, and so on). +The above defines `whoami`: a web service that outputs information about the machine it is deployed on (its IP address, host, and others). Start the `whoami` service with the following command: @@ -73,7 +73,7 @@ docker-compose up -d whoami Go back to your browser (`http://localhost:8080/api/rawdata`) and see that Traefik has automatically detected the new container and updated its own configuration. -When Traefik detects new services, it creates the corresponding routes so you can call them ... _let's see!_ (Here, we're using curl) +When Traefik detects new services, it creates the corresponding routes so you can call them ... _let's see!_ (Here, you're using curl) ```shell curl -H Host:whoami.docker.localhost http://127.0.0.1 @@ -103,7 +103,7 @@ Finally, see that Traefik load-balances between the two instances of your servic curl -H Host:whoami.docker.localhost http://127.0.0.1 ``` -The output will show alternatively one of the followings: +The output will show alternatively one of the following: ```yaml Hostname: a656c8ddca6c diff --git a/docs/content/index.md b/docs/content/index.md index 6bb820f50..f4b16c8ff 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -18,7 +18,7 @@ Traefik is natively compliant with every major cluster technology, such as Kuber With Traefik, there is no need to maintain and synchronize a separate configuration file: everything happens automatically, in real time (no restarts, no connection interruptions). With Traefik, you spend time developing and deploying new features to your system, not on configuring and maintaining its working state. -Developing Traefik, our main goal is to make it simple to use, and we're sure you'll enjoy it. +Developing Traefik, our main goal is to make it effortless to use, and we're sure you'll enjoy it. -- The Traefik Maintainer Team diff --git a/docs/content/operations/dashboard.md b/docs/content/operations/dashboard.md index c838f0afd..8c3902cc8 100644 --- a/docs/content/operations/dashboard.md +++ b/docs/content/operations/dashboard.md @@ -71,11 +71,11 @@ with a router attached to the service `api@internal` in the to allow defining: - One or more security features through [middlewares](../middlewares/overview.md) - like authentication ([basicAuth](../middlewares/http/basicauth.md) , [digestAuth](../middlewares/http/digestauth.md), + like authentication ([basicAuth](../middlewares/http/basicauth.md), [digestAuth](../middlewares/http/digestauth.md), [forwardAuth](../middlewares/http/forwardauth.md)) or [whitelisting](../middlewares/http/ipwhitelist.md). - A [router rule](#dashboard-router-rule) for accessing the dashboard, - through Traefik itself (sometimes referred as "Traefik-ception"). + through Traefik itself (sometimes referred to as "Traefik-ception"). ### Dashboard Router Rule @@ -83,7 +83,7 @@ As underlined in the [documentation for the `api.dashboard` option](./api.md#das the [router rule](../routing/routers/index.md#rule) defined for Traefik must match the path prefixes `/api` and `/dashboard`. -We recommend to use a "Host Based rule" as ```Host(`traefik.example.com`)``` to match everything on the host domain, +We recommend using a "Host Based rule" as ```Host(`traefik.example.com`)``` to match everything on the host domain, or to make sure that the defined rule captures both prefixes: ```bash tab="Host Rule" diff --git a/docs/content/operations/ping.md b/docs/content/operations/ping.md index 3dc1de3d9..a2b4577f3 100644 --- a/docs/content/operations/ping.md +++ b/docs/content/operations/ping.md @@ -33,7 +33,7 @@ whose default value is `traefik` (port `8080`). | Path | Method | Description | |---------|---------------|-----------------------------------------------------------------------------------------------------| -| `/ping` | `GET`, `HEAD` | A simple endpoint to check for Traefik process liveness. Return a code `200` with the content: `OK` | +| `/ping` | `GET`, `HEAD` | An endpoint to check for Traefik process liveness. Return a code `200` with the content: `OK` | !!! note The `cli` comes with a [`healthcheck`](./cli.md#healthcheck) command which can be used for calling this endpoint. @@ -92,10 +92,11 @@ ping: _Optional, Default=503_ During the period in which Traefik is gracefully shutting down, the ping handler -returns a 503 status code by default. If Traefik is behind e.g. a load-balancer +returns a `503` status code by default. +If Traefik is behind, for example a load-balancer doing health checks (such as the Kubernetes LivenessProbe), another code might -be expected as the signal for graceful termination. In which case, the -terminatingStatusCode can be used to set the code returned by the ping +be expected as the signal for graceful termination. +In that case, the terminatingStatusCode can be used to set the code returned by the ping handler during termination. ```yaml tab="File (YAML)" From 6df9578acec8cb202d320fb170fbd5df36752ecf Mon Sep 17 00:00:00 2001 From: sven Date: Tue, 2 Jan 2024 17:56:06 +0100 Subject: [PATCH 09/21] Update wording of compose example --- .../docker-compose/basic-example/index.md | 66 +++++++++++-------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/docs/content/user-guides/docker-compose/basic-example/index.md b/docs/content/user-guides/docker-compose/basic-example/index.md index f91520fae..65b5e3d7a 100644 --- a/docs/content/user-guides/docker-compose/basic-example/index.md +++ b/docs/content/user-guides/docker-compose/basic-example/index.md @@ -1,16 +1,15 @@ --- title: "Traefik Docker Documentation" -description: "This guide covers a Docker Compose file exposing a service using the Docker provider in Traefik Proxy. Read the technical documentation." +description: "Learn how to use Docker Compose to expose a service with Traefik Proxy." --- # Docker Compose example -In this section, we quickly go over a Docker Compose file exposing a service using the Docker provider. -This will also be used as a starting point for the other Docker Compose guides. +In this section, you will learn how to use [Docker Compose](https://docs.docker.com/compose/ "Link to Docker Compose") to expose a service using the Docker provider. ## Setup -- Edit a `docker-compose.yml` file with the following content: +Create a `docker-compose.yml` file with the following content: ```yaml --8<-- "content/user-guides/docker-compose/basic-example/docker-compose.yml" @@ -45,33 +44,44 @@ This will also be used as a starting point for the other Docker Compose guides. ``` -- Replace `whoami.localhost` by your **own domain** within the `traefik.http.routers.whoami.rule` label of the `whoami` service. -- Run `docker-compose up -d` within the folder where you created the previous file. -- Wait a bit and visit `http://your_own_domain` to confirm everything went fine. - You should see the output of the whoami service. Something similar to: +Replace `whoami.localhost` by your **own domain** within the `traefik.http.routers.whoami.rule` label of the `whoami` service. - ```text - Hostname: d7f919e54651 - IP: 127.0.0.1 - IP: 192.168.64.2 - GET / HTTP/1.1 - Host: whoami.localhost - User-Agent: curl/7.52.1 - Accept: */* - Accept-Encoding: gzip - X-Forwarded-For: 192.168.64.1 - X-Forwarded-Host: whoami.localhost - X-Forwarded-Port: 80 - X-Forwarded-Proto: http - X-Forwarded-Server: 7f0c797dbc51 - X-Real-Ip: 192.168.64.1 - ``` +Now run `docker-compose up -d` within the folder where you created the previous file. +This will start Docker Compose in background mode. + +!!! info "This can take a moment" + + Docker Compose will now create and start the services declared in the `docker-compose.yml`. + +Wait a bit and visit `http://your_own_domain` to confirm everything went fine. + +You should see the output of the whoami service. +It should be similar to the following example: + +```text +Hostname: d7f919e54651 +IP: 127.0.0.1 +IP: 192.168.64.2 +GET / HTTP/1.1 +Host: whoami.localhost +User-Agent: curl/7.52.1 +Accept: */* +Accept-Encoding: gzip +X-Forwarded-For: 192.168.64.1 +X-Forwarded-Host: whoami.localhost +X-Forwarded-Port: 80 +X-Forwarded-Proto: http +X-Forwarded-Server: 7f0c797dbc51 +X-Real-Ip: 192.168.64.1 +``` ## Details -- As an example, we use [whoami](https://github.com/traefik/whoami "Link to the GitHub repo of whoami") (a tiny Go server that prints OS information and HTTP request to output) which was used to define our `simple-service` container. +Let's break it down and go through it, step-by-step. -- We define an entry point, along with the exposure of the matching port within Docker Compose, which allow us to "open and accept" HTTP traffic: +You use [whoami](https://github.com/traefik/whoami "Link to the GitHub repo of whoami"), a tiny Go server that prints OS information and HTTP request to output as service container. + +Second, you define an entry point, along with the exposure of the matching port within Docker Compose, which allows to "open and accept" HTTP traffic: ```yaml command: @@ -82,7 +92,7 @@ ports: - "80:80" ``` -- We expose the Traefik API to be able to check the configuration if needed: +Third, you expose the Traefik API to be able to check the configuration if needed: ```yaml command: @@ -101,7 +111,7 @@ ports: curl -s 127.0.0.1:8080/api/rawdata | jq . ``` -- We allow Traefik to gather configuration from Docker: +Fourth, you allow Traefik to gather configuration from Docker: ```yaml traefik: From 74ab88d47e5a5e0fff1e9171fff9baea7e3322bf Mon Sep 17 00:00:00 2001 From: Ari Yonaty Date: Tue, 2 Jan 2024 09:20:06 -0800 Subject: [PATCH 10/21] docs: fix description for anonymous usage statistics references --- docs/content/reference/static-configuration/cli-ref.md | 2 +- docs/content/reference/static-configuration/env-ref.md | 2 +- pkg/config/static/static_config.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index 03409a1c3..f67a3b3c1 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -217,7 +217,7 @@ plugin's version. Periodically check if a new version has been released. (Default: ```true```) `--global.sendanonymoususage`: -Periodically send anonymous usage statistics. If the option is not specified, it will be enabled by default. (Default: ```false```) +Periodically send anonymous usage statistics. If the option is not specified, it will be disabled by default. (Default: ```false```) `--hostresolver`: Enable CNAME Flattening. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index d3de13a66..41eb2697f 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -217,7 +217,7 @@ plugin's version. Periodically check if a new version has been released. (Default: ```true```) `TRAEFIK_GLOBAL_SENDANONYMOUSUSAGE`: -Periodically send anonymous usage statistics. If the option is not specified, it will be enabled by default. (Default: ```false```) +Periodically send anonymous usage statistics. If the option is not specified, it will be disabled by default. (Default: ```false```) `TRAEFIK_HOSTRESOLVER`: Enable CNAME Flattening. (Default: ```false```) diff --git a/pkg/config/static/static_config.go b/pkg/config/static/static_config.go index e3419fd7a..669226083 100644 --- a/pkg/config/static/static_config.go +++ b/pkg/config/static/static_config.go @@ -91,7 +91,7 @@ type CertificateResolver struct { // Global holds the global configuration. type Global struct { CheckNewVersion bool `description:"Periodically check if a new version has been released." json:"checkNewVersion,omitempty" toml:"checkNewVersion,omitempty" yaml:"checkNewVersion,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` - SendAnonymousUsage bool `description:"Periodically send anonymous usage statistics. If the option is not specified, it will be enabled by default." json:"sendAnonymousUsage,omitempty" toml:"sendAnonymousUsage,omitempty" yaml:"sendAnonymousUsage,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` + SendAnonymousUsage bool `description:"Periodically send anonymous usage statistics. If the option is not specified, it will be disabled by default." json:"sendAnonymousUsage,omitempty" toml:"sendAnonymousUsage,omitempty" yaml:"sendAnonymousUsage,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` } // ServersTransport options to configure communication between Traefik and the servers. From 004256267888302b5478074a05ba62034a78c7d3 Mon Sep 17 00:00:00 2001 From: Domenico Andreoli Date: Tue, 2 Jan 2024 18:46:05 +0100 Subject: [PATCH 11/21] docs: fix the explanation of the TLS challenge --- .../user-guides/docker-compose/acme-dns/index.md | 10 +++++----- .../user-guides/docker-compose/acme-http/index.md | 10 +++++----- .../user-guides/docker-compose/acme-tls/index.md | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/content/user-guides/docker-compose/acme-dns/index.md b/docs/content/user-guides/docker-compose/acme-dns/index.md index 59872c44e..56f32ed33 100644 --- a/docs/content/user-guides/docker-compose/acme-dns/index.md +++ b/docs/content/user-guides/docker-compose/acme-dns/index.md @@ -3,9 +3,9 @@ title: "Traefik Docker DNS Challenge Documentation" description: "Learn how to create a certificate with the Let's Encrypt DNS challenge to use HTTPS on a Service exposed with Traefik Proxy. Read the tehnical documentation." --- -# Docker-compose with let's encrypt: DNS Challenge +# Docker-compose with Let's Encrypt: DNS Challenge -This guide aim to demonstrate how to create a certificate with the let's encrypt DNS challenge to use https on a simple service exposed with Traefik. +This guide aim to demonstrate how to create a certificate with the Let's Encrypt DNS challenge to use https on a simple service exposed with Traefik. Please also read the [basic example](../basic-example) for details on how to expose such a service. ## Prerequisite @@ -52,7 +52,7 @@ For the DNS challenge, you'll need: !!! Note If you uncommented the `acme.caserver` line, you will get an SSL error, but if you display the certificate and see it was emitted by `Fake LE Intermediate X1` then it means all is good. - (It is the staging environment intermediate certificate used by let's encrypt). + (It is the staging environment intermediate certificate used by Let's Encrypt). You can now safely comment the `acme.caserver` line, remove the `letsencrypt/acme.json` file and restart Traefik to issue a valid certificate. ## Explanation @@ -69,7 +69,7 @@ ports: - "443:443" ``` -- We configure the DNS let's encrypt challenge: +- We configure the DNS Let's Encrypt challenge: ```yaml command: @@ -77,7 +77,7 @@ command: - "--certificatesresolvers.myresolver.acme.dnschallenge=true" # Tell which provider to use - "--certificatesresolvers.myresolver.acme.dnschallenge.provider=ovh" - # The email to provide to let's encrypt + # The email to provide to Let's Encrypt - "--certificatesresolvers.myresolver.acme.email=postmaster@example.com" ``` diff --git a/docs/content/user-guides/docker-compose/acme-http/index.md b/docs/content/user-guides/docker-compose/acme-http/index.md index 7f8a05873..67808853e 100644 --- a/docs/content/user-guides/docker-compose/acme-http/index.md +++ b/docs/content/user-guides/docker-compose/acme-http/index.md @@ -3,9 +3,9 @@ title: "Traefik Docker HTTP Challenge Documentation" description: "Learn how to create a certificate with the Let's Encrypt HTTP challenge to use HTTPS on a Service exposed with Traefik Proxy. Read the technical documentation." --- -# Docker-compose with let's encrypt : HTTP Challenge +# Docker-compose with Let's Encrypt : HTTP Challenge -This guide aim to demonstrate how to create a certificate with the let's encrypt HTTP challenge to use https on a simple service exposed with Traefik. +This guide aim to demonstrate how to create a certificate with the Let's Encrypt HTTP challenge to use https on a simple service exposed with Traefik. Please also read the [basic example](../basic-example) for details on how to expose such a service. ## Prerequisite @@ -38,7 +38,7 @@ For the HTTP challenge you will need: !!! Note If you uncommented the `acme.caserver` line, you will get an SSL error, but if you display the certificate and see it was emitted by `Fake LE Intermediate X1` then it means all is good. - (It is the staging environment intermediate certificate used by let's encrypt). + (It is the staging environment intermediate certificate used by Let's Encrypt). You can now safely comment the `acme.caserver` line, remove the `letsencrypt/acme.json` file and restart Traefik to issue a valid certificate. ## Explanation @@ -55,7 +55,7 @@ ports: - "443:443" ``` -- We configure the HTTPS let's encrypt challenge: +- We configure the HTTPS Let's Encrypt challenge: ```yaml command: @@ -63,7 +63,7 @@ command: - "--certificatesresolvers.myresolver.acme.httpchallenge=true" # Tell it to use our predefined entrypoint named "web" - "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web" - # The email to provide to let's encrypt + # The email to provide to Let's Encrypt - "--certificatesresolvers.myresolver.acme.email=postmaster@example.com" ``` diff --git a/docs/content/user-guides/docker-compose/acme-tls/index.md b/docs/content/user-guides/docker-compose/acme-tls/index.md index 3457b6ae1..b201a4c95 100644 --- a/docs/content/user-guides/docker-compose/acme-tls/index.md +++ b/docs/content/user-guides/docker-compose/acme-tls/index.md @@ -3,9 +3,9 @@ title: "Traefik Docker TLS Challenge Documentation" description: "Learn how to create a certificate with the Let's Encrypt TLS challenge to use HTTPS on a service exposed with Traefik Proxy. Read the technical documentation." --- -# Docker-compose with let's encrypt: TLS Challenge +# Docker-compose with Let's Encrypt: TLS Challenge -This guide aim to demonstrate how to create a certificate with the let's encrypt TLS challenge to use https on a simple service exposed with Traefik. +This guide aim to demonstrate how to create a certificate with the Let's Encrypt TLS challenge to use https on a simple service exposed with Traefik. Please also read the [basic example](../basic-example) for details on how to expose such a service. ## Prerequisite @@ -38,7 +38,7 @@ For the TLS challenge you will need: !!! Note If you uncommented the `acme.caserver` line, you will get an SSL error, but if you display the certificate and see it was emitted by `Fake LE Intermediate X1` then it means all is good. - (It is the staging environment intermediate certificate used by let's encrypt). + (It is the staging environment intermediate certificate used by Let's Encrypt). You can now safely comment the `acme.caserver` line, remove the `letsencrypt/acme.json` file and restart Traefik to issue a valid certificate. ## Explanation @@ -55,7 +55,7 @@ ports: - "443:443" ``` -- We configure the Https let's encrypt challenge: +- We configure the TLS Let's Encrypt challenge: ```yaml command: From 2a9471d2781dfb5e66e874811ff221983df4e8ee Mon Sep 17 00:00:00 2001 From: youpsla Date: Tue, 2 Jan 2024 19:12:06 +0100 Subject: [PATCH 12/21] docs: fix typo --- docs/content/user-guides/docker-compose/acme-dns/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/user-guides/docker-compose/acme-dns/index.md b/docs/content/user-guides/docker-compose/acme-dns/index.md index 56f32ed33..84fc9c8dc 100644 --- a/docs/content/user-guides/docker-compose/acme-dns/index.md +++ b/docs/content/user-guides/docker-compose/acme-dns/index.md @@ -175,7 +175,7 @@ services: - "ovh_consumer_key" ``` -- The environment variable within our `whoami` service are suffixed by `_FILE` which allow us to point to files containing the value, instead of exposing the value itself. +- The environment variable within our `traefik` service are suffixed by `_FILE` which allow us to point to files containing the value, instead of exposing the value itself. The acme client will read the content of those file to get the required configuration values. ```yaml From a84d5c0ef1379b9e863d0c32927a614d3478761e Mon Sep 17 00:00:00 2001 From: Romain Date: Tue, 2 Jan 2024 20:04:06 +0100 Subject: [PATCH 13/21] Adjust deprecation notice for Kubernetes CRD provider Co-authored-by: Baptiste Mayelle --- docs/content/deprecation/features.md | 24 +++++++++++------------ pkg/provider/kubernetes/crd/kubernetes.go | 1 - 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/docs/content/deprecation/features.md b/docs/content/deprecation/features.md index c9e54134f..1ae7e8b93 100644 --- a/docs/content/deprecation/features.md +++ b/docs/content/deprecation/features.md @@ -2,14 +2,14 @@ This page is maintained and updated periodically to reflect our roadmap and any decisions around feature deprecation. -| Feature | Deprecated | End of Support | Removal | -|-----------------------------------------------------------------------------------------------------|------------|----------------|---------| -| [Pilot](#pilot) | 2.7 | 2.8 | 2.9 | -| [Consul Enterprise Namespace](#consul-enterprise-namespace) | 2.8 | N/A | 3.0 | -| [TLS 1.0 and 1.1 Support](#tls-10-and-11) | N/A | 2.8 | N/A | -| [Nomad Namespace](#nomad-namespace) | 2.10 | N/A | 3.0 | -| [Kubernetes CRDs API Group `traefik.containo.us`](#kubernetes-crds-api-group-traefikcontainous) | 2.10 | N/A | 3.0 | -| [Kubernetes CRDs API Version `traefik.io/v1alpha1`](#kubernetes-crds-api-version-traefikiov1alpha1) | N/A | N/A | 3.0 | +| Feature | Deprecated | End of Support | Removal | +|-------------------------------------------------------------------------------------------------------------|------------|----------------|---------| +| [Pilot](#pilot) | 2.7 | 2.8 | 2.9 | +| [Consul Enterprise Namespace](#consul-enterprise-namespace) | 2.8 | N/A | 3.0 | +| [TLS 1.0 and 1.1 Support](#tls-10-and-11) | N/A | 2.8 | N/A | +| [Nomad Namespace](#nomad-namespace) | 2.10 | N/A | 3.0 | +| [Kubernetes CRDs API Group `traefik.containo.us`](#kubernetes-crd-provider-api-group-traefikcontainous) | 2.10 | N/A | 3.0 | +| [Kubernetes CRDs API Version `traefik.io/v1alpha1`](#kubernetes-crd-provider-api-version-traefikiov1alpha1) | 3.0 | N/A | 4.0 | ## Impact @@ -35,10 +35,10 @@ Starting on 2.8 the default TLS options will use the minimum version of TLS 1.2. Starting on 2.10 the `namespace` option of the Nomad provider is deprecated, please use the `namespaces` options instead. -### Kubernetes CRDs API Group `traefik.containo.us` +### Kubernetes CRD Provider API Group `traefik.containo.us` -In v2.10, the Kubernetes CRDs API Group `traefik.containo.us` is deprecated, and its support will end starting with Traefik v3. Please use the API Group `traefik.io` instead. +In v2.10, the Kubernetes CRD provider API Group `traefik.containo.us` is deprecated, and its support will end starting with Traefik v3. Please use the API Group `traefik.io` instead. -### Kubernetes CRDs API Version `traefik.io/v1alpha1` +### Kubernetes CRD Provider API Version `traefik.io/v1alpha1` -The newly introduced Kubernetes CRD API Version `traefik.io/v1alpha1` will subsequently be removed in Traefik v3. The following version will be `traefik.io/v1`. +The Kubernetes CRD provider API Version `traefik.io/v1alpha1` will subsequently be deprecated in Traefik v3. The next version will be `traefik.io/v1`. diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index 03807ac9c..65f859215 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -123,7 +123,6 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. logger := log.FromContext(ctxLog) logger.Warn("CRDs API Group \"traefik.containo.us\" is deprecated, and its support will end starting with Traefik v3. Please use the API Group \"traefik.io\" instead.") - logger.Warn("CRDs API Version \"traefik.io/v1alpha1\" will not be supported in Traefik v3 itself. However, an automatic migration path to the next version will be available.") k8sClient, err := p.newK8sClient(ctxLog) if err != nil { From 7345afd8b630a0cedb5271205b98efbffb178caf Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Tue, 2 Jan 2024 20:36:06 +0100 Subject: [PATCH 14/21] Update quic-go to v0.40.1 --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 62ac8306b..b46d2528a 100644 --- a/go.mod +++ b/go.mod @@ -53,7 +53,7 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 - github.com/quic-go/quic-go v0.39.1 + github.com/quic-go/quic-go v0.40.1 github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.8.4 @@ -293,7 +293,7 @@ require ( github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/qtls-go1-20 v0.3.4 // indirect + github.com/quic-go/qtls-go1-20 v0.4.1 // indirect github.com/redis/go-redis/v9 v9.2.1 // indirect github.com/sacloud/api-client-go v0.2.8 // indirect github.com/sacloud/go-http v0.1.6 // indirect diff --git a/go.sum b/go.sum index ea218e429..136bd54ec 100644 --- a/go.sum +++ b/go.sum @@ -1579,10 +1579,10 @@ github.com/qri-io/jsonpointer v0.1.0/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH github.com/qri-io/jsonschema v0.1.1/go.mod h1:QpzJ6gBQ0GYgGmh7mDQ1YsvvhSgE4rYj0k8t5MBOmUY= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg= -github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= -github.com/quic-go/quic-go v0.39.1 h1:d/m3oaN/SD2c+f7/yEjZxe2zEVotXprnrCCJ2y/ZZFE= -github.com/quic-go/quic-go v0.39.1/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q= +github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs= +github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= +github.com/quic-go/quic-go v0.40.1 h1:X3AGzUNFs0jVuO3esAGnTfvdgvL4fq655WaOi1snv1Q= +github.com/quic-go/quic-go v0.40.1/go.mod h1:PeN7kuVJ4xZbxSv/4OX6S1USOX8MJvydwpTx31vx60c= github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac h1:wBGhHdXKICZmvAPWS8gQoMyOWDH7QAi9bU4Z1nDWnFU= github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac/go.mod h1:67sLWL17mVlO1HFROaTBmU71NB4R8UNCesFHhg0f6LQ= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= From 5be13802dcb7f3d4599a89f7a399f6eb4454363d Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Tue, 2 Jan 2024 20:58:06 +0100 Subject: [PATCH 15/21] chore: update github.com/fsnotify/fsnotify to v1.7.0 --- go.mod | 3 +-- go.sum | 6 ++---- pkg/provider/file/file.go | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index b46d2528a..96545f462 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( github.com/docker/docker v20.10.21+incompatible github.com/docker/go-connections v0.4.0 github.com/fatih/structs v1.1.0 + github.com/fsnotify/fsnotify v1.7.0 github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2 github.com/go-acme/lego/v4 v4.14.0 github.com/go-check/check v0.0.0-00010101000000-000000000000 @@ -76,7 +77,6 @@ require ( golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 google.golang.org/grpc v1.58.3 gopkg.in/DataDog/dd-trace-go.v1 v1.56.1 - gopkg.in/fsnotify.v1 v1.4.7 gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.26.3 k8s.io/apiextensions-apiserver v0.26.3 @@ -179,7 +179,6 @@ require ( github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/exoscale/egoscale v0.100.1 // indirect github.com/fatih/color v1.15.0 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/fvbommel/sortorder v1.0.1 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-errors/errors v1.0.1 // indirect diff --git a/go.sum b/go.sum index 136bd54ec..23db178eb 100644 --- a/go.sum +++ b/go.sum @@ -672,8 +672,8 @@ github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE= github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= @@ -2227,7 +2227,6 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/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.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2515,7 +2514,6 @@ gopkg.in/dancannon/gorethink.v3 v3.0.5/go.mod h1:GXsi1e3N2OcKhcP6nsYABTiUejbWMFO gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fatih/pool.v2 v2.0.0 h1:xIFeWtxifuQJGk/IEPKsTduEKcKvPmhoiVDGpC40nKg= gopkg.in/fatih/pool.v2 v2.0.0/go.mod h1:8xVGeu1/2jr2wm5V9SPuMht2H5AEmf5aFMGSQixtjTY= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= diff --git a/pkg/provider/file/file.go b/pkg/provider/file/file.go index 548f0cbc4..21599431c 100644 --- a/pkg/provider/file/file.go +++ b/pkg/provider/file/file.go @@ -11,13 +11,13 @@ import ( "text/template" "github.com/Masterminds/sprig/v3" + "github.com/fsnotify/fsnotify" "github.com/traefik/paerser/file" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/provider" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/tls" - "gopkg.in/fsnotify.v1" ) const providerName = "file" From 56e2110dc586f468c9b5c68dabe41f38fcd6d0ff Mon Sep 17 00:00:00 2001 From: Julien Salleyron Date: Tue, 2 Jan 2024 22:02:05 +0100 Subject: [PATCH 16/21] Fix readHeaderTimeout in proxyproto --- pkg/server/server_entrypoint_tcp.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/server/server_entrypoint_tcp.go b/pkg/server/server_entrypoint_tcp.go index e3e22998e..26b417293 100644 --- a/pkg/server/server_entrypoint_tcp.go +++ b/pkg/server/server_entrypoint_tcp.go @@ -418,7 +418,12 @@ func (ln tcpKeepAliveListener) Accept() (net.Conn, error) { } func buildProxyProtocolListener(ctx context.Context, entryPoint *static.EntryPoint, listener net.Listener) (net.Listener, error) { - proxyListener := &proxyproto.Listener{Listener: listener} + timeout := entryPoint.Transport.RespondingTimeouts.ReadTimeout + // proxyproto use 200ms if ReadHeaderTimeout is set to 0 and not no timeout + if timeout == 0 { + timeout = -1 + } + proxyListener := &proxyproto.Listener{Listener: listener, ReadHeaderTimeout: time.Duration(timeout)} if entryPoint.ProxyProtocol.Insecure { log.FromContext(ctx).Infof("Enabling ProxyProtocol without trusted IPs: Insecure") From 9adf0fb638d9c252a079459263c1b2635302331e Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 3 Jan 2024 11:12:05 +0100 Subject: [PATCH 17/21] Prepare release v2.11.0-rc1 --- .github/PULL_REQUEST_TEMPLATE.md | 4 +- .semaphore/semaphore.yml | 2 +- CHANGELOG.md | 22 ++ .../getting-started/configuration-overview.md | 2 +- .../getting-started/install-traefik.md | 8 +- .../quick-start-with-kubernetes.md | 2 +- docs/content/getting-started/quick-start.md | 2 +- docs/content/observability/access-logs.md | 2 +- docs/content/providers/docker.md | 2 +- docs/content/providers/kubernetes-crd.md | 4 +- docs/content/providers/kubernetes-ingress.md | 2 +- .../kubernetes-crd-definition-v1.yml | 276 +++++++++--------- .../kubernetes-gateway-traefik-lb-svc.yml | 2 +- .../traefik.containo.us_ingressroutes.yaml | 26 +- .../traefik.containo.us_ingressroutetcps.yaml | 16 +- .../traefik.containo.us_ingressrouteudps.yaml | 2 +- .../traefik.containo.us_middlewares.yaml | 66 ++--- .../traefik.containo.us_middlewaretcps.yaml | 6 +- ...traefik.containo.us_serverstransports.yaml | 2 +- .../traefik.containo.us_tlsoptions.yaml | 8 +- .../traefik.containo.us_tlsstores.yaml | 2 +- .../traefik.containo.us_traefikservices.yaml | 10 +- .../traefik.io_ingressroutes.yaml | 26 +- .../traefik.io_ingressroutetcps.yaml | 16 +- .../traefik.io_ingressrouteudps.yaml | 2 +- .../traefik.io_middlewares.yaml | 66 ++--- .../traefik.io_middlewaretcps.yaml | 6 +- .../traefik.io_serverstransports.yaml | 2 +- .../traefik.io_tlsoptions.yaml | 8 +- .../traefik.io_tlsstores.yaml | 2 +- .../traefik.io_traefikservices.yaml | 10 +- .../routing/providers/kubernetes-crd.md | 2 +- .../routing/providers/kubernetes-ingress.md | 6 +- .../user-guides/crd-acme/03-deployments.yml | 2 +- docs/content/user-guides/crd-acme/index.md | 12 +- docs/content/user-guides/crd-acme/k3s.yml | 2 +- .../acme-dns/docker-compose.yml | 2 +- .../acme-dns/docker-compose_secrets.yml | 2 +- .../acme-http/docker-compose.yml | 2 +- .../acme-tls/docker-compose.yml | 2 +- .../basic-example/docker-compose.yml | 2 +- .../docker-compose/basic-example/index.md | 2 +- integration/fixtures/k8s/01-traefik-crd.yml | 276 +++++++++--------- pkg/config/dynamic/middlewares.go | 50 ++-- pkg/config/dynamic/tcp_config.go | 2 +- pkg/config/dynamic/tcp_middlewares.go | 2 +- .../v1alpha1/ingressroute.go | 28 +- .../v1alpha1/ingressroutetcp.go | 18 +- .../v1alpha1/ingressrouteudp.go | 2 +- .../traefikcontainous/v1alpha1/middleware.go | 24 +- .../v1alpha1/middlewaretcp.go | 6 +- .../v1alpha1/serverstransport.go | 2 +- .../crd/traefikcontainous/v1alpha1/service.go | 8 +- .../traefikcontainous/v1alpha1/tlsoption.go | 8 +- .../traefikcontainous/v1alpha1/tlsstore.go | 2 +- .../crd/traefikio/v1alpha1/ingressroute.go | 28 +- .../crd/traefikio/v1alpha1/ingressroutetcp.go | 18 +- .../crd/traefikio/v1alpha1/ingressrouteudp.go | 2 +- .../crd/traefikio/v1alpha1/middleware.go | 24 +- .../crd/traefikio/v1alpha1/middlewaretcp.go | 6 +- .../traefikio/v1alpha1/serverstransport.go | 2 +- .../crd/traefikio/v1alpha1/service.go | 8 +- .../crd/traefikio/v1alpha1/tlsoption.go | 8 +- .../crd/traefikio/v1alpha1/tlsstore.go | 2 +- script/gcg/traefik-bugfix.toml | 10 +- script/gcg/traefik-final-release-part1.toml | 10 +- script/gcg/traefik-final-release-part2.toml | 8 +- script/gcg/traefik-rc-first.toml | 6 +- script/gcg/traefik-rc-new.toml | 10 +- 69 files changed, 617 insertions(+), 595 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index b01448af0..1cade3ff1 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,11 +2,11 @@ PLEASE READ THIS MESSAGE. Documentation fixes or enhancements: -- for Traefik v2: use branch v2.10 +- for Traefik v2: use branch v2.11 - for Traefik v3: use branch v3.0 Bug fixes: -- for Traefik v2: use branch v2.10 +- for Traefik v2: use branch v2.11 - for Traefik v3: use branch v3.0 Enhancements: diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index a4a01946f..d9a63e1f7 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -64,7 +64,7 @@ blocks: - name: GH_VERSION value: 2.32.1 - name: CODENAME - value: "saintmarcelin" + value: "mimolette" - name: IN_DOCKER value: "" prologue: diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d40ab83e..a38879596 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ +## [v2.11.0-rc1](https://github.com/traefik/traefik/tree/v2.11.0-rc1) (2024-01-02) +[All Commits](https://github.com/traefik/traefik/compare/0a7964300166d167f68d5502bc245b3b9c8842b4...v2.11.0-rc1) + +**Enhancements:** +- **[middleware]** Deprecate IPWhiteList middleware in favor of IPAllowList ([#10249](https://github.com/traefik/traefik/pull/10249) by [lbenguigui](https://github.com/lbenguigui)) +- **[redis]** Add Redis Sentinel support ([#10245](https://github.com/traefik/traefik/pull/10245) by [youkoulayley](https://github.com/youkoulayley)) +- **[server]** Add KeepAliveMaxTime and KeepAliveMaxRequests features to entrypoints ([#10247](https://github.com/traefik/traefik/pull/10247) by [juliens](https://github.com/juliens)) +- **[sticky-session]** Hash WRR sticky cookies ([#10243](https://github.com/traefik/traefik/pull/10243) by [youkoulayley](https://github.com/youkoulayley)) + +**Bug fixes:** +- **[file]** Update github.com/fsnotify/fsnotify to v1.7.0 ([#10313](https://github.com/traefik/traefik/pull/10313) by [ldez](https://github.com/ldez)) +- **[http3]** Update quic-go to v0.40.1 ([#10296](https://github.com/traefik/traefik/pull/10296) by [ldez](https://github.com/ldez)) +- **[server]** Fix ReadHeaderTimeout for PROXY protocol ([#10320](https://github.com/traefik/traefik/pull/10320) by [juliens](https://github.com/juliens)) + +**Documentation:** +- **[acme]** Fix TLS challenge explanation ([#10293](https://github.com/traefik/traefik/pull/10293) by [cavokz](https://github.com/cavokz)) +- **[docker,acme]** Fix typo ([#10294](https://github.com/traefik/traefik/pull/10294) by [youpsla](https://github.com/youpsla)) +- **[docker]** Update wording of compose example ([#10276](https://github.com/traefik/traefik/pull/10276) by [svx](https://github.com/svx)) +- **[k8s/crd]** Adjust deprecation notice for Kubernetes CRD provider ([#10317](https://github.com/traefik/traefik/pull/10317) by [rtribotte](https://github.com/rtribotte)) +- Fix description for anonymous usage statistics references ([#10287](https://github.com/traefik/traefik/pull/10287) by [ariyonaty](https://github.com/ariyonaty)) +- Documentation enhancements ([#10261](https://github.com/traefik/traefik/pull/10261) by [svx](https://github.com/svx)) + ## [v2.10.7](https://github.com/traefik/traefik/tree/v2.10.7) (2023-12-06) [All Commits](https://github.com/traefik/traefik/compare/v2.10.6...v2.10.7) diff --git a/docs/content/getting-started/configuration-overview.md b/docs/content/getting-started/configuration-overview.md index 2e5e10c50..734e29871 100644 --- a/docs/content/getting-started/configuration-overview.md +++ b/docs/content/getting-started/configuration-overview.md @@ -79,7 +79,7 @@ traefik --help # or docker run traefik[:version] --help -# ex: docker run traefik:v2.10 --help +# ex: docker run traefik:v2.11 --help ``` Check the [CLI reference](../reference/static-configuration/cli.md "Link to CLI reference overview") for an overview about all available arguments. diff --git a/docs/content/getting-started/install-traefik.md b/docs/content/getting-started/install-traefik.md index 57dea428c..b97a8fc32 100644 --- a/docs/content/getting-started/install-traefik.md +++ b/docs/content/getting-started/install-traefik.md @@ -16,12 +16,12 @@ You can install Traefik with the following flavors: Choose one of the [official Docker images](https://hub.docker.com/_/traefik) and run it with one sample configuration file: -* [YAML](https://raw.githubusercontent.com/traefik/traefik/v2.10/traefik.sample.yml) -* [TOML](https://raw.githubusercontent.com/traefik/traefik/v2.10/traefik.sample.toml) +* [YAML](https://raw.githubusercontent.com/traefik/traefik/v2.11/traefik.sample.yml) +* [TOML](https://raw.githubusercontent.com/traefik/traefik/v2.11/traefik.sample.toml) ```shell docker run -d -p 8080:8080 -p 80:80 \ - -v $PWD/traefik.yml:/etc/traefik/traefik.yml traefik:v2.10 + -v $PWD/traefik.yml:/etc/traefik/traefik.yml traefik:v2.11 ``` For more details, go to the [Docker provider documentation](../providers/docker.md) @@ -29,7 +29,7 @@ For more details, go to the [Docker provider documentation](../providers/docker. !!! tip * Prefer a fixed version than the latest that could be an unexpected version. - ex: `traefik:v2.10` + ex: `traefik:v2.11` * Docker images are based from the [Alpine Linux Official image](https://hub.docker.com/_/alpine). * Any orchestrator using docker images can fetch the official Traefik docker image. diff --git a/docs/content/getting-started/quick-start-with-kubernetes.md b/docs/content/getting-started/quick-start-with-kubernetes.md index 8359bc6ef..e81cd07b0 100644 --- a/docs/content/getting-started/quick-start-with-kubernetes.md +++ b/docs/content/getting-started/quick-start-with-kubernetes.md @@ -130,7 +130,7 @@ spec: serviceAccountName: traefik-account containers: - name: traefik - image: traefik:v2.10 + image: traefik:v2.11 args: - --api.insecure - --providers.kubernetesingress diff --git a/docs/content/getting-started/quick-start.md b/docs/content/getting-started/quick-start.md index 08e173011..6ebb1b065 100644 --- a/docs/content/getting-started/quick-start.md +++ b/docs/content/getting-started/quick-start.md @@ -20,7 +20,7 @@ version: '3' services: reverse-proxy: # The official v2 Traefik docker image - image: traefik:v2.10 + image: traefik:v2.11 # Enables the web UI and tells Traefik to listen to docker command: --api.insecure=true --providers.docker ports: diff --git a/docs/content/observability/access-logs.md b/docs/content/observability/access-logs.md index 73c581ece..f96473a95 100644 --- a/docs/content/observability/access-logs.md +++ b/docs/content/observability/access-logs.md @@ -254,7 +254,7 @@ version: "3.7" services: traefik: - image: traefik:v2.10 + image: traefik:v2.11 environment: - TZ=US/Alaska command: diff --git a/docs/content/providers/docker.md b/docs/content/providers/docker.md index e3fc985fc..d6a121965 100644 --- a/docs/content/providers/docker.md +++ b/docs/content/providers/docker.md @@ -267,7 +267,7 @@ See the sections [Docker API Access](#docker-api-access) and [Docker Swarm API A services: traefik: - image: traefik:v2.10 # The official v2 Traefik docker image + image: traefik:v2.11 # The official v2 Traefik docker image ports: - "80:80" volumes: diff --git a/docs/content/providers/kubernetes-crd.md b/docs/content/providers/kubernetes-crd.md index f0c2635bc..9c9707ded 100644 --- a/docs/content/providers/kubernetes-crd.md +++ b/docs/content/providers/kubernetes-crd.md @@ -35,10 +35,10 @@ the Traefik engineering team developed a [Custom Resource Definition](https://ku ```bash # Install Traefik Resource Definitions: - kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml + kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.11/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml # Install RBAC for Traefik: - kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml + kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.11/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml ``` ## Resource Configuration diff --git a/docs/content/providers/kubernetes-ingress.md b/docs/content/providers/kubernetes-ingress.md index c9e9d8289..f9fcd7e61 100644 --- a/docs/content/providers/kubernetes-ingress.md +++ b/docs/content/providers/kubernetes-ingress.md @@ -502,6 +502,6 @@ providers: ### Further To learn more about the various aspects of the Ingress specification that Traefik supports, -many examples of Ingresses definitions are located in the test [examples](https://github.com/traefik/traefik/tree/v2.10/pkg/provider/kubernetes/ingress/fixtures) of the Traefik repository. +many examples of Ingresses definitions are located in the test [examples](https://github.com/traefik/traefik/tree/v2.11/pkg/provider/kubernetes/ingress/fixtures) of the Traefik repository. {!traefik-for-business-applications.md!} diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml index 960f98fe7..d92afbe86 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml @@ -37,7 +37,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string @@ -54,11 +54,11 @@ spec: - Rule type: string match: - description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#rule' + description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#rule' type: string middlewares: description: 'Middlewares defines the list of references to - Middleware resources. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-middleware' + Middleware resources. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-middleware' items: description: MiddlewareRef is a reference to a Middleware resource. @@ -77,7 +77,7 @@ spec: type: array priority: description: 'Priority defines the router''s priority. More - info: https://doc.traefik.io/traefik/v2.10/routing/routers/#priority' + info: https://doc.traefik.io/traefik/v2.11/routing/routers/#priority' type: integer services: description: Services defines the list of Service. It can contain @@ -150,7 +150,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -195,16 +195,16 @@ spec: type: object type: array tls: - description: 'TLS defines the TLS configuration. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls' + description: 'TLS defines the TLS configuration. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls' properties: certResolver: description: 'CertResolver defines the name of the certificate resolver to use. Cert resolvers have to be configured in the - static configuration. More info: https://doc.traefik.io/traefik/v2.10/https/acme/#certificate-resolvers' + static configuration. More info: https://doc.traefik.io/traefik/v2.11/https/acme/#certificate-resolvers' type: string domains: description: 'Domains defines the list of domains that will be - used to issue certificates. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#domains' + used to issue certificates. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#domains' items: description: Domain holds a domain name with SANs. properties: @@ -222,15 +222,15 @@ spec: options: description: 'Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. If not defined, - the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: name: description: 'Name defines the name of the referenced TLSOption. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsoption' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsoption' type: string namespace: description: 'Namespace defines the namespace of the referenced - TLSOption. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsoption' + TLSOption. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsoption' type: string required: - name @@ -246,11 +246,11 @@ spec: properties: name: description: 'Name defines the name of the referenced TLSStore. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsstore' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsstore' type: string namespace: description: 'Namespace defines the namespace of the referenced - TLSStore. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsstore' + TLSStore. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsstore' type: string required: - name @@ -304,7 +304,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string @@ -315,7 +315,7 @@ spec: description: RouteTCP holds the TCP route configuration. properties: match: - description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#rule_1' + description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#rule_1' type: string middlewares: description: Middlewares defines the list of references to MiddlewareTCP @@ -338,7 +338,7 @@ spec: type: array priority: description: 'Priority defines the router''s priority. More - info: https://doc.traefik.io/traefik/v2.10/routing/routers/#priority_1' + info: https://doc.traefik.io/traefik/v2.11/routing/routers/#priority_1' type: integer services: description: Services defines the list of TCP services. @@ -370,7 +370,7 @@ spec: x-kubernetes-int-or-string: true proxyProtocol: description: 'ProxyProtocol defines the PROXY protocol - configuration. More info: https://doc.traefik.io/traefik/v2.10/routing/services/#proxy-protocol' + configuration. More info: https://doc.traefik.io/traefik/v2.11/routing/services/#proxy-protocol' properties: version: description: Version defines the PROXY Protocol version @@ -401,16 +401,16 @@ spec: type: array tls: description: 'TLS defines the TLS configuration on a layer 4 / TCP - Route. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls_1' + Route. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls_1' properties: certResolver: description: 'CertResolver defines the name of the certificate resolver to use. Cert resolvers have to be configured in the - static configuration. More info: https://doc.traefik.io/traefik/v2.10/https/acme/#certificate-resolvers' + static configuration. More info: https://doc.traefik.io/traefik/v2.11/https/acme/#certificate-resolvers' type: string domains: description: 'Domains defines the list of domains that will be - used to issue certificates. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#domains' + used to issue certificates. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#domains' items: description: Domain holds a domain name with SANs. properties: @@ -428,7 +428,7 @@ spec: options: description: 'Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. If not defined, - the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: name: description: Name defines the name of the referenced Traefik @@ -514,7 +514,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string @@ -592,7 +592,7 @@ spec: schema: openAPIV3Schema: description: 'Middleware is the CRD implementation of a Traefik Middleware. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/overview/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/overview/' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -612,7 +612,7 @@ spec: addPrefix: description: 'AddPrefix holds the add prefix middleware configuration. This middleware updates the path of a request before forwarding - it. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/addprefix/' + it. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/addprefix/' properties: prefix: description: Prefix is the string to add before the current path @@ -622,11 +622,11 @@ spec: basicAuth: description: 'BasicAuth holds the basic auth middleware configuration. This middleware restricts access to your services to known users. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/' properties: headerField: description: 'HeaderField defines a header field to store the - authenticated user. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield' + authenticated user. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield' type: string realm: description: 'Realm allows the protected resources on a server @@ -646,7 +646,7 @@ spec: buffering: description: 'Buffering holds the buffering middleware configuration. This middleware retries or limits the size of requests that can - be forwarded to backends. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/buffering/#maxrequestbodybytes' + be forwarded to backends. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/buffering/#maxrequestbodybytes' properties: maxRequestBodyBytes: description: 'MaxRequestBodyBytes defines the maximum allowed @@ -679,13 +679,13 @@ spec: retryExpression: description: 'RetryExpression defines the retry conditions. It is a logical combination of functions with operators AND (&&) - and OR (||). More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/buffering/#retryexpression' + and OR (||). More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/buffering/#retryexpression' type: string type: object chain: description: 'Chain holds the configuration of the chain middleware. This middleware enables to define reusable combinations of other - pieces of middleware. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/chain/' + pieces of middleware. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/chain/' properties: middlewares: description: Middlewares is the list of MiddlewareRef which composes @@ -739,7 +739,7 @@ spec: compress: description: 'Compress holds the compress middleware configuration. This middleware compresses responses before sending them to the - client, using gzip compression. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/compress/' + client, using gzip compression. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/compress/' properties: excludedContentTypes: description: ExcludedContentTypes defines the list of content @@ -773,11 +773,11 @@ spec: digestAuth: description: 'DigestAuth holds the digest auth middleware configuration. This middleware restricts access to your services to known users. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/digestauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/digestauth/' properties: headerField: description: 'HeaderField defines a header field to store the - authenticated user. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield' + authenticated user. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield' type: string realm: description: 'Realm allows the protected resources on a server @@ -796,7 +796,7 @@ spec: errors: description: 'ErrorPage holds the custom error middleware configuration. This middleware returns a custom page in lieu of the default, according - to configured ranges of HTTP Status codes. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/errorpages/' + to configured ranges of HTTP Status codes. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/errorpages/' properties: query: description: Query defines the URL for the error page (hosted @@ -805,7 +805,7 @@ spec: type: string service: description: 'Service defines the reference to a Kubernetes Service - that will serve the error page. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/errorpages/#service' + that will serve the error page. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/errorpages/#service' properties: kind: description: Kind defines the kind of the Service. @@ -869,7 +869,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -918,7 +918,7 @@ spec: forwardAuth: description: 'ForwardAuth holds the forward auth middleware configuration. This middleware delegates the request authentication to a Service. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/' properties: address: description: Address defines the authentication server address. @@ -941,7 +941,7 @@ spec: description: 'AuthResponseHeadersRegex defines the regex to match headers to copy from the authentication server response and set on forwarded request, after stripping all headers that match - the regex. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/#authresponseheadersregex' + the regex. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/#authresponseheadersregex' type: string tls: description: TLS defines the configuration used to secure the @@ -972,7 +972,7 @@ spec: headers: description: 'Headers holds the headers middleware configuration. This middleware manages the requests and responses headers. More - info: https://doc.traefik.io/traefik/v2.10/middlewares/http/headers/#customrequestheaders' + info: https://doc.traefik.io/traefik/v2.11/middlewares/http/headers/#customrequestheaders' properties: accessControlAllowCredentials: description: AccessControlAllowCredentials defines whether the @@ -1133,7 +1133,7 @@ spec: inFlightReq: description: 'InFlightReq holds the in-flight request middleware configuration. This middleware limits the number of requests being processed and - served concurrently. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/inflightreq/' + served concurrently. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/inflightreq/' properties: amount: description: Amount defines the maximum amount of allowed simultaneous @@ -1147,11 +1147,11 @@ spec: group requests as originating from a common source. If several strategies are defined at the same time, an error will be raised. If none are set, the default is to use the requestHost. More - info: https://doc.traefik.io/traefik/v2.10/middlewares/http/inflightreq/#sourcecriterion' + info: https://doc.traefik.io/traefik/v2.11/middlewares/http/inflightreq/#sourcecriterion' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1179,11 +1179,11 @@ spec: ipAllowList: description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1207,12 +1207,12 @@ spec: ipWhiteList: description: 'IPWhiteList holds the IP whitelist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/ Deprecated: please use IPAllowList instead.' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1236,7 +1236,7 @@ spec: passTLSClientCert: description: 'PassTLSClientCert holds the pass TLS client cert middleware configuration. This middleware adds the selected data from the passed - client TLS certificate to a header. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/passtlsclientcert/' + client TLS certificate to a header. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/passtlsclientcert/' properties: info: description: Info selects the specific client certificate details @@ -1343,7 +1343,7 @@ spec: rateLimit: description: 'RateLimit holds the rate limit configuration. This middleware ensures that services will receive a fair amount of requests, and - allows one to define what fair is. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ratelimit/' + allows one to define what fair is. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ratelimit/' properties: average: description: Average is the maximum rate, by default in requests/s, @@ -1376,7 +1376,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1404,7 +1404,7 @@ spec: redirectRegex: description: 'RedirectRegex holds the redirect regex middleware configuration. This middleware redirects a request using regex matching and replacement. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/redirectregex/#regex' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/redirectregex/#regex' properties: permanent: description: Permanent defines whether the redirection is permanent @@ -1422,7 +1422,7 @@ spec: redirectScheme: description: 'RedirectScheme holds the redirect scheme middleware configuration. This middleware redirects requests from a scheme/port - to another. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/redirectscheme/' + to another. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/redirectscheme/' properties: permanent: description: Permanent defines whether the redirection is permanent @@ -1438,7 +1438,7 @@ spec: replacePath: description: 'ReplacePath holds the replace path middleware configuration. This middleware replaces the path of the request URL and store the - original path in an X-Replaced-Path header. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/replacepath/' + original path in an X-Replaced-Path header. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/replacepath/' properties: path: description: Path defines the path to use as replacement in the @@ -1448,7 +1448,7 @@ spec: replacePathRegex: description: 'ReplacePathRegex holds the replace path regex middleware configuration. This middleware replaces the path of a URL using - regex matching and replacement. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/replacepathregex/' + regex matching and replacement. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/replacepathregex/' properties: regex: description: Regex defines the regular expression used to match @@ -1464,7 +1464,7 @@ spec: middleware reissues requests a given number of times to a backend server if that server does not reply. As soon as the server answers, the middleware stops retrying, regardless of the response status. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/retry/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/retry/' properties: attempts: description: Attempts defines how many times the request should @@ -1484,7 +1484,7 @@ spec: stripPrefix: description: 'StripPrefix holds the strip prefix middleware configuration. This middleware removes the specified prefixes from the URL path. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/stripprefix/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/stripprefix/' properties: forceSlash: description: 'ForceSlash ensures that the resulting stripped path @@ -1501,7 +1501,7 @@ spec: stripPrefixRegex: description: 'StripPrefixRegex holds the strip prefix regex middleware configuration. This middleware removes the matching prefixes from - the URL path. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/stripprefixregex/' + the URL path. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/stripprefixregex/' properties: regex: description: Regex defines the regular expression to match the @@ -1537,7 +1537,7 @@ spec: schema: openAPIV3Schema: description: 'MiddlewareTCP is the CRD implementation of a Traefik TCP middleware. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/overview/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/overview/' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -1567,7 +1567,7 @@ spec: ipAllowList: description: 'IPAllowList defines the IPAllowList middleware configuration. This middleware accepts/refuses connections based on the client - IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipallowlist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of @@ -1579,7 +1579,7 @@ spec: ipWhiteList: description: 'IPWhiteList defines the IPWhiteList middleware configuration. This middleware accepts/refuses connections based on the client - IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of @@ -1617,7 +1617,7 @@ spec: description: 'ServersTransport is the CRD implementation of a ServersTransport. If no serversTransport is specified, the default@internal will be used. The default@internal serversTransport is created from the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#serverstransport_1' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#serverstransport_1' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -1736,7 +1736,7 @@ spec: openAPIV3Schema: description: 'TLSOption is the CRD implementation of a Traefik TLS Option, allowing to configure some parameters of the TLS connection. More info: - https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -1756,13 +1756,13 @@ spec: alpnProtocols: description: 'ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference. More - info: https://doc.traefik.io/traefik/v2.10/https/tls/#alpn-protocols' + info: https://doc.traefik.io/traefik/v2.11/https/tls/#alpn-protocols' items: type: string type: array cipherSuites: description: 'CipherSuites defines the list of supported cipher suites - for TLS versions up to TLS 1.2. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#cipher-suites' + for TLS versions up to TLS 1.2. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#cipher-suites' items: type: string type: array @@ -1789,7 +1789,7 @@ spec: type: object curvePreferences: description: 'CurvePreferences defines the preferred elliptic curves - in a specific order. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#curve-preferences' + in a specific order. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#curve-preferences' items: type: string type: array @@ -1842,7 +1842,7 @@ spec: description: 'TLSStore is the CRD implementation of a Traefik TLS Store. For the time being, only the TLSStore named default is supported. This means that you cannot have two stores that are named default in different Kubernetes - namespaces. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#certificates-stores' + namespaces. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#certificates-stores' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -1932,7 +1932,7 @@ spec: openAPIV3Schema: description: 'TraefikService is the CRD implementation of a Traefik Service. TraefikService object allows to: - Apply weight to Services on load-balancing - - Mirror traffic on services More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-traefikservice' + - Mirror traffic on services More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-traefikservice' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -2038,7 +2038,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -2129,7 +2129,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -2236,7 +2236,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -2275,7 +2275,7 @@ spec: type: array sticky: description: 'Sticky defines whether sticky sessions are enabled. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#stickiness-and-load-balancing' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#stickiness-and-load-balancing' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -2344,7 +2344,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string @@ -2361,11 +2361,11 @@ spec: - Rule type: string match: - description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#rule' + description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#rule' type: string middlewares: description: 'Middlewares defines the list of references to - Middleware resources. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-middleware' + Middleware resources. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-middleware' items: description: MiddlewareRef is a reference to a Middleware resource. @@ -2384,7 +2384,7 @@ spec: type: array priority: description: 'Priority defines the router''s priority. More - info: https://doc.traefik.io/traefik/v2.10/routing/routers/#priority' + info: https://doc.traefik.io/traefik/v2.11/routing/routers/#priority' type: integer services: description: Services defines the list of Service. It can contain @@ -2457,7 +2457,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -2502,16 +2502,16 @@ spec: type: object type: array tls: - description: 'TLS defines the TLS configuration. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls' + description: 'TLS defines the TLS configuration. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls' properties: certResolver: description: 'CertResolver defines the name of the certificate resolver to use. Cert resolvers have to be configured in the - static configuration. More info: https://doc.traefik.io/traefik/v2.10/https/acme/#certificate-resolvers' + static configuration. More info: https://doc.traefik.io/traefik/v2.11/https/acme/#certificate-resolvers' type: string domains: description: 'Domains defines the list of domains that will be - used to issue certificates. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#domains' + used to issue certificates. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#domains' items: description: Domain holds a domain name with SANs. properties: @@ -2529,15 +2529,15 @@ spec: options: description: 'Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. If not defined, - the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: name: description: 'Name defines the name of the referenced TLSOption. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsoption' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsoption' type: string namespace: description: 'Namespace defines the namespace of the referenced - TLSOption. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsoption' + TLSOption. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsoption' type: string required: - name @@ -2553,11 +2553,11 @@ spec: properties: name: description: 'Name defines the name of the referenced TLSStore. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsstore' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsstore' type: string namespace: description: 'Namespace defines the namespace of the referenced - TLSStore. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsstore' + TLSStore. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsstore' type: string required: - name @@ -2611,7 +2611,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string @@ -2622,7 +2622,7 @@ spec: description: RouteTCP holds the TCP route configuration. properties: match: - description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#rule_1' + description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#rule_1' type: string middlewares: description: Middlewares defines the list of references to MiddlewareTCP @@ -2645,7 +2645,7 @@ spec: type: array priority: description: 'Priority defines the router''s priority. More - info: https://doc.traefik.io/traefik/v2.10/routing/routers/#priority_1' + info: https://doc.traefik.io/traefik/v2.11/routing/routers/#priority_1' type: integer services: description: Services defines the list of TCP services. @@ -2677,7 +2677,7 @@ spec: x-kubernetes-int-or-string: true proxyProtocol: description: 'ProxyProtocol defines the PROXY protocol - configuration. More info: https://doc.traefik.io/traefik/v2.10/routing/services/#proxy-protocol' + configuration. More info: https://doc.traefik.io/traefik/v2.11/routing/services/#proxy-protocol' properties: version: description: Version defines the PROXY Protocol version @@ -2708,16 +2708,16 @@ spec: type: array tls: description: 'TLS defines the TLS configuration on a layer 4 / TCP - Route. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls_1' + Route. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls_1' properties: certResolver: description: 'CertResolver defines the name of the certificate resolver to use. Cert resolvers have to be configured in the - static configuration. More info: https://doc.traefik.io/traefik/v2.10/https/acme/#certificate-resolvers' + static configuration. More info: https://doc.traefik.io/traefik/v2.11/https/acme/#certificate-resolvers' type: string domains: description: 'Domains defines the list of domains that will be - used to issue certificates. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#domains' + used to issue certificates. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#domains' items: description: Domain holds a domain name with SANs. properties: @@ -2735,7 +2735,7 @@ spec: options: description: 'Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. If not defined, - the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: name: description: Name defines the name of the referenced Traefik @@ -2821,7 +2821,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string @@ -2899,7 +2899,7 @@ spec: schema: openAPIV3Schema: description: 'Middleware is the CRD implementation of a Traefik Middleware. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/overview/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/overview/' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -2919,7 +2919,7 @@ spec: addPrefix: description: 'AddPrefix holds the add prefix middleware configuration. This middleware updates the path of a request before forwarding - it. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/addprefix/' + it. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/addprefix/' properties: prefix: description: Prefix is the string to add before the current path @@ -2929,11 +2929,11 @@ spec: basicAuth: description: 'BasicAuth holds the basic auth middleware configuration. This middleware restricts access to your services to known users. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/' properties: headerField: description: 'HeaderField defines a header field to store the - authenticated user. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield' + authenticated user. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield' type: string realm: description: 'Realm allows the protected resources on a server @@ -2953,7 +2953,7 @@ spec: buffering: description: 'Buffering holds the buffering middleware configuration. This middleware retries or limits the size of requests that can - be forwarded to backends. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/buffering/#maxrequestbodybytes' + be forwarded to backends. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/buffering/#maxrequestbodybytes' properties: maxRequestBodyBytes: description: 'MaxRequestBodyBytes defines the maximum allowed @@ -2986,13 +2986,13 @@ spec: retryExpression: description: 'RetryExpression defines the retry conditions. It is a logical combination of functions with operators AND (&&) - and OR (||). More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/buffering/#retryexpression' + and OR (||). More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/buffering/#retryexpression' type: string type: object chain: description: 'Chain holds the configuration of the chain middleware. This middleware enables to define reusable combinations of other - pieces of middleware. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/chain/' + pieces of middleware. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/chain/' properties: middlewares: description: Middlewares is the list of MiddlewareRef which composes @@ -3046,7 +3046,7 @@ spec: compress: description: 'Compress holds the compress middleware configuration. This middleware compresses responses before sending them to the - client, using gzip compression. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/compress/' + client, using gzip compression. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/compress/' properties: excludedContentTypes: description: ExcludedContentTypes defines the list of content @@ -3080,11 +3080,11 @@ spec: digestAuth: description: 'DigestAuth holds the digest auth middleware configuration. This middleware restricts access to your services to known users. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/digestauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/digestauth/' properties: headerField: description: 'HeaderField defines a header field to store the - authenticated user. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield' + authenticated user. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield' type: string realm: description: 'Realm allows the protected resources on a server @@ -3103,7 +3103,7 @@ spec: errors: description: 'ErrorPage holds the custom error middleware configuration. This middleware returns a custom page in lieu of the default, according - to configured ranges of HTTP Status codes. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/errorpages/' + to configured ranges of HTTP Status codes. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/errorpages/' properties: query: description: Query defines the URL for the error page (hosted @@ -3112,7 +3112,7 @@ spec: type: string service: description: 'Service defines the reference to a Kubernetes Service - that will serve the error page. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/errorpages/#service' + that will serve the error page. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/errorpages/#service' properties: kind: description: Kind defines the kind of the Service. @@ -3176,7 +3176,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -3225,7 +3225,7 @@ spec: forwardAuth: description: 'ForwardAuth holds the forward auth middleware configuration. This middleware delegates the request authentication to a Service. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/' properties: address: description: Address defines the authentication server address. @@ -3248,7 +3248,7 @@ spec: description: 'AuthResponseHeadersRegex defines the regex to match headers to copy from the authentication server response and set on forwarded request, after stripping all headers that match - the regex. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/#authresponseheadersregex' + the regex. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/#authresponseheadersregex' type: string tls: description: TLS defines the configuration used to secure the @@ -3279,7 +3279,7 @@ spec: headers: description: 'Headers holds the headers middleware configuration. This middleware manages the requests and responses headers. More - info: https://doc.traefik.io/traefik/v2.10/middlewares/http/headers/#customrequestheaders' + info: https://doc.traefik.io/traefik/v2.11/middlewares/http/headers/#customrequestheaders' properties: accessControlAllowCredentials: description: AccessControlAllowCredentials defines whether the @@ -3440,7 +3440,7 @@ spec: inFlightReq: description: 'InFlightReq holds the in-flight request middleware configuration. This middleware limits the number of requests being processed and - served concurrently. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/inflightreq/' + served concurrently. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/inflightreq/' properties: amount: description: Amount defines the maximum amount of allowed simultaneous @@ -3454,11 +3454,11 @@ spec: group requests as originating from a common source. If several strategies are defined at the same time, an error will be raised. If none are set, the default is to use the requestHost. More - info: https://doc.traefik.io/traefik/v2.10/middlewares/http/inflightreq/#sourcecriterion' + info: https://doc.traefik.io/traefik/v2.11/middlewares/http/inflightreq/#sourcecriterion' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3486,11 +3486,11 @@ spec: ipAllowList: description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3514,12 +3514,12 @@ spec: ipWhiteList: description: 'IPWhiteList holds the IP whitelist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/ Deprecated: please use IPAllowList instead.' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3543,7 +3543,7 @@ spec: passTLSClientCert: description: 'PassTLSClientCert holds the pass TLS client cert middleware configuration. This middleware adds the selected data from the passed - client TLS certificate to a header. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/passtlsclientcert/' + client TLS certificate to a header. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/passtlsclientcert/' properties: info: description: Info selects the specific client certificate details @@ -3650,7 +3650,7 @@ spec: rateLimit: description: 'RateLimit holds the rate limit configuration. This middleware ensures that services will receive a fair amount of requests, and - allows one to define what fair is. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ratelimit/' + allows one to define what fair is. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ratelimit/' properties: average: description: Average is the maximum rate, by default in requests/s, @@ -3683,7 +3683,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3711,7 +3711,7 @@ spec: redirectRegex: description: 'RedirectRegex holds the redirect regex middleware configuration. This middleware redirects a request using regex matching and replacement. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/redirectregex/#regex' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/redirectregex/#regex' properties: permanent: description: Permanent defines whether the redirection is permanent @@ -3729,7 +3729,7 @@ spec: redirectScheme: description: 'RedirectScheme holds the redirect scheme middleware configuration. This middleware redirects requests from a scheme/port - to another. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/redirectscheme/' + to another. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/redirectscheme/' properties: permanent: description: Permanent defines whether the redirection is permanent @@ -3745,7 +3745,7 @@ spec: replacePath: description: 'ReplacePath holds the replace path middleware configuration. This middleware replaces the path of the request URL and store the - original path in an X-Replaced-Path header. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/replacepath/' + original path in an X-Replaced-Path header. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/replacepath/' properties: path: description: Path defines the path to use as replacement in the @@ -3755,7 +3755,7 @@ spec: replacePathRegex: description: 'ReplacePathRegex holds the replace path regex middleware configuration. This middleware replaces the path of a URL using - regex matching and replacement. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/replacepathregex/' + regex matching and replacement. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/replacepathregex/' properties: regex: description: Regex defines the regular expression used to match @@ -3771,7 +3771,7 @@ spec: middleware reissues requests a given number of times to a backend server if that server does not reply. As soon as the server answers, the middleware stops retrying, regardless of the response status. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/retry/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/retry/' properties: attempts: description: Attempts defines how many times the request should @@ -3791,7 +3791,7 @@ spec: stripPrefix: description: 'StripPrefix holds the strip prefix middleware configuration. This middleware removes the specified prefixes from the URL path. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/stripprefix/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/stripprefix/' properties: forceSlash: description: 'ForceSlash ensures that the resulting stripped path @@ -3808,7 +3808,7 @@ spec: stripPrefixRegex: description: 'StripPrefixRegex holds the strip prefix regex middleware configuration. This middleware removes the matching prefixes from - the URL path. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/stripprefixregex/' + the URL path. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/stripprefixregex/' properties: regex: description: Regex defines the regular expression to match the @@ -3844,7 +3844,7 @@ spec: schema: openAPIV3Schema: description: 'MiddlewareTCP is the CRD implementation of a Traefik TCP middleware. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/overview/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/overview/' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -3874,7 +3874,7 @@ spec: ipAllowList: description: 'IPAllowList defines the IPAllowList middleware configuration. This middleware accepts/refuses connections based on the client - IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipallowlist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of @@ -3886,7 +3886,7 @@ spec: ipWhiteList: description: 'IPWhiteList defines the IPWhiteList middleware configuration. This middleware accepts/refuses connections based on the client - IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of @@ -3924,7 +3924,7 @@ spec: description: 'ServersTransport is the CRD implementation of a ServersTransport. If no serversTransport is specified, the default@internal will be used. The default@internal serversTransport is created from the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#serverstransport_1' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#serverstransport_1' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -4043,7 +4043,7 @@ spec: openAPIV3Schema: description: 'TLSOption is the CRD implementation of a Traefik TLS Option, allowing to configure some parameters of the TLS connection. More info: - https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -4063,13 +4063,13 @@ spec: alpnProtocols: description: 'ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference. More - info: https://doc.traefik.io/traefik/v2.10/https/tls/#alpn-protocols' + info: https://doc.traefik.io/traefik/v2.11/https/tls/#alpn-protocols' items: type: string type: array cipherSuites: description: 'CipherSuites defines the list of supported cipher suites - for TLS versions up to TLS 1.2. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#cipher-suites' + for TLS versions up to TLS 1.2. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#cipher-suites' items: type: string type: array @@ -4096,7 +4096,7 @@ spec: type: object curvePreferences: description: 'CurvePreferences defines the preferred elliptic curves - in a specific order. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#curve-preferences' + in a specific order. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#curve-preferences' items: type: string type: array @@ -4149,7 +4149,7 @@ spec: description: 'TLSStore is the CRD implementation of a Traefik TLS Store. For the time being, only the TLSStore named default is supported. This means that you cannot have two stores that are named default in different Kubernetes - namespaces. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#certificates-stores' + namespaces. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#certificates-stores' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -4239,7 +4239,7 @@ spec: openAPIV3Schema: description: 'TraefikService is the CRD implementation of a Traefik Service. TraefikService object allows to: - Apply weight to Services on load-balancing - - Mirror traffic on services More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-traefikservice' + - Mirror traffic on services More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-traefikservice' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -4345,7 +4345,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -4436,7 +4436,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -4543,7 +4543,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -4582,7 +4582,7 @@ spec: type: array sticky: description: 'Sticky defines whether sticky sessions are enabled. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#stickiness-and-load-balancing' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#stickiness-and-load-balancing' properties: cookie: description: Cookie defines the sticky cookie configuration. diff --git a/docs/content/reference/dynamic-configuration/kubernetes-gateway-traefik-lb-svc.yml b/docs/content/reference/dynamic-configuration/kubernetes-gateway-traefik-lb-svc.yml index d1316a0a0..be0c7e225 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-gateway-traefik-lb-svc.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-gateway-traefik-lb-svc.yml @@ -25,7 +25,7 @@ spec: serviceAccountName: traefik-controller containers: - name: traefik - image: traefik:v2.10 + image: traefik:v2.11 args: - --entrypoints.web.address=:80 - --entrypoints.websecure.address=:443 diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutes.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutes.yaml index 1d4ef4537..1d2d5e891 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutes.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutes.yaml @@ -37,7 +37,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string @@ -54,11 +54,11 @@ spec: - Rule type: string match: - description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#rule' + description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#rule' type: string middlewares: description: 'Middlewares defines the list of references to - Middleware resources. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-middleware' + Middleware resources. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-middleware' items: description: MiddlewareRef is a reference to a Middleware resource. @@ -77,7 +77,7 @@ spec: type: array priority: description: 'Priority defines the router''s priority. More - info: https://doc.traefik.io/traefik/v2.10/routing/routers/#priority' + info: https://doc.traefik.io/traefik/v2.11/routing/routers/#priority' type: integer services: description: Services defines the list of Service. It can contain @@ -150,7 +150,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -195,16 +195,16 @@ spec: type: object type: array tls: - description: 'TLS defines the TLS configuration. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls' + description: 'TLS defines the TLS configuration. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls' properties: certResolver: description: 'CertResolver defines the name of the certificate resolver to use. Cert resolvers have to be configured in the - static configuration. More info: https://doc.traefik.io/traefik/v2.10/https/acme/#certificate-resolvers' + static configuration. More info: https://doc.traefik.io/traefik/v2.11/https/acme/#certificate-resolvers' type: string domains: description: 'Domains defines the list of domains that will be - used to issue certificates. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#domains' + used to issue certificates. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#domains' items: description: Domain holds a domain name with SANs. properties: @@ -222,15 +222,15 @@ spec: options: description: 'Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. If not defined, - the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: name: description: 'Name defines the name of the referenced TLSOption. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsoption' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsoption' type: string namespace: description: 'Namespace defines the namespace of the referenced - TLSOption. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsoption' + TLSOption. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsoption' type: string required: - name @@ -246,11 +246,11 @@ spec: properties: name: description: 'Name defines the name of the referenced TLSStore. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsstore' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsstore' type: string namespace: description: 'Namespace defines the namespace of the referenced - TLSStore. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsstore' + TLSStore. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsstore' type: string required: - name diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutetcps.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutetcps.yaml index 7fed7a23d..7bc51acf2 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutetcps.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutetcps.yaml @@ -37,7 +37,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string @@ -48,7 +48,7 @@ spec: description: RouteTCP holds the TCP route configuration. properties: match: - description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#rule_1' + description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#rule_1' type: string middlewares: description: Middlewares defines the list of references to MiddlewareTCP @@ -71,7 +71,7 @@ spec: type: array priority: description: 'Priority defines the router''s priority. More - info: https://doc.traefik.io/traefik/v2.10/routing/routers/#priority_1' + info: https://doc.traefik.io/traefik/v2.11/routing/routers/#priority_1' type: integer services: description: Services defines the list of TCP services. @@ -103,7 +103,7 @@ spec: x-kubernetes-int-or-string: true proxyProtocol: description: 'ProxyProtocol defines the PROXY protocol - configuration. More info: https://doc.traefik.io/traefik/v2.10/routing/services/#proxy-protocol' + configuration. More info: https://doc.traefik.io/traefik/v2.11/routing/services/#proxy-protocol' properties: version: description: Version defines the PROXY Protocol version @@ -134,16 +134,16 @@ spec: type: array tls: description: 'TLS defines the TLS configuration on a layer 4 / TCP - Route. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls_1' + Route. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls_1' properties: certResolver: description: 'CertResolver defines the name of the certificate resolver to use. Cert resolvers have to be configured in the - static configuration. More info: https://doc.traefik.io/traefik/v2.10/https/acme/#certificate-resolvers' + static configuration. More info: https://doc.traefik.io/traefik/v2.11/https/acme/#certificate-resolvers' type: string domains: description: 'Domains defines the list of domains that will be - used to issue certificates. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#domains' + used to issue certificates. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#domains' items: description: Domain holds a domain name with SANs. properties: @@ -161,7 +161,7 @@ spec: options: description: 'Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. If not defined, - the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: name: description: Name defines the name of the referenced Traefik diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressrouteudps.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressrouteudps.yaml index 718f73312..d6fd93be3 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressrouteudps.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressrouteudps.yaml @@ -37,7 +37,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml index ad53a5e9a..1299b14d9 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewares.yaml @@ -18,7 +18,7 @@ spec: schema: openAPIV3Schema: description: 'Middleware is the CRD implementation of a Traefik Middleware. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/overview/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/overview/' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -38,7 +38,7 @@ spec: addPrefix: description: 'AddPrefix holds the add prefix middleware configuration. This middleware updates the path of a request before forwarding - it. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/addprefix/' + it. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/addprefix/' properties: prefix: description: Prefix is the string to add before the current path @@ -48,11 +48,11 @@ spec: basicAuth: description: 'BasicAuth holds the basic auth middleware configuration. This middleware restricts access to your services to known users. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/' properties: headerField: description: 'HeaderField defines a header field to store the - authenticated user. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield' + authenticated user. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield' type: string realm: description: 'Realm allows the protected resources on a server @@ -72,7 +72,7 @@ spec: buffering: description: 'Buffering holds the buffering middleware configuration. This middleware retries or limits the size of requests that can - be forwarded to backends. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/buffering/#maxrequestbodybytes' + be forwarded to backends. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/buffering/#maxrequestbodybytes' properties: maxRequestBodyBytes: description: 'MaxRequestBodyBytes defines the maximum allowed @@ -105,13 +105,13 @@ spec: retryExpression: description: 'RetryExpression defines the retry conditions. It is a logical combination of functions with operators AND (&&) - and OR (||). More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/buffering/#retryexpression' + and OR (||). More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/buffering/#retryexpression' type: string type: object chain: description: 'Chain holds the configuration of the chain middleware. This middleware enables to define reusable combinations of other - pieces of middleware. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/chain/' + pieces of middleware. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/chain/' properties: middlewares: description: Middlewares is the list of MiddlewareRef which composes @@ -165,7 +165,7 @@ spec: compress: description: 'Compress holds the compress middleware configuration. This middleware compresses responses before sending them to the - client, using gzip compression. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/compress/' + client, using gzip compression. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/compress/' properties: excludedContentTypes: description: ExcludedContentTypes defines the list of content @@ -199,11 +199,11 @@ spec: digestAuth: description: 'DigestAuth holds the digest auth middleware configuration. This middleware restricts access to your services to known users. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/digestauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/digestauth/' properties: headerField: description: 'HeaderField defines a header field to store the - authenticated user. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield' + authenticated user. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield' type: string realm: description: 'Realm allows the protected resources on a server @@ -222,7 +222,7 @@ spec: errors: description: 'ErrorPage holds the custom error middleware configuration. This middleware returns a custom page in lieu of the default, according - to configured ranges of HTTP Status codes. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/errorpages/' + to configured ranges of HTTP Status codes. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/errorpages/' properties: query: description: Query defines the URL for the error page (hosted @@ -231,7 +231,7 @@ spec: type: string service: description: 'Service defines the reference to a Kubernetes Service - that will serve the error page. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/errorpages/#service' + that will serve the error page. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/errorpages/#service' properties: kind: description: Kind defines the kind of the Service. @@ -295,7 +295,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -344,7 +344,7 @@ spec: forwardAuth: description: 'ForwardAuth holds the forward auth middleware configuration. This middleware delegates the request authentication to a Service. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/' properties: address: description: Address defines the authentication server address. @@ -367,7 +367,7 @@ spec: description: 'AuthResponseHeadersRegex defines the regex to match headers to copy from the authentication server response and set on forwarded request, after stripping all headers that match - the regex. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/#authresponseheadersregex' + the regex. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/#authresponseheadersregex' type: string tls: description: TLS defines the configuration used to secure the @@ -398,7 +398,7 @@ spec: headers: description: 'Headers holds the headers middleware configuration. This middleware manages the requests and responses headers. More - info: https://doc.traefik.io/traefik/v2.10/middlewares/http/headers/#customrequestheaders' + info: https://doc.traefik.io/traefik/v2.11/middlewares/http/headers/#customrequestheaders' properties: accessControlAllowCredentials: description: AccessControlAllowCredentials defines whether the @@ -559,7 +559,7 @@ spec: inFlightReq: description: 'InFlightReq holds the in-flight request middleware configuration. This middleware limits the number of requests being processed and - served concurrently. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/inflightreq/' + served concurrently. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/inflightreq/' properties: amount: description: Amount defines the maximum amount of allowed simultaneous @@ -573,11 +573,11 @@ spec: group requests as originating from a common source. If several strategies are defined at the same time, an error will be raised. If none are set, the default is to use the requestHost. More - info: https://doc.traefik.io/traefik/v2.10/middlewares/http/inflightreq/#sourcecriterion' + info: https://doc.traefik.io/traefik/v2.11/middlewares/http/inflightreq/#sourcecriterion' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -605,11 +605,11 @@ spec: ipAllowList: description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -633,12 +633,12 @@ spec: ipWhiteList: description: 'IPWhiteList holds the IP whitelist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/ Deprecated: please use IPAllowList instead.' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -662,7 +662,7 @@ spec: passTLSClientCert: description: 'PassTLSClientCert holds the pass TLS client cert middleware configuration. This middleware adds the selected data from the passed - client TLS certificate to a header. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/passtlsclientcert/' + client TLS certificate to a header. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/passtlsclientcert/' properties: info: description: Info selects the specific client certificate details @@ -769,7 +769,7 @@ spec: rateLimit: description: 'RateLimit holds the rate limit configuration. This middleware ensures that services will receive a fair amount of requests, and - allows one to define what fair is. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ratelimit/' + allows one to define what fair is. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ratelimit/' properties: average: description: Average is the maximum rate, by default in requests/s, @@ -802,7 +802,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -830,7 +830,7 @@ spec: redirectRegex: description: 'RedirectRegex holds the redirect regex middleware configuration. This middleware redirects a request using regex matching and replacement. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/redirectregex/#regex' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/redirectregex/#regex' properties: permanent: description: Permanent defines whether the redirection is permanent @@ -848,7 +848,7 @@ spec: redirectScheme: description: 'RedirectScheme holds the redirect scheme middleware configuration. This middleware redirects requests from a scheme/port - to another. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/redirectscheme/' + to another. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/redirectscheme/' properties: permanent: description: Permanent defines whether the redirection is permanent @@ -864,7 +864,7 @@ spec: replacePath: description: 'ReplacePath holds the replace path middleware configuration. This middleware replaces the path of the request URL and store the - original path in an X-Replaced-Path header. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/replacepath/' + original path in an X-Replaced-Path header. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/replacepath/' properties: path: description: Path defines the path to use as replacement in the @@ -874,7 +874,7 @@ spec: replacePathRegex: description: 'ReplacePathRegex holds the replace path regex middleware configuration. This middleware replaces the path of a URL using - regex matching and replacement. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/replacepathregex/' + regex matching and replacement. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/replacepathregex/' properties: regex: description: Regex defines the regular expression used to match @@ -890,7 +890,7 @@ spec: middleware reissues requests a given number of times to a backend server if that server does not reply. As soon as the server answers, the middleware stops retrying, regardless of the response status. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/retry/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/retry/' properties: attempts: description: Attempts defines how many times the request should @@ -910,7 +910,7 @@ spec: stripPrefix: description: 'StripPrefix holds the strip prefix middleware configuration. This middleware removes the specified prefixes from the URL path. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/stripprefix/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/stripprefix/' properties: forceSlash: description: 'ForceSlash ensures that the resulting stripped path @@ -927,7 +927,7 @@ spec: stripPrefixRegex: description: 'StripPrefixRegex holds the strip prefix regex middleware configuration. This middleware removes the matching prefixes from - the URL path. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/stripprefixregex/' + the URL path. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/stripprefixregex/' properties: regex: description: Regex defines the regular expression to match the diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml index 025dd2f7b..95912a7c2 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml @@ -18,7 +18,7 @@ spec: schema: openAPIV3Schema: description: 'MiddlewareTCP is the CRD implementation of a Traefik TCP middleware. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/overview/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/overview/' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -48,7 +48,7 @@ spec: ipAllowList: description: 'IPAllowList defines the IPAllowList middleware configuration. This middleware accepts/refuses connections based on the client - IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipallowlist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of @@ -60,7 +60,7 @@ spec: ipWhiteList: description: 'IPWhiteList defines the IPWhiteList middleware configuration. This middleware accepts/refuses connections based on the client - IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_serverstransports.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_serverstransports.yaml index 6d555f91b..3fea058aa 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_serverstransports.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_serverstransports.yaml @@ -20,7 +20,7 @@ spec: description: 'ServersTransport is the CRD implementation of a ServersTransport. If no serversTransport is specified, the default@internal will be used. The default@internal serversTransport is created from the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#serverstransport_1' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#serverstransport_1' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_tlsoptions.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_tlsoptions.yaml index a8308332f..7676fcbc5 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_tlsoptions.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_tlsoptions.yaml @@ -19,7 +19,7 @@ spec: openAPIV3Schema: description: 'TLSOption is the CRD implementation of a Traefik TLS Option, allowing to configure some parameters of the TLS connection. More info: - https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -39,13 +39,13 @@ spec: alpnProtocols: description: 'ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference. More - info: https://doc.traefik.io/traefik/v2.10/https/tls/#alpn-protocols' + info: https://doc.traefik.io/traefik/v2.11/https/tls/#alpn-protocols' items: type: string type: array cipherSuites: description: 'CipherSuites defines the list of supported cipher suites - for TLS versions up to TLS 1.2. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#cipher-suites' + for TLS versions up to TLS 1.2. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#cipher-suites' items: type: string type: array @@ -72,7 +72,7 @@ spec: type: object curvePreferences: description: 'CurvePreferences defines the preferred elliptic curves - in a specific order. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#curve-preferences' + in a specific order. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#curve-preferences' items: type: string type: array diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_tlsstores.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_tlsstores.yaml index b5f669621..df54837af 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_tlsstores.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_tlsstores.yaml @@ -20,7 +20,7 @@ spec: description: 'TLSStore is the CRD implementation of a Traefik TLS Store. For the time being, only the TLSStore named default is supported. This means that you cannot have two stores that are named default in different Kubernetes - namespaces. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#certificates-stores' + namespaces. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#certificates-stores' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_traefikservices.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_traefikservices.yaml index 431b8d92e..78b78cb9a 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_traefikservices.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_traefikservices.yaml @@ -19,7 +19,7 @@ spec: openAPIV3Schema: description: 'TraefikService is the CRD implementation of a Traefik Service. TraefikService object allows to: - Apply weight to Services on load-balancing - - Mirror traffic on services More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-traefikservice' + - Mirror traffic on services More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-traefikservice' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -125,7 +125,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -216,7 +216,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -323,7 +323,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -362,7 +362,7 @@ spec: type: array sticky: description: 'Sticky defines whether sticky sessions are enabled. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#stickiness-and-load-balancing' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#stickiness-and-load-balancing' properties: cookie: description: Cookie defines the sticky cookie configuration. diff --git a/docs/content/reference/dynamic-configuration/traefik.io_ingressroutes.yaml b/docs/content/reference/dynamic-configuration/traefik.io_ingressroutes.yaml index 3b78294f3..67878499c 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_ingressroutes.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_ingressroutes.yaml @@ -37,7 +37,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string @@ -54,11 +54,11 @@ spec: - Rule type: string match: - description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#rule' + description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#rule' type: string middlewares: description: 'Middlewares defines the list of references to - Middleware resources. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-middleware' + Middleware resources. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-middleware' items: description: MiddlewareRef is a reference to a Middleware resource. @@ -77,7 +77,7 @@ spec: type: array priority: description: 'Priority defines the router''s priority. More - info: https://doc.traefik.io/traefik/v2.10/routing/routers/#priority' + info: https://doc.traefik.io/traefik/v2.11/routing/routers/#priority' type: integer services: description: Services defines the list of Service. It can contain @@ -150,7 +150,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -195,16 +195,16 @@ spec: type: object type: array tls: - description: 'TLS defines the TLS configuration. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls' + description: 'TLS defines the TLS configuration. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls' properties: certResolver: description: 'CertResolver defines the name of the certificate resolver to use. Cert resolvers have to be configured in the - static configuration. More info: https://doc.traefik.io/traefik/v2.10/https/acme/#certificate-resolvers' + static configuration. More info: https://doc.traefik.io/traefik/v2.11/https/acme/#certificate-resolvers' type: string domains: description: 'Domains defines the list of domains that will be - used to issue certificates. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#domains' + used to issue certificates. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#domains' items: description: Domain holds a domain name with SANs. properties: @@ -222,15 +222,15 @@ spec: options: description: 'Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. If not defined, - the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: name: description: 'Name defines the name of the referenced TLSOption. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsoption' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsoption' type: string namespace: description: 'Namespace defines the namespace of the referenced - TLSOption. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsoption' + TLSOption. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsoption' type: string required: - name @@ -246,11 +246,11 @@ spec: properties: name: description: 'Name defines the name of the referenced TLSStore. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsstore' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsstore' type: string namespace: description: 'Namespace defines the namespace of the referenced - TLSStore. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsstore' + TLSStore. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsstore' type: string required: - name diff --git a/docs/content/reference/dynamic-configuration/traefik.io_ingressroutetcps.yaml b/docs/content/reference/dynamic-configuration/traefik.io_ingressroutetcps.yaml index 6a17c70c5..1fdfe7109 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_ingressroutetcps.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_ingressroutetcps.yaml @@ -37,7 +37,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string @@ -48,7 +48,7 @@ spec: description: RouteTCP holds the TCP route configuration. properties: match: - description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#rule_1' + description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#rule_1' type: string middlewares: description: Middlewares defines the list of references to MiddlewareTCP @@ -71,7 +71,7 @@ spec: type: array priority: description: 'Priority defines the router''s priority. More - info: https://doc.traefik.io/traefik/v2.10/routing/routers/#priority_1' + info: https://doc.traefik.io/traefik/v2.11/routing/routers/#priority_1' type: integer services: description: Services defines the list of TCP services. @@ -103,7 +103,7 @@ spec: x-kubernetes-int-or-string: true proxyProtocol: description: 'ProxyProtocol defines the PROXY protocol - configuration. More info: https://doc.traefik.io/traefik/v2.10/routing/services/#proxy-protocol' + configuration. More info: https://doc.traefik.io/traefik/v2.11/routing/services/#proxy-protocol' properties: version: description: Version defines the PROXY Protocol version @@ -134,16 +134,16 @@ spec: type: array tls: description: 'TLS defines the TLS configuration on a layer 4 / TCP - Route. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls_1' + Route. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls_1' properties: certResolver: description: 'CertResolver defines the name of the certificate resolver to use. Cert resolvers have to be configured in the - static configuration. More info: https://doc.traefik.io/traefik/v2.10/https/acme/#certificate-resolvers' + static configuration. More info: https://doc.traefik.io/traefik/v2.11/https/acme/#certificate-resolvers' type: string domains: description: 'Domains defines the list of domains that will be - used to issue certificates. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#domains' + used to issue certificates. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#domains' items: description: Domain holds a domain name with SANs. properties: @@ -161,7 +161,7 @@ spec: options: description: 'Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. If not defined, - the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: name: description: Name defines the name of the referenced Traefik diff --git a/docs/content/reference/dynamic-configuration/traefik.io_ingressrouteudps.yaml b/docs/content/reference/dynamic-configuration/traefik.io_ingressrouteudps.yaml index cd30cd43c..a65c27547 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_ingressrouteudps.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_ingressrouteudps.yaml @@ -37,7 +37,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string diff --git a/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml b/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml index 868a8f3ac..8060217f5 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml @@ -18,7 +18,7 @@ spec: schema: openAPIV3Schema: description: 'Middleware is the CRD implementation of a Traefik Middleware. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/overview/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/overview/' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -38,7 +38,7 @@ spec: addPrefix: description: 'AddPrefix holds the add prefix middleware configuration. This middleware updates the path of a request before forwarding - it. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/addprefix/' + it. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/addprefix/' properties: prefix: description: Prefix is the string to add before the current path @@ -48,11 +48,11 @@ spec: basicAuth: description: 'BasicAuth holds the basic auth middleware configuration. This middleware restricts access to your services to known users. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/' properties: headerField: description: 'HeaderField defines a header field to store the - authenticated user. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield' + authenticated user. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield' type: string realm: description: 'Realm allows the protected resources on a server @@ -72,7 +72,7 @@ spec: buffering: description: 'Buffering holds the buffering middleware configuration. This middleware retries or limits the size of requests that can - be forwarded to backends. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/buffering/#maxrequestbodybytes' + be forwarded to backends. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/buffering/#maxrequestbodybytes' properties: maxRequestBodyBytes: description: 'MaxRequestBodyBytes defines the maximum allowed @@ -105,13 +105,13 @@ spec: retryExpression: description: 'RetryExpression defines the retry conditions. It is a logical combination of functions with operators AND (&&) - and OR (||). More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/buffering/#retryexpression' + and OR (||). More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/buffering/#retryexpression' type: string type: object chain: description: 'Chain holds the configuration of the chain middleware. This middleware enables to define reusable combinations of other - pieces of middleware. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/chain/' + pieces of middleware. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/chain/' properties: middlewares: description: Middlewares is the list of MiddlewareRef which composes @@ -165,7 +165,7 @@ spec: compress: description: 'Compress holds the compress middleware configuration. This middleware compresses responses before sending them to the - client, using gzip compression. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/compress/' + client, using gzip compression. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/compress/' properties: excludedContentTypes: description: ExcludedContentTypes defines the list of content @@ -199,11 +199,11 @@ spec: digestAuth: description: 'DigestAuth holds the digest auth middleware configuration. This middleware restricts access to your services to known users. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/digestauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/digestauth/' properties: headerField: description: 'HeaderField defines a header field to store the - authenticated user. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield' + authenticated user. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield' type: string realm: description: 'Realm allows the protected resources on a server @@ -222,7 +222,7 @@ spec: errors: description: 'ErrorPage holds the custom error middleware configuration. This middleware returns a custom page in lieu of the default, according - to configured ranges of HTTP Status codes. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/errorpages/' + to configured ranges of HTTP Status codes. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/errorpages/' properties: query: description: Query defines the URL for the error page (hosted @@ -231,7 +231,7 @@ spec: type: string service: description: 'Service defines the reference to a Kubernetes Service - that will serve the error page. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/errorpages/#service' + that will serve the error page. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/errorpages/#service' properties: kind: description: Kind defines the kind of the Service. @@ -295,7 +295,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -344,7 +344,7 @@ spec: forwardAuth: description: 'ForwardAuth holds the forward auth middleware configuration. This middleware delegates the request authentication to a Service. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/' properties: address: description: Address defines the authentication server address. @@ -367,7 +367,7 @@ spec: description: 'AuthResponseHeadersRegex defines the regex to match headers to copy from the authentication server response and set on forwarded request, after stripping all headers that match - the regex. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/#authresponseheadersregex' + the regex. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/#authresponseheadersregex' type: string tls: description: TLS defines the configuration used to secure the @@ -398,7 +398,7 @@ spec: headers: description: 'Headers holds the headers middleware configuration. This middleware manages the requests and responses headers. More - info: https://doc.traefik.io/traefik/v2.10/middlewares/http/headers/#customrequestheaders' + info: https://doc.traefik.io/traefik/v2.11/middlewares/http/headers/#customrequestheaders' properties: accessControlAllowCredentials: description: AccessControlAllowCredentials defines whether the @@ -559,7 +559,7 @@ spec: inFlightReq: description: 'InFlightReq holds the in-flight request middleware configuration. This middleware limits the number of requests being processed and - served concurrently. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/inflightreq/' + served concurrently. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/inflightreq/' properties: amount: description: Amount defines the maximum amount of allowed simultaneous @@ -573,11 +573,11 @@ spec: group requests as originating from a common source. If several strategies are defined at the same time, an error will be raised. If none are set, the default is to use the requestHost. More - info: https://doc.traefik.io/traefik/v2.10/middlewares/http/inflightreq/#sourcecriterion' + info: https://doc.traefik.io/traefik/v2.11/middlewares/http/inflightreq/#sourcecriterion' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -605,11 +605,11 @@ spec: ipAllowList: description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -633,12 +633,12 @@ spec: ipWhiteList: description: 'IPWhiteList holds the IP whitelist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/ Deprecated: please use IPAllowList instead.' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -662,7 +662,7 @@ spec: passTLSClientCert: description: 'PassTLSClientCert holds the pass TLS client cert middleware configuration. This middleware adds the selected data from the passed - client TLS certificate to a header. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/passtlsclientcert/' + client TLS certificate to a header. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/passtlsclientcert/' properties: info: description: Info selects the specific client certificate details @@ -769,7 +769,7 @@ spec: rateLimit: description: 'RateLimit holds the rate limit configuration. This middleware ensures that services will receive a fair amount of requests, and - allows one to define what fair is. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ratelimit/' + allows one to define what fair is. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ratelimit/' properties: average: description: Average is the maximum rate, by default in requests/s, @@ -802,7 +802,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -830,7 +830,7 @@ spec: redirectRegex: description: 'RedirectRegex holds the redirect regex middleware configuration. This middleware redirects a request using regex matching and replacement. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/redirectregex/#regex' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/redirectregex/#regex' properties: permanent: description: Permanent defines whether the redirection is permanent @@ -848,7 +848,7 @@ spec: redirectScheme: description: 'RedirectScheme holds the redirect scheme middleware configuration. This middleware redirects requests from a scheme/port - to another. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/redirectscheme/' + to another. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/redirectscheme/' properties: permanent: description: Permanent defines whether the redirection is permanent @@ -864,7 +864,7 @@ spec: replacePath: description: 'ReplacePath holds the replace path middleware configuration. This middleware replaces the path of the request URL and store the - original path in an X-Replaced-Path header. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/replacepath/' + original path in an X-Replaced-Path header. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/replacepath/' properties: path: description: Path defines the path to use as replacement in the @@ -874,7 +874,7 @@ spec: replacePathRegex: description: 'ReplacePathRegex holds the replace path regex middleware configuration. This middleware replaces the path of a URL using - regex matching and replacement. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/replacepathregex/' + regex matching and replacement. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/replacepathregex/' properties: regex: description: Regex defines the regular expression used to match @@ -890,7 +890,7 @@ spec: middleware reissues requests a given number of times to a backend server if that server does not reply. As soon as the server answers, the middleware stops retrying, regardless of the response status. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/retry/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/retry/' properties: attempts: description: Attempts defines how many times the request should @@ -910,7 +910,7 @@ spec: stripPrefix: description: 'StripPrefix holds the strip prefix middleware configuration. This middleware removes the specified prefixes from the URL path. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/stripprefix/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/stripprefix/' properties: forceSlash: description: 'ForceSlash ensures that the resulting stripped path @@ -927,7 +927,7 @@ spec: stripPrefixRegex: description: 'StripPrefixRegex holds the strip prefix regex middleware configuration. This middleware removes the matching prefixes from - the URL path. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/stripprefixregex/' + the URL path. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/stripprefixregex/' properties: regex: description: Regex defines the regular expression to match the diff --git a/docs/content/reference/dynamic-configuration/traefik.io_middlewaretcps.yaml b/docs/content/reference/dynamic-configuration/traefik.io_middlewaretcps.yaml index 3439ea445..e393b6c35 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_middlewaretcps.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_middlewaretcps.yaml @@ -18,7 +18,7 @@ spec: schema: openAPIV3Schema: description: 'MiddlewareTCP is the CRD implementation of a Traefik TCP middleware. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/overview/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/overview/' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -48,7 +48,7 @@ spec: ipAllowList: description: 'IPAllowList defines the IPAllowList middleware configuration. This middleware accepts/refuses connections based on the client - IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipallowlist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of @@ -60,7 +60,7 @@ spec: ipWhiteList: description: 'IPWhiteList defines the IPWhiteList middleware configuration. This middleware accepts/refuses connections based on the client - IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of diff --git a/docs/content/reference/dynamic-configuration/traefik.io_serverstransports.yaml b/docs/content/reference/dynamic-configuration/traefik.io_serverstransports.yaml index 01bf9758c..3fe6f987e 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_serverstransports.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_serverstransports.yaml @@ -20,7 +20,7 @@ spec: description: 'ServersTransport is the CRD implementation of a ServersTransport. If no serversTransport is specified, the default@internal will be used. The default@internal serversTransport is created from the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#serverstransport_1' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#serverstransport_1' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation diff --git a/docs/content/reference/dynamic-configuration/traefik.io_tlsoptions.yaml b/docs/content/reference/dynamic-configuration/traefik.io_tlsoptions.yaml index 754eb0339..5f6341b70 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_tlsoptions.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_tlsoptions.yaml @@ -19,7 +19,7 @@ spec: openAPIV3Schema: description: 'TLSOption is the CRD implementation of a Traefik TLS Option, allowing to configure some parameters of the TLS connection. More info: - https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -39,13 +39,13 @@ spec: alpnProtocols: description: 'ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference. More - info: https://doc.traefik.io/traefik/v2.10/https/tls/#alpn-protocols' + info: https://doc.traefik.io/traefik/v2.11/https/tls/#alpn-protocols' items: type: string type: array cipherSuites: description: 'CipherSuites defines the list of supported cipher suites - for TLS versions up to TLS 1.2. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#cipher-suites' + for TLS versions up to TLS 1.2. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#cipher-suites' items: type: string type: array @@ -72,7 +72,7 @@ spec: type: object curvePreferences: description: 'CurvePreferences defines the preferred elliptic curves - in a specific order. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#curve-preferences' + in a specific order. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#curve-preferences' items: type: string type: array diff --git a/docs/content/reference/dynamic-configuration/traefik.io_tlsstores.yaml b/docs/content/reference/dynamic-configuration/traefik.io_tlsstores.yaml index f9b03d99b..bda4fe94f 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_tlsstores.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_tlsstores.yaml @@ -20,7 +20,7 @@ spec: description: 'TLSStore is the CRD implementation of a Traefik TLS Store. For the time being, only the TLSStore named default is supported. This means that you cannot have two stores that are named default in different Kubernetes - namespaces. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#certificates-stores' + namespaces. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#certificates-stores' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation diff --git a/docs/content/reference/dynamic-configuration/traefik.io_traefikservices.yaml b/docs/content/reference/dynamic-configuration/traefik.io_traefikservices.yaml index 187d1d1c6..64aca355c 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_traefikservices.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_traefikservices.yaml @@ -19,7 +19,7 @@ spec: openAPIV3Schema: description: 'TraefikService is the CRD implementation of a Traefik Service. TraefikService object allows to: - Apply weight to Services on load-balancing - - Mirror traffic on services More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-traefikservice' + - Mirror traffic on services More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-traefikservice' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -125,7 +125,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -216,7 +216,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -323,7 +323,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -362,7 +362,7 @@ spec: type: array sticky: description: 'Sticky defines whether sticky sessions are enabled. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#stickiness-and-load-balancing' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#stickiness-and-load-balancing' properties: cookie: description: Cookie defines the sticky cookie configuration. diff --git a/docs/content/routing/providers/kubernetes-crd.md b/docs/content/routing/providers/kubernetes-crd.md index 17f8bf8e5..98963bd09 100644 --- a/docs/content/routing/providers/kubernetes-crd.md +++ b/docs/content/routing/providers/kubernetes-crd.md @@ -48,7 +48,7 @@ The Kubernetes Ingress Controller, The Custom Resource Way. serviceAccountName: traefik-ingress-controller containers: - name: traefik - image: traefik:v2.10 + image: traefik:v2.11 args: - --log.level=DEBUG - --api diff --git a/docs/content/routing/providers/kubernetes-ingress.md b/docs/content/routing/providers/kubernetes-ingress.md index 9156cc67e..65730bc91 100644 --- a/docs/content/routing/providers/kubernetes-ingress.md +++ b/docs/content/routing/providers/kubernetes-ingress.md @@ -147,7 +147,7 @@ which in turn will create the resulting routers, services, handlers, etc. serviceAccountName: traefik-ingress-controller containers: - name: traefik - image: traefik:v2.10 + image: traefik:v2.11 args: - --entrypoints.web.address=:80 - --providers.kubernetesingress @@ -550,7 +550,7 @@ This way, any Ingress attached to this Entrypoint will have TLS termination by d serviceAccountName: traefik-ingress-controller containers: - name: traefik - image: traefik:v2.10 + image: traefik:v2.11 args: - --entrypoints.websecure.address=:443 - --entrypoints.websecure.http.tls @@ -760,7 +760,7 @@ For more options, please refer to the available [annotations](#on-ingress). serviceAccountName: traefik-ingress-controller containers: - name: traefik - image: traefik:v2.10 + image: traefik:v2.11 args: - --entrypoints.websecure.address=:443 - --providers.kubernetesingress diff --git a/docs/content/user-guides/crd-acme/03-deployments.yml b/docs/content/user-guides/crd-acme/03-deployments.yml index 81e806bd9..55cff5009 100644 --- a/docs/content/user-guides/crd-acme/03-deployments.yml +++ b/docs/content/user-guides/crd-acme/03-deployments.yml @@ -26,7 +26,7 @@ spec: serviceAccountName: traefik-ingress-controller containers: - name: traefik - image: traefik:v2.10 + image: traefik:v2.11 args: - --api.insecure - --accesslog diff --git a/docs/content/user-guides/crd-acme/index.md b/docs/content/user-guides/crd-acme/index.md index d75e42e7b..c291675f7 100644 --- a/docs/content/user-guides/crd-acme/index.md +++ b/docs/content/user-guides/crd-acme/index.md @@ -49,10 +49,10 @@ and the RBAC authorization resources which will be referenced through the `servi ```bash # Install Traefik Resource Definitions: -kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml +kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.11/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml # Install RBAC for Traefik: -kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml +kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.11/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml ``` ### Services @@ -60,7 +60,7 @@ kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/co Then, the services. One for Traefik itself, and one for the app it routes for, i.e. in this case our demo HTTP server: [whoami](https://github.com/traefik/whoami). ```bash -kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/user-guides/crd-acme/02-services.yml +kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.11/docs/content/user-guides/crd-acme/02-services.yml ``` ```yaml @@ -73,7 +73,7 @@ Next, the deployments, i.e. the actual pods behind the services. Again, one pod for Traefik, and one for the whoami app. ```bash -kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/user-guides/crd-acme/03-deployments.yml +kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.11/docs/content/user-guides/crd-acme/03-deployments.yml ``` ```yaml @@ -100,7 +100,7 @@ Look it up. We can now finally apply the actual ingressRoutes, with: ```bash -kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/user-guides/crd-acme/04-ingressroutes.yml +kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.11/docs/content/user-guides/crd-acme/04-ingressroutes.yml ``` ```yaml @@ -126,7 +126,7 @@ Nowadays, TLS v1.0 and v1.1 are deprecated. In order to force TLS v1.2 or later on all your IngressRoute, you can define the `default` TLSOption: ```bash -kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.10/docs/content/user-guides/crd-acme/05-tlsoption.yml +kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.11/docs/content/user-guides/crd-acme/05-tlsoption.yml ``` ```yaml diff --git a/docs/content/user-guides/crd-acme/k3s.yml b/docs/content/user-guides/crd-acme/k3s.yml index 71f4b7158..84c989499 100644 --- a/docs/content/user-guides/crd-acme/k3s.yml +++ b/docs/content/user-guides/crd-acme/k3s.yml @@ -26,5 +26,5 @@ node: - K3S_CLUSTER_SECRET=somethingtotallyrandom volumes: # this is where you would place a alternative traefik image (saved as a .tar file with - # 'docker save'), if you want to use it, instead of the traefik:v2.10 image. + # 'docker save'), if you want to use it, instead of the traefik:v2.11 image. - /somewhere/on/your/host/custom-image:/var/lib/rancher/k3s/agent/images diff --git a/docs/content/user-guides/docker-compose/acme-dns/docker-compose.yml b/docs/content/user-guides/docker-compose/acme-dns/docker-compose.yml index 1e69fdb9e..13beb1e9e 100644 --- a/docs/content/user-guides/docker-compose/acme-dns/docker-compose.yml +++ b/docs/content/user-guides/docker-compose/acme-dns/docker-compose.yml @@ -3,7 +3,7 @@ version: "3.3" services: traefik: - image: "traefik:v2.10" + image: "traefik:v2.11" container_name: "traefik" command: #- "--log.level=DEBUG" diff --git a/docs/content/user-guides/docker-compose/acme-dns/docker-compose_secrets.yml b/docs/content/user-guides/docker-compose/acme-dns/docker-compose_secrets.yml index f2b7dd0f3..c98f67b67 100644 --- a/docs/content/user-guides/docker-compose/acme-dns/docker-compose_secrets.yml +++ b/docs/content/user-guides/docker-compose/acme-dns/docker-compose_secrets.yml @@ -13,7 +13,7 @@ secrets: services: traefik: - image: "traefik:v2.10" + image: "traefik:v2.11" container_name: "traefik" command: #- "--log.level=DEBUG" diff --git a/docs/content/user-guides/docker-compose/acme-http/docker-compose.yml b/docs/content/user-guides/docker-compose/acme-http/docker-compose.yml index 249356bda..d4db80f53 100644 --- a/docs/content/user-guides/docker-compose/acme-http/docker-compose.yml +++ b/docs/content/user-guides/docker-compose/acme-http/docker-compose.yml @@ -3,7 +3,7 @@ version: "3.3" services: traefik: - image: "traefik:v2.10" + image: "traefik:v2.11" container_name: "traefik" command: #- "--log.level=DEBUG" diff --git a/docs/content/user-guides/docker-compose/acme-tls/docker-compose.yml b/docs/content/user-guides/docker-compose/acme-tls/docker-compose.yml index 008b7610f..7e9bec323 100644 --- a/docs/content/user-guides/docker-compose/acme-tls/docker-compose.yml +++ b/docs/content/user-guides/docker-compose/acme-tls/docker-compose.yml @@ -3,7 +3,7 @@ version: "3.3" services: traefik: - image: "traefik:v2.10" + image: "traefik:v2.11" container_name: "traefik" command: #- "--log.level=DEBUG" diff --git a/docs/content/user-guides/docker-compose/basic-example/docker-compose.yml b/docs/content/user-guides/docker-compose/basic-example/docker-compose.yml index b93afdd3a..c040750cd 100644 --- a/docs/content/user-guides/docker-compose/basic-example/docker-compose.yml +++ b/docs/content/user-guides/docker-compose/basic-example/docker-compose.yml @@ -3,7 +3,7 @@ version: "3.3" services: traefik: - image: "traefik:v2.10" + image: "traefik:v2.11" container_name: "traefik" command: #- "--log.level=DEBUG" diff --git a/docs/content/user-guides/docker-compose/basic-example/index.md b/docs/content/user-guides/docker-compose/basic-example/index.md index 65b5e3d7a..4efef3bcb 100644 --- a/docs/content/user-guides/docker-compose/basic-example/index.md +++ b/docs/content/user-guides/docker-compose/basic-example/index.md @@ -31,7 +31,7 @@ Create a `docker-compose.yml` file with the following content: services: traefik: - image: "traefik:v2.10" + image: "traefik:v2.11" ... networks: - traefiknet diff --git a/integration/fixtures/k8s/01-traefik-crd.yml b/integration/fixtures/k8s/01-traefik-crd.yml index 960f98fe7..d92afbe86 100644 --- a/integration/fixtures/k8s/01-traefik-crd.yml +++ b/integration/fixtures/k8s/01-traefik-crd.yml @@ -37,7 +37,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string @@ -54,11 +54,11 @@ spec: - Rule type: string match: - description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#rule' + description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#rule' type: string middlewares: description: 'Middlewares defines the list of references to - Middleware resources. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-middleware' + Middleware resources. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-middleware' items: description: MiddlewareRef is a reference to a Middleware resource. @@ -77,7 +77,7 @@ spec: type: array priority: description: 'Priority defines the router''s priority. More - info: https://doc.traefik.io/traefik/v2.10/routing/routers/#priority' + info: https://doc.traefik.io/traefik/v2.11/routing/routers/#priority' type: integer services: description: Services defines the list of Service. It can contain @@ -150,7 +150,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -195,16 +195,16 @@ spec: type: object type: array tls: - description: 'TLS defines the TLS configuration. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls' + description: 'TLS defines the TLS configuration. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls' properties: certResolver: description: 'CertResolver defines the name of the certificate resolver to use. Cert resolvers have to be configured in the - static configuration. More info: https://doc.traefik.io/traefik/v2.10/https/acme/#certificate-resolvers' + static configuration. More info: https://doc.traefik.io/traefik/v2.11/https/acme/#certificate-resolvers' type: string domains: description: 'Domains defines the list of domains that will be - used to issue certificates. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#domains' + used to issue certificates. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#domains' items: description: Domain holds a domain name with SANs. properties: @@ -222,15 +222,15 @@ spec: options: description: 'Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. If not defined, - the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: name: description: 'Name defines the name of the referenced TLSOption. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsoption' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsoption' type: string namespace: description: 'Namespace defines the namespace of the referenced - TLSOption. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsoption' + TLSOption. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsoption' type: string required: - name @@ -246,11 +246,11 @@ spec: properties: name: description: 'Name defines the name of the referenced TLSStore. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsstore' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsstore' type: string namespace: description: 'Namespace defines the namespace of the referenced - TLSStore. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsstore' + TLSStore. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsstore' type: string required: - name @@ -304,7 +304,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string @@ -315,7 +315,7 @@ spec: description: RouteTCP holds the TCP route configuration. properties: match: - description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#rule_1' + description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#rule_1' type: string middlewares: description: Middlewares defines the list of references to MiddlewareTCP @@ -338,7 +338,7 @@ spec: type: array priority: description: 'Priority defines the router''s priority. More - info: https://doc.traefik.io/traefik/v2.10/routing/routers/#priority_1' + info: https://doc.traefik.io/traefik/v2.11/routing/routers/#priority_1' type: integer services: description: Services defines the list of TCP services. @@ -370,7 +370,7 @@ spec: x-kubernetes-int-or-string: true proxyProtocol: description: 'ProxyProtocol defines the PROXY protocol - configuration. More info: https://doc.traefik.io/traefik/v2.10/routing/services/#proxy-protocol' + configuration. More info: https://doc.traefik.io/traefik/v2.11/routing/services/#proxy-protocol' properties: version: description: Version defines the PROXY Protocol version @@ -401,16 +401,16 @@ spec: type: array tls: description: 'TLS defines the TLS configuration on a layer 4 / TCP - Route. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls_1' + Route. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls_1' properties: certResolver: description: 'CertResolver defines the name of the certificate resolver to use. Cert resolvers have to be configured in the - static configuration. More info: https://doc.traefik.io/traefik/v2.10/https/acme/#certificate-resolvers' + static configuration. More info: https://doc.traefik.io/traefik/v2.11/https/acme/#certificate-resolvers' type: string domains: description: 'Domains defines the list of domains that will be - used to issue certificates. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#domains' + used to issue certificates. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#domains' items: description: Domain holds a domain name with SANs. properties: @@ -428,7 +428,7 @@ spec: options: description: 'Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. If not defined, - the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: name: description: Name defines the name of the referenced Traefik @@ -514,7 +514,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string @@ -592,7 +592,7 @@ spec: schema: openAPIV3Schema: description: 'Middleware is the CRD implementation of a Traefik Middleware. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/overview/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/overview/' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -612,7 +612,7 @@ spec: addPrefix: description: 'AddPrefix holds the add prefix middleware configuration. This middleware updates the path of a request before forwarding - it. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/addprefix/' + it. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/addprefix/' properties: prefix: description: Prefix is the string to add before the current path @@ -622,11 +622,11 @@ spec: basicAuth: description: 'BasicAuth holds the basic auth middleware configuration. This middleware restricts access to your services to known users. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/' properties: headerField: description: 'HeaderField defines a header field to store the - authenticated user. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield' + authenticated user. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield' type: string realm: description: 'Realm allows the protected resources on a server @@ -646,7 +646,7 @@ spec: buffering: description: 'Buffering holds the buffering middleware configuration. This middleware retries or limits the size of requests that can - be forwarded to backends. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/buffering/#maxrequestbodybytes' + be forwarded to backends. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/buffering/#maxrequestbodybytes' properties: maxRequestBodyBytes: description: 'MaxRequestBodyBytes defines the maximum allowed @@ -679,13 +679,13 @@ spec: retryExpression: description: 'RetryExpression defines the retry conditions. It is a logical combination of functions with operators AND (&&) - and OR (||). More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/buffering/#retryexpression' + and OR (||). More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/buffering/#retryexpression' type: string type: object chain: description: 'Chain holds the configuration of the chain middleware. This middleware enables to define reusable combinations of other - pieces of middleware. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/chain/' + pieces of middleware. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/chain/' properties: middlewares: description: Middlewares is the list of MiddlewareRef which composes @@ -739,7 +739,7 @@ spec: compress: description: 'Compress holds the compress middleware configuration. This middleware compresses responses before sending them to the - client, using gzip compression. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/compress/' + client, using gzip compression. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/compress/' properties: excludedContentTypes: description: ExcludedContentTypes defines the list of content @@ -773,11 +773,11 @@ spec: digestAuth: description: 'DigestAuth holds the digest auth middleware configuration. This middleware restricts access to your services to known users. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/digestauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/digestauth/' properties: headerField: description: 'HeaderField defines a header field to store the - authenticated user. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield' + authenticated user. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield' type: string realm: description: 'Realm allows the protected resources on a server @@ -796,7 +796,7 @@ spec: errors: description: 'ErrorPage holds the custom error middleware configuration. This middleware returns a custom page in lieu of the default, according - to configured ranges of HTTP Status codes. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/errorpages/' + to configured ranges of HTTP Status codes. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/errorpages/' properties: query: description: Query defines the URL for the error page (hosted @@ -805,7 +805,7 @@ spec: type: string service: description: 'Service defines the reference to a Kubernetes Service - that will serve the error page. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/errorpages/#service' + that will serve the error page. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/errorpages/#service' properties: kind: description: Kind defines the kind of the Service. @@ -869,7 +869,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -918,7 +918,7 @@ spec: forwardAuth: description: 'ForwardAuth holds the forward auth middleware configuration. This middleware delegates the request authentication to a Service. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/' properties: address: description: Address defines the authentication server address. @@ -941,7 +941,7 @@ spec: description: 'AuthResponseHeadersRegex defines the regex to match headers to copy from the authentication server response and set on forwarded request, after stripping all headers that match - the regex. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/#authresponseheadersregex' + the regex. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/#authresponseheadersregex' type: string tls: description: TLS defines the configuration used to secure the @@ -972,7 +972,7 @@ spec: headers: description: 'Headers holds the headers middleware configuration. This middleware manages the requests and responses headers. More - info: https://doc.traefik.io/traefik/v2.10/middlewares/http/headers/#customrequestheaders' + info: https://doc.traefik.io/traefik/v2.11/middlewares/http/headers/#customrequestheaders' properties: accessControlAllowCredentials: description: AccessControlAllowCredentials defines whether the @@ -1133,7 +1133,7 @@ spec: inFlightReq: description: 'InFlightReq holds the in-flight request middleware configuration. This middleware limits the number of requests being processed and - served concurrently. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/inflightreq/' + served concurrently. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/inflightreq/' properties: amount: description: Amount defines the maximum amount of allowed simultaneous @@ -1147,11 +1147,11 @@ spec: group requests as originating from a common source. If several strategies are defined at the same time, an error will be raised. If none are set, the default is to use the requestHost. More - info: https://doc.traefik.io/traefik/v2.10/middlewares/http/inflightreq/#sourcecriterion' + info: https://doc.traefik.io/traefik/v2.11/middlewares/http/inflightreq/#sourcecriterion' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1179,11 +1179,11 @@ spec: ipAllowList: description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1207,12 +1207,12 @@ spec: ipWhiteList: description: 'IPWhiteList holds the IP whitelist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/ Deprecated: please use IPAllowList instead.' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1236,7 +1236,7 @@ spec: passTLSClientCert: description: 'PassTLSClientCert holds the pass TLS client cert middleware configuration. This middleware adds the selected data from the passed - client TLS certificate to a header. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/passtlsclientcert/' + client TLS certificate to a header. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/passtlsclientcert/' properties: info: description: Info selects the specific client certificate details @@ -1343,7 +1343,7 @@ spec: rateLimit: description: 'RateLimit holds the rate limit configuration. This middleware ensures that services will receive a fair amount of requests, and - allows one to define what fair is. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ratelimit/' + allows one to define what fair is. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ratelimit/' properties: average: description: Average is the maximum rate, by default in requests/s, @@ -1376,7 +1376,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -1404,7 +1404,7 @@ spec: redirectRegex: description: 'RedirectRegex holds the redirect regex middleware configuration. This middleware redirects a request using regex matching and replacement. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/redirectregex/#regex' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/redirectregex/#regex' properties: permanent: description: Permanent defines whether the redirection is permanent @@ -1422,7 +1422,7 @@ spec: redirectScheme: description: 'RedirectScheme holds the redirect scheme middleware configuration. This middleware redirects requests from a scheme/port - to another. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/redirectscheme/' + to another. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/redirectscheme/' properties: permanent: description: Permanent defines whether the redirection is permanent @@ -1438,7 +1438,7 @@ spec: replacePath: description: 'ReplacePath holds the replace path middleware configuration. This middleware replaces the path of the request URL and store the - original path in an X-Replaced-Path header. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/replacepath/' + original path in an X-Replaced-Path header. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/replacepath/' properties: path: description: Path defines the path to use as replacement in the @@ -1448,7 +1448,7 @@ spec: replacePathRegex: description: 'ReplacePathRegex holds the replace path regex middleware configuration. This middleware replaces the path of a URL using - regex matching and replacement. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/replacepathregex/' + regex matching and replacement. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/replacepathregex/' properties: regex: description: Regex defines the regular expression used to match @@ -1464,7 +1464,7 @@ spec: middleware reissues requests a given number of times to a backend server if that server does not reply. As soon as the server answers, the middleware stops retrying, regardless of the response status. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/retry/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/retry/' properties: attempts: description: Attempts defines how many times the request should @@ -1484,7 +1484,7 @@ spec: stripPrefix: description: 'StripPrefix holds the strip prefix middleware configuration. This middleware removes the specified prefixes from the URL path. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/stripprefix/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/stripprefix/' properties: forceSlash: description: 'ForceSlash ensures that the resulting stripped path @@ -1501,7 +1501,7 @@ spec: stripPrefixRegex: description: 'StripPrefixRegex holds the strip prefix regex middleware configuration. This middleware removes the matching prefixes from - the URL path. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/stripprefixregex/' + the URL path. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/stripprefixregex/' properties: regex: description: Regex defines the regular expression to match the @@ -1537,7 +1537,7 @@ spec: schema: openAPIV3Schema: description: 'MiddlewareTCP is the CRD implementation of a Traefik TCP middleware. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/overview/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/overview/' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -1567,7 +1567,7 @@ spec: ipAllowList: description: 'IPAllowList defines the IPAllowList middleware configuration. This middleware accepts/refuses connections based on the client - IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipallowlist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of @@ -1579,7 +1579,7 @@ spec: ipWhiteList: description: 'IPWhiteList defines the IPWhiteList middleware configuration. This middleware accepts/refuses connections based on the client - IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of @@ -1617,7 +1617,7 @@ spec: description: 'ServersTransport is the CRD implementation of a ServersTransport. If no serversTransport is specified, the default@internal will be used. The default@internal serversTransport is created from the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#serverstransport_1' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#serverstransport_1' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -1736,7 +1736,7 @@ spec: openAPIV3Schema: description: 'TLSOption is the CRD implementation of a Traefik TLS Option, allowing to configure some parameters of the TLS connection. More info: - https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -1756,13 +1756,13 @@ spec: alpnProtocols: description: 'ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference. More - info: https://doc.traefik.io/traefik/v2.10/https/tls/#alpn-protocols' + info: https://doc.traefik.io/traefik/v2.11/https/tls/#alpn-protocols' items: type: string type: array cipherSuites: description: 'CipherSuites defines the list of supported cipher suites - for TLS versions up to TLS 1.2. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#cipher-suites' + for TLS versions up to TLS 1.2. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#cipher-suites' items: type: string type: array @@ -1789,7 +1789,7 @@ spec: type: object curvePreferences: description: 'CurvePreferences defines the preferred elliptic curves - in a specific order. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#curve-preferences' + in a specific order. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#curve-preferences' items: type: string type: array @@ -1842,7 +1842,7 @@ spec: description: 'TLSStore is the CRD implementation of a Traefik TLS Store. For the time being, only the TLSStore named default is supported. This means that you cannot have two stores that are named default in different Kubernetes - namespaces. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#certificates-stores' + namespaces. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#certificates-stores' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -1932,7 +1932,7 @@ spec: openAPIV3Schema: description: 'TraefikService is the CRD implementation of a Traefik Service. TraefikService object allows to: - Apply weight to Services on load-balancing - - Mirror traffic on services More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-traefikservice' + - Mirror traffic on services More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-traefikservice' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -2038,7 +2038,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -2129,7 +2129,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -2236,7 +2236,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -2275,7 +2275,7 @@ spec: type: array sticky: description: 'Sticky defines whether sticky sessions are enabled. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#stickiness-and-load-balancing' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#stickiness-and-load-balancing' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -2344,7 +2344,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string @@ -2361,11 +2361,11 @@ spec: - Rule type: string match: - description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#rule' + description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#rule' type: string middlewares: description: 'Middlewares defines the list of references to - Middleware resources. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-middleware' + Middleware resources. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-middleware' items: description: MiddlewareRef is a reference to a Middleware resource. @@ -2384,7 +2384,7 @@ spec: type: array priority: description: 'Priority defines the router''s priority. More - info: https://doc.traefik.io/traefik/v2.10/routing/routers/#priority' + info: https://doc.traefik.io/traefik/v2.11/routing/routers/#priority' type: integer services: description: Services defines the list of Service. It can contain @@ -2457,7 +2457,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -2502,16 +2502,16 @@ spec: type: object type: array tls: - description: 'TLS defines the TLS configuration. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls' + description: 'TLS defines the TLS configuration. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls' properties: certResolver: description: 'CertResolver defines the name of the certificate resolver to use. Cert resolvers have to be configured in the - static configuration. More info: https://doc.traefik.io/traefik/v2.10/https/acme/#certificate-resolvers' + static configuration. More info: https://doc.traefik.io/traefik/v2.11/https/acme/#certificate-resolvers' type: string domains: description: 'Domains defines the list of domains that will be - used to issue certificates. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#domains' + used to issue certificates. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#domains' items: description: Domain holds a domain name with SANs. properties: @@ -2529,15 +2529,15 @@ spec: options: description: 'Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. If not defined, - the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: name: description: 'Name defines the name of the referenced TLSOption. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsoption' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsoption' type: string namespace: description: 'Namespace defines the namespace of the referenced - TLSOption. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsoption' + TLSOption. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsoption' type: string required: - name @@ -2553,11 +2553,11 @@ spec: properties: name: description: 'Name defines the name of the referenced TLSStore. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsstore' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsstore' type: string namespace: description: 'Namespace defines the namespace of the referenced - TLSStore. More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsstore' + TLSStore. More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsstore' type: string required: - name @@ -2611,7 +2611,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string @@ -2622,7 +2622,7 @@ spec: description: RouteTCP holds the TCP route configuration. properties: match: - description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#rule_1' + description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#rule_1' type: string middlewares: description: Middlewares defines the list of references to MiddlewareTCP @@ -2645,7 +2645,7 @@ spec: type: array priority: description: 'Priority defines the router''s priority. More - info: https://doc.traefik.io/traefik/v2.10/routing/routers/#priority_1' + info: https://doc.traefik.io/traefik/v2.11/routing/routers/#priority_1' type: integer services: description: Services defines the list of TCP services. @@ -2677,7 +2677,7 @@ spec: x-kubernetes-int-or-string: true proxyProtocol: description: 'ProxyProtocol defines the PROXY protocol - configuration. More info: https://doc.traefik.io/traefik/v2.10/routing/services/#proxy-protocol' + configuration. More info: https://doc.traefik.io/traefik/v2.11/routing/services/#proxy-protocol' properties: version: description: Version defines the PROXY Protocol version @@ -2708,16 +2708,16 @@ spec: type: array tls: description: 'TLS defines the TLS configuration on a layer 4 / TCP - Route. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls_1' + Route. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls_1' properties: certResolver: description: 'CertResolver defines the name of the certificate resolver to use. Cert resolvers have to be configured in the - static configuration. More info: https://doc.traefik.io/traefik/v2.10/https/acme/#certificate-resolvers' + static configuration. More info: https://doc.traefik.io/traefik/v2.11/https/acme/#certificate-resolvers' type: string domains: description: 'Domains defines the list of domains that will be - used to issue certificates. More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#domains' + used to issue certificates. More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#domains' items: description: Domain holds a domain name with SANs. properties: @@ -2735,7 +2735,7 @@ spec: options: description: 'Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. If not defined, - the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: name: description: Name defines the name of the referenced Traefik @@ -2821,7 +2821,7 @@ spec: entryPoints: description: 'EntryPoints defines the list of entry point names to bind to. Entry points have to be configured in the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ Default: all.' items: type: string @@ -2899,7 +2899,7 @@ spec: schema: openAPIV3Schema: description: 'Middleware is the CRD implementation of a Traefik Middleware. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/overview/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/overview/' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -2919,7 +2919,7 @@ spec: addPrefix: description: 'AddPrefix holds the add prefix middleware configuration. This middleware updates the path of a request before forwarding - it. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/addprefix/' + it. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/addprefix/' properties: prefix: description: Prefix is the string to add before the current path @@ -2929,11 +2929,11 @@ spec: basicAuth: description: 'BasicAuth holds the basic auth middleware configuration. This middleware restricts access to your services to known users. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/' properties: headerField: description: 'HeaderField defines a header field to store the - authenticated user. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield' + authenticated user. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield' type: string realm: description: 'Realm allows the protected resources on a server @@ -2953,7 +2953,7 @@ spec: buffering: description: 'Buffering holds the buffering middleware configuration. This middleware retries or limits the size of requests that can - be forwarded to backends. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/buffering/#maxrequestbodybytes' + be forwarded to backends. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/buffering/#maxrequestbodybytes' properties: maxRequestBodyBytes: description: 'MaxRequestBodyBytes defines the maximum allowed @@ -2986,13 +2986,13 @@ spec: retryExpression: description: 'RetryExpression defines the retry conditions. It is a logical combination of functions with operators AND (&&) - and OR (||). More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/buffering/#retryexpression' + and OR (||). More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/buffering/#retryexpression' type: string type: object chain: description: 'Chain holds the configuration of the chain middleware. This middleware enables to define reusable combinations of other - pieces of middleware. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/chain/' + pieces of middleware. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/chain/' properties: middlewares: description: Middlewares is the list of MiddlewareRef which composes @@ -3046,7 +3046,7 @@ spec: compress: description: 'Compress holds the compress middleware configuration. This middleware compresses responses before sending them to the - client, using gzip compression. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/compress/' + client, using gzip compression. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/compress/' properties: excludedContentTypes: description: ExcludedContentTypes defines the list of content @@ -3080,11 +3080,11 @@ spec: digestAuth: description: 'DigestAuth holds the digest auth middleware configuration. This middleware restricts access to your services to known users. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/digestauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/digestauth/' properties: headerField: description: 'HeaderField defines a header field to store the - authenticated user. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield' + authenticated user. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield' type: string realm: description: 'Realm allows the protected resources on a server @@ -3103,7 +3103,7 @@ spec: errors: description: 'ErrorPage holds the custom error middleware configuration. This middleware returns a custom page in lieu of the default, according - to configured ranges of HTTP Status codes. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/errorpages/' + to configured ranges of HTTP Status codes. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/errorpages/' properties: query: description: Query defines the URL for the error page (hosted @@ -3112,7 +3112,7 @@ spec: type: string service: description: 'Service defines the reference to a Kubernetes Service - that will serve the error page. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/errorpages/#service' + that will serve the error page. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/errorpages/#service' properties: kind: description: Kind defines the kind of the Service. @@ -3176,7 +3176,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -3225,7 +3225,7 @@ spec: forwardAuth: description: 'ForwardAuth holds the forward auth middleware configuration. This middleware delegates the request authentication to a Service. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/' properties: address: description: Address defines the authentication server address. @@ -3248,7 +3248,7 @@ spec: description: 'AuthResponseHeadersRegex defines the regex to match headers to copy from the authentication server response and set on forwarded request, after stripping all headers that match - the regex. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/#authresponseheadersregex' + the regex. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/#authresponseheadersregex' type: string tls: description: TLS defines the configuration used to secure the @@ -3279,7 +3279,7 @@ spec: headers: description: 'Headers holds the headers middleware configuration. This middleware manages the requests and responses headers. More - info: https://doc.traefik.io/traefik/v2.10/middlewares/http/headers/#customrequestheaders' + info: https://doc.traefik.io/traefik/v2.11/middlewares/http/headers/#customrequestheaders' properties: accessControlAllowCredentials: description: AccessControlAllowCredentials defines whether the @@ -3440,7 +3440,7 @@ spec: inFlightReq: description: 'InFlightReq holds the in-flight request middleware configuration. This middleware limits the number of requests being processed and - served concurrently. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/inflightreq/' + served concurrently. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/inflightreq/' properties: amount: description: Amount defines the maximum amount of allowed simultaneous @@ -3454,11 +3454,11 @@ spec: group requests as originating from a common source. If several strategies are defined at the same time, an error will be raised. If none are set, the default is to use the requestHost. More - info: https://doc.traefik.io/traefik/v2.10/middlewares/http/inflightreq/#sourcecriterion' + info: https://doc.traefik.io/traefik/v2.11/middlewares/http/inflightreq/#sourcecriterion' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3486,11 +3486,11 @@ spec: ipAllowList: description: 'IPAllowList holds the IP allowlist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3514,12 +3514,12 @@ spec: ipWhiteList: description: 'IPWhiteList holds the IP whitelist middleware configuration. This middleware accepts / refuses requests based on the client IP. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/ Deprecated: please use IPAllowList instead.' properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration used - by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3543,7 +3543,7 @@ spec: passTLSClientCert: description: 'PassTLSClientCert holds the pass TLS client cert middleware configuration. This middleware adds the selected data from the passed - client TLS certificate to a header. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/passtlsclientcert/' + client TLS certificate to a header. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/passtlsclientcert/' properties: info: description: Info selects the specific client certificate details @@ -3650,7 +3650,7 @@ spec: rateLimit: description: 'RateLimit holds the rate limit configuration. This middleware ensures that services will receive a fair amount of requests, and - allows one to define what fair is. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ratelimit/' + allows one to define what fair is. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ratelimit/' properties: average: description: Average is the maximum rate, by default in requests/s, @@ -3683,7 +3683,7 @@ spec: properties: ipStrategy: description: 'IPStrategy holds the IP strategy configuration - used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy' + used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy' properties: depth: description: Depth tells Traefik to use the X-Forwarded-For @@ -3711,7 +3711,7 @@ spec: redirectRegex: description: 'RedirectRegex holds the redirect regex middleware configuration. This middleware redirects a request using regex matching and replacement. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/redirectregex/#regex' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/redirectregex/#regex' properties: permanent: description: Permanent defines whether the redirection is permanent @@ -3729,7 +3729,7 @@ spec: redirectScheme: description: 'RedirectScheme holds the redirect scheme middleware configuration. This middleware redirects requests from a scheme/port - to another. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/redirectscheme/' + to another. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/redirectscheme/' properties: permanent: description: Permanent defines whether the redirection is permanent @@ -3745,7 +3745,7 @@ spec: replacePath: description: 'ReplacePath holds the replace path middleware configuration. This middleware replaces the path of the request URL and store the - original path in an X-Replaced-Path header. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/replacepath/' + original path in an X-Replaced-Path header. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/replacepath/' properties: path: description: Path defines the path to use as replacement in the @@ -3755,7 +3755,7 @@ spec: replacePathRegex: description: 'ReplacePathRegex holds the replace path regex middleware configuration. This middleware replaces the path of a URL using - regex matching and replacement. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/replacepathregex/' + regex matching and replacement. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/replacepathregex/' properties: regex: description: Regex defines the regular expression used to match @@ -3771,7 +3771,7 @@ spec: middleware reissues requests a given number of times to a backend server if that server does not reply. As soon as the server answers, the middleware stops retrying, regardless of the response status. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/retry/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/retry/' properties: attempts: description: Attempts defines how many times the request should @@ -3791,7 +3791,7 @@ spec: stripPrefix: description: 'StripPrefix holds the strip prefix middleware configuration. This middleware removes the specified prefixes from the URL path. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/stripprefix/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/stripprefix/' properties: forceSlash: description: 'ForceSlash ensures that the resulting stripped path @@ -3808,7 +3808,7 @@ spec: stripPrefixRegex: description: 'StripPrefixRegex holds the strip prefix regex middleware configuration. This middleware removes the matching prefixes from - the URL path. More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/stripprefixregex/' + the URL path. More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/stripprefixregex/' properties: regex: description: Regex defines the regular expression to match the @@ -3844,7 +3844,7 @@ spec: schema: openAPIV3Schema: description: 'MiddlewareTCP is the CRD implementation of a Traefik TCP middleware. - More info: https://doc.traefik.io/traefik/v2.10/middlewares/overview/' + More info: https://doc.traefik.io/traefik/v2.11/middlewares/overview/' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -3874,7 +3874,7 @@ spec: ipAllowList: description: 'IPAllowList defines the IPAllowList middleware configuration. This middleware accepts/refuses connections based on the client - IP. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/' + IP. More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipallowlist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of @@ -3886,7 +3886,7 @@ spec: ipWhiteList: description: 'IPWhiteList defines the IPWhiteList middleware configuration. This middleware accepts/refuses connections based on the client - IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/' + IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/' properties: sourceRange: description: SourceRange defines the allowed IPs (or ranges of @@ -3924,7 +3924,7 @@ spec: description: 'ServersTransport is the CRD implementation of a ServersTransport. If no serversTransport is specified, the default@internal will be used. The default@internal serversTransport is created from the static configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#serverstransport_1' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#serverstransport_1' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -4043,7 +4043,7 @@ spec: openAPIV3Schema: description: 'TLSOption is the CRD implementation of a Traefik TLS Option, allowing to configure some parameters of the TLS connection. More info: - https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options' + https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -4063,13 +4063,13 @@ spec: alpnProtocols: description: 'ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference. More - info: https://doc.traefik.io/traefik/v2.10/https/tls/#alpn-protocols' + info: https://doc.traefik.io/traefik/v2.11/https/tls/#alpn-protocols' items: type: string type: array cipherSuites: description: 'CipherSuites defines the list of supported cipher suites - for TLS versions up to TLS 1.2. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#cipher-suites' + for TLS versions up to TLS 1.2. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#cipher-suites' items: type: string type: array @@ -4096,7 +4096,7 @@ spec: type: object curvePreferences: description: 'CurvePreferences defines the preferred elliptic curves - in a specific order. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#curve-preferences' + in a specific order. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#curve-preferences' items: type: string type: array @@ -4149,7 +4149,7 @@ spec: description: 'TLSStore is the CRD implementation of a Traefik TLS Store. For the time being, only the TLSStore named default is supported. This means that you cannot have two stores that are named default in different Kubernetes - namespaces. More info: https://doc.traefik.io/traefik/v2.10/https/tls/#certificates-stores' + namespaces. More info: https://doc.traefik.io/traefik/v2.11/https/tls/#certificates-stores' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -4239,7 +4239,7 @@ spec: openAPIV3Schema: description: 'TraefikService is the CRD implementation of a Traefik Service. TraefikService object allows to: - Apply weight to Services on load-balancing - - Mirror traffic on services More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-traefikservice' + - Mirror traffic on services More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-traefikservice' properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -4345,7 +4345,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -4436,7 +4436,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -4543,7 +4543,7 @@ spec: type: string sticky: description: 'Sticky defines the sticky sessions configuration. - More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions' + More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions' properties: cookie: description: Cookie defines the sticky cookie configuration. @@ -4582,7 +4582,7 @@ spec: type: array sticky: description: 'Sticky defines whether sticky sessions are enabled. - More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#stickiness-and-load-balancing' + More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#stickiness-and-load-balancing' properties: cookie: description: Cookie defines the sticky cookie configuration. diff --git a/pkg/config/dynamic/middlewares.go b/pkg/config/dynamic/middlewares.go index 714c459a6..391f22de4 100644 --- a/pkg/config/dynamic/middlewares.go +++ b/pkg/config/dynamic/middlewares.go @@ -56,7 +56,7 @@ type ContentType struct { // AddPrefix holds the add prefix middleware configuration. // This middleware updates the path of a request before forwarding it. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/addprefix/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/addprefix/ type AddPrefix struct { // Prefix is the string to add before the current path in the requested URL. // It should include a leading slash (/). @@ -67,7 +67,7 @@ type AddPrefix struct { // BasicAuth holds the basic auth middleware configuration. // This middleware restricts access to your services to known users. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/ type BasicAuth struct { // Users is an array of authorized users. // Each user must be declared using the name:hashed-password format. @@ -82,7 +82,7 @@ type BasicAuth struct { // Default: false. RemoveHeader bool `json:"removeHeader,omitempty" toml:"removeHeader,omitempty" yaml:"removeHeader,omitempty" export:"true"` // HeaderField defines a header field to store the authenticated user. - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield HeaderField string `json:"headerField,omitempty" toml:"headerField,omitempty" yaml:"headerField,omitempty" export:"true"` } @@ -90,7 +90,7 @@ type BasicAuth struct { // Buffering holds the buffering middleware configuration. // This middleware retries or limits the size of requests that can be forwarded to backends. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/buffering/#maxrequestbodybytes +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/buffering/#maxrequestbodybytes type Buffering struct { // MaxRequestBodyBytes defines the maximum allowed body size for the request (in bytes). // If the request exceeds the allowed size, it is not forwarded to the service, and the client gets a 413 (Request Entity Too Large) response. @@ -108,7 +108,7 @@ type Buffering struct { MemResponseBodyBytes int64 `json:"memResponseBodyBytes,omitempty" toml:"memResponseBodyBytes,omitempty" yaml:"memResponseBodyBytes,omitempty" export:"true"` // RetryExpression defines the retry conditions. // It is a logical combination of functions with operators AND (&&) and OR (||). - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/buffering/#retryexpression + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/buffering/#retryexpression RetryExpression string `json:"retryExpression,omitempty" toml:"retryExpression,omitempty" yaml:"retryExpression,omitempty" export:"true"` } @@ -125,7 +125,7 @@ type Chain struct { // CircuitBreaker holds the circuit breaker middleware configuration. // This middleware protects the system from stacking requests to unhealthy services, resulting in cascading failures. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/circuitbreaker/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/circuitbreaker/ type CircuitBreaker struct { // Expression defines the expression that, once matched, opens the circuit breaker and applies the fallback mechanism instead of calling the services. Expression string `json:"expression,omitempty" toml:"expression,omitempty" yaml:"expression,omitempty" export:"true"` @@ -148,7 +148,7 @@ func (c *CircuitBreaker) SetDefaults() { // Compress holds the compress middleware configuration. // This middleware compresses responses before sending them to the client, using gzip compression. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/compress/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/compress/ type Compress struct { // ExcludedContentTypes defines the list of content types to compare the Content-Type header of the incoming requests and responses before compressing. ExcludedContentTypes []string `json:"excludedContentTypes,omitempty" toml:"excludedContentTypes,omitempty" yaml:"excludedContentTypes,omitempty" export:"true"` @@ -161,7 +161,7 @@ type Compress struct { // DigestAuth holds the digest auth middleware configuration. // This middleware restricts access to your services to known users. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/digestauth/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/digestauth/ type DigestAuth struct { // Users defines the authorized users. // Each user should be declared using the name:realm:encoded-password format. @@ -174,7 +174,7 @@ type DigestAuth struct { // Default: traefik. Realm string `json:"realm,omitempty" toml:"realm,omitempty" yaml:"realm,omitempty"` // HeaderField defines a header field to store the authenticated user. - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield HeaderField string `json:"headerField,omitempty" toml:"headerField,omitempty" yaml:"headerField,omitempty" export:"true"` } @@ -200,7 +200,7 @@ type ErrorPage struct { // ForwardAuth holds the forward auth middleware configuration. // This middleware delegates the request authentication to a Service. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/ type ForwardAuth struct { // Address defines the authentication server address. Address string `json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"` @@ -211,7 +211,7 @@ type ForwardAuth struct { // AuthResponseHeaders defines the list of headers to copy from the authentication server response and set on forwarded request, replacing any existing conflicting headers. AuthResponseHeaders []string `json:"authResponseHeaders,omitempty" toml:"authResponseHeaders,omitempty" yaml:"authResponseHeaders,omitempty" export:"true"` // AuthResponseHeadersRegex defines the regex to match headers to copy from the authentication server response and set on forwarded request, after stripping all headers that match the regex. - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/#authresponseheadersregex + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/#authresponseheadersregex AuthResponseHeadersRegex string `json:"authResponseHeadersRegex,omitempty" toml:"authResponseHeadersRegex,omitempty" yaml:"authResponseHeadersRegex,omitempty" export:"true"` // AuthRequestHeaders defines the list of the headers to copy from the request to the authentication server. // If not set or empty then all request headers are passed. @@ -222,7 +222,7 @@ type ForwardAuth struct { // Headers holds the headers middleware configuration. // This middleware manages the requests and responses headers. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/headers/#customrequestheaders +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/headers/#customrequestheaders type Headers struct { // CustomRequestHeaders defines the header names and values to apply to the request. CustomRequestHeaders map[string]string `json:"customRequestHeaders,omitempty" toml:"customRequestHeaders,omitempty" yaml:"customRequestHeaders,omitempty" export:"true"` @@ -347,7 +347,7 @@ func (h *Headers) HasSecureHeadersDefined() bool { // +k8s:deepcopy-gen=true // IPStrategy holds the IP strategy configuration used by Traefik to determine the client IP. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/#ipstrategy +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/#ipstrategy type IPStrategy struct { // Depth tells Traefik to use the X-Forwarded-For header and take the IP located at the depth position (starting from the right). Depth int `json:"depth,omitempty" toml:"depth,omitempty" yaml:"depth,omitempty" export:"true"` @@ -388,7 +388,7 @@ func (s *IPStrategy) Get() (ip.Strategy, error) { // IPWhiteList holds the IP whitelist middleware configuration. // This middleware accepts / refuses requests based on the client IP. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipwhitelist/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipwhitelist/ // Deprecated: please use IPAllowList instead. type IPWhiteList struct { // SourceRange defines the set of allowed IPs (or ranges of allowed IPs by using CIDR notation). @@ -400,7 +400,7 @@ type IPWhiteList struct { // IPAllowList holds the IP allowlist middleware configuration. // This middleware accepts / refuses requests based on the client IP. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ipallowlist/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ipallowlist/ type IPAllowList struct { // SourceRange defines the set of allowed IPs (or ranges of allowed IPs by using CIDR notation). SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"` @@ -411,7 +411,7 @@ type IPAllowList struct { // InFlightReq holds the in-flight request middleware configuration. // This middleware limits the number of requests being processed and served concurrently. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/inflightreq/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/inflightreq/ type InFlightReq struct { // Amount defines the maximum amount of allowed simultaneous in-flight request. // The middleware responds with HTTP 429 Too Many Requests if there are already amount requests in progress (based on the same sourceCriterion strategy). @@ -419,7 +419,7 @@ type InFlightReq struct { // SourceCriterion defines what criterion is used to group requests as originating from a common source. // If several strategies are defined at the same time, an error will be raised. // If none are set, the default is to use the requestHost. - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/inflightreq/#sourcecriterion + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/inflightreq/#sourcecriterion SourceCriterion *SourceCriterion `json:"sourceCriterion,omitempty" toml:"sourceCriterion,omitempty" yaml:"sourceCriterion,omitempty" export:"true"` } @@ -427,7 +427,7 @@ type InFlightReq struct { // PassTLSClientCert holds the pass TLS client cert middleware configuration. // This middleware adds the selected data from the passed client TLS certificate to a header. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/passtlsclientcert/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/passtlsclientcert/ type PassTLSClientCert struct { // PEM sets the X-Forwarded-Tls-Client-Cert header with the certificate. PEM bool `json:"pem,omitempty" toml:"pem,omitempty" yaml:"pem,omitempty" export:"true"` @@ -483,7 +483,7 @@ func (r *RateLimit) SetDefaults() { // RedirectRegex holds the redirect regex middleware configuration. // This middleware redirects a request using regex matching and replacement. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/redirectregex/#regex +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/redirectregex/#regex type RedirectRegex struct { // Regex defines the regex used to match and capture elements from the request URL. Regex string `json:"regex,omitempty" toml:"regex,omitempty" yaml:"regex,omitempty"` @@ -497,7 +497,7 @@ type RedirectRegex struct { // RedirectScheme holds the redirect scheme middleware configuration. // This middleware redirects requests from a scheme/port to another. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/redirectscheme/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/redirectscheme/ type RedirectScheme struct { // Scheme defines the scheme of the new URL. Scheme string `json:"scheme,omitempty" toml:"scheme,omitempty" yaml:"scheme,omitempty" export:"true"` @@ -511,7 +511,7 @@ type RedirectScheme struct { // ReplacePath holds the replace path middleware configuration. // This middleware replaces the path of the request URL and store the original path in an X-Replaced-Path header. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/replacepath/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/replacepath/ type ReplacePath struct { // Path defines the path to use as replacement in the request URL. Path string `json:"path,omitempty" toml:"path,omitempty" yaml:"path,omitempty" export:"true"` @@ -521,7 +521,7 @@ type ReplacePath struct { // ReplacePathRegex holds the replace path regex middleware configuration. // This middleware replaces the path of a URL using regex matching and replacement. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/replacepathregex/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/replacepathregex/ type ReplacePathRegex struct { // Regex defines the regular expression used to match and capture the path from the request URL. Regex string `json:"regex,omitempty" toml:"regex,omitempty" yaml:"regex,omitempty" export:"true"` @@ -534,7 +534,7 @@ type ReplacePathRegex struct { // Retry holds the retry middleware configuration. // This middleware reissues requests a given number of times to a backend server if that server does not reply. // As soon as the server answers, the middleware stops retrying, regardless of the response status. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/retry/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/retry/ type Retry struct { // Attempts defines how many times the request should be retried. Attempts int `json:"attempts,omitempty" toml:"attempts,omitempty" yaml:"attempts,omitempty" export:"true"` @@ -550,7 +550,7 @@ type Retry struct { // StripPrefix holds the strip prefix middleware configuration. // This middleware removes the specified prefixes from the URL path. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/stripprefix/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/stripprefix/ type StripPrefix struct { // Prefixes defines the prefixes to strip from the request URL. Prefixes []string `json:"prefixes,omitempty" toml:"prefixes,omitempty" yaml:"prefixes,omitempty" export:"true"` @@ -568,7 +568,7 @@ func (s *StripPrefix) SetDefaults() { // StripPrefixRegex holds the strip prefix regex middleware configuration. // This middleware removes the matching prefixes from the URL path. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/stripprefixregex/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/stripprefixregex/ type StripPrefixRegex struct { // Regex defines the regular expression to match the path prefix from the request URL. Regex []string `json:"regex,omitempty" toml:"regex,omitempty" yaml:"regex,omitempty" export:"true"` diff --git a/pkg/config/dynamic/tcp_config.go b/pkg/config/dynamic/tcp_config.go index 2bd871d02..0403125bb 100644 --- a/pkg/config/dynamic/tcp_config.go +++ b/pkg/config/dynamic/tcp_config.go @@ -114,7 +114,7 @@ type TCPServer struct { // +k8s:deepcopy-gen=true // ProxyProtocol holds the PROXY Protocol configuration. -// More info: https://doc.traefik.io/traefik/v2.10/routing/services/#proxy-protocol +// More info: https://doc.traefik.io/traefik/v2.11/routing/services/#proxy-protocol type ProxyProtocol struct { // Version defines the PROXY Protocol version to use. Version int `json:"version,omitempty" toml:"version,omitempty" yaml:"version,omitempty" export:"true"` diff --git a/pkg/config/dynamic/tcp_middlewares.go b/pkg/config/dynamic/tcp_middlewares.go index f4052cd82..bf6dbdb25 100644 --- a/pkg/config/dynamic/tcp_middlewares.go +++ b/pkg/config/dynamic/tcp_middlewares.go @@ -14,7 +14,7 @@ type TCPMiddleware struct { // TCPInFlightConn holds the TCP InFlightConn middleware configuration. // This middleware prevents services from being overwhelmed with high load, // by limiting the number of allowed simultaneous connections for one IP. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/inflightconn/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/inflightconn/ type TCPInFlightConn struct { // Amount defines the maximum amount of allowed simultaneous connections. // The middleware closes the connection if there are already amount connections opened. diff --git a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/ingressroute.go b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/ingressroute.go index 27df9c505..ec86b458e 100644 --- a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/ingressroute.go +++ b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/ingressroute.go @@ -13,72 +13,72 @@ type IngressRouteSpec struct { Routes []Route `json:"routes"` // EntryPoints defines the list of entry point names to bind to. // Entry points have to be configured in the static configuration. - // More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + // More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ // Default: all. EntryPoints []string `json:"entryPoints,omitempty"` // TLS defines the TLS configuration. - // More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls + // More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls TLS *TLS `json:"tls,omitempty"` } // Route holds the HTTP route configuration. type Route struct { // Match defines the router's rule. - // More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#rule + // More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#rule Match string `json:"match"` // Kind defines the kind of the route. // Rule is the only supported kind. // +kubebuilder:validation:Enum=Rule Kind string `json:"kind"` // Priority defines the router's priority. - // More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#priority + // More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#priority Priority int `json:"priority,omitempty"` // Services defines the list of Service. // It can contain any combination of TraefikService and/or reference to a Kubernetes Service. Services []Service `json:"services,omitempty"` // Middlewares defines the list of references to Middleware resources. - // More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-middleware + // More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-middleware Middlewares []MiddlewareRef `json:"middlewares,omitempty"` } // TLS holds the TLS configuration. -// More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls +// More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls type TLS struct { // SecretName is the name of the referenced Kubernetes Secret to specify the certificate details. SecretName string `json:"secretName,omitempty"` // Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. // If not defined, the `default` TLSOption is used. - // More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options + // More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options Options *TLSOptionRef `json:"options,omitempty"` // Store defines the reference to the TLSStore, that will be used to store certificates. // Please note that only `default` TLSStore can be used. Store *TLSStoreRef `json:"store,omitempty"` // CertResolver defines the name of the certificate resolver to use. // Cert resolvers have to be configured in the static configuration. - // More info: https://doc.traefik.io/traefik/v2.10/https/acme/#certificate-resolvers + // More info: https://doc.traefik.io/traefik/v2.11/https/acme/#certificate-resolvers CertResolver string `json:"certResolver,omitempty"` // Domains defines the list of domains that will be used to issue certificates. - // More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#domains + // More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#domains Domains []types.Domain `json:"domains,omitempty"` } // TLSOptionRef is a reference to a TLSOption resource. type TLSOptionRef struct { // Name defines the name of the referenced TLSOption. - // More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsoption + // More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsoption Name string `json:"name"` // Namespace defines the namespace of the referenced TLSOption. - // More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsoption + // More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsoption Namespace string `json:"namespace,omitempty"` } // TLSStoreRef is a reference to a TLSStore resource. type TLSStoreRef struct { // Name defines the name of the referenced TLSStore. - // More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsstore + // More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsstore Name string `json:"name"` // Namespace defines the namespace of the referenced TLSStore. - // More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsstore + // More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsstore Namespace string `json:"namespace,omitempty"` } @@ -95,7 +95,7 @@ type LoadBalancerSpec struct { // Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. Namespace string `json:"namespace,omitempty"` // Sticky defines the sticky sessions configuration. - // More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions + // More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions Sticky *dynamic.Sticky `json:"sticky,omitempty"` // Port defines the port of a Kubernetes Service. // This can be a reference to a named port. diff --git a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/ingressroutetcp.go index acc3c94e7..17cd2f77a 100644 --- a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/ingressroutetcp.go @@ -13,21 +13,21 @@ type IngressRouteTCPSpec struct { Routes []RouteTCP `json:"routes"` // EntryPoints defines the list of entry point names to bind to. // Entry points have to be configured in the static configuration. - // More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + // More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ // Default: all. EntryPoints []string `json:"entryPoints,omitempty"` // TLS defines the TLS configuration on a layer 4 / TCP Route. - // More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls_1 + // More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls_1 TLS *TLSTCP `json:"tls,omitempty"` } // RouteTCP holds the TCP route configuration. type RouteTCP struct { // Match defines the router's rule. - // More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#rule_1 + // More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#rule_1 Match string `json:"match"` // Priority defines the router's priority. - // More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#priority_1 + // More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#priority_1 Priority int `json:"priority,omitempty"` // Services defines the list of TCP services. Services []ServiceTCP `json:"services,omitempty"` @@ -36,7 +36,7 @@ type RouteTCP struct { } // TLSTCP holds the TLS configuration for an IngressRouteTCP. -// More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls_1 +// More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls_1 type TLSTCP struct { // SecretName is the name of the referenced Kubernetes Secret to specify the certificate details. SecretName string `json:"secretName,omitempty"` @@ -44,17 +44,17 @@ type TLSTCP struct { Passthrough bool `json:"passthrough,omitempty"` // Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. // If not defined, the `default` TLSOption is used. - // More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options + // More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options Options *ObjectReference `json:"options,omitempty"` // Store defines the reference to the TLSStore, that will be used to store certificates. // Please note that only `default` TLSStore can be used. Store *ObjectReference `json:"store,omitempty"` // CertResolver defines the name of the certificate resolver to use. // Cert resolvers have to be configured in the static configuration. - // More info: https://doc.traefik.io/traefik/v2.10/https/acme/#certificate-resolvers + // More info: https://doc.traefik.io/traefik/v2.11/https/acme/#certificate-resolvers CertResolver string `json:"certResolver,omitempty"` // Domains defines the list of domains that will be used to issue certificates. - // More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#domains + // More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#domains Domains []types.Domain `json:"domains,omitempty"` } @@ -76,7 +76,7 @@ type ServiceTCP struct { // A negative value means an infinite deadline (i.e. the reading capability is never closed). TerminationDelay *int `json:"terminationDelay,omitempty"` // ProxyProtocol defines the PROXY protocol configuration. - // More info: https://doc.traefik.io/traefik/v2.10/routing/services/#proxy-protocol + // More info: https://doc.traefik.io/traefik/v2.11/routing/services/#proxy-protocol ProxyProtocol *dynamic.ProxyProtocol `json:"proxyProtocol,omitempty"` // NativeLB controls, when creating the load-balancer, // whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. diff --git a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/ingressrouteudp.go index 84dd9b652..4c7c0dd5c 100644 --- a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/ingressrouteudp.go @@ -11,7 +11,7 @@ type IngressRouteUDPSpec struct { Routes []RouteUDP `json:"routes"` // EntryPoints defines the list of entry point names to bind to. // Entry points have to be configured in the static configuration. - // More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + // More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ // Default: all. EntryPoints []string `json:"entryPoints,omitempty"` } diff --git a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middleware.go index 65b969540..21c1e3cfb 100644 --- a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middleware.go @@ -12,7 +12,7 @@ import ( // +kubebuilder:storageversion // Middleware is the CRD implementation of a Traefik Middleware. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/overview/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/overview/ type Middleware struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. @@ -58,7 +58,7 @@ type MiddlewareSpec struct { // ErrorPage holds the custom error middleware configuration. // This middleware returns a custom page in lieu of the default, according to configured ranges of HTTP Status codes. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/errorpages/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/errorpages/ type ErrorPage struct { // Status defines which status or range of statuses should result in an error page. // It can be either a status code as a number (500), @@ -67,7 +67,7 @@ type ErrorPage struct { // or a combination of the two (404,418,500-599). Status []string `json:"status,omitempty"` // Service defines the reference to a Kubernetes Service that will serve the error page. - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/errorpages/#service + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/errorpages/#service Service Service `json:"service,omitempty"` // Query defines the URL for the error page (hosted by service). // The {status} variable can be used in order to insert the status code in the URL. @@ -92,7 +92,7 @@ type CircuitBreaker struct { // Chain holds the configuration of the chain middleware. // This middleware enables to define reusable combinations of other pieces of middleware. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/chain/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/chain/ type Chain struct { // Middlewares is the list of MiddlewareRef which composes the chain. Middlewares []MiddlewareRef `json:"middlewares,omitempty"` @@ -102,7 +102,7 @@ type Chain struct { // BasicAuth holds the basic auth middleware configuration. // This middleware restricts access to your services to known users. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/ type BasicAuth struct { // Secret is the name of the referenced Kubernetes Secret containing user credentials. Secret string `json:"secret,omitempty"` @@ -113,7 +113,7 @@ type BasicAuth struct { // Default: false. RemoveHeader bool `json:"removeHeader,omitempty"` // HeaderField defines a header field to store the authenticated user. - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield HeaderField string `json:"headerField,omitempty"` } @@ -121,7 +121,7 @@ type BasicAuth struct { // DigestAuth holds the digest auth middleware configuration. // This middleware restricts access to your services to known users. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/digestauth/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/digestauth/ type DigestAuth struct { // Secret is the name of the referenced Kubernetes Secret containing user credentials. Secret string `json:"secret,omitempty"` @@ -131,7 +131,7 @@ type DigestAuth struct { // Default: traefik. Realm string `json:"realm,omitempty"` // HeaderField defines a header field to store the authenticated user. - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield HeaderField string `json:"headerField,omitempty"` } @@ -139,7 +139,7 @@ type DigestAuth struct { // ForwardAuth holds the forward auth middleware configuration. // This middleware delegates the request authentication to a Service. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/ type ForwardAuth struct { // Address defines the authentication server address. Address string `json:"address,omitempty"` @@ -148,7 +148,7 @@ type ForwardAuth struct { // AuthResponseHeaders defines the list of headers to copy from the authentication server response and set on forwarded request, replacing any existing conflicting headers. AuthResponseHeaders []string `json:"authResponseHeaders,omitempty"` // AuthResponseHeadersRegex defines the regex to match headers to copy from the authentication server response and set on forwarded request, after stripping all headers that match the regex. - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/#authresponseheadersregex + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/#authresponseheadersregex AuthResponseHeadersRegex string `json:"authResponseHeadersRegex,omitempty"` // AuthRequestHeaders defines the list of the headers to copy from the request to the authentication server. // If not set or empty then all request headers are passed. @@ -174,7 +174,7 @@ type ClientTLS struct { // RateLimit holds the rate limit configuration. // This middleware ensures that services will receive a fair amount of requests, and allows one to define what fair is. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ratelimit/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ratelimit/ type RateLimit struct { // Average is the maximum rate, by default in requests/s, allowed for the given source. // It defaults to 0, which means no rate limiting. @@ -198,7 +198,7 @@ type RateLimit struct { // Retry holds the retry middleware configuration. // This middleware reissues requests a given number of times to a backend server if that server does not reply. // As soon as the server answers, the middleware stops retrying, regardless of the response status. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/retry/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/retry/ type Retry struct { // Attempts defines how many times the request should be retried. Attempts int `json:"attempts,omitempty"` diff --git a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middlewaretcp.go index 923c3d404..82c126687 100644 --- a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/middlewaretcp.go @@ -9,7 +9,7 @@ import ( // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // MiddlewareTCP is the CRD implementation of a Traefik TCP middleware. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/overview/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/overview/ type MiddlewareTCP struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. @@ -28,11 +28,11 @@ type MiddlewareTCPSpec struct { // IPWhiteList defines the IPWhiteList middleware configuration. // This middleware accepts/refuses connections based on the client IP. // Deprecated: please use IPAllowList instead. - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/ + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/ IPWhiteList *dynamic.TCPIPWhiteList `json:"ipWhiteList,omitempty"` // IPAllowList defines the IPAllowList middleware configuration. // This middleware accepts/refuses connections based on the client IP. - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/ + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipallowlist/ IPAllowList *dynamic.TCPIPAllowList `json:"ipAllowList,omitempty"` } diff --git a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/serverstransport.go b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/serverstransport.go index be4d9decb..e36f2b285 100644 --- a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/serverstransport.go +++ b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/serverstransport.go @@ -12,7 +12,7 @@ import ( // ServersTransport is the CRD implementation of a ServersTransport. // If no serversTransport is specified, the default@internal will be used. // The default@internal serversTransport is created from the static configuration. -// More info: https://doc.traefik.io/traefik/v2.10/routing/services/#serverstransport_1 +// More info: https://doc.traefik.io/traefik/v2.11/routing/services/#serverstransport_1 type ServersTransport struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. diff --git a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/service.go b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/service.go index b14625897..6ea8b492c 100644 --- a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/service.go +++ b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/service.go @@ -13,7 +13,7 @@ import ( // TraefikService object allows to: // - Apply weight to Services on load-balancing // - Mirror traffic on services -// More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-traefikservice +// More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-traefikservice type TraefikService struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. @@ -49,7 +49,7 @@ type TraefikServiceSpec struct { // +k8s:deepcopy-gen=true // Mirroring holds the mirroring service configuration. -// More info: https://doc.traefik.io/traefik/v2.10/routing/services/#mirroring-service +// More info: https://doc.traefik.io/traefik/v2.11/routing/services/#mirroring-service type Mirroring struct { LoadBalancerSpec `json:",inline"` @@ -75,11 +75,11 @@ type MirrorService struct { // +k8s:deepcopy-gen=true // WeightedRoundRobin holds the weighted round-robin configuration. -// More info: https://doc.traefik.io/traefik/v2.10/routing/services/#weighted-round-robin-service +// More info: https://doc.traefik.io/traefik/v2.11/routing/services/#weighted-round-robin-service type WeightedRoundRobin struct { // Services defines the list of Kubernetes Service and/or TraefikService to load-balance, with weight. Services []Service `json:"services,omitempty"` // Sticky defines whether sticky sessions are enabled. - // More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#stickiness-and-load-balancing + // More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#stickiness-and-load-balancing Sticky *dynamic.Sticky `json:"sticky,omitempty"` } diff --git a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/tlsoption.go index 996e36a94..0e6e2274d 100644 --- a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/tlsoption.go +++ b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/tlsoption.go @@ -9,7 +9,7 @@ import ( // +kubebuilder:storageversion // TLSOption is the CRD implementation of a Traefik TLS Option, allowing to configure some parameters of the TLS connection. -// More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options +// More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options type TLSOption struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. @@ -32,10 +32,10 @@ type TLSOptionSpec struct { // Default: None. MaxVersion string `json:"maxVersion,omitempty"` // CipherSuites defines the list of supported cipher suites for TLS versions up to TLS 1.2. - // More info: https://doc.traefik.io/traefik/v2.10/https/tls/#cipher-suites + // More info: https://doc.traefik.io/traefik/v2.11/https/tls/#cipher-suites CipherSuites []string `json:"cipherSuites,omitempty"` // CurvePreferences defines the preferred elliptic curves in a specific order. - // More info: https://doc.traefik.io/traefik/v2.10/https/tls/#curve-preferences + // More info: https://doc.traefik.io/traefik/v2.11/https/tls/#curve-preferences CurvePreferences []string `json:"curvePreferences,omitempty"` // ClientAuth defines the server's policy for TLS Client Authentication. ClientAuth ClientAuth `json:"clientAuth,omitempty"` @@ -46,7 +46,7 @@ type TLSOptionSpec struct { // Deprecated: https://github.com/golang/go/issues/45430 PreferServerCipherSuites bool `json:"preferServerCipherSuites,omitempty"` // ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference. - // More info: https://doc.traefik.io/traefik/v2.10/https/tls/#alpn-protocols + // More info: https://doc.traefik.io/traefik/v2.11/https/tls/#alpn-protocols ALPNProtocols []string `json:"alpnProtocols,omitempty"` } diff --git a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/tlsstore.go b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/tlsstore.go index 082dbc5b1..c6f5d293a 100644 --- a/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/tlsstore.go +++ b/pkg/provider/kubernetes/crd/traefikcontainous/v1alpha1/tlsstore.go @@ -12,7 +12,7 @@ import ( // TLSStore is the CRD implementation of a Traefik TLS Store. // For the time being, only the TLSStore named default is supported. // This means that you cannot have two stores that are named default in different Kubernetes namespaces. -// More info: https://doc.traefik.io/traefik/v2.10/https/tls/#certificates-stores +// More info: https://doc.traefik.io/traefik/v2.11/https/tls/#certificates-stores type TLSStore struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroute.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroute.go index 27df9c505..ec86b458e 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroute.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroute.go @@ -13,72 +13,72 @@ type IngressRouteSpec struct { Routes []Route `json:"routes"` // EntryPoints defines the list of entry point names to bind to. // Entry points have to be configured in the static configuration. - // More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + // More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ // Default: all. EntryPoints []string `json:"entryPoints,omitempty"` // TLS defines the TLS configuration. - // More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls + // More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls TLS *TLS `json:"tls,omitempty"` } // Route holds the HTTP route configuration. type Route struct { // Match defines the router's rule. - // More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#rule + // More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#rule Match string `json:"match"` // Kind defines the kind of the route. // Rule is the only supported kind. // +kubebuilder:validation:Enum=Rule Kind string `json:"kind"` // Priority defines the router's priority. - // More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#priority + // More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#priority Priority int `json:"priority,omitempty"` // Services defines the list of Service. // It can contain any combination of TraefikService and/or reference to a Kubernetes Service. Services []Service `json:"services,omitempty"` // Middlewares defines the list of references to Middleware resources. - // More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-middleware + // More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-middleware Middlewares []MiddlewareRef `json:"middlewares,omitempty"` } // TLS holds the TLS configuration. -// More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls +// More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls type TLS struct { // SecretName is the name of the referenced Kubernetes Secret to specify the certificate details. SecretName string `json:"secretName,omitempty"` // Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. // If not defined, the `default` TLSOption is used. - // More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options + // More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options Options *TLSOptionRef `json:"options,omitempty"` // Store defines the reference to the TLSStore, that will be used to store certificates. // Please note that only `default` TLSStore can be used. Store *TLSStoreRef `json:"store,omitempty"` // CertResolver defines the name of the certificate resolver to use. // Cert resolvers have to be configured in the static configuration. - // More info: https://doc.traefik.io/traefik/v2.10/https/acme/#certificate-resolvers + // More info: https://doc.traefik.io/traefik/v2.11/https/acme/#certificate-resolvers CertResolver string `json:"certResolver,omitempty"` // Domains defines the list of domains that will be used to issue certificates. - // More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#domains + // More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#domains Domains []types.Domain `json:"domains,omitempty"` } // TLSOptionRef is a reference to a TLSOption resource. type TLSOptionRef struct { // Name defines the name of the referenced TLSOption. - // More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsoption + // More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsoption Name string `json:"name"` // Namespace defines the namespace of the referenced TLSOption. - // More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsoption + // More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsoption Namespace string `json:"namespace,omitempty"` } // TLSStoreRef is a reference to a TLSStore resource. type TLSStoreRef struct { // Name defines the name of the referenced TLSStore. - // More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsstore + // More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsstore Name string `json:"name"` // Namespace defines the namespace of the referenced TLSStore. - // More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-tlsstore + // More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-tlsstore Namespace string `json:"namespace,omitempty"` } @@ -95,7 +95,7 @@ type LoadBalancerSpec struct { // Namespace defines the namespace of the referenced Kubernetes Service or TraefikService. Namespace string `json:"namespace,omitempty"` // Sticky defines the sticky sessions configuration. - // More info: https://doc.traefik.io/traefik/v2.10/routing/services/#sticky-sessions + // More info: https://doc.traefik.io/traefik/v2.11/routing/services/#sticky-sessions Sticky *dynamic.Sticky `json:"sticky,omitempty"` // Port defines the port of a Kubernetes Service. // This can be a reference to a named port. diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroutetcp.go index acc3c94e7..17cd2f77a 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressroutetcp.go @@ -13,21 +13,21 @@ type IngressRouteTCPSpec struct { Routes []RouteTCP `json:"routes"` // EntryPoints defines the list of entry point names to bind to. // Entry points have to be configured in the static configuration. - // More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + // More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ // Default: all. EntryPoints []string `json:"entryPoints,omitempty"` // TLS defines the TLS configuration on a layer 4 / TCP Route. - // More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls_1 + // More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls_1 TLS *TLSTCP `json:"tls,omitempty"` } // RouteTCP holds the TCP route configuration. type RouteTCP struct { // Match defines the router's rule. - // More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#rule_1 + // More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#rule_1 Match string `json:"match"` // Priority defines the router's priority. - // More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#priority_1 + // More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#priority_1 Priority int `json:"priority,omitempty"` // Services defines the list of TCP services. Services []ServiceTCP `json:"services,omitempty"` @@ -36,7 +36,7 @@ type RouteTCP struct { } // TLSTCP holds the TLS configuration for an IngressRouteTCP. -// More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#tls_1 +// More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#tls_1 type TLSTCP struct { // SecretName is the name of the referenced Kubernetes Secret to specify the certificate details. SecretName string `json:"secretName,omitempty"` @@ -44,17 +44,17 @@ type TLSTCP struct { Passthrough bool `json:"passthrough,omitempty"` // Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection. // If not defined, the `default` TLSOption is used. - // More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options + // More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options Options *ObjectReference `json:"options,omitempty"` // Store defines the reference to the TLSStore, that will be used to store certificates. // Please note that only `default` TLSStore can be used. Store *ObjectReference `json:"store,omitempty"` // CertResolver defines the name of the certificate resolver to use. // Cert resolvers have to be configured in the static configuration. - // More info: https://doc.traefik.io/traefik/v2.10/https/acme/#certificate-resolvers + // More info: https://doc.traefik.io/traefik/v2.11/https/acme/#certificate-resolvers CertResolver string `json:"certResolver,omitempty"` // Domains defines the list of domains that will be used to issue certificates. - // More info: https://doc.traefik.io/traefik/v2.10/routing/routers/#domains + // More info: https://doc.traefik.io/traefik/v2.11/routing/routers/#domains Domains []types.Domain `json:"domains,omitempty"` } @@ -76,7 +76,7 @@ type ServiceTCP struct { // A negative value means an infinite deadline (i.e. the reading capability is never closed). TerminationDelay *int `json:"terminationDelay,omitempty"` // ProxyProtocol defines the PROXY protocol configuration. - // More info: https://doc.traefik.io/traefik/v2.10/routing/services/#proxy-protocol + // More info: https://doc.traefik.io/traefik/v2.11/routing/services/#proxy-protocol ProxyProtocol *dynamic.ProxyProtocol `json:"proxyProtocol,omitempty"` // NativeLB controls, when creating the load-balancer, // whether the LB's children are directly the pods IPs or if the only child is the Kubernetes Service clusterIP. diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressrouteudp.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressrouteudp.go index 84dd9b652..4c7c0dd5c 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressrouteudp.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/ingressrouteudp.go @@ -11,7 +11,7 @@ type IngressRouteUDPSpec struct { Routes []RouteUDP `json:"routes"` // EntryPoints defines the list of entry point names to bind to. // Entry points have to be configured in the static configuration. - // More info: https://doc.traefik.io/traefik/v2.10/routing/entrypoints/ + // More info: https://doc.traefik.io/traefik/v2.11/routing/entrypoints/ // Default: all. EntryPoints []string `json:"entryPoints,omitempty"` } diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go index 65b969540..21c1e3cfb 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middleware.go @@ -12,7 +12,7 @@ import ( // +kubebuilder:storageversion // Middleware is the CRD implementation of a Traefik Middleware. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/overview/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/overview/ type Middleware struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. @@ -58,7 +58,7 @@ type MiddlewareSpec struct { // ErrorPage holds the custom error middleware configuration. // This middleware returns a custom page in lieu of the default, according to configured ranges of HTTP Status codes. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/errorpages/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/errorpages/ type ErrorPage struct { // Status defines which status or range of statuses should result in an error page. // It can be either a status code as a number (500), @@ -67,7 +67,7 @@ type ErrorPage struct { // or a combination of the two (404,418,500-599). Status []string `json:"status,omitempty"` // Service defines the reference to a Kubernetes Service that will serve the error page. - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/errorpages/#service + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/errorpages/#service Service Service `json:"service,omitempty"` // Query defines the URL for the error page (hosted by service). // The {status} variable can be used in order to insert the status code in the URL. @@ -92,7 +92,7 @@ type CircuitBreaker struct { // Chain holds the configuration of the chain middleware. // This middleware enables to define reusable combinations of other pieces of middleware. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/chain/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/chain/ type Chain struct { // Middlewares is the list of MiddlewareRef which composes the chain. Middlewares []MiddlewareRef `json:"middlewares,omitempty"` @@ -102,7 +102,7 @@ type Chain struct { // BasicAuth holds the basic auth middleware configuration. // This middleware restricts access to your services to known users. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/ type BasicAuth struct { // Secret is the name of the referenced Kubernetes Secret containing user credentials. Secret string `json:"secret,omitempty"` @@ -113,7 +113,7 @@ type BasicAuth struct { // Default: false. RemoveHeader bool `json:"removeHeader,omitempty"` // HeaderField defines a header field to store the authenticated user. - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield HeaderField string `json:"headerField,omitempty"` } @@ -121,7 +121,7 @@ type BasicAuth struct { // DigestAuth holds the digest auth middleware configuration. // This middleware restricts access to your services to known users. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/digestauth/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/digestauth/ type DigestAuth struct { // Secret is the name of the referenced Kubernetes Secret containing user credentials. Secret string `json:"secret,omitempty"` @@ -131,7 +131,7 @@ type DigestAuth struct { // Default: traefik. Realm string `json:"realm,omitempty"` // HeaderField defines a header field to store the authenticated user. - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/basicauth/#headerfield + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/basicauth/#headerfield HeaderField string `json:"headerField,omitempty"` } @@ -139,7 +139,7 @@ type DigestAuth struct { // ForwardAuth holds the forward auth middleware configuration. // This middleware delegates the request authentication to a Service. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/ type ForwardAuth struct { // Address defines the authentication server address. Address string `json:"address,omitempty"` @@ -148,7 +148,7 @@ type ForwardAuth struct { // AuthResponseHeaders defines the list of headers to copy from the authentication server response and set on forwarded request, replacing any existing conflicting headers. AuthResponseHeaders []string `json:"authResponseHeaders,omitempty"` // AuthResponseHeadersRegex defines the regex to match headers to copy from the authentication server response and set on forwarded request, after stripping all headers that match the regex. - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/forwardauth/#authresponseheadersregex + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/forwardauth/#authresponseheadersregex AuthResponseHeadersRegex string `json:"authResponseHeadersRegex,omitempty"` // AuthRequestHeaders defines the list of the headers to copy from the request to the authentication server. // If not set or empty then all request headers are passed. @@ -174,7 +174,7 @@ type ClientTLS struct { // RateLimit holds the rate limit configuration. // This middleware ensures that services will receive a fair amount of requests, and allows one to define what fair is. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/ratelimit/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/ratelimit/ type RateLimit struct { // Average is the maximum rate, by default in requests/s, allowed for the given source. // It defaults to 0, which means no rate limiting. @@ -198,7 +198,7 @@ type RateLimit struct { // Retry holds the retry middleware configuration. // This middleware reissues requests a given number of times to a backend server if that server does not reply. // As soon as the server answers, the middleware stops retrying, regardless of the response status. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/http/retry/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/http/retry/ type Retry struct { // Attempts defines how many times the request should be retried. Attempts int `json:"attempts,omitempty"` diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middlewaretcp.go index 923c3d404..82c126687 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middlewaretcp.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/middlewaretcp.go @@ -9,7 +9,7 @@ import ( // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // MiddlewareTCP is the CRD implementation of a Traefik TCP middleware. -// More info: https://doc.traefik.io/traefik/v2.10/middlewares/overview/ +// More info: https://doc.traefik.io/traefik/v2.11/middlewares/overview/ type MiddlewareTCP struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. @@ -28,11 +28,11 @@ type MiddlewareTCPSpec struct { // IPWhiteList defines the IPWhiteList middleware configuration. // This middleware accepts/refuses connections based on the client IP. // Deprecated: please use IPAllowList instead. - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipwhitelist/ + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipwhitelist/ IPWhiteList *dynamic.TCPIPWhiteList `json:"ipWhiteList,omitempty"` // IPAllowList defines the IPAllowList middleware configuration. // This middleware accepts/refuses connections based on the client IP. - // More info: https://doc.traefik.io/traefik/v2.10/middlewares/tcp/ipallowlist/ + // More info: https://doc.traefik.io/traefik/v2.11/middlewares/tcp/ipallowlist/ IPAllowList *dynamic.TCPIPAllowList `json:"ipAllowList,omitempty"` } diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransport.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransport.go index be4d9decb..e36f2b285 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransport.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransport.go @@ -12,7 +12,7 @@ import ( // ServersTransport is the CRD implementation of a ServersTransport. // If no serversTransport is specified, the default@internal will be used. // The default@internal serversTransport is created from the static configuration. -// More info: https://doc.traefik.io/traefik/v2.10/routing/services/#serverstransport_1 +// More info: https://doc.traefik.io/traefik/v2.11/routing/services/#serverstransport_1 type ServersTransport struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/service.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/service.go index b14625897..6ea8b492c 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/service.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/service.go @@ -13,7 +13,7 @@ import ( // TraefikService object allows to: // - Apply weight to Services on load-balancing // - Mirror traffic on services -// More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#kind-traefikservice +// More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#kind-traefikservice type TraefikService struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. @@ -49,7 +49,7 @@ type TraefikServiceSpec struct { // +k8s:deepcopy-gen=true // Mirroring holds the mirroring service configuration. -// More info: https://doc.traefik.io/traefik/v2.10/routing/services/#mirroring-service +// More info: https://doc.traefik.io/traefik/v2.11/routing/services/#mirroring-service type Mirroring struct { LoadBalancerSpec `json:",inline"` @@ -75,11 +75,11 @@ type MirrorService struct { // +k8s:deepcopy-gen=true // WeightedRoundRobin holds the weighted round-robin configuration. -// More info: https://doc.traefik.io/traefik/v2.10/routing/services/#weighted-round-robin-service +// More info: https://doc.traefik.io/traefik/v2.11/routing/services/#weighted-round-robin-service type WeightedRoundRobin struct { // Services defines the list of Kubernetes Service and/or TraefikService to load-balance, with weight. Services []Service `json:"services,omitempty"` // Sticky defines whether sticky sessions are enabled. - // More info: https://doc.traefik.io/traefik/v2.10/routing/providers/kubernetes-crd/#stickiness-and-load-balancing + // More info: https://doc.traefik.io/traefik/v2.11/routing/providers/kubernetes-crd/#stickiness-and-load-balancing Sticky *dynamic.Sticky `json:"sticky,omitempty"` } diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsoption.go index 996e36a94..0e6e2274d 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsoption.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsoption.go @@ -9,7 +9,7 @@ import ( // +kubebuilder:storageversion // TLSOption is the CRD implementation of a Traefik TLS Option, allowing to configure some parameters of the TLS connection. -// More info: https://doc.traefik.io/traefik/v2.10/https/tls/#tls-options +// More info: https://doc.traefik.io/traefik/v2.11/https/tls/#tls-options type TLSOption struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. @@ -32,10 +32,10 @@ type TLSOptionSpec struct { // Default: None. MaxVersion string `json:"maxVersion,omitempty"` // CipherSuites defines the list of supported cipher suites for TLS versions up to TLS 1.2. - // More info: https://doc.traefik.io/traefik/v2.10/https/tls/#cipher-suites + // More info: https://doc.traefik.io/traefik/v2.11/https/tls/#cipher-suites CipherSuites []string `json:"cipherSuites,omitempty"` // CurvePreferences defines the preferred elliptic curves in a specific order. - // More info: https://doc.traefik.io/traefik/v2.10/https/tls/#curve-preferences + // More info: https://doc.traefik.io/traefik/v2.11/https/tls/#curve-preferences CurvePreferences []string `json:"curvePreferences,omitempty"` // ClientAuth defines the server's policy for TLS Client Authentication. ClientAuth ClientAuth `json:"clientAuth,omitempty"` @@ -46,7 +46,7 @@ type TLSOptionSpec struct { // Deprecated: https://github.com/golang/go/issues/45430 PreferServerCipherSuites bool `json:"preferServerCipherSuites,omitempty"` // ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference. - // More info: https://doc.traefik.io/traefik/v2.10/https/tls/#alpn-protocols + // More info: https://doc.traefik.io/traefik/v2.11/https/tls/#alpn-protocols ALPNProtocols []string `json:"alpnProtocols,omitempty"` } diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsstore.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsstore.go index 082dbc5b1..c6f5d293a 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsstore.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/tlsstore.go @@ -12,7 +12,7 @@ import ( // TLSStore is the CRD implementation of a Traefik TLS Store. // For the time being, only the TLSStore named default is supported. // This means that you cannot have two stores that are named default in different Kubernetes namespaces. -// More info: https://doc.traefik.io/traefik/v2.10/https/tls/#certificates-stores +// More info: https://doc.traefik.io/traefik/v2.11/https/tls/#certificates-stores type TLSStore struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. diff --git a/script/gcg/traefik-bugfix.toml b/script/gcg/traefik-bugfix.toml index d1f7eed10..2ee1b473a 100644 --- a/script/gcg/traefik-bugfix.toml +++ b/script/gcg/traefik-bugfix.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example new bugfix v2.10.7 -CurrentRef = "v2.10" -PreviousRef = "v2.10.6" -BaseBranch = "v2.10" -FutureCurrentRefName = "v2.10.7" +# example new bugfix v2.11.1 +CurrentRef = "v2.11" +PreviousRef = "v2.11.0" +BaseBranch = "v2.11" +FutureCurrentRefName = "v2.11.1" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10 diff --git a/script/gcg/traefik-final-release-part1.toml b/script/gcg/traefik-final-release-part1.toml index ee2bd3017..2e73738fb 100644 --- a/script/gcg/traefik-final-release-part1.toml +++ b/script/gcg/traefik-final-release-part1.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example final release of v2.10.0 -CurrentRef = "v2.10" -PreviousRef = "v2.10.0-rc1" -BaseBranch = "v2.10" -FutureCurrentRefName = "v2.10.0" +# example final release of v2.11.0 +CurrentRef = "v2.11" +PreviousRef = "v2.11.0-rc1" +BaseBranch = "v2.11" +FutureCurrentRefName = "v2.11.0" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10 diff --git a/script/gcg/traefik-final-release-part2.toml b/script/gcg/traefik-final-release-part2.toml index 9f3abf827..bfd11e0f1 100644 --- a/script/gcg/traefik-final-release-part2.toml +++ b/script/gcg/traefik-final-release-part2.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example final release of v2.10.0 -CurrentRef = "v2.10.0-rc1" -PreviousRef = "v2.9.0-rc1" +# example final release of v2.11.0 +CurrentRef = "v2.11.0-rc1" +PreviousRef = "v2.10.0-rc1" BaseBranch = "master" -FutureCurrentRefName = "v2.10.0-rc1" +FutureCurrentRefName = "v2.11.0-rc1" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10 diff --git a/script/gcg/traefik-rc-first.toml b/script/gcg/traefik-rc-first.toml index 67793a9c0..d49585928 100644 --- a/script/gcg/traefik-rc-first.toml +++ b/script/gcg/traefik-rc-first.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example RC1 of v2.9.0 +# example RC1 of v2.11.0 CurrentRef = "master" -PreviousRef = "v2.8.0-rc1" +PreviousRef = "v2.10.0-rc1" BaseBranch = "master" -FutureCurrentRefName = "v2.9.0-rc1" +FutureCurrentRefName = "v2.11.0-rc1" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10 diff --git a/script/gcg/traefik-rc-new.toml b/script/gcg/traefik-rc-new.toml index 61363d378..eb3e59310 100644 --- a/script/gcg/traefik-rc-new.toml +++ b/script/gcg/traefik-rc-new.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example RC2 of v2.10.0 -CurrentRef = "v2.10" -PreviousRef = "v2.10.0-rc1" -BaseBranch = "v2.10" -FutureCurrentRefName = "v2.10.0-rc2" +# example RC2 of v2.11.0 +CurrentRef = "v2.11" +PreviousRef = "v2.11.0-rc1" +BaseBranch = "v2.11" +FutureCurrentRefName = "v2.11.0-rc2" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10 From 45bb00be04daafbeb15b1009159cf914a22b0830 Mon Sep 17 00:00:00 2001 From: Romain Date: Fri, 5 Jan 2024 16:04:05 +0100 Subject: [PATCH 18/21] Improve migration guide Co-authored-by: Baptiste Mayelle --- docs/content/deprecation/features.md | 15 +- docs/content/migration/v2-to-v3.md | 390 +++++++++++++++--- .../reference/static-configuration/cli-ref.md | 3 - .../reference/static-configuration/env-ref.md | 3 - .../reference/static-configuration/file.toml | 1 - .../reference/static-configuration/file.yaml | 1 - pkg/config/static/experimental.go | 1 - 7 files changed, 348 insertions(+), 66 deletions(-) diff --git a/docs/content/deprecation/features.md b/docs/content/deprecation/features.md index 50b42873b..1cf2355df 100644 --- a/docs/content/deprecation/features.md +++ b/docs/content/deprecation/features.md @@ -4,20 +4,23 @@ This page is maintained and updated periodically to reflect our roadmap and any | Feature | Deprecated | End of Support | Removal | |----------------------------------------------------------------------------------------------------------------------|------------|----------------|---------| -| [Kubernetes CRDs API Version `traefik.io/v1alpha1`](#kubernetes-crds-api-version-traefikiov1alpha1) | 3.0 | N/A | 4.0 | +| [Kubernetes CRD Provider API Version `traefik.io/v1alpha1`](#kubernetes-crd-provider-api-version-traefikiov1alpha1) | 3.0 | N/A | 4.0 | | [Kubernetes Ingress API Version `networking.k8s.io/v1beta1`](#kubernetes-ingress-api-version-networkingk8siov1beta1) | N/A | N/A | 3.0 | | [CRD API Version `apiextensions.k8s.io/v1beta1`](#kubernetes-ingress-api-version-networkingk8siov1beta1) | N/A | N/A | 3.0 | ## Impact -### Kubernetes CRDs API Version `traefik.io/v1alpha1` +### Kubernetes CRD Provider API Version `traefik.io/v1alpha1` -The Kubernetes CRD provider API Version `traefik.io/v1alpha1` will subsequently be deprecated in Traefik v3. The next version will be `traefik.io/v1`. +The Kubernetes CRD provider API Version `traefik.io/v1alpha1` is deprecated in Traefik v3. +Please use the API Group `traefik.io/v1` instead. ### Kubernetes Ingress API Version `networking.k8s.io/v1beta1` -The Kubernetes Ingress API Version `networking.k8s.io/v1beta1` is removed in v3. Please use the API Group `networking.k8s.io/v1` instead. +The Kubernetes Ingress API Version `networking.k8s.io/v1beta1` support is removed in v3. +Please use the API Group `networking.k8s.io/v1` instead. -### Traefik CRD API Version `apiextensions.k8s.io/v1beta1` +### Traefik CRD Definitions API Version `apiextensions.k8s.io/v1beta1` -The Traefik CRD API Version `apiextensions.k8s.io/v1beta1` is removed in v3. Please use the API Group `apiextensions.k8s.io/v1` instead. +The Traefik CRD definitions API Version `apiextensions.k8s.io/v1beta1` support is removed in v3. +Please use the API Group `apiextensions.k8s.io/v1` instead. diff --git a/docs/content/migration/v2-to-v3.md b/docs/content/migration/v2-to-v3.md index b9a2fd769..dcc7505a1 100644 --- a/docs/content/migration/v2-to-v3.md +++ b/docs/content/migration/v2-to-v3.md @@ -10,28 +10,335 @@ How to Migrate from Traefik v2 to Traefik v3. The version 3 of Traefik introduces a number of breaking changes, which require one to update their configuration when they migrate from v2 to v3. -The goal of this page is to recapitulate all of these changes, and in particular to give examples, -feature by feature, of how the configuration looked like in v2, and how it now looks like in v3. +The goal of this page is to recapitulate all of these changes, +and in particular to give examples, feature by feature, +of how the configuration looked like in v2, +and how it now looks like in v3. -## IPWhiteList +## Static configuration + +### Docker & Docker Swarm + +In v3, the provider Docker has been split into 2 providers: + +- Docker provider (without Swarm support) +- Swarm provider (Swarm support only) + +??? example "An example usage of v2 Docker provider with Swarm" + + ```yaml tab="File (YAML)" + providers: + docker: + swarmMode: true + ``` + + ```toml tab="File (TOML)" + [providers.docker] + swarmMode=true + ``` + + ```bash tab="CLI" + --providers.docker.swarmMode=true + ``` + +This configuration is now unsupported and would prevent Traefik to start. + +#### Remediation + +In v3, the `swarmMode` should not be used with the Docker provider, and, to use Swarm, the Swarm provider should be used instead. + +??? example "An example usage of the Swarm provider" + + ```yaml tab="File (YAML)" + providers: + swarm: + endpoint: "tcp://127.0.0.1:2377" + ``` + + ```toml tab="File (TOML)" + [providers.swarm] + endpoint="tcp://127.0.0.1:2377" + ``` + + ```bash tab="CLI" + --providers.swarm.endpoint=tcp://127.0.0.1:2377 + ``` + +### HTTP3 Experimental Configuration + +In v3, HTTP/3 is no longer an experimental feature. +It can be enabled on entry points without the associated `experimental.http3` option, which is now removed. +It is now unsupported and would prevent Traefik to start. + +??? example "An example usage of v2 Experimental `http3` option" + + ```yaml tab="File (YAML)" + experimental: + http3: true + ``` + + ```toml tab="File (TOML)" + [experimental] + http3=true + ``` + + ```bash tab="CLI" + --experimental.http3=true + ``` + +#### Remediation + +The `http3` option should be removed from the static configuration experimental section. + +### Consul provider + +The Consul provider `namespace` option was deprecated in v2 and is now removed in v3. +It is now unsupported and would prevent Traefik to start. + +??? example "An example usage of v2 Consul `namespace` option" + + ```yaml tab="File (YAML)" + consul: + namespace: foobar + ``` + + ```toml tab="File (TOML)" + [consul] + namespace=foobar + ``` + + ```bash tab="CLI" + --consul.namespace=foobar + ``` + +#### Remediation + +In v3, the `namespaces` option should be used instead of the `namespace` option. + +??? example "An example usage of Consul `namespaces` option" + + ```yaml tab="File (YAML)" + consul: + namespaces: + - foobar + ``` + + ```toml tab="File (TOML)" + [consul] + namespaces=["foobar"] + ``` + + ```bash tab="CLI" + --consul.namespaces=foobar + ``` + +### ConsulCatalog provider + +The ConsulCatalog provider `namespace` option was deprecated in v2 and is now removed in v3. +It is now unsupported and would prevent Traefik to start. + +??? example "An example usage of v2 ConsulCatalog `namespace` option" + + ```yaml tab="File (YAML)" + consulCatalog: + namespace: foobar + ``` + + ```toml tab="File (TOML)" + [consulCatalog] + namespace=foobar + ``` + + ```bash tab="CLI" + --consulCatalog.namespace=foobar + ``` + +#### Remediation + +In v3, the `namespaces` option should be used instead of the `namespace` option. + +??? example "An example usage of ConsulCatalog `namespaces` option" + + ```yaml tab="File (YAML)" + consulCatalog: + namespaces: + - foobar + ``` + + ```toml tab="File (TOML)" + [consulCatalog] + namespaces=["foobar"] + ``` + + ```bash tab="CLI" + --consulCatalog.namespaces=foobar + ``` + +### Nomad provider + +The Nomad provider `namespace` option was deprecated in v2 and is now removed in v3. +It is now unsupported and would prevent Traefik to start. + +??? example "An example usage of v2 Nomad `namespace` option" + + ```yaml tab="File (YAML)" + nomad: + namespace: foobar + ``` + + ```toml tab="File (TOML)" + [nomad] + namespace=foobar + ``` + + ```bash tab="CLI" + --nomad.namespace=foobar + ``` + +#### Remediation + +In v3, the `namespaces` option should be used instead of the `namespace` option. + +??? example "An example usage of Nomad `namespaces` option" + + ```yaml tab="File (YAML)" + nomad: + namespaces: + - foobar + ``` + + ```toml tab="File (TOML)" + [nomad] + namespaces=["foobar"] + ``` + + ```bash tab="CLI" + --nomad.namespaces=foobar + ``` + +### Rancher v1 Provider + +In v3, the Rancher v1 provider has been removed because Rancher v1 is [no longer actively maintaned](https://rancher.com/docs/os/v1.x/en/support/), +and Rancher v2 is supported as a standard Kubernetes provider. + +??? example "An example of Traefik v2 Rancher v1 configuration" + + ```yaml tab="File (YAML)" + providers: + rancher: {} + ``` + + ```toml tab="File (TOML)" + [providers.rancher] + ``` + + ```bash tab="CLI" + --providers.rancher=true + ``` + +This configuration is now unsupported and would prevent Traefik to start. + +#### Remediation + +Rancher 2.x requires Kubernetes and does not have a metadata endpoint of its own for Traefik to query. +As such, Rancher 2.x users should utilize the [Kubernetes CRD provider](../providers/kubernetes-crd.md) directly. + +Also, all Rancher provider related configuration should be removed from the static configuration. + +### Marathon provider + +Marathon maintenance [ended on October 31, 2021](https://github.com/mesosphere/marathon/blob/master/README.md). +In v3, the Marathon provider has been removed. + +??? example "An example of v2 Marathon provider configuration" + + ```yaml tab="File (YAML)" + providers: + marathon: {} + ``` + + ```toml tab="File (TOML)" + [providers.marathon] + ``` + + ```bash tab="CLI" + --providers.marathon=true + ``` + +This configuration is now unsupported and would prevent Traefik to start. + +#### Remediation + +All Marathon provider related configuration should be removed from the static configuration. + +### InfluxDB v1 + +InfluxDB v1.x maintenance [ended in 2021](https://www.influxdata.com/blog/influxdb-oss-and-enterprise-roadmap-update-from-influxdays-emea/). +In v3, the InfluxDB v1 metrics provider has been removed. + +??? example "An example of Traefik v2 InfluxDB v1 metrics configuration" + + ```yaml tab="File (YAML)" + metrics: + influxDB: {} + ``` + + ```toml tab="File (TOML)" + [metrics.influxDB] + ``` + + ```bash tab="CLI" + --metrics.influxDB=true + ``` + +This configuration is now unsupported and would prevent Traefik to start. + +#### Remediation + +All InfluxDB v1 metrics provider related configuration should be removed from the static configuration. + +### Pilot + +Traefik Pilot is no longer available since October 4th, 2022. + +??? example "An example of v2 Pilot configuration" + + ```yaml tab="File (YAML)" + pilot: + token: foobar + ``` + + ```toml tab="File (TOML)" + [pilot] + token=foobar + ``` + + ```bash tab="CLI" + --pilot.token=foobar + ``` + +In v2, Pilot configuration was deprecated and ineffective, +it is now unsupported and would prevent Traefik to start. + +#### Remediation + +All Pilot related configuration should be removed from the static configuration. + +## Dynamic configuration + +### IPWhiteList In v3, we renamed the `IPWhiteList` middleware to `IPAllowList` without changing anything to the configuration. -## gRPC Metrics +### Deprecated Options Removal -In v3, the reported status code for gRPC requests is now the value of the `Grpc-Status` header. - -## Deprecated Options Removal - -- The `pilot` option has been removed from the static configuration. - The `tracing.datadog.globaltag` option has been removed. -- The `namespace` option of Consul, Consul Catalog and Nomad providers has been removed. - The `tls.caOptional` option has been removed from the ForwardAuth middleware, as well as from the HTTP, Consul, Etcd, Redis, ZooKeeper, Consul Catalog, and Docker providers. - `sslRedirect`, `sslTemporaryRedirect`, `sslHost`, `sslForceHost` and `featurePolicy` options of the Headers middleware have been removed. - The `forceSlash` option of the StripPrefix middleware has been removed. - The `preferServerCipherSuites` option has been removed. -## Matchers +### Matchers In v3, the `Headers` and `HeadersRegexp` matchers have been renamed to `Header` and `HeaderRegexp` respectively. @@ -48,61 +355,42 @@ and should be explicitly combined using logical operators to mimic previous beha `HostHeader` has been removed, use `Host` instead. -## Content-Type Auto-Detection - -In v3, the `Content-Type` header is not auto-detected anymore when it is not set by the backend. -One should use the `ContentType` middleware to enable the `Content-Type` header value auto-detection. - -## HTTP/3 - -In v3, HTTP/3 is no longer an experimental feature. -The `experimental.http3` option has been removed from the static configuration. - -## TCP ServersTransport - -In v3, the support of `TCPServersTransport` has been introduced. -When using the KubernetesCRD provider, it is therefore necessary to update [RBAC](../reference/dynamic-configuration/kubernetes-crd.md#rbac) and [CRD](../reference/dynamic-configuration/kubernetes-crd.md) manifests. - ### TCP LoadBalancer `terminationDelay` option The TCP LoadBalancer `terminationDelay` option has been removed. This option can now be configured directly on the `TCPServersTransport` level, please take a look at this [documentation](../routing/services/index.md#terminationdelay) -## Rancher v1 - -In v3, the rancher v1 provider has been removed because Rancher v1 is [no longer actively maintaned](https://rancher.com/docs/os/v1.x/en/support/) and v2 is supported as a standard Kubernetes provider. - -Rancher 2.x requires Kubernetes and does not have a metadata endpoint of its own for Traefik to query. -As such, Rancher 2.x users should utilize the [Kubernetes CRD provider](../providers/kubernetes-crd.md) directly. - -## Marathon provider - -In v3, the Marathon provider has been removed. - -## InfluxDB v1 - -In v3, the InfluxDB v1 metrics provider has been removed because InfluxDB v1.x maintenance [ended in 2021](https://www.influxdata.com/blog/influxdb-oss-and-enterprise-roadmap-update-from-influxdays-emea/). - -## Kubernetes CRDs API Group `traefik.containo.us` +### Kubernetes CRDs API Group `traefik.containo.us` In v3, the Kubernetes CRDs API Group `traefik.containo.us` has been removed. Please use the API Group `traefik.io` instead. -## Docker & Docker Swarm - -In v3, the provider Docker has been split into 2 providers: - -- Docker provider (without Swarm support) -- Swarm provider (Swarm support only) - -## Kubernetes Ingress API Group `networking.k8s.io/v1beta1` +### Kubernetes Ingress API Group `networking.k8s.io/v1beta1` In v3, the Kubernetes Ingress API Group `networking.k8s.io/v1beta1` ([removed since Kubernetes v1.22](https://kubernetes.io/docs/reference/using-api/deprecation-guide/#ingress-v122)) support has been removed. Please use the API Group `networking.k8s.io/v1` instead. -## Traefik CRD API Version `apiextensions.k8s.io/v1beta1` +### Traefik CRD API Version `apiextensions.k8s.io/v1beta1` In v3, the Traefik CRD API Version `apiextensions.k8s.io/v1beta1` ([removed since Kubernetes v1.22](https://kubernetes.io/docs/reference/using-api/deprecation-guide/#customresourcedefinition-v122)) support has been removed. Please use the CRD definition with the API Version `apiextensions.k8s.io/v1` instead. + +## Operations + +### Traefik RBAC Update + +In v3, the support of `TCPServersTransport` has been introduced. +When using the KubernetesCRD provider, it is therefore necessary to update [RBAC](../reference/dynamic-configuration/kubernetes-crd.md#rbac) and [CRD](../reference/dynamic-configuration/kubernetes-crd.md) manifests. + +### Content-Type Auto-Detection + +In v3, the `Content-Type` header is not auto-detected anymore when it is not set by the backend. +One should use the `ContentType` middleware to enable the `Content-Type` header value auto-detection. + +### Observability + +#### gRPC Metrics + +In v3, the reported status code for gRPC requests is now the value of the `Grpc-Status` header. diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index 8f6441ea9..8e64fd2ae 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -201,9 +201,6 @@ WriteTimeout is the maximum duration before timing out writes of the response. I `--entrypoints..udp.timeout`: Timeout defines how long to wait on an idle session before releasing the related resources. (Default: ```3```) -`--experimental.http3`: -Enable HTTP3. (Default: ```false```) - `--experimental.kubernetesgateway`: Allow the Kubernetes gateway api provider usage. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 2a8302879..36dd4040c 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -201,9 +201,6 @@ WriteTimeout is the maximum duration before timing out writes of the response. I `TRAEFIK_ENTRYPOINTS__UDP_TIMEOUT`: Timeout defines how long to wait on an idle session before releasing the related resources. (Default: ```3```) -`TRAEFIK_EXPERIMENTAL_HTTP3`: -Enable HTTP3. (Default: ```false```) - `TRAEFIK_EXPERIMENTAL_KUBERNETESGATEWAY`: Allow the Kubernetes gateway api provider usage. (Default: ```false```) diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index 5ae9a9356..6d75b4dbc 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -459,7 +459,6 @@ [experimental] kubernetesGateway = true - http3 = true [experimental.plugins] [experimental.plugins.Descriptor0] moduleName = "foobar" diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index 0dc2390c2..4410e29eb 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -489,7 +489,6 @@ certificatesResolvers: tailscale: {} experimental: kubernetesGateway: true - http3: true plugins: Descriptor0: moduleName: foobar diff --git a/pkg/config/static/experimental.go b/pkg/config/static/experimental.go index 936dfd534..7428f6a08 100644 --- a/pkg/config/static/experimental.go +++ b/pkg/config/static/experimental.go @@ -8,5 +8,4 @@ type Experimental struct { LocalPlugins map[string]plugins.LocalDescriptor `description:"Local plugins configuration." json:"localPlugins,omitempty" toml:"localPlugins,omitempty" yaml:"localPlugins,omitempty" export:"true"` KubernetesGateway bool `description:"Allow the Kubernetes gateway api provider usage." json:"kubernetesGateway,omitempty" toml:"kubernetesGateway,omitempty" yaml:"kubernetesGateway,omitempty" export:"true"` - HTTP3 bool `description:"Enable HTTP3." json:"http3,omitempty" toml:"http3,omitempty" yaml:"http3,omitempty" export:"true"` } From 4ddef9830b3f895c223a664d1e7d6f3c1b290d73 Mon Sep 17 00:00:00 2001 From: Jesse Haka Date: Mon, 8 Jan 2024 10:10:06 +0200 Subject: [PATCH 19/21] Migrate to opentelemetry --- cmd/traefik/traefik.go | 80 +-- docs/content/migration/v2-to-v3.md | 21 + docs/content/observability/tracing/datadog.md | 139 ----- docs/content/observability/tracing/elastic.md | 93 --- .../content/observability/tracing/haystack.md | 176 ------ docs/content/observability/tracing/instana.md | 117 ---- docs/content/observability/tracing/jaeger.md | 294 --------- .../observability/tracing/opentelemetry.md | 304 +++++++--- .../content/observability/tracing/overview.md | 76 ++- docs/content/observability/tracing/zipkin.md | 110 ---- .../reference/static-configuration/cli-ref.md | 184 +----- .../reference/static-configuration/env-ref.md | 184 +----- .../reference/static-configuration/file.toml | 74 +-- .../reference/static-configuration/file.yaml | 83 +-- docs/mkdocs.yml | 10 - go.mod | 96 +-- go.sum | 283 +++------ .../tracing/otel-collector-config.yaml | 21 + .../fixtures/tracing/simple-jaeger.toml | 70 --- ...llector.toml => simple-opentelemetry.toml} | 26 +- .../fixtures/tracing/simple-zipkin.toml | 66 -- integration/fixtures/tracing/tempo.yaml | 56 ++ integration/resources/compose/tracing.yml | 21 +- integration/tracing_test.go | 569 ++++++++++++------ pkg/api/handler_overview_test.go | 5 +- pkg/api/testdata/overview-features.json | 2 +- pkg/config/dynamic/fixtures/sample.toml | 58 +- pkg/config/static/static_config.go | 38 +- pkg/logs/haystack.go | 28 - pkg/logs/haystack_test.go | 24 - pkg/logs/jaeger.go | 23 - pkg/logs/jaeger_test.go | 24 - pkg/metrics/opentelemetry.go | 2 +- pkg/middlewares/addprefix/add_prefix.go | 7 +- pkg/middlewares/auth/basic_auth.go | 14 +- pkg/middlewares/auth/digest_auth.go | 16 +- pkg/middlewares/auth/forward.go | 57 +- pkg/middlewares/auth/forward_test.go | 64 +- pkg/middlewares/buffering/buffering.go | 7 +- .../circuitbreaker/circuit_breaker.go | 8 +- pkg/middlewares/compress/compress.go | 7 +- .../connectionheader/connectionheader.go | 35 +- pkg/middlewares/customerrors/custom_errors.go | 12 +- pkg/middlewares/grpcweb/grpcweb.go | 2 +- pkg/middlewares/headers/headers.go | 7 +- pkg/middlewares/headers/headers_test.go | 7 +- pkg/middlewares/inflightreq/inflight_req.go | 7 +- pkg/middlewares/ipallowlist/ip_allowlist.go | 8 +- pkg/middlewares/metrics/metrics.go | 18 + .../passtlsclientcert/pass_tls_client_cert.go | 7 +- pkg/middlewares/ratelimiter/rate_limiter.go | 10 +- pkg/middlewares/redirect/redirect.go | 9 +- pkg/middlewares/replacepath/replace_path.go | 7 +- .../replacepathregex/replace_path_regex.go | 7 +- pkg/middlewares/retry/retry.go | 39 +- pkg/middlewares/stripprefix/strip_prefix.go | 7 +- .../stripprefixregex/strip_prefix_regex.go | 7 +- pkg/middlewares/tracing/entrypoint.go | 62 +- pkg/middlewares/tracing/entrypoint_test.go | 92 ++- pkg/middlewares/tracing/forwarder.go | 59 -- pkg/middlewares/tracing/forwarder_test.go | 136 ----- pkg/middlewares/tracing/middleware.go | 71 +++ pkg/middlewares/tracing/mock_tracing_test.go | 92 ++- pkg/middlewares/tracing/router.go | 60 ++ pkg/middlewares/tracing/router_test.go | 86 +++ pkg/middlewares/tracing/service.go | 45 ++ pkg/middlewares/tracing/service_test.go | 80 +++ pkg/middlewares/tracing/wrapper.go | 69 --- pkg/redactor/redactor_config_test.go | 68 +-- .../testdata/anonymized-static-config.json | 60 +- pkg/server/middleware/chainbuilder.go | 19 +- pkg/server/middleware/middlewares.go | 2 +- pkg/server/middleware/plugins.go | 9 +- pkg/server/router/router.go | 11 +- pkg/server/server.go | 14 +- pkg/server/service/proxy.go | 44 +- pkg/server/service/service.go | 13 +- pkg/server/service/tracing_roundtripper.go | 42 ++ pkg/tracing/datadog/datadog.go | 84 --- pkg/tracing/elastic/elastic.go | 74 --- pkg/tracing/haystack/haystack.go | 72 --- pkg/tracing/instana/instana.go | 61 -- pkg/tracing/jaeger/jaeger.go | 124 ---- pkg/tracing/opentelemetry/opentelemetry.go | 115 ++-- .../opentelemetry/opentelemetry_test.go | 33 +- pkg/tracing/operation_name.go | 65 -- pkg/tracing/operation_name_test.go | 135 ----- pkg/tracing/tracing.go | 317 +++++----- pkg/tracing/zipkin/zipkin.go | 71 --- 89 files changed, 2113 insertions(+), 3898 deletions(-) delete mode 100644 docs/content/observability/tracing/datadog.md delete mode 100644 docs/content/observability/tracing/elastic.md delete mode 100644 docs/content/observability/tracing/haystack.md delete mode 100644 docs/content/observability/tracing/instana.md delete mode 100644 docs/content/observability/tracing/jaeger.md delete mode 100644 docs/content/observability/tracing/zipkin.md create mode 100644 integration/fixtures/tracing/otel-collector-config.yaml delete mode 100644 integration/fixtures/tracing/simple-jaeger.toml rename integration/fixtures/tracing/{simple-jaeger-collector.toml => simple-opentelemetry.toml} (76%) delete mode 100644 integration/fixtures/tracing/simple-zipkin.toml create mode 100644 integration/fixtures/tracing/tempo.yaml delete mode 100644 pkg/logs/haystack.go delete mode 100644 pkg/logs/haystack_test.go delete mode 100644 pkg/logs/jaeger.go delete mode 100644 pkg/logs/jaeger_test.go delete mode 100644 pkg/middlewares/tracing/forwarder.go delete mode 100644 pkg/middlewares/tracing/forwarder_test.go create mode 100644 pkg/middlewares/tracing/middleware.go create mode 100644 pkg/middlewares/tracing/router.go create mode 100644 pkg/middlewares/tracing/router_test.go create mode 100644 pkg/middlewares/tracing/service.go create mode 100644 pkg/middlewares/tracing/service_test.go delete mode 100644 pkg/middlewares/tracing/wrapper.go create mode 100644 pkg/server/service/tracing_roundtripper.go delete mode 100644 pkg/tracing/datadog/datadog.go delete mode 100644 pkg/tracing/elastic/elastic.go delete mode 100644 pkg/tracing/haystack/haystack.go delete mode 100644 pkg/tracing/instana/instana.go delete mode 100644 pkg/tracing/jaeger/jaeger.go delete mode 100644 pkg/tracing/operation_name.go delete mode 100644 pkg/tracing/operation_name_test.go delete mode 100644 pkg/tracing/zipkin/zipkin.go diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index f3e01f7b8..0ac89fb46 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -5,6 +5,7 @@ import ( "crypto/x509" "encoding/json" "fmt" + "io" stdlog "log" "net/http" "os" @@ -43,9 +44,9 @@ import ( "github.com/traefik/traefik/v3/pkg/tcp" traefiktls "github.com/traefik/traefik/v3/pkg/tls" "github.com/traefik/traefik/v3/pkg/tracing" - "github.com/traefik/traefik/v3/pkg/tracing/jaeger" "github.com/traefik/traefik/v3/pkg/types" "github.com/traefik/traefik/v3/pkg/version" + "go.opentelemetry.io/otel/trace" ) func main() { @@ -265,10 +266,9 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err managerFactory := service.NewManagerFactory(*staticConfiguration, routinesPool, metricsRegistry, roundTripperManager, acmeHTTPHandler) // Router factory - accessLog := setupAccessLog(staticConfiguration.AccessLog) - tracer := setupTracing(staticConfiguration.Tracing) + tracer, tracerCloser := setupTracing(staticConfiguration.Tracing) chainBuilder := middleware.NewChainBuilder(metricsRegistry, accessLog, tracer) routerFactory := server.NewRouterFactory(*staticConfiguration, managerFactory, tlsManager, chainBuilder, pluginBuilder, metricsRegistry, dialerManager) @@ -351,7 +351,7 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err } }) - return server.NewServer(routinesPool, serverEntryPointsTCP, serverEntryPointsUDP, watcher, chainBuilder, accessLog), nil + return server.NewServer(routinesPool, serverEntryPointsTCP, serverEntryPointsUDP, watcher, chainBuilder, accessLog, tracerCloser), nil } func getHTTPChallengeHandler(acmeProviders []*acme.Provider, httpChallengeProvider http.Handler) http.Handler { @@ -564,78 +564,18 @@ func setupAccessLog(conf *types.AccessLog) *accesslog.Handler { return accessLoggerMiddleware } -func setupTracing(conf *static.Tracing) *tracing.Tracing { +func setupTracing(conf *static.Tracing) (trace.Tracer, io.Closer) { if conf == nil { - return nil + return nil, nil } - var backend tracing.Backend - - if conf.Jaeger != nil { - backend = conf.Jaeger - } - - if conf.Zipkin != nil { - if backend != nil { - log.Error().Msg("Multiple tracing backend are not supported: cannot create Zipkin backend.") - } else { - backend = conf.Zipkin - } - } - - if conf.Datadog != nil { - if backend != nil { - log.Error().Msg("Multiple tracing backend are not supported: cannot create Datadog backend.") - } else { - backend = conf.Datadog - } - } - - if conf.Instana != nil { - if backend != nil { - log.Error().Msg("Multiple tracing backend are not supported: cannot create Instana backend.") - } else { - backend = conf.Instana - } - } - - if conf.Haystack != nil { - if backend != nil { - log.Error().Msg("Multiple tracing backend are not supported: cannot create Haystack backend.") - } else { - backend = conf.Haystack - } - } - - if conf.Elastic != nil { - if backend != nil { - log.Error().Msg("Multiple tracing backend are not supported: cannot create Elastic backend.") - } else { - backend = conf.Elastic - } - } - - if conf.OpenTelemetry != nil { - if backend != nil { - log.Error().Msg("Tracing backends are all mutually exclusive: cannot create OpenTelemetry backend.") - } else { - backend = conf.OpenTelemetry - } - } - - if backend == nil { - log.Debug().Msg("Could not initialize tracing, using Jaeger by default") - defaultBackend := &jaeger.Config{} - defaultBackend.SetDefaults() - backend = defaultBackend - } - - tracer, err := tracing.NewTracing(conf.ServiceName, conf.SpanNameLimit, backend) + tracer, closer, err := tracing.NewTracing(conf) if err != nil { log.Warn().Err(err).Msg("Unable to create tracer") - return nil + return nil, nil } - return tracer + + return tracer, closer } func checkNewVersion() { diff --git a/docs/content/migration/v2-to-v3.md b/docs/content/migration/v2-to-v3.md index dcc7505a1..70b27f820 100644 --- a/docs/content/migration/v2-to-v3.md +++ b/docs/content/migration/v2-to-v3.md @@ -394,3 +394,24 @@ One should use the `ContentType` middleware to enable the `Content-Type` header #### gRPC Metrics In v3, the reported status code for gRPC requests is now the value of the `Grpc-Status` header. + +#### Tracing + +In v3, the tracing feature has been revamped and is now powered exclusively by [OpenTelemetry](https://opentelemetry.io/ "Link to website of OTel") (OTel). +!!! warning "Important" + + Traefik v3 **no** longer supports direct output formats for specific vendors such as Instana, Jaeger, Zipkin, Haystack, Datadog, and Elastic. +Instead, it focuses on pure OpenTelemetry implementation, providing a unified and standardized approach for observability. + +Here are two possible transition strategies: + +1. OTLP Ingestion Endpoints: + + Most vendors now offer OpenTelemetry Protocol (OTLP) ingestion endpoints. + You can seamlessly integrate Traefik v3 with these endpoints to continue leveraging tracing capabilities. + +2. Legacy Stack Compatibility: + + For legacy stacks that cannot immediately upgrade to the latest vendor agents supporting OTLP ingestion, + using OpenTelemetry (OTel) collectors with appropriate exporters configuration is a viable solution. + This allows continued compatibility with the existing infrastructure. diff --git a/docs/content/observability/tracing/datadog.md b/docs/content/observability/tracing/datadog.md deleted file mode 100644 index fe14bc72f..000000000 --- a/docs/content/observability/tracing/datadog.md +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: "Traefik Datadog Tracing Documentation" -description: "Traefik Proxy supports Datadog for tracing. Read the technical documentation to enable Datadog for observability." ---- - -# Datadog - -To enable the Datadog tracer: - -```yaml tab="File (YAML)" -tracing: - datadog: {} -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.datadog] -``` - -```bash tab="CLI" ---tracing.datadog=true -``` - -#### `localAgentHostPort` - -_Optional, Default="localhost:8126"_ - -Local Agent Host Port instructs the reporter to send spans to the Datadog Agent at this address (host:port). - -```yaml tab="File (YAML)" -tracing: - datadog: - localAgentHostPort: localhost:8126 -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.datadog] - localAgentHostPort = "localhost:8126" -``` - -```bash tab="CLI" ---tracing.datadog.localAgentHostPort=localhost:8126 -``` - -#### `localAgentSocket` - -_Optional, Default=""_ - -Local Agent Socket instructs the reporter to send spans to the Datadog Agent at this UNIX socket. - -```yaml tab="File (YAML)" -tracing: - datadog: - localAgentSocket: /var/run/datadog/apm.socket -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.datadog] - localAgentSocket = "/var/run/datadog/apm.socket" -``` - -```bash tab="CLI" ---tracing.datadog.localAgentSocket=/var/run/datadog/apm.socket -``` - -#### `debug` - -_Optional, Default=false_ - -Enables Datadog debug. - -```yaml tab="File (YAML)" -tracing: - datadog: - debug: true -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.datadog] - debug = true -``` - -```bash tab="CLI" ---tracing.datadog.debug=true -``` - -#### `globalTags` - -_Optional, Default=empty_ - -Applies a list of shared key:value tags on all spans. - -```yaml tab="File (YAML)" -tracing: - datadog: - globalTags: - tag1: foo - tag2: bar -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.datadog] - [tracing.datadog.globalTags] - tag1 = "foo" - tag2 = "bar" -``` - -```bash tab="CLI" ---tracing.datadog.globalTags.tag1=foo ---tracing.datadog.globalTags.tag2=bar -``` - -#### `prioritySampling` - -_Optional, Default=false_ - -Enables priority sampling. -When using distributed tracing, -this option must be enabled in order to get all the parts of a distributed trace sampled. - -```yaml tab="File (YAML)" -tracing: - datadog: - prioritySampling: true -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.datadog] - prioritySampling = true -``` - -```bash tab="CLI" ---tracing.datadog.prioritySampling=true -``` diff --git a/docs/content/observability/tracing/elastic.md b/docs/content/observability/tracing/elastic.md deleted file mode 100644 index 0cb0dccee..000000000 --- a/docs/content/observability/tracing/elastic.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: "Traefik Elastic Documentation" -description: "Traefik supports several tracing backends, including Elastic. Learn how to implement it for observability in Traefik Proxy. Read the technical documentation." ---- - -# Elastic - -To enable the Elastic tracer: - -```yaml tab="File (YAML)" -tracing: - elastic: {} -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.elastic] -``` - -```bash tab="CLI" ---tracing.elastic=true -``` - -#### `serverURL` - -_Optional, Default="http://localhost:8200"_ - -URL of the Elastic APM server. - -```yaml tab="File (YAML)" -tracing: - elastic: - serverURL: "http://apm:8200" -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.elastic] - serverURL = "http://apm:8200" -``` - -```bash tab="CLI" ---tracing.elastic.serverurl="http://apm:8200" -``` - -#### `secretToken` - -_Optional, Default=""_ - -Token used to connect to Elastic APM Server. - -```yaml tab="File (YAML)" -tracing: - elastic: - secretToken: "mytoken" -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.elastic] - secretToken = "mytoken" -``` - -```bash tab="CLI" ---tracing.elastic.secrettoken="mytoken" -``` - -#### `serviceEnvironment` - -_Optional, Default=""_ - -Environment's name where Traefik is deployed in, e.g. `production` or `staging`. - -```yaml tab="File (YAML)" -tracing: - elastic: - serviceEnvironment: "production" -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.elastic] - serviceEnvironment = "production" -``` - -```bash tab="CLI" ---tracing.elastic.serviceenvironment="production" -``` - -### Further - -Additional configuration of Elastic APM Go agent can be done using environment variables. -See [APM Go agent reference](https://www.elastic.co/guide/en/apm/agent/go/current/configuration.html). diff --git a/docs/content/observability/tracing/haystack.md b/docs/content/observability/tracing/haystack.md deleted file mode 100644 index af9945ed7..000000000 --- a/docs/content/observability/tracing/haystack.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: "Traefik Haystack Documentation" -description: "Traefik supports several tracing backends, including Haystack. Learn how to implement it for observability in Traefik Proxy. Read the technical documentation." ---- - -# Haystack - -To enable the Haystack tracer: - -```yaml tab="File (YAML)" -tracing: - haystack: {} -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.haystack] -``` - -```bash tab="CLI" ---tracing.haystack=true -``` - -#### `localAgentHost` - -_Required, Default="127.0.0.1"_ - -Local Agent Host instructs reporter to send spans to the Haystack Agent at this address. - -```yaml tab="File (YAML)" -tracing: - haystack: - localAgentHost: 127.0.0.1 -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.haystack] - localAgentHost = "127.0.0.1" -``` - -```bash tab="CLI" ---tracing.haystack.localAgentHost=127.0.0.1 -``` - -#### `localAgentPort` - -_Required, Default=35000_ - -Local Agent Port instructs reporter to send spans to the Haystack Agent at this port. - -```yaml tab="File (YAML)" -tracing: - haystack: - localAgentPort: 35000 -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.haystack] - localAgentPort = 35000 -``` - -```bash tab="CLI" ---tracing.haystack.localAgentPort=35000 -``` - -#### `globalTag` - -_Optional, Default=empty_ - -Applies shared key:value tag on all spans. - -```yaml tab="File (YAML)" -tracing: - haystack: - globalTag: sample:test -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.haystack] - globalTag = "sample:test" -``` - -```bash tab="CLI" ---tracing.haystack.globalTag=sample:test -``` - -#### `traceIDHeaderName` - -_Optional, Default=empty_ - -Sets the header name used to store the trace ID. - -```yaml tab="File (YAML)" -tracing: - haystack: - traceIDHeaderName: Trace-ID -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.haystack] - traceIDHeaderName = "Trace-ID" -``` - -```bash tab="CLI" ---tracing.haystack.traceIDHeaderName=Trace-ID -``` - -#### `parentIDHeaderName` - -_Optional, Default=empty_ - -Sets the header name used to store the parent ID. - -```yaml tab="File (YAML)" -tracing: - haystack: - parentIDHeaderName: Parent-Message-ID -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.haystack] - parentIDHeaderName = "Parent-Message-ID" -``` - -```bash tab="CLI" ---tracing.haystack.parentIDHeaderName=Parent-Message-ID -``` - -#### `spanIDHeaderName` - -_Optional, Default=empty_ - -Sets the header name used to store the span ID. - -```yaml tab="File (YAML)" -tracing: - haystack: - spanIDHeaderName: Message-ID -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.haystack] - spanIDHeaderName = "Message-ID" -``` - -```bash tab="CLI" ---tracing.haystack.spanIDHeaderName=Message-ID -``` - -#### `baggagePrefixHeaderName` - -_Optional, Default=empty_ - -Sets the header name prefix used to store baggage items in a map. - -```yaml tab="File (YAML)" -tracing: - haystack: - baggagePrefixHeaderName: "sample" -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.haystack] - baggagePrefixHeaderName = "sample" -``` - -```bash tab="CLI" ---tracing.haystack.baggagePrefixHeaderName=sample -``` diff --git a/docs/content/observability/tracing/instana.md b/docs/content/observability/tracing/instana.md deleted file mode 100644 index 914d9d3f4..000000000 --- a/docs/content/observability/tracing/instana.md +++ /dev/null @@ -1,117 +0,0 @@ ---- -title: "Traefik Instana Documentation" -description: "Traefik supports several tracing backends, including Instana. Learn how to implement it for observability in Traefik Proxy. Read the technical documentation." ---- - -# Instana - -To enable the Instana tracer: - -```yaml tab="File (YAML)" -tracing: - instana: {} -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.instana] -``` - -```bash tab="CLI" ---tracing.instana=true -``` - -#### `localAgentHost` - -_Required, Default="127.0.0.1"_ - -Local Agent Host instructs reporter to send spans to the Instana Agent at this address. - -```yaml tab="File (YAML)" -tracing: - instana: - localAgentHost: 127.0.0.1 -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.instana] - localAgentHost = "127.0.0.1" -``` - -```bash tab="CLI" ---tracing.instana.localAgentHost=127.0.0.1 -``` - -#### `localAgentPort` - -_Required, Default=42699_ - -Local Agent port instructs reporter to send spans to the Instana Agent listening on this port. - -```yaml tab="File (YAML)" -tracing: - instana: - localAgentPort: 42699 -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.instana] - localAgentPort = 42699 -``` - -```bash tab="CLI" ---tracing.instana.localAgentPort=42699 -``` - -#### `logLevel` - -_Required, Default="info"_ - -Sets Instana tracer log level. - -Valid values are: - -- `error` -- `warn` -- `debug` -- `info` - -```yaml tab="File (YAML)" -tracing: - instana: - logLevel: info -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.instana] - logLevel = "info" -``` - -```bash tab="CLI" ---tracing.instana.logLevel=info -``` - -#### `enableAutoProfile` - -_Required, Default=false_ - -Enables [automatic profiling](https://www.ibm.com/docs/en/obi/current?topic=instana-profile-processes) for the Traefik process. - -```yaml tab="File (YAML)" -tracing: - instana: - enableAutoProfile: true -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.instana] - enableAutoProfile = true -``` - -```bash tab="CLI" ---tracing.instana.enableAutoProfile=true -``` diff --git a/docs/content/observability/tracing/jaeger.md b/docs/content/observability/tracing/jaeger.md deleted file mode 100644 index d40ffed6d..000000000 --- a/docs/content/observability/tracing/jaeger.md +++ /dev/null @@ -1,294 +0,0 @@ ---- -title: "Traefik Jaeger Documentation" -description: "Traefik supports several tracing backends, including Jaeger. Learn how to implement it for observability in Traefik Proxy. Read the technical documentation." ---- - -# Jaeger - -To enable the Jaeger tracer: - -```yaml tab="File (YAML)" -tracing: - jaeger: {} -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.jaeger] -``` - -```bash tab="CLI" ---tracing.jaeger=true -``` - -!!! warning - Traefik is able to send data over the compact thrift protocol to the [Jaeger agent](https://www.jaegertracing.io/docs/deployment/#agent) - or a [Jaeger collector](https://www.jaegertracing.io/docs/deployment/#collector). - -!!! info - All Jaeger configuration can be overridden by [environment variables](https://github.com/jaegertracing/jaeger-client-go#environment-variables) - -#### `samplingServerURL` - -_Required, Default="http://localhost:5778/sampling"_ - -Address of the Jaeger Agent HTTP sampling server. - -```yaml tab="File (YAML)" -tracing: - jaeger: - samplingServerURL: http://localhost:5778/sampling -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.jaeger] - samplingServerURL = "http://localhost:5778/sampling" -``` - -```bash tab="CLI" ---tracing.jaeger.samplingServerURL=http://localhost:5778/sampling -``` - -#### `samplingType` - -_Required, Default="const"_ - -Type of the sampler. - -Valid values are: - -- `const` -- `probabilistic` -- `rateLimiting` - -```yaml tab="File (YAML)" -tracing: - jaeger: - samplingType: const -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.jaeger] - samplingType = "const" -``` - -```bash tab="CLI" ---tracing.jaeger.samplingType=const -``` - -#### `samplingParam` - -_Required, Default=1.0_ - -Value passed to the sampler. - -Valid values are: - -- for `const` sampler, 0 or 1 for always false/true respectively -- for `probabilistic` sampler, a probability between 0 and 1 -- for `rateLimiting` sampler, the number of spans per second - -```yaml tab="File (YAML)" -tracing: - jaeger: - samplingParam: 1.0 -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.jaeger] - samplingParam = 1.0 -``` - -```bash tab="CLI" ---tracing.jaeger.samplingParam=1.0 -``` - -#### `localAgentHostPort` - -_Required, Default="127.0.0.1:6831"_ - -Local Agent Host Port instructs the reporter to send spans to the Jaeger Agent at this address (host:port). - -```yaml tab="File (YAML)" -tracing: - jaeger: - localAgentHostPort: 127.0.0.1:6831 -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.jaeger] - localAgentHostPort = "127.0.0.1:6831" -``` - -```bash tab="CLI" ---tracing.jaeger.localAgentHostPort=127.0.0.1:6831 -``` - -#### `gen128Bit` - -_Optional, Default=false_ - -Generates 128 bits trace IDs, compatible with OpenCensus. - -```yaml tab="File (YAML)" -tracing: - jaeger: - gen128Bit: true -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.jaeger] - gen128Bit = true -``` - -```bash tab="CLI" ---tracing.jaeger.gen128Bit -``` - -#### `propagation` - -_Required, Default="jaeger"_ - -Sets the propagation header type. - -Valid values are: - -- `jaeger`, jaeger's default trace header. -- `b3`, compatible with OpenZipkin - -```yaml tab="File (YAML)" -tracing: - jaeger: - propagation: jaeger -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.jaeger] - propagation = "jaeger" -``` - -```bash tab="CLI" ---tracing.jaeger.propagation=jaeger -``` - -#### `traceContextHeaderName` - -_Required, Default="uber-trace-id"_ - -HTTP header name used to propagate tracing context. -This must be in lower-case to avoid mismatches when decoding incoming headers. - -```yaml tab="File (YAML)" -tracing: - jaeger: - traceContextHeaderName: uber-trace-id -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.jaeger] - traceContextHeaderName = "uber-trace-id" -``` - -```bash tab="CLI" ---tracing.jaeger.traceContextHeaderName=uber-trace-id -``` - -### disableAttemptReconnecting - -_Optional, Default=true_ - -Disables the UDP connection helper that periodically re-resolves the agent's hostname and reconnects if there was a change. -Enabling the re-resolving of UDP address make the client more robust in Kubernetes deployments. - -```yaml tab="File (YAML)" -tracing: - jaeger: - disableAttemptReconnecting: false -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.jaeger] - disableAttemptReconnecting = false -``` - -```bash tab="CLI" ---tracing.jaeger.disableAttemptReconnecting=false -``` - -### `collector` -#### `endpoint` - -_Optional, Default=""_ - -Collector Endpoint instructs the reporter to send spans to the Jaeger Collector at this URL. - -```yaml tab="File (YAML)" -tracing: - jaeger: - collector: - endpoint: http://127.0.0.1:14268/api/traces?format=jaeger.thrift -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.jaeger.collector] - endpoint = "http://127.0.0.1:14268/api/traces?format=jaeger.thrift" -``` - -```bash tab="CLI" ---tracing.jaeger.collector.endpoint=http://127.0.0.1:14268/api/traces?format=jaeger.thrift -``` - -#### `user` - -_Optional, Default=""_ - -User instructs the reporter to include a user for basic HTTP authentication when sending spans to the Jaeger Collector. - -```yaml tab="File (YAML)" -tracing: - jaeger: - collector: - user: my-user -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.jaeger.collector] - user = "my-user" -``` - -```bash tab="CLI" ---tracing.jaeger.collector.user=my-user -``` - -#### `password` - -_Optional, Default=""_ - -Password instructs the reporter to include a password for basic HTTP authentication when sending spans to the Jaeger Collector. - -```yaml tab="File (YAML)" -tracing: - jaeger: - collector: - password: my-password -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.jaeger.collector] - password = "my-password" -``` - -```bash tab="CLI" ---tracing.jaeger.collector.password=my-password -``` diff --git a/docs/content/observability/tracing/opentelemetry.md b/docs/content/observability/tracing/opentelemetry.md index d39e09b58..52b37a0a5 100644 --- a/docs/content/observability/tracing/opentelemetry.md +++ b/docs/content/observability/tracing/opentelemetry.md @@ -9,122 +9,75 @@ To enable the OpenTelemetry tracer: ```yaml tab="File (YAML)" tracing: - openTelemetry: {} + otlp: {} ``` ```toml tab="File (TOML)" [tracing] - [tracing.openTelemetry] + [tracing.otlp] ``` ```bash tab="CLI" ---tracing.openTelemetry=true +--tracing.otlp=true ``` -!!! info "The OpenTelemetry trace reporter will export traces to the collector using HTTP by default, see the [gRPC Section](#grpc-configuration) to use gRPC." +!!! info "The OpenTelemetry trace reporter will export traces to the collector using HTTP by default (http://localhost:4318/v1/traces), +see the [gRPC Section](#grpc-configuration) to use gRPC." !!! info "Trace sampling" - By default, the OpenTelemetry trace reporter will sample 100% of traces. + By default, the OpenTelemetry trace reporter will sample 100% of traces. See [OpenTelemetry's SDK configuration](https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/#general-sdk-configuration) to customize the sampling strategy. -#### `address` +### HTTP configuration -_Required, Default="localhost:4318", Format="`:`"_ +_Optional_ -Address of the OpenTelemetry Collector to send spans to. +This instructs the reporter to send spans to the OpenTelemetry Collector using HTTP. ```yaml tab="File (YAML)" tracing: - openTelemetry: - address: localhost:4318 + otlp: + http: {} ``` ```toml tab="File (TOML)" [tracing] - [tracing.openTelemetry] - address = "localhost:4318" + [tracing.otlp.http] ``` ```bash tab="CLI" ---tracing.openTelemetry.address=localhost:4318 +--tracing.otlp.http=true ``` -#### `headers` +#### `endpoint` -_Optional, Default={}_ +_Required, Default="http://localhost:4318/v1/traces", Format="`://:`"_ -Additional headers sent with spans by the reporter to the OpenTelemetry Collector. +URL of the OpenTelemetry Collector to send spans to. ```yaml tab="File (YAML)" tracing: - openTelemetry: - headers: - foo: bar - baz: buz + otlp: + http: + endpoint: http://localhost:4318/v1/traces ``` ```toml tab="File (TOML)" [tracing] - [tracing.openTelemetry.headers] - foo = "bar" - baz = "buz" + [tracing.otlp.http] + endpoint = "http://localhost:4318/v1/traces" ``` ```bash tab="CLI" ---tracing.openTelemetry.headers.foo=bar --tracing.openTelemetry.headers.baz=buz -``` - -#### `insecure` - -_Optional, Default=false_ - -Allows reporter to send spans to the OpenTelemetry Collector without using a secured protocol. - -```yaml tab="File (YAML)" -tracing: - openTelemetry: - insecure: true -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.openTelemetry] - insecure = true -``` - -```bash tab="CLI" ---tracing.openTelemetry.insecure=true -``` - -#### `path` - -_Required, Default="/v1/traces"_ - -Allows to override the default URL path used for sending traces. -This option has no effect when using gRPC transport. - -```yaml tab="File (YAML)" -tracing: - openTelemetry: - path: /foo/v1/traces -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.openTelemetry] - path = "/foo/v1/traces" -``` - -```bash tab="CLI" ---tracing.openTelemetry.path=/foo/v1/traces +--tracing.otlp.http.endpoint=http://localhost:4318/v1/traces ``` #### `tls` _Optional_ -Defines the TLS configuration used by the reporter to send spans to the OpenTelemetry Collector. +Defines the Client TLS configuration used by the reporter to send spans to the OpenTelemetry Collector. ##### `ca` @@ -135,18 +88,19 @@ it defaults to the system bundle. ```yaml tab="File (YAML)" tracing: - openTelemetry: - tls: - ca: path/to/ca.crt + otlp: + http: + tls: + ca: path/to/ca.crt ``` ```toml tab="File (TOML)" -[tracing.openTelemetry.tls] +[tracing.otlp.http.tls] ca = "path/to/ca.crt" ``` ```bash tab="CLI" ---tracing.openTelemetry.tls.ca=path/to/ca.crt +--tracing.otlp.http.tls.ca=path/to/ca.crt ``` ##### `cert` @@ -158,21 +112,22 @@ When using this option, setting the `key` option is required. ```yaml tab="File (YAML)" tracing: - openTelemetry: - tls: - cert: path/to/foo.cert - key: path/to/foo.key + otlp: + http: + tls: + cert: path/to/foo.cert + key: path/to/foo.key ``` ```toml tab="File (TOML)" -[tracing.openTelemetry.tls] +[tracing.otlp.http.tls] cert = "path/to/foo.cert" key = "path/to/foo.key" ``` ```bash tab="CLI" ---tracing.openTelemetry.tls.cert=path/to/foo.cert ---tracing.openTelemetry.tls.key=path/to/foo.key +--tracing.otlp.http.tls.cert=path/to/foo.cert +--tracing.otlp.http.tls.key=path/to/foo.key ``` ##### `key` @@ -184,21 +139,22 @@ When using this option, setting the `cert` option is required. ```yaml tab="File (YAML)" tracing: - openTelemetry: - tls: - cert: path/to/foo.cert - key: path/to/foo.key + otlp: + http: + tls: + cert: path/to/foo.cert + key: path/to/foo.key ``` ```toml tab="File (TOML)" -[tracing.openTelemetry.tls] +[tracing.otlp.http.tls] cert = "path/to/foo.cert" key = "path/to/foo.key" ``` ```bash tab="CLI" ---tracing.openTelemetry.tls.cert=path/to/foo.cert ---tracing.openTelemetry.tls.key=path/to/foo.key +--tracing.otlp.http.tls.cert=path/to/foo.cert +--tracing.otlp.http.tls.key=path/to/foo.key ``` ##### `insecureSkipVerify` @@ -210,18 +166,19 @@ the TLS connection to the OpenTelemetry Collector accepts any certificate presen ```yaml tab="File (YAML)" tracing: - openTelemetry: - tls: - insecureSkipVerify: true + otlp: + http: + tls: + insecureSkipVerify: true ``` ```toml tab="File (TOML)" -[tracing.openTelemetry.tls] +[tracing.otlp.http.tls] insecureSkipVerify = true ``` ```bash tab="CLI" ---tracing.openTelemetry.tls.insecureSkipVerify=true +--tracing.otlp.http.tls.insecureSkipVerify=true ``` #### gRPC configuration @@ -232,15 +189,168 @@ This instructs the reporter to send spans to the OpenTelemetry Collector using g ```yaml tab="File (YAML)" tracing: - openTelemetry: + otlp: grpc: {} ``` ```toml tab="File (TOML)" [tracing] - [tracing.openTelemetry.grpc] + [tracing.otlp.grpc] ``` ```bash tab="CLI" ---tracing.openTelemetry.grpc=true +--tracing.otlp.grpc=true +``` + +#### `endpoint` + +_Required, Default="localhost:4317", Format="`:`"_ + +Address of the OpenTelemetry Collector to send spans to. + +```yaml tab="File (YAML)" +tracing: + otlp: + grpc: + endpoint: localhost:4317 +``` + +```toml tab="File (TOML)" +[tracing] + [tracing.otlp.grpc] + endpoint = "localhost:4317" +``` + +```bash tab="CLI" +--tracing.otlp.grpc.endpoint=localhost:4317 +``` +#### `insecure` + +_Optional, Default=false_ + +Allows reporter to send spans to the OpenTelemetry Collector without using a secured protocol. + +```yaml tab="File (YAML)" +tracing: + otlp: + grpc: + insecure: true +``` + +```toml tab="File (TOML)" +[tracing] + [tracing.otlp.grpc] + insecure = true +``` + +```bash tab="CLI" +--tracing.otlp.grpc.insecure=true +``` + +#### `tls` + +_Optional_ + +Defines the Client TLS configuration used by the reporter to send spans to the OpenTelemetry Collector. + +##### `ca` + +_Optional_ + +`ca` is the path to the certificate authority used for the secure connection to the OpenTelemetry Collector, +it defaults to the system bundle. + +```yaml tab="File (YAML)" +tracing: + otlp: + grpc: + tls: + ca: path/to/ca.crt +``` + +```toml tab="File (TOML)" +[tracing.otlp.grpc.tls] + ca = "path/to/ca.crt" +``` + +```bash tab="CLI" +--tracing.otlp.grpc.tls.ca=path/to/ca.crt +``` + +##### `cert` + +_Optional_ + +`cert` is the path to the public certificate used for the secure connection to the OpenTelemetry Collector. +When using this option, setting the `key` option is required. + +```yaml tab="File (YAML)" +tracing: + otlp: + grpc: + tls: + cert: path/to/foo.cert + key: path/to/foo.key +``` + +```toml tab="File (TOML)" +[tracing.otlp.grpc.tls] + cert = "path/to/foo.cert" + key = "path/to/foo.key" +``` + +```bash tab="CLI" +--tracing.otlp.grpc.tls.cert=path/to/foo.cert +--tracing.otlp.grpc.tls.key=path/to/foo.key +``` + +##### `key` + +_Optional_ + +`key` is the path to the private key used for the secure connection to the OpenTelemetry Collector. +When using this option, setting the `cert` option is required. + +```yaml tab="File (YAML)" +tracing: + otlp: + grpc: + tls: + cert: path/to/foo.cert + key: path/to/foo.key +``` + +```toml tab="File (TOML)" +[tracing.otlp.grpc.tls] + cert = "path/to/foo.cert" + key = "path/to/foo.key" +``` + +```bash tab="CLI" +--tracing.otlp.grpc.tls.cert=path/to/foo.cert +--tracing.otlp.grpc.tls.key=path/to/foo.key +``` + +##### `insecureSkipVerify` + +_Optional, Default=false_ + +If `insecureSkipVerify` is `true`, +the TLS connection to the OpenTelemetry Collector accepts any certificate presented by the server regardless of the hostnames it covers. + +```yaml tab="File (YAML)" +tracing: + otlp: + grpc: + tls: + insecureSkipVerify: true +``` + +```toml tab="File (TOML)" +[tracing.otlp.grpc.tls] + insecureSkipVerify = true +``` + +```bash tab="CLI" +--tracing.otlp.grpc.tls.insecureSkipVerify=true ``` diff --git a/docs/content/observability/tracing/overview.md b/docs/content/observability/tracing/overview.md index f4126274a..18b8c4f3e 100644 --- a/docs/content/observability/tracing/overview.md +++ b/docs/content/observability/tracing/overview.md @@ -10,21 +10,13 @@ Visualize the Requests Flow The tracing system allows developers to visualize call flows in their infrastructure. -Traefik uses OpenTracing, an open standard designed for distributed tracing. +Traefik uses [OpenTelemetry](https://opentelemetry.io/ "Link to website of OTel"), an open standard designed for distributed tracing. -Traefik supports seven tracing backends: +Please check our dedicated [OTel docs](./opentelemetry.md) to learn more. -- [Jaeger](./jaeger.md) -- [Zipkin](./zipkin.md) -- [Datadog](./datadog.md) -- [Instana](./instana.md) -- [Haystack](./haystack.md) -- [Elastic](./elastic.md) -- [OpenTelemetry](./opentelemetry.md) ## Configuration -By default, Traefik uses Jaeger as tracing backend. To enable the tracing: @@ -62,25 +54,71 @@ tracing: --tracing.serviceName=traefik ``` -#### `spanNameLimit` +#### `sampleRate` -_Required, Default=0_ +_Optional, Default=1.0_ -Span name limit allows for name truncation in case of very long names. -This can prevent certain tracing providers to drop traces that exceed their length limits. - -`0` means no truncation will occur. +The proportion of requests to trace, specified between 0.0 and 1.0. ```yaml tab="File (YAML)" tracing: - spanNameLimit: 150 + sampleRate: 0.2 ``` ```toml tab="File (TOML)" [tracing] - spanNameLimit = 150 + sampleRate = 0.2 ``` ```bash tab="CLI" ---tracing.spanNameLimit=150 +--tracing.sampleRate=0.2 +``` + +#### `headers` + +_Optional, Default={}_ + +Defines additional headers to be sent with the span's payload. + +```yaml tab="File (YAML)" +tracing: + headers: + foo: bar + baz: buz +``` + +```toml tab="File (TOML)" +[tracing] + [tracing.headers] + foo = "bar" + baz = "buz" +``` + +```bash tab="CLI" +--tracing.headers.foo=bar --tracing.headers.baz=buz +``` + +#### `globalAttributes` + +_Optional, Default=empty_ + +Applies a list of shared key:value attributes on all spans. + +```yaml tab="File (YAML)" +tracing: + globalAttributes: + attr1: foo + attr2: bar +``` + +```toml tab="File (TOML)" +[tracing] + [tracing.globalAttributes] + attr1 = "foo" + attr2 = "bar" +``` + +```bash tab="CLI" +--tracing.globalAttributes.attr1=foo +--tracing.globalAttributes.attr2=bar ``` diff --git a/docs/content/observability/tracing/zipkin.md b/docs/content/observability/tracing/zipkin.md deleted file mode 100644 index 146dae6e1..000000000 --- a/docs/content/observability/tracing/zipkin.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: "Traefik Zipkin Documentation" -description: "Traefik supports several tracing backends, including Zipkin. Learn how to implement it for observability in Traefik Proxy. Read the technical documentation." ---- - -# Zipkin - -To enable the Zipkin tracer: - -```yaml tab="File (YAML)" -tracing: - zipkin: {} -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.zipkin] -``` - -```bash tab="CLI" ---tracing.zipkin=true -``` - -#### `httpEndpoint` - -_Required, Default="http://localhost:9411/api/v2/spans"_ - -HTTP endpoint used to send data. - -```yaml tab="File (YAML)" -tracing: - zipkin: - httpEndpoint: http://localhost:9411/api/v2/spans -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.zipkin] - httpEndpoint = "http://localhost:9411/api/v2/spans" -``` - -```bash tab="CLI" ---tracing.zipkin.httpEndpoint=http://localhost:9411/api/v2/spans -``` - -#### `sameSpan` - -_Optional, Default=false_ - -Uses SameSpan RPC style traces. - -```yaml tab="File (YAML)" -tracing: - zipkin: - sameSpan: true -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.zipkin] - sameSpan = true -``` - -```bash tab="CLI" ---tracing.zipkin.sameSpan=true -``` - -#### `id128Bit` - -_Optional, Default=true_ - -Uses 128 bits trace IDs. - -```yaml tab="File (YAML)" -tracing: - zipkin: - id128Bit: false -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.zipkin] - id128Bit = false -``` - -```bash tab="CLI" ---tracing.zipkin.id128Bit=false -``` - -#### `sampleRate` - -_Required, Default=1.0_ - -The proportion of requests to trace, specified between 0.0 and 1.0. - -```yaml tab="File (YAML)" -tracing: - zipkin: - sampleRate: 0.2 -``` - -```toml tab="File (TOML)" -[tracing] - [tracing.zipkin] - sampleRate = 0.2 -``` - -```bash tab="CLI" ---tracing.zipkin.sampleRate=0.2 -``` diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index 8e64fd2ae..efb874437 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -987,170 +987,50 @@ Defines the allowed SPIFFE trust domain. `--tracing`: OpenTracing configuration. (Default: ```false```) -`--tracing.datadog`: -Settings for Datadog. (Default: ```false```) +`--tracing.globalattributes.`: +Defines additional attributes (key:value) on all spans. -`--tracing.datadog.bagageprefixheadername`: -Sets the header name prefix used to store baggage items in a map. - -`--tracing.datadog.debug`: -Enables Datadog debug. (Default: ```false```) - -`--tracing.datadog.globaltags.`: -Sets a list of key:value tags on all spans. - -`--tracing.datadog.localagenthostport`: -Sets the Datadog Agent host:port. (Default: ```localhost:8126```) - -`--tracing.datadog.localagentsocket`: -Sets the socket for the Datadog Agent. - -`--tracing.datadog.parentidheadername`: -Sets the header name used to store the parent ID. - -`--tracing.datadog.prioritysampling`: -Enables priority sampling. When using distributed tracing, this option must be enabled in order to get all the parts of a distributed trace sampled. (Default: ```false```) - -`--tracing.datadog.samplingpriorityheadername`: -Sets the header name used to store the sampling priority. - -`--tracing.datadog.traceidheadername`: -Sets the header name used to store the trace ID. - -`--tracing.elastic`: -Settings for Elastic. (Default: ```false```) - -`--tracing.elastic.secrettoken`: -Sets the token used to connect to Elastic APM Server. - -`--tracing.elastic.serverurl`: -Sets the URL of the Elastic APM server. - -`--tracing.elastic.serviceenvironment`: -Sets the name of the environment Traefik is deployed in, e.g. 'production' or 'staging'. - -`--tracing.haystack`: -Settings for Haystack. (Default: ```false```) - -`--tracing.haystack.baggageprefixheadername`: -Sets the header name prefix used to store baggage items in a map. - -`--tracing.haystack.globaltag`: -Sets a key:value tag on all spans. - -`--tracing.haystack.localagenthost`: -Sets the Haystack Agent host. (Default: ```127.0.0.1```) - -`--tracing.haystack.localagentport`: -Sets the Haystack Agent port. (Default: ```35000```) - -`--tracing.haystack.parentidheadername`: -Sets the header name used to store the parent ID. - -`--tracing.haystack.spanidheadername`: -Sets the header name used to store the span ID. - -`--tracing.haystack.traceidheadername`: -Sets the header name used to store the trace ID. - -`--tracing.instana`: -Settings for Instana. (Default: ```false```) - -`--tracing.instana.enableautoprofile`: -Enables automatic profiling for the Traefik process. (Default: ```false```) - -`--tracing.instana.localagenthost`: -Sets the Instana Agent host. - -`--tracing.instana.localagentport`: -Sets the Instana Agent port. (Default: ```42699```) - -`--tracing.instana.loglevel`: -Sets the log level for the Instana tracer. ('error','warn','info','debug') (Default: ```info```) - -`--tracing.jaeger`: -Settings for Jaeger. (Default: ```false```) - -`--tracing.jaeger.collector.endpoint`: -Instructs reporter to send spans to jaeger-collector at this URL. - -`--tracing.jaeger.collector.password`: -Password for basic http authentication when sending spans to jaeger-collector. - -`--tracing.jaeger.collector.user`: -User for basic http authentication when sending spans to jaeger-collector. - -`--tracing.jaeger.disableattemptreconnecting`: -Disables the periodic re-resolution of the agent's hostname and reconnection if there was a change. (Default: ```true```) - -`--tracing.jaeger.gen128bit`: -Generates 128 bits span IDs. (Default: ```false```) - -`--tracing.jaeger.localagenthostport`: -Sets the Jaeger Agent host:port. (Default: ```127.0.0.1:6831```) - -`--tracing.jaeger.propagation`: -Sets the propagation format (jaeger/b3). (Default: ```jaeger```) - -`--tracing.jaeger.samplingparam`: -Sets the sampling parameter. (Default: ```1.000000```) - -`--tracing.jaeger.samplingserverurl`: -Sets the sampling server URL. (Default: ```http://localhost:5778/sampling```) - -`--tracing.jaeger.samplingtype`: -Sets the sampling type. (Default: ```const```) - -`--tracing.jaeger.tracecontextheadername`: -Sets the header name used to store the trace ID. (Default: ```uber-trace-id```) - -`--tracing.opentelemetry`: -Settings for OpenTelemetry. (Default: ```false```) - -`--tracing.opentelemetry.address`: -Sets the address (host:port) of the collector endpoint. (Default: ```localhost:4318```) - -`--tracing.opentelemetry.grpc`: -gRPC specific configuration for the OpenTelemetry collector. (Default: ```true```) - -`--tracing.opentelemetry.headers.`: +`--tracing.headers.`: Defines additional headers to be sent with the payloads. -`--tracing.opentelemetry.insecure`: +`--tracing.otlp`: +Settings for OpenTelemetry. (Default: ```false```) + +`--tracing.otlp.grpc.endpoint`: +Sets the gRPC endpoint (host:port) of the collector. (Default: ```localhost:4317```) + +`--tracing.otlp.grpc.insecure`: Disables client transport security for the exporter. (Default: ```false```) -`--tracing.opentelemetry.path`: -Sets the URL path of the collector endpoint. - -`--tracing.opentelemetry.tls.ca`: +`--tracing.otlp.grpc.tls.ca`: TLS CA -`--tracing.opentelemetry.tls.cert`: +`--tracing.otlp.grpc.tls.cert`: TLS cert -`--tracing.opentelemetry.tls.insecureskipverify`: +`--tracing.otlp.grpc.tls.insecureskipverify`: TLS insecure skip verify (Default: ```false```) -`--tracing.opentelemetry.tls.key`: +`--tracing.otlp.grpc.tls.key`: TLS key +`--tracing.otlp.http.endpoint`: +Sets the HTTP endpoint (scheme://host:port/v1/traces) of the collector. (Default: ```localhost:4318```) + +`--tracing.otlp.http.tls.ca`: +TLS CA + +`--tracing.otlp.http.tls.cert`: +TLS cert + +`--tracing.otlp.http.tls.insecureskipverify`: +TLS insecure skip verify (Default: ```false```) + +`--tracing.otlp.http.tls.key`: +TLS key + +`--tracing.samplerate`: +Sets the rate between 0.0 and 1.0 of requests to trace. (Default: ```1.000000```) + `--tracing.servicename`: Set the name for this service. (Default: ```traefik```) - -`--tracing.spannamelimit`: -Set the maximum character limit for Span names (default 0 = no limit). (Default: ```0```) - -`--tracing.zipkin`: -Settings for Zipkin. (Default: ```false```) - -`--tracing.zipkin.httpendpoint`: -Sets the HTTP Endpoint to report traces to. (Default: ```http://localhost:9411/api/v2/spans```) - -`--tracing.zipkin.id128bit`: -Uses 128 bits root span IDs. (Default: ```true```) - -`--tracing.zipkin.samespan`: -Uses SameSpan RPC style traces. (Default: ```false```) - -`--tracing.zipkin.samplerate`: -Sets the rate between 0.0 and 1.0 of requests to trace. (Default: ```1.000000```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 36dd4040c..10659e2e1 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -987,170 +987,50 @@ Defines the allowed SPIFFE trust domain. `TRAEFIK_TRACING`: OpenTracing configuration. (Default: ```false```) -`TRAEFIK_TRACING_DATADOG`: -Settings for Datadog. (Default: ```false```) +`TRAEFIK_TRACING_GLOBALATTRIBUTES_`: +Defines additional attributes (key:value) on all spans. -`TRAEFIK_TRACING_DATADOG_BAGAGEPREFIXHEADERNAME`: -Sets the header name prefix used to store baggage items in a map. - -`TRAEFIK_TRACING_DATADOG_DEBUG`: -Enables Datadog debug. (Default: ```false```) - -`TRAEFIK_TRACING_DATADOG_GLOBALTAGS_`: -Sets a list of key:value tags on all spans. - -`TRAEFIK_TRACING_DATADOG_LOCALAGENTHOSTPORT`: -Sets the Datadog Agent host:port. (Default: ```localhost:8126```) - -`TRAEFIK_TRACING_DATADOG_LOCALAGENTSOCKET`: -Sets the socket for the Datadog Agent. - -`TRAEFIK_TRACING_DATADOG_PARENTIDHEADERNAME`: -Sets the header name used to store the parent ID. - -`TRAEFIK_TRACING_DATADOG_PRIORITYSAMPLING`: -Enables priority sampling. When using distributed tracing, this option must be enabled in order to get all the parts of a distributed trace sampled. (Default: ```false```) - -`TRAEFIK_TRACING_DATADOG_SAMPLINGPRIORITYHEADERNAME`: -Sets the header name used to store the sampling priority. - -`TRAEFIK_TRACING_DATADOG_TRACEIDHEADERNAME`: -Sets the header name used to store the trace ID. - -`TRAEFIK_TRACING_ELASTIC`: -Settings for Elastic. (Default: ```false```) - -`TRAEFIK_TRACING_ELASTIC_SECRETTOKEN`: -Sets the token used to connect to Elastic APM Server. - -`TRAEFIK_TRACING_ELASTIC_SERVERURL`: -Sets the URL of the Elastic APM server. - -`TRAEFIK_TRACING_ELASTIC_SERVICEENVIRONMENT`: -Sets the name of the environment Traefik is deployed in, e.g. 'production' or 'staging'. - -`TRAEFIK_TRACING_HAYSTACK`: -Settings for Haystack. (Default: ```false```) - -`TRAEFIK_TRACING_HAYSTACK_BAGGAGEPREFIXHEADERNAME`: -Sets the header name prefix used to store baggage items in a map. - -`TRAEFIK_TRACING_HAYSTACK_GLOBALTAG`: -Sets a key:value tag on all spans. - -`TRAEFIK_TRACING_HAYSTACK_LOCALAGENTHOST`: -Sets the Haystack Agent host. (Default: ```127.0.0.1```) - -`TRAEFIK_TRACING_HAYSTACK_LOCALAGENTPORT`: -Sets the Haystack Agent port. (Default: ```35000```) - -`TRAEFIK_TRACING_HAYSTACK_PARENTIDHEADERNAME`: -Sets the header name used to store the parent ID. - -`TRAEFIK_TRACING_HAYSTACK_SPANIDHEADERNAME`: -Sets the header name used to store the span ID. - -`TRAEFIK_TRACING_HAYSTACK_TRACEIDHEADERNAME`: -Sets the header name used to store the trace ID. - -`TRAEFIK_TRACING_INSTANA`: -Settings for Instana. (Default: ```false```) - -`TRAEFIK_TRACING_INSTANA_ENABLEAUTOPROFILE`: -Enables automatic profiling for the Traefik process. (Default: ```false```) - -`TRAEFIK_TRACING_INSTANA_LOCALAGENTHOST`: -Sets the Instana Agent host. - -`TRAEFIK_TRACING_INSTANA_LOCALAGENTPORT`: -Sets the Instana Agent port. (Default: ```42699```) - -`TRAEFIK_TRACING_INSTANA_LOGLEVEL`: -Sets the log level for the Instana tracer. ('error','warn','info','debug') (Default: ```info```) - -`TRAEFIK_TRACING_JAEGER`: -Settings for Jaeger. (Default: ```false```) - -`TRAEFIK_TRACING_JAEGER_COLLECTOR_ENDPOINT`: -Instructs reporter to send spans to jaeger-collector at this URL. - -`TRAEFIK_TRACING_JAEGER_COLLECTOR_PASSWORD`: -Password for basic http authentication when sending spans to jaeger-collector. - -`TRAEFIK_TRACING_JAEGER_COLLECTOR_USER`: -User for basic http authentication when sending spans to jaeger-collector. - -`TRAEFIK_TRACING_JAEGER_DISABLEATTEMPTRECONNECTING`: -Disables the periodic re-resolution of the agent's hostname and reconnection if there was a change. (Default: ```true```) - -`TRAEFIK_TRACING_JAEGER_GEN128BIT`: -Generates 128 bits span IDs. (Default: ```false```) - -`TRAEFIK_TRACING_JAEGER_LOCALAGENTHOSTPORT`: -Sets the Jaeger Agent host:port. (Default: ```127.0.0.1:6831```) - -`TRAEFIK_TRACING_JAEGER_PROPAGATION`: -Sets the propagation format (jaeger/b3). (Default: ```jaeger```) - -`TRAEFIK_TRACING_JAEGER_SAMPLINGPARAM`: -Sets the sampling parameter. (Default: ```1.000000```) - -`TRAEFIK_TRACING_JAEGER_SAMPLINGSERVERURL`: -Sets the sampling server URL. (Default: ```http://localhost:5778/sampling```) - -`TRAEFIK_TRACING_JAEGER_SAMPLINGTYPE`: -Sets the sampling type. (Default: ```const```) - -`TRAEFIK_TRACING_JAEGER_TRACECONTEXTHEADERNAME`: -Sets the header name used to store the trace ID. (Default: ```uber-trace-id```) - -`TRAEFIK_TRACING_OPENTELEMETRY`: -Settings for OpenTelemetry. (Default: ```false```) - -`TRAEFIK_TRACING_OPENTELEMETRY_ADDRESS`: -Sets the address (host:port) of the collector endpoint. (Default: ```localhost:4318```) - -`TRAEFIK_TRACING_OPENTELEMETRY_GRPC`: -gRPC specific configuration for the OpenTelemetry collector. (Default: ```true```) - -`TRAEFIK_TRACING_OPENTELEMETRY_HEADERS_`: +`TRAEFIK_TRACING_HEADERS_`: Defines additional headers to be sent with the payloads. -`TRAEFIK_TRACING_OPENTELEMETRY_INSECURE`: +`TRAEFIK_TRACING_OTLP`: +Settings for OpenTelemetry. (Default: ```false```) + +`TRAEFIK_TRACING_OTLP_GRPC_ENDPOINT`: +Sets the gRPC endpoint (host:port) of the collector. (Default: ```localhost:4317```) + +`TRAEFIK_TRACING_OTLP_GRPC_INSECURE`: Disables client transport security for the exporter. (Default: ```false```) -`TRAEFIK_TRACING_OPENTELEMETRY_PATH`: -Sets the URL path of the collector endpoint. - -`TRAEFIK_TRACING_OPENTELEMETRY_TLS_CA`: +`TRAEFIK_TRACING_OTLP_GRPC_TLS_CA`: TLS CA -`TRAEFIK_TRACING_OPENTELEMETRY_TLS_CERT`: +`TRAEFIK_TRACING_OTLP_GRPC_TLS_CERT`: TLS cert -`TRAEFIK_TRACING_OPENTELEMETRY_TLS_INSECURESKIPVERIFY`: +`TRAEFIK_TRACING_OTLP_GRPC_TLS_INSECURESKIPVERIFY`: TLS insecure skip verify (Default: ```false```) -`TRAEFIK_TRACING_OPENTELEMETRY_TLS_KEY`: +`TRAEFIK_TRACING_OTLP_GRPC_TLS_KEY`: TLS key +`TRAEFIK_TRACING_OTLP_HTTP_ENDPOINT`: +Sets the HTTP endpoint (scheme://host:port/v1/traces) of the collector. (Default: ```localhost:4318```) + +`TRAEFIK_TRACING_OTLP_HTTP_TLS_CA`: +TLS CA + +`TRAEFIK_TRACING_OTLP_HTTP_TLS_CERT`: +TLS cert + +`TRAEFIK_TRACING_OTLP_HTTP_TLS_INSECURESKIPVERIFY`: +TLS insecure skip verify (Default: ```false```) + +`TRAEFIK_TRACING_OTLP_HTTP_TLS_KEY`: +TLS key + +`TRAEFIK_TRACING_SAMPLERATE`: +Sets the rate between 0.0 and 1.0 of requests to trace. (Default: ```1.000000```) + `TRAEFIK_TRACING_SERVICENAME`: Set the name for this service. (Default: ```traefik```) - -`TRAEFIK_TRACING_SPANNAMELIMIT`: -Set the maximum character limit for Span names (default 0 = no limit). (Default: ```0```) - -`TRAEFIK_TRACING_ZIPKIN`: -Settings for Zipkin. (Default: ```false```) - -`TRAEFIK_TRACING_ZIPKIN_HTTPENDPOINT`: -Sets the HTTP Endpoint to report traces to. (Default: ```http://localhost:9411/api/v2/spans```) - -`TRAEFIK_TRACING_ZIPKIN_ID128BIT`: -Uses 128 bits root span IDs. (Default: ```true```) - -`TRAEFIK_TRACING_ZIPKIN_SAMESPAN`: -Uses SameSpan RPC style traces. (Default: ```false```) - -`TRAEFIK_TRACING_ZIPKIN_SAMPLERATE`: -Sets the rate between 0.0 and 1.0 of requests to trace. (Default: ```1.000000```) diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index 6d75b4dbc..58acc5ac7 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -367,68 +367,28 @@ [tracing] serviceName = "foobar" - spanNameLimit = 42 - [tracing.jaeger] - samplingServerURL = "foobar" - samplingType = "foobar" - samplingParam = 42.0 - localAgentHostPort = "foobar" - gen128Bit = true - propagation = "foobar" - traceContextHeaderName = "foobar" - disableAttemptReconnecting = true - [tracing.jaeger.collector] - endpoint = "foobar" - user = "foobar" - password = "foobar" - [tracing.zipkin] - httpEndpoint = "foobar" - sameSpan = true - id128Bit = true - sampleRate = 42.0 - [tracing.datadog] - localAgentHostPort = "foobar" - localAgentSocket = "foobar" - [tracing.datadog.globalTags] - tag1 = "foobar" - tag2 = "foobar" - debug = true - prioritySampling = true - traceIDHeaderName = "foobar" - parentIDHeaderName = "foobar" - samplingPriorityHeaderName = "foobar" - bagagePrefixHeaderName = "foobar" - [tracing.instana] - localAgentHost = "foobar" - localAgentPort = 42 - logLevel = "foobar" - enableAutoProfile = true - [tracing.haystack] - localAgentHost = "foobar" - localAgentPort = 42 - globalTag = "foobar" - traceIDHeaderName = "foobar" - parentIDHeaderName = "foobar" - spanIDHeaderName = "foobar" - baggagePrefixHeaderName = "foobar" - [tracing.elastic] - serverURL = "foobar" - secretToken = "foobar" - serviceEnvironment = "foobar" - [tracing.openTelemetry] - address = "foobar" + sampleRate = 42 + [tracing.headers] + header1 = "foobar" + header2 = "foobar" + [tracing.globalAttributes] + attr1 = "foobar" + attr2 = "foobar" + [tracing.otlp.grpc] + endpoint = "foobar" insecure = true - path = "foobar" - [tracing.openTelemetry.headers] - name0 = "foobar" - name1 = "foobar" - [tracing.openTelemetry.tls] + [tracing.otlp.grpc.tls] ca = "foobar" - caOptional = true cert = "foobar" key = "foobar" insecureSkipVerify = true - [tracing.openTelemetry.grpc] + [tracing.otlp.http] + endpoint = "foobar" + [tracing.otlp.http.tls] + ca = "foobar" + cert = "foobar" + key = "foobar" + insecureSkipVerify = true [hostResolver] cnameFlattening = true diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index 4410e29eb..d822979c9 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -397,68 +397,29 @@ accessLog: bufferingSize: 42 tracing: serviceName: foobar - spanNameLimit: 42 - jaeger: - samplingServerURL: foobar - samplingType: foobar - samplingParam: 42 - localAgentHostPort: foobar - gen128Bit: true - propagation: foobar - traceContextHeaderName: foobar - disableAttemptReconnecting: true - collector: + sampleRate: 42 + headers: + header1: foobar + header2: foobar + globalAttributes: + attr1: foobar + attr2: foobar + otlp: + grpc: endpoint: foobar - user: foobar - password: foobar - zipkin: - httpEndpoint: foobar - sameSpan: true - id128Bit: true - sampleRate: 42 - datadog: - localAgentHostPort: foobar - localAgentSocket: foobar - globalTags: - tag1: foobar - tag2: foobar - debug: true - prioritySampling: true - traceIDHeaderName: foobar - parentIDHeaderName: foobar - samplingPriorityHeaderName: foobar - bagagePrefixHeaderName: foobar - instana: - localAgentHost: foobar - localAgentPort: 42 - logLevel: foobar - enableAutoProfile: true - haystack: - localAgentHost: foobar - localAgentPort: 42 - globalTag: foobar - traceIDHeaderName: foobar - parentIDHeaderName: foobar - spanIDHeaderName: foobar - baggagePrefixHeaderName: foobar - elastic: - serverURL: foobar - secretToken: foobar - serviceEnvironment: foobar - openTelemetry: - address: foobar - headers: - name0: foobar - name1: foobar - insecure: true - path: foobar - tls: - ca: foobar - caOptional: true - cert: foobar - key: foobar - insecureSkipVerify: true - grpc: {} + insecure: true + tls: + ca: foobar + cert: foobar + key: foobar + insecureSkipVerify: true + http: + endpoint: foobar + tls: + ca: foobar + cert: foobar + key: foobar + insecureSkipVerify: true hostResolver: cnameFlattening: true resolvConfig: foobar diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 01cd88a98..6ba875a3f 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -153,19 +153,9 @@ nav: - 'Access Logs': 'observability/access-logs.md' - 'Metrics': - 'Overview': 'observability/metrics/overview.md' - - 'Datadog': 'observability/metrics/datadog.md' - - 'InfluxDB2': 'observability/metrics/influxdb2.md' - 'OpenTelemetry': 'observability/metrics/opentelemetry.md' - - 'Prometheus': 'observability/metrics/prometheus.md' - - 'StatsD': 'observability/metrics/statsd.md' - 'Tracing': - 'Overview': 'observability/tracing/overview.md' - - 'Jaeger': 'observability/tracing/jaeger.md' - - 'Zipkin': 'observability/tracing/zipkin.md' - - 'Datadog': 'observability/tracing/datadog.md' - - 'Instana': 'observability/tracing/instana.md' - - 'Haystack': 'observability/tracing/haystack.md' - - 'Elastic': 'observability/tracing/elastic.md' - 'OpenTelemetry': 'observability/tracing/opentelemetry.md' - 'User Guides': - 'Kubernetes and Let''s Encrypt': 'user-guides/crd-acme/index.md' diff --git a/go.mod b/go.mod index f0a5faf49..25d529a2d 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.21 require ( github.com/BurntSushi/toml v1.3.2 - github.com/ExpediaDotCom/haystack-client-go v0.0.0-20190315171017-e7edbdf53a61 github.com/Masterminds/sprig/v3 v3.2.3 github.com/abbot/go-http-auth v0.0.0-00010101000000-000000000000 github.com/andybalholm/brotli v1.0.6 @@ -36,7 +35,6 @@ require ( github.com/http-wasm/http-wasm-host-go v0.5.2 github.com/influxdata/influxdb-client-go/v2 v2.7.0 github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d - github.com/instana/go-sensor v1.38.3 github.com/klauspost/compress v1.17.1 github.com/kvtools/consul v1.0.2 github.com/kvtools/etcdv3 v1.0.2 @@ -49,54 +47,46 @@ require ( github.com/mitchellh/hashstructure v1.0.0 github.com/mitchellh/mapstructure v1.5.0 github.com/natefinch/lumberjack v0.0.0-20201021141957-47ffae23317c - github.com/opentracing/opentracing-go v1.2.0 - github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5 - github.com/openzipkin/zipkin-go v0.2.2 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pires/go-proxyproto v0.6.1 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 github.com/quic-go/quic-go v0.40.1 - github.com/rs/zerolog v1.28.0 + github.com/rs/zerolog v1.29.0 github.com/sirupsen/logrus v1.9.3 github.com/spiffe/go-spiffe/v2 v2.1.1 github.com/stretchr/testify v1.8.4 github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154 github.com/tailscale/tscert v0.0.0-20220316030059-54bbcb9f74e2 github.com/tetratelabs/wazero v1.5.0 + github.com/tidwall/gjson v1.17.0 github.com/traefik/grpc-web v0.16.0 github.com/traefik/paerser v0.2.0 github.com/traefik/yaegi v0.15.1 - github.com/uber/jaeger-client-go v2.30.0+incompatible - github.com/uber/jaeger-lib v2.2.0+incompatible github.com/unrolled/render v1.0.2 github.com/unrolled/secure v1.0.9 github.com/vdemeester/shakers v0.1.0 github.com/vulcand/oxy/v2 v2.0.0-20230427132221-be5cf38f3c1c github.com/vulcand/predicate v1.2.0 - go.elastic.co/apm v1.13.1 - go.elastic.co/apm/module/apmot v1.13.1 go.opentelemetry.io/collector/pdata v0.66.0 - go.opentelemetry.io/otel v1.19.0 - go.opentelemetry.io/otel/bridge/opentracing v1.19.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 - go.opentelemetry.io/otel/metric v1.19.0 - go.opentelemetry.io/otel/sdk v1.19.0 - go.opentelemetry.io/otel/sdk/metric v1.19.0 - go.opentelemetry.io/otel/trace v1.19.0 + go.opentelemetry.io/otel v1.21.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 + go.opentelemetry.io/otel/metric v1.21.0 + go.opentelemetry.io/otel/sdk v1.21.0 + go.opentelemetry.io/otel/sdk/metric v1.21.0 + go.opentelemetry.io/otel/trace v1.21.0 golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 golang.org/x/mod v0.12.0 golang.org/x/net v0.17.0 golang.org/x/text v0.13.0 golang.org/x/time v0.3.0 golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 - google.golang.org/grpc v1.58.3 - gopkg.in/DataDog/dd-trace-go.v1 v1.56.1 + google.golang.org/grpc v1.59.0 gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.26.3 k8s.io/apiextensions-apiserver v0.26.3 @@ -129,13 +119,6 @@ require ( github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect - github.com/DataDog/appsec-internal-go v1.0.0 // indirect - github.com/DataDog/datadog-agent/pkg/obfuscate v0.48.0 // indirect - github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.48.0-devel.0.20230725154044-2549ba9058df // indirect - github.com/DataDog/datadog-go/v5 v5.3.0 // indirect - github.com/DataDog/go-libddwaf v1.5.0 // indirect - github.com/DataDog/go-tuf v1.0.2-0.5.2 // indirect - github.com/DataDog/sketches-go v1.4.2 // indirect github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.2.0 // indirect @@ -148,7 +131,6 @@ require ( github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 // indirect github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect github.com/armon/go-metrics v0.4.1 // indirect - github.com/armon/go-radix v1.0.0 // indirect github.com/aws/aws-sdk-go-v2 v1.20.3 // indirect github.com/aws/aws-sdk-go-v2/config v1.18.28 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.13.27 // indirect @@ -190,26 +172,23 @@ require ( github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.4.0 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect - github.com/ebitengine/purego v0.5.0-alpha.1 // indirect - github.com/elastic/go-licenser v0.3.1 // indirect - github.com/elastic/go-sysinfo v1.1.1 // indirect - github.com/elastic/go-windows v1.0.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/exoscale/egoscale v0.100.1 // indirect github.com/fatih/color v1.15.0 // indirect github.com/fvbommel/sortorder v1.0.1 // indirect github.com/ghodss/yaml v1.0.0 // indirect + github.com/gin-gonic/gin v1.7.7 // indirect github.com/go-errors/errors v1.0.1 // indirect github.com/go-jose/go-jose/v3 v3.0.0 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect 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-resty/resty/v2 v2.7.0 // indirect + github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/go-zookeeper/zk v1.0.3 // indirect github.com/gofrs/flock v0.8.0 // indirect @@ -219,7 +198,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect @@ -248,9 +227,7 @@ require ( github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect github.com/jaguilar/vt100 v0.0.0-20150826170717-2703a27b14ea // indirect - github.com/jcchavezs/porto v0.1.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -264,7 +241,6 @@ require ( github.com/liquidweb/go-lwApi v0.0.5 // indirect github.com/liquidweb/liquidweb-cli v0.6.9 // indirect github.com/liquidweb/liquidweb-go v1.6.3 // indirect - github.com/looplab/fsm v0.1.0 // indirect github.com/magiconair/properties v1.8.6 // indirect github.com/mailgun/minheap v0.0.0-20170619185613-3dbe6c6bf55f // indirect github.com/mailgun/multibuf v0.1.2 // indirect @@ -300,15 +276,14 @@ require ( github.com/nrdcg/porkbun v0.2.0 // indirect github.com/nzdjb/go-metaname v1.0.0 // indirect github.com/onsi/ginkgo v1.16.5 // indirect - github.com/onsi/ginkgo/v2 v2.9.5 // indirect + github.com/onsi/ginkgo/v2 v2.11.0 // indirect + github.com/onsi/gomega v1.27.10 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.0.2 // indirect + github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect github.com/opencontainers/runc v1.1.5 // indirect - github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect - github.com/outcaste-io/ristretto v0.2.3 // indirect github.com/ovh/go-ovh v1.4.1 // indirect - github.com/philhofer/fwd v1.1.2 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pquerna/otp v1.4.0 // indirect @@ -323,22 +298,21 @@ require ( github.com/sacloud/iaas-api-go v1.11.1 // indirect github.com/sacloud/packages-go v0.0.9 // indirect github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b // indirect - github.com/santhosh-tekuri/jsonschema v1.2.4 // indirect github.com/scaleway/scaleway-sdk-go v1.0.0-beta.17 // indirect - github.com/secure-systems-lab/go-securesystemslib v0.7.0 // indirect github.com/shopspring/decimal v1.2.0 // indirect github.com/simplesurance/bunny-go v0.0.0-20221115111006-e11d9dc91f04 // indirect github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect github.com/softlayer/softlayer-go v1.1.2 // indirect github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect - github.com/spf13/cast v1.3.1 // indirect + github.com/spf13/cast v1.5.0 // indirect github.com/spf13/cobra v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.1 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 // indirect github.com/theupdateframework/notary v0.6.1 // indirect - github.com/tinylib/msgp v1.1.8 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect github.com/tonistiigi/fsutil v0.0.0-20201103201449-0834f99b7b85 // indirect github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect github.com/transip/gotransip/v6 v6.20.0 // indirect @@ -351,42 +325,34 @@ require ( github.com/yandex-cloud/go-genproto v0.0.0-20220805142335-27b56ddae16f // indirect github.com/yandex-cloud/go-sdk v0.0.0-20220805164847-cf028e604997 // indirect github.com/zeebo/errs v1.2.2 // indirect - go.elastic.co/apm/module/apmhttp v1.13.1 // indirect - go.elastic.co/fastjson v1.1.0 // indirect go.etcd.io/etcd/api/v3 v3.5.5 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.5 // indirect go.etcd.io/etcd/client/v3 v3.5.5 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/mock v0.3.0 // indirect go.uber.org/multierr v1.8.0 // indirect go.uber.org/ratelimit v0.2.0 // indirect go.uber.org/zap v1.21.0 // indirect - go4.org/intern v0.0.0-20230525184215-6c62f75575cb // indirect - go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 // indirect golang.org/x/crypto v0.14.0 // indirect - golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/oauth2 v0.10.0 // indirect + golang.org/x/oauth2 v0.11.0 // indirect golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.13.0 // indirect + golang.org/x/sys v0.14.0 // indirect golang.org/x/term v0.13.0 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/api v0.128.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect + google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/h2non/gock.v1 v1.0.16 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ns1/ns1-go.v2 v2.7.6 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect - inet.af/netaddr v0.0.0-20230525184311-b8eac61e914a // indirect - k8s.io/klog/v2 v2.80.1 // indirect + k8s.io/klog/v2 v2.90.1 // indirect k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect nhooyr.io/websocket v1.8.7 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect diff --git a/go.sum b/go.sum index 9780e2eb5..e51ba4439 100644 --- a/go.sum +++ b/go.sum @@ -118,25 +118,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/appsec-internal-go v1.0.0 h1:2u5IkF4DBj3KVeQn5Vg2vjPUtt513zxEYglcqnd500U= -github.com/DataDog/appsec-internal-go v1.0.0/go.mod h1:+Y+4klVWKPOnZx6XESG7QHydOaUGEXyH2j/vSg9JiNM= -github.com/DataDog/datadog-agent/pkg/obfuscate v0.48.0 h1:bUMSNsw1iofWiju9yc1f+kBd33E3hMJtq9GuU602Iy8= -github.com/DataDog/datadog-agent/pkg/obfuscate v0.48.0/go.mod h1:HzySONXnAgSmIQfL6gOv9hWprKJkx8CicuXuUbmgWfo= -github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.48.0-devel.0.20230725154044-2549ba9058df h1:PbzrhHhs2+RRdKKti7JBSM8ATIeiji2T2cVt/d8GT8k= -github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.48.0-devel.0.20230725154044-2549ba9058df/go.mod h1:5Q39ZOIOwZMnFyRadp+5gH1bFdjmb+Pgxe+j5XOwaTg= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/datadog-go/v5 v5.3.0 h1:2q2qjFOb3RwAZNU+ez27ZVDwErJv5/VpbBPprz7Z+s8= -github.com/DataDog/datadog-go/v5 v5.3.0/go.mod h1:XRDJk1pTc00gm+ZDiBKsjh7oOOtJfYfglVCmFb8C2+Q= -github.com/DataDog/go-libddwaf v1.5.0 h1:lrHP3VrEriy1M5uQuaOcKphf5GU40mBhihMAp6Ik55c= -github.com/DataDog/go-libddwaf v1.5.0/go.mod h1:Fpnmoc2k53h6desQrH1P0/gR52CUzkLNFugE5zWwUBQ= -github.com/DataDog/go-tuf v1.0.2-0.5.2 h1:EeZr937eKAWPxJ26IykAdWA4A0jQXJgkhUjqEI/w7+I= -github.com/DataDog/go-tuf v1.0.2-0.5.2/go.mod h1:zBcq6f654iVqmkk8n2Cx81E1JnNTMOAx1UEO/wZR+P0= -github.com/DataDog/gostackparse v0.7.0 h1:i7dLkXHvYzHV308hnkvVGDL3BR4FWl7IsXNPz/IGQh4= -github.com/DataDog/gostackparse v0.7.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM= -github.com/DataDog/sketches-go v1.4.2 h1:gppNudE9d19cQ98RYABOetxIhpTCl4m7CnbRZjvVA/o= -github.com/DataDog/sketches-go v1.4.2/go.mod h1:xJIXldczJyyjnbDop7ZZcLxJdV3+7Kra7H1KMgpgkLk= -github.com/ExpediaDotCom/haystack-client-go v0.0.0-20190315171017-e7edbdf53a61 h1:1NIUJ+MAMpqDr4LWIfNsoJR+G7zg/8GZVwuRkmJxtTc= -github.com/ExpediaDotCom/haystack-client-go v0.0.0-20190315171017-e7edbdf53a61/go.mod h1:62qWSDaEI0BLykU+zQza5CAKgW0lOy9oBSz3/DvYz4w= github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= @@ -157,7 +139,6 @@ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugX github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= @@ -188,8 +169,6 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/sarama v1.38.1 h1:lqqPUPQZ7zPqYlWpTh+LQ9bhYNu2xJL6k1SJN4WVe2A= -github.com/Shopify/sarama v1.38.1/go.mod h1:iwv9a67Ha8VNa+TifujYoWGxWnu2kNVAQdSdZ4X2o5g= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= @@ -227,7 +206,6 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= @@ -308,8 +286,6 @@ github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0Bsq github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/bugsnag/panicwrap v1.2.0 h1:OzrKrRvXis8qEvOkfcxNcYbOd2O7xXS2nnKMEMABFQA= github.com/bugsnag/panicwrap v1.2.0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/bytedance/sonic v1.10.0 h1:qtNZduETEIWJVIyDl01BeNxur2rW9OwTQ/yBqFRkKEk= -github.com/bytedance/sonic v1.10.0/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7FVlAwDAVw= github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= @@ -330,10 +306,6 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= -github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= -github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= -github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo= -github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= 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= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -370,7 +342,6 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/compose-spec/compose-go v1.0.2/go.mod h1:gCIA3No0j5nNszz2X0yd/mkigTIWcOgHiPa9guWvoec= github.com/compose-spec/compose-go v1.0.3 h1:yvut1x9H4TUMptNA4mZ63VGVtDNX1OKy2TZCi6yFw8Q= @@ -546,8 +517,6 @@ github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -617,28 +586,12 @@ github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-resiliency v1.4.0 h1:3OK9bWpPk5q6pbFAaYSEwD9CLUSHG8bnZuqX2yMt3B0= -github.com/eapache/go-resiliency v1.4.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 h1:Oy0F4ALJ04o5Qqpdz8XLIpNA3WM/iSIXqxtqo7UGVws= -github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0= -github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/ebitengine/purego v0.5.0-alpha.1 h1:0gVgWGb8GjKYs7cufvfNSleJAD00m2xWC26FMwOjNrw= -github.com/ebitengine/purego v0.5.0-alpha.1/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= -github.com/elastic/go-licenser v0.3.1 h1:RmRukU/JUmts+rpexAw0Fvt2ly7VVu6mw8z4HrEzObU= -github.com/elastic/go-licenser v0.3.1/go.mod h1:D8eNQk70FOCVBl3smCGQt/lv7meBeQno2eI1S5apiHQ= -github.com/elastic/go-sysinfo v1.1.1 h1:ZVlaLDyhVkDfjwPGU55CQRCRolNpc7P0BbyhhQZQmMI= -github.com/elastic/go-sysinfo v1.1.1/go.mod h1:i1ZYdU10oLNfRzq4vq62BEwD2fH8KaWh6eh0ikPT9F0= -github.com/elastic/go-windows v1.0.0 h1:qLURgZFkkrYyTTkvYpsZIgf83AUsdIHfvlJaqaZ7aSY= -github.com/elastic/go-windows v1.0.0/go.mod h1:TsU0Nrp7/y3+VwE82FoZF8gC/XFg/Elz6CcloAxnPgU= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= @@ -682,6 +635,8 @@ github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoD github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= @@ -703,8 +658,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= -github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= -github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= +github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-acme/lego/v4 v4.14.0 h1:/skZoRHgVh0d2RK7l1g3Ch8HqeqP9LB8ZEjLdGEpcDE= github.com/go-acme/lego/v4 v4.14.0/go.mod h1:zjmvNCDLGz7GrC1OqdVpVmZFKSRabEDtWbdzmcpBsGo= @@ -734,8 +689,8 @@ github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTg github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= @@ -770,8 +725,8 @@ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91 github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= -github.com/go-playground/validator/v10 v10.15.1 h1:BSe8uhN+xQ4r5guV/ywQI4gO59C2raYcGffYWZEjZzM= -github.com/go-playground/validator/v10 v10.15.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= +github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= @@ -801,8 +756,6 @@ github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/E github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk= github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= github.com/goccy/go-json v0.7.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= @@ -814,9 +767,8 @@ github.com/gofrs/flock v0.7.3/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14j github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY= github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= -github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= github.com/gogo/googleapis v1.3.0/go.mod h1:d+q1s/xVJxZGKWwC/6UfPIF33J+G1Tq4GYv9Y+Tg/EU= @@ -839,8 +791,8 @@ github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOW github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -880,8 +832,6 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -907,8 +857,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.0.0-20191015185424-71da34e4d9b3/go.mod h1:ZXFeSndFcK4vB1NR4voH1Zm38K7ViUNiYtfIBDxrwf0= github.com/google/go-github/v28 v28.1.1 h1:kORf5ekX5qwXO2mGzXXOjMe/g6ap8ahVe0sBEulhSxo= github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM= @@ -1068,9 +1018,8 @@ github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= -github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= github.com/hashicorp/hcl/v2 v2.8.2/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= @@ -1114,32 +1063,15 @@ github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7 github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= github.com/infobloxopen/infoblox-go-client v1.1.1 h1:728A6LbLjptj/7kZjHyIxQnm768PWHfGFm0HH8FnbtU= github.com/infobloxopen/infoblox-go-client v1.1.1/go.mod h1:BXiw7S2b9qJoM8MS40vfgCNB2NLHGusk1DtO16BD9zI= -github.com/instana/go-sensor v1.38.3 h1:/PdHEDveLmUCvK+O6REvSv8kKljX8vaj9JMjMeCHAWk= -github.com/instana/go-sensor v1.38.3/go.mod h1:E42MelHWFz11qqaLwvgt0j98v2s2O/bq22UDkGaG0Gg= -github.com/instana/testify v1.6.2-0.20200721153833-94b1851f4d65 h1:T25FL3WEzgmKB0m6XCJNZ65nw09/QIp3T1yXr487D+A= -github.com/instana/testify v1.6.2-0.20200721153833-94b1851f4d65/go.mod h1:nYhEREG/B7HUY7P+LKOrqy53TpIqmJ9JyUShcaEKtGw= github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/jarcoal/httpmock v1.0.8/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= github.com/jarcoal/httpmock v1.3.0 h1:2RJ8GP0IIaWwcC9Fp2BmVi8Kog3v2Hn7VXM3fTd+nuc= github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg= -github.com/jcchavezs/porto v0.1.0 h1:Xmxxn25zQMmgE7/yHYmh19KcItG81hIwfbEEFnd6w/Q= -github.com/jcchavezs/porto v0.1.0/go.mod h1:fESH0gzDHiutHRdX2hv27ojnOVFco37hg1W6E9EZF4A= -github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= -github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= -github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= -github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= -github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg= -github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo= -github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8= -github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= -github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= -github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/gorm v1.9.2/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo= +github.com/jinzhu/gorm v1.9.11 h1:gaHGvE+UnWGlbWG4Y3FUwY1EcZ5n6S9WtqBA/uySMLE= github.com/jinzhu/gorm v1.9.11/go.mod h1:bu/pK8szGZ2puuErfU0RwyeNdsf3e6nCX/noXaVxkfw= -github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o= -github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs= github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= @@ -1155,8 +1087,6 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548/go.mod h1:hGT6jSUVzF6no3QaDSMLGLEHtHSBSefs+MgcDWnmhmo= github.com/jmoiron/sqlx v0.0.0-20180124204410-05cef0741ade/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU= -github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4= -github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= @@ -1198,8 +1128,6 @@ github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.17.1 h1:NE3C767s2ak2bweCZo3+rdP4U/HoyVXLv/X9f2gPS5g= github.com/klauspost/compress v1.17.1/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -1270,8 +1198,6 @@ github.com/liquidweb/liquidweb-cli v0.6.9/go.mod h1:cE1uvQ+x24NGUL75D0QagOFCG8Wd github.com/liquidweb/liquidweb-go v1.6.3 h1:NVHvcnX3eb3BltiIoA+gLYn15nOpkYkdizOEYGSKrk4= github.com/liquidweb/liquidweb-go v1.6.3/go.mod h1:SuXXp+thr28LnjEw18AYtWwIbWMHSUiajPQs8T9c/Rc= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= -github.com/looplab/fsm v0.1.0 h1:Qte7Zdn/5hBNbXzP7yxVU4OIFHWXBovyTT2LaBTyC20= -github.com/looplab/fsm v0.1.0/go.mod h1:m2VaOfDHxqXBBMgc26m6yUOwkFn8H2AlJDE+jd/uafI= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -1469,8 +1395,8 @@ 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.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= -github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -1484,8 +1410,8 @@ github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+t github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= -github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -1495,8 +1421,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8= +github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc10/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= @@ -1521,7 +1447,6 @@ github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3 github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opencontainers/selinux v1.10.0 h1:rAiKF8hTcgLI3w0DHm6i0ylVVcOrlgR1kK99DRLDhyU= github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 h1:lM6RxxfUMrYL/f8bWEUqdXrANWtrL7Nndbm9iFN0DlU= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= @@ -1529,16 +1454,12 @@ github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5 h1:ZCnq+JUrvXcDVhX/xRolRBZifmabN1HcS1wrPSvxhrU= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2 h1:nY8Hti+WKaP0cRsSeQ026wU03QsM762XBeCXBb9NAWI= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/oracle/oci-go-sdk v24.3.0+incompatible h1:x4mcfb4agelf1O4/1/auGlZ1lr97jXRSSN5MxTgG/zU= github.com/oracle/oci-go-sdk v24.3.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= -github.com/outcaste-io/ristretto v0.2.3 h1:AK4zt/fJ76kjlYObOeNwh4T3asEuaCmp26pOvUOL9w0= -github.com/outcaste-io/ristretto v0.2.3/go.mod h1:W8HywhmtlopSB1jeMg3JtdIhf+DYkLAr0VN/s4+MHac= github.com/ovh/go-ovh v1.4.1 h1:VBGa5wMyQtTP7Zb+w97zRCh9sLtM/2YKRyy+MEJmWaM= github.com/ovh/go-ovh v1.4.1/go.mod h1:6bL6pPyUT7tBfI0pqOegJgRjgjuO+mOo+MyXd1EEC0M= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= @@ -1552,17 +1473,10 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0= -github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= -github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= -github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pires/go-proxyproto v0.6.1 h1:EBupykFmo22SDjv4fQVQd2J9NOoLPmyZA/15ldOGkPw= github.com/pires/go-proxyproto v0.6.1/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY= github.com/pivotal/image-relocation v0.0.0-20191111101224-e94aff6df06c/go.mod h1:/JNbQwGylYm3AQh8q+MBF8e/h0W1Jy20JGTvozuXYTE= @@ -1626,7 +1540,6 @@ github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJ github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190425082905-87a4384529e0/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -1649,26 +1562,22 @@ github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58 github.com/quic-go/quic-go v0.40.1 h1:X3AGzUNFs0jVuO3esAGnTfvdgvL4fq655WaOi1snv1Q= github.com/quic-go/quic-go v0.40.1/go.mod h1:PeN7kuVJ4xZbxSv/4OX6S1USOX8MJvydwpTx31vx60c= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= -github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= -github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052 h1:Qp27Idfgi6ACvFQat5+VJvlYToylpM/hcyLBI3WaKPA= -github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052/go.mod h1:uvX/8buq8uVeiZiFht+0lqSLBHF+uGV8BrTv8W/SIwk= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= 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/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY= -github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= +github.com/rs/zerolog v1.29.0 h1:Zes4hju04hjbvkVkOhdl2HpZa+0PmVwigmo8XoORE5w= +github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -1685,8 +1594,6 @@ github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiB github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b h1:jUK33OXuZP/l6babJtnLo1qsGvq6G9so9KMflGAm4YA= github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b/go.mod h1:8458kAagoME2+LN5//WxE71ysZ3B7r22fdgb7qVmXSY= -github.com/santhosh-tekuri/jsonschema v1.2.4 h1:hNhW8e7t+H1vgY+1QeEQpveR6D4+OwKPXCfD2aieJis= -github.com/santhosh-tekuri/jsonschema v1.2.4/go.mod h1:TEAUOeZSmIxTTuHatJzrvARHiuO9LYd+cIxzgEHCQI4= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.17 h1:1WuWJu7/e8SqK+uQl7lfk/N/oMZTL2NE/TJsNKRNMc4= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.17/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= @@ -1694,8 +1601,6 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUt github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= -github.com/secure-systems-lab/go-securesystemslib v0.7.0 h1:OwvJ5jQf9LnIAS83waAjPbcMsODrTQUpJ02eNLUoxBg= -github.com/secure-systems-lab/go-securesystemslib v0.7.0/go.mod h1:/2gYnlnHVQ6xeGtfIqFy7Do03K4cdCY0A/GlJLDKLHI= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= @@ -1733,16 +1638,15 @@ github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e/go.mod h1:fKZCUVd github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= @@ -1817,8 +1721,12 @@ github.com/tetratelabs/wazero v1.5.0 h1:Yz3fZHivfDiZFUXnWMPUoiW7s8tC1sjdBtlJn08q github.com/tetratelabs/wazero v1.5.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A= github.com/theupdateframework/notary v0.6.1 h1:7wshjstgS9x9F5LuB1L5mBI2xNMObWqjz+cjWoom6l0= github.com/theupdateframework/notary v0.6.1/go.mod h1:MOfgIfmox8s7/7fduvB2xyPPMJCrjRLRizA8OFwpnKY= -github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= -github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= +github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= +github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tonistiigi/fsutil v0.0.0-20201103201449-0834f99b7b85 h1:014iQD8i8EabPWK2XgUuOTxg5s2nhfDmq6GupskfUO8= @@ -1836,12 +1744,7 @@ github.com/traefik/yaegi v0.15.1/go.mod h1:AVRxhaI2G+nUsaM1zyktzwXn69G3t/AuTDrCi github.com/transip/gotransip/v6 v6.20.0 h1:AuvwyOZ51f2brzMbTqlRy/wmaM3kF7Vx5Wds8xcDflY= github.com/transip/gotransip/v6 v6.20.0/go.mod h1:nzv9eN2tdsUrm5nG5ZX6AugYIU4qgsMwIn2c0EZLk8c= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= -github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= -github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw= github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= @@ -1849,9 +1752,8 @@ github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E= github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= -github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= -github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ultradns/ultradns-go-sdk v1.5.0-20230427130837-23c9b0c h1:mKnW6IGLw7uXu6DL6RitufZWcXS6hCnauXRUFof7rKM= github.com/ultradns/ultradns-go-sdk v1.5.0-20230427130837-23c9b0c/go.mod h1:F4UyVEmq4/m5lAmx+GccrxyRCXmnBjzUL09JLTQFp94= github.com/unrolled/render v1.0.2 h1:dGS3EmChQP3yOi1YeFNO/Dx+MbWZhdvhQJTXochM5bs= @@ -1927,14 +1829,6 @@ github.com/zmap/zcrypto v0.0.0-20190729165852-9051775e6a2e h1:mvOa4+/DXStR4ZXOks github.com/zmap/zcrypto v0.0.0-20190729165852-9051775e6a2e/go.mod h1:w7kd3qXHh8FNaczNjslXqvFQiv5mMWRXlL9klTUAHc8= github.com/zmap/zlint v0.0.0-20190806154020-fd021b4cfbeb h1:vxqkjztXSaPVDc8FQCdHTaejm2x747f6yPbnu1h2xkg= github.com/zmap/zlint v0.0.0-20190806154020-fd021b4cfbeb/go.mod h1:29UiAJNsiVdvTBFCJW8e3q6dcDbOoPkhMgttOSCIMMY= -go.elastic.co/apm v1.13.1 h1:ICIcUcQOImg/bve9mQVyLCvm1cSUZ1afdwK6ACnxczU= -go.elastic.co/apm v1.13.1/go.mod h1:dylGv2HKR0tiCV+wliJz1KHtDyuD8SPe69oV7VyK6WY= -go.elastic.co/apm/module/apmhttp v1.13.1 h1:g2id6+AY8NRSA6nzwPDSU1AmBiHyZeh/lJRBlXq2yfQ= -go.elastic.co/apm/module/apmhttp v1.13.1/go.mod h1:PmSy4HY0asQzoFpl+gna9n+ebfI43fPvo21sd22gquE= -go.elastic.co/apm/module/apmot v1.13.1 h1:4PCbjgVz0A/9a/wuiHu1en83TLgmBbK9fJwLgES8Rr8= -go.elastic.co/apm/module/apmot v1.13.1/go.mod h1:NnG6U6ahaixUHpjQioL0QvVtOxWjVn8Z09qJHSCsmqU= -go.elastic.co/fastjson v1.1.0 h1:3MrGBWWVIxe/xvsbpghtkFoPciPhOCmjsR/HfwEeQR4= -go.elastic.co/fastjson v1.1.0/go.mod h1:boNGISWMjQsUPy/t6yqt2/1Wx4YNPSe+mZjlyw9vKKI= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= @@ -1963,30 +1857,26 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/collector/pdata v0.66.0 h1:UdE5U6MsDNzuiWaXdjGx2lC3ElVqWmN/hiUE8vyvSuM= go.opentelemetry.io/collector/pdata v0.66.0/go.mod h1:pqyaznLzk21m+1KL6fwOsRryRELL+zNM0qiVSn0MbVc= -go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= -go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= -go.opentelemetry.io/otel/bridge/opentracing v1.19.0 h1:HCvsUi6uuhat/nAuxCl41A+OPxXXPxMNTRxKZx7hTW4= -go.opentelemetry.io/otel/bridge/opentracing v1.19.0/go.mod h1:n46h+7L/lcSuHhpqJQiUdb4eux19NNxTuWJ/ZMnIQMg= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 h1:NmnYCiR0qNufkldjVvyQfZTHSdzeHoZ41zggMsdMcLM= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0/go.mod h1:UVAO61+umUsHLtYb8KXXRoHtxUkdOPkYidzW3gipRLQ= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 h1:wNMDy/LVGLj2h3p6zg4d0gypKfWKSWI14E1C4smOgl8= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0/go.mod h1:YfbDdXAAkemWJK3H/DshvlrxqFB2rtW4rY6ky/3x/H0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= -go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= -go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= -go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= -go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= -go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k= -go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY= -go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= -go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= +go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= +go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 h1:jd0+5t/YynESZqsSyPz+7PAFdEop0dlN0+PkyHYo8oI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0/go.mod h1:U707O40ee1FpQGyhvqnzmCJm1Wh6OX6GGBVn0E6Uyyk= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0 h1:bflGWrfYyuulcdxf14V6n9+CoQcu5SAAdHmDPAJnlps= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0/go.mod h1:qcTO4xHAxZLaLxPd60TdE88rxtItPHgHWqOhOGRr0as= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 h1:digkEZCJWobwBqMwC0cwCq8/wkkRy/OowZg5OArWZrM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h1:/OpE/y70qVkndM0TrxT4KBoN3RsFZP0QaofcfYrj76I= +go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= +go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0= +go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q= +go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= +go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= @@ -1994,14 +1884,13 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -2018,14 +1907,6 @@ go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= -go4.org/intern v0.0.0-20211027215823-ae77deb06f29/go.mod h1:cS2ma+47FKrLPdXFpr7CuxiTW3eyJbWew4qx0qtQWDA= -go4.org/intern v0.0.0-20230525184215-6c62f75575cb h1:ae7kzL5Cfdmcecbh22ll7lYP3iuUdnfnhiPcSaDgH/8= -go4.org/intern v0.0.0-20230525184215-6c62f75575cb/go.mod h1:Ycrt6raEcnF5FTsLiLKkhBTO6DPX3RCUCUVnks3gFJU= -go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= -go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 h1:WJhcL4p+YeDxmZWg141nRm7XC8IDmhz7lk5GpadO1Sg= -go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= -golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc= -golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -2096,7 +1977,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= @@ -2111,7 +1991,6 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2143,6 +2022,7 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191021144547-ec77196f6094/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -2182,7 +2062,6 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -2200,8 +2079,8 @@ golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= -golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= +golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= +golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= 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= @@ -2214,7 +2093,6 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2258,7 +2136,6 @@ golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2338,24 +2215,21 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2370,7 +2244,6 @@ 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/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2434,7 +2307,6 @@ golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -2457,15 +2329,12 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= 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= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2 h1:CCXrcPKiGGotvnN6jfUsKk4rRqm7q09/YbKb5xCEvtM= @@ -2560,12 +2429,12 @@ google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g= -google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0= -google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw= -google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= +google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY= +google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q= +google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -2597,8 +2466,8 @@ google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= -google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/grpc/examples v0.0.0-20201130180447-c456688b1860/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -2616,8 +2485,6 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/DataDog/dd-trace-go.v1 v1.56.1 h1:AUe/ZF7xm6vYnigPe+TY54DmfWYJxhMRaw/TfvrbzvE= -gopkg.in/DataDog/dd-trace-go.v1 v1.56.1/go.mod h1:KDLJ3CWVOSuVVwu+0ZR5KZo2rP6c7YyBV3v387dIpUU= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -2638,8 +2505,10 @@ gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/gorethink/gorethink.v3 v3.0.5 h1:e2Uc/Xe+hpcVQFsj6MuHlYog3r0JYpnTzwDj/y2O4MU= gopkg.in/gorethink/gorethink.v3 v3.0.5/go.mod h1:+3yIIHJUGMBK+wyPH+iN5TP+88ikFDfZdqTlK3Y9q8I= -gopkg.in/h2non/gock.v1 v1.0.15 h1:SzLqcIlb/fDfg7UvukMpNcWsu7sI5tWwL+KCATZqks0= +gopkg.in/h2non/gentleman.v1 v1.0.4/go.mod h1:JYuHVdFzS4MKOXe0o+chKJ4hCe6tqKKw9XH9YP6WFrg= gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= +gopkg.in/h2non/gock.v1 v1.0.16 h1:F11k+OafeuFENsjei5t2vMTSTs9L62AdyTe4E1cgdG8= +gopkg.in/h2non/gock.v1 v1.0.16/go.mod h1:XVuDAssexPLwgxCLMvDTWNU5eqklsydR6I5phZ9oPB8= gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -2689,10 +2558,6 @@ 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= -howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M= -howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= -inet.af/netaddr v0.0.0-20230525184311-b8eac61e914a h1:1XCVEdxrvL6c0TGOhecLuB7U9zYNdxZEjvOqJreKZiM= -inet.af/netaddr v0.0.0-20230525184311-b8eac61e914a/go.mod h1:e83i32mAQOW1LAqEIweALsuK2Uw4mhQadA5r7b0Wobo= k8s.io/api v0.0.0-20180904230853-4e7be11eab3f/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= k8s.io/api v0.0.0-20191016110408-35e52d86657a/go.mod h1:/L5qH+AD540e7Cetbui1tuJeXdmNhO8jM6VkXeDdDhQ= k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= @@ -2756,8 +2621,8 @@ k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.10.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= -k8s.io/klog/v2 v2.80.1/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-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4= k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= diff --git a/integration/fixtures/tracing/otel-collector-config.yaml b/integration/fixtures/tracing/otel-collector-config.yaml new file mode 100644 index 000000000..4f51aec4b --- /dev/null +++ b/integration/fixtures/tracing/otel-collector-config.yaml @@ -0,0 +1,21 @@ +receivers: + otlp: + protocols: + grpc: + http: +exporters: + otlp/tempo: + endpoint: http://tempo:4317 + tls: + insecure: true +service: + telemetry: + logs: + level: "error" + extensions: [ health_check ] + pipelines: + traces: + receivers: [otlp] + exporters: [otlp/tempo] +extensions: + health_check: \ No newline at end of file diff --git a/integration/fixtures/tracing/simple-jaeger.toml b/integration/fixtures/tracing/simple-jaeger.toml deleted file mode 100644 index bf02ced6a..000000000 --- a/integration/fixtures/tracing/simple-jaeger.toml +++ /dev/null @@ -1,70 +0,0 @@ -[global] - checkNewVersion = false - sendAnonymousUsage = false - -[log] - level = "DEBUG" - noColor = true - -[api] - insecure = true - -[entryPoints] - [entryPoints.web] - address = ":8000" - -[tracing] - servicename = "tracing" - [tracing.jaeger] - samplingType = "const" - samplingParam = 1.0 - samplingServerURL = "http://{{.IP}}:5778/sampling" - localAgentHostPort = "{{.IP}}:6831" - traceContextHeaderName = "{{.TraceContextHeaderName}}" - -[providers.file] - filename = "{{ .SelfFilename }}" - -## dynamic configuration ## - -[http.routers] - [http.routers.router1] - Service = "service1" - Middlewares = ["retry", "ratelimit-1"] - Rule = "Path(`/ratelimit`)" - [http.routers.router2] - Service = "service2" - Middlewares = ["retry"] - Rule = "Path(`/retry`)" - [http.routers.router3] - Service = "service3" - Middlewares = ["retry", "basic-auth"] - Rule = "Path(`/auth`)" - -[http.middlewares] - [http.middlewares.retry.retry] - attempts = 3 - [http.middlewares.basic-auth.basicAuth] - users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"] - [http.middlewares.ratelimit-1.rateLimit] - average = 1 - burst = 2 - -[http.services] - [http.services.service1] - [http.services.service1.loadBalancer] - passHostHeader = true - [[http.services.service1.loadBalancer.servers]] - url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}" - - [http.services.service2] - [http.services.service2.loadBalancer] - passHostHeader = true - [[http.services.service2.loadBalancer.servers]] - url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}" - - [http.services.service3] - [http.services.service3.loadBalancer] - passHostHeader = true - [[http.services.service3.loadBalancer.servers]] - url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}" diff --git a/integration/fixtures/tracing/simple-jaeger-collector.toml b/integration/fixtures/tracing/simple-opentelemetry.toml similarity index 76% rename from integration/fixtures/tracing/simple-jaeger-collector.toml rename to integration/fixtures/tracing/simple-opentelemetry.toml index e858e2a57..77d779800 100644 --- a/integration/fixtures/tracing/simple-jaeger-collector.toml +++ b/integration/fixtures/tracing/simple-opentelemetry.toml @@ -15,12 +15,15 @@ [tracing] servicename = "tracing" - [tracing.jaeger] - samplingType = "const" - samplingParam = 1.0 - samplingServerURL = "http://{{.IP}}:5778/sampling" - [tracing.jaeger.collector] - endpoint = "http://{{.IP}}:14268/api/traces?format=jaeger.thrift" + sampleRate = 1.0 +{{if .IsHTTP}} + [tracing.otlp.http] + endpoint = "http://{{.IP}}:4318" +{{else}} + [tracing.otlp.grpc] + endpoint = "{{.IP}}:4317" + insecure = true +{{end}} [providers.file] filename = "{{ .SelfFilename }}" @@ -28,6 +31,10 @@ ## dynamic configuration ## [http.routers] + [http.routers.router0] + Service = "service0" + Middlewares = [] + Rule = "Path(`/basic`)" [http.routers.router1] Service = "service1" Middlewares = ["retry", "ratelimit-1"] @@ -50,8 +57,13 @@ average = 1 burst = 2 - [http.services] + [http.services.service0] + [http.services.service0.loadBalancer] + passHostHeader = true + [[http.services.service0.loadBalancer.servers]] + url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}" + [http.services.service1] [http.services.service1.loadBalancer] passHostHeader = true diff --git a/integration/fixtures/tracing/simple-zipkin.toml b/integration/fixtures/tracing/simple-zipkin.toml deleted file mode 100644 index ef935fa28..000000000 --- a/integration/fixtures/tracing/simple-zipkin.toml +++ /dev/null @@ -1,66 +0,0 @@ -[global] - checkNewVersion = false - sendAnonymousUsage = false - -[log] - level = "DEBUG" - noColor = true - -[api] - insecure = true - -[entryPoints] - [entryPoints.web] - address = ":8000" - -[tracing] - servicename = "tracing" - [tracing.zipkin] - httpEndpoint = "http://{{.IP}}:9411/api/v2/spans" - -[providers.file] - filename = "{{ .SelfFilename }}" - -## dynamic configuration ## - -[http.routers] - [http.routers.router1] - service = "service1" - middlewares = ["retry", "ratelimit-1"] - rule = "Path(`/ratelimit`)" - [http.routers.router2] - service = "service2" - middlewares = ["retry"] - rule = "Path(`/retry`)" - [http.routers.router3] - service = "service3" - middlewares = ["retry", "basic-auth"] - rule = "Path(`/auth`)" - -[http.middlewares] - [http.middlewares.retry.retry] - attempts = 3 - [http.middlewares.basic-auth.basicAuth] - users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"] - [http.middlewares.ratelimit-1.rateLimit] - average = 1 - burst = 2 - -[http.services] - [http.services.service1] - [http.services.service1.loadBalancer] - passHostHeader = true - [[http.services.service1.loadBalancer.servers]] - url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}" - - [http.services.service2] - [http.services.service2.loadBalancer] - passHostHeader = true - [[http.services.service2.loadBalancer.servers]] - url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}" - - [http.services.service3] - [http.services.service3.loadBalancer] - passHostHeader = true - [[http.services.service3.loadBalancer.servers]] - url = "http://{{.WhoamiIP}}:{{.WhoamiPort}}" diff --git a/integration/fixtures/tracing/tempo.yaml b/integration/fixtures/tracing/tempo.yaml new file mode 100644 index 000000000..0a115bfaa --- /dev/null +++ b/integration/fixtures/tracing/tempo.yaml @@ -0,0 +1,56 @@ +server: + http_listen_port: 3200 + +query_frontend: + search: + duration_slo: 5s + throughput_bytes_slo: 1.073741824e+09 + trace_by_id: + duration_slo: 5s + +distributor: + receivers: + otlp: + protocols: + grpc: + +ingester: + lifecycler: + address: 127.0.0.1 + ring: + kvstore: + store: inmemory + replication_factor: 1 + final_sleep: 0s + trace_idle_period: 1s + max_block_duration: 1m + complete_block_timeout: 5s + flush_check_period: 1s +compactor: + compaction: + block_retention: 1h + +metrics_generator: + registry: + external_labels: + source: tempo + cluster: docker-compose + storage: + path: /tmp/tempo/generator/wal + remote_write: + - url: http://prometheus:9090/api/v1/write + send_exemplars: true + +storage: + trace: + backend: local # backend configuration to use + wal: + path: /tmp/tempo/wal # where to store the wal locally + local: + path: /tmp/tempo/blocks + +overrides: + defaults: + metrics_generator: + processors: [service-graphs, span-metrics] # enables metrics generator + diff --git a/integration/resources/compose/tracing.yml b/integration/resources/compose/tracing.yml index aeea9b378..4cd02cec0 100644 --- a/integration/resources/compose/tracing.yml +++ b/integration/resources/compose/tracing.yml @@ -1,16 +1,15 @@ version: "3.8" services: - zipkin: - image: openzipkin/zipkin:2.16.2 - environment: - STORAGE_TYPE: mem - JAVA_OPTS: -Dlogging.level.zipkin=DEBUG - - jaeger: - image: jaegertracing/all-in-one:1.14 - environment: - COLLECTOR_ZIPKIN_HTTP_PORT: 9411 - + tempo: + hostname: tempo + image: grafana/tempo:latest + command: [ "-config.file=/etc/tempo.yaml" ] + volumes: + - ./fixtures/tracing/tempo.yaml:/etc/tempo.yaml + otel-collector: + image: otel/opentelemetry-collector-contrib:0.89.0 + volumes: + - ./fixtures/tracing/otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml whoami: image: traefik/whoami diff --git a/integration/tracing_test.go b/integration/tracing_test.go index f2a1f29ad..328b63d17 100644 --- a/integration/tracing_test.go +++ b/integration/tracing_test.go @@ -1,20 +1,26 @@ package integration import ( + "encoding/json" + "io" "net/http" + "net/url" "os" + "strings" "time" "github.com/go-check/check" + "github.com/tidwall/gjson" "github.com/traefik/traefik/v3/integration/try" checker "github.com/vdemeester/shakers" ) type TracingSuite struct { BaseSuite - whoamiIP string - whoamiPort int - tracerIP string + whoamiIP string + whoamiPort int + tempoIP string + otelCollectorIP string } type TracingTemplate struct { @@ -22,39 +28,157 @@ type TracingTemplate struct { WhoamiPort int IP string TraceContextHeaderName string + IsHTTP bool } func (s *TracingSuite) SetUpSuite(c *check.C) { s.createComposeProject(c, "tracing") s.composeUp(c) +} + +func (s *TracingSuite) SetUpTest(c *check.C) { + s.composeUp(c, "tempo", "otel-collector", "whoami") s.whoamiIP = s.getComposeServiceIP(c, "whoami") s.whoamiPort = 80 -} -func (s *TracingSuite) startZipkin(c *check.C) { - s.composeUp(c, "zipkin") - s.tracerIP = s.getComposeServiceIP(c, "zipkin") + // Wait for whoami to turn ready. + err := try.GetRequest("http://"+s.whoamiIP+":80", 30*time.Second, try.StatusCodeIs(http.StatusOK)) + c.Assert(err, checker.IsNil) - // Wait for Zipkin to turn ready. - err := try.GetRequest("http://"+s.tracerIP+":9411/api/v2/services", 20*time.Second, try.StatusCodeIs(http.StatusOK)) + s.tempoIP = s.getComposeServiceIP(c, "tempo") + + // Wait for tempo to turn ready. + err = try.GetRequest("http://"+s.tempoIP+":3200/ready", 30*time.Second, try.StatusCodeIs(http.StatusOK)) + c.Assert(err, checker.IsNil) + + s.otelCollectorIP = s.getComposeServiceIP(c, "otel-collector") + + // Wait for otel collector to turn ready. + err = try.GetRequest("http://"+s.otelCollectorIP+":13133/", 30*time.Second, try.StatusCodeIs(http.StatusOK)) c.Assert(err, checker.IsNil) } -func (s *TracingSuite) TestZipkinRateLimit(c *check.C) { - s.startZipkin(c) - // defer s.composeStop(c, "zipkin") +func (s *TracingSuite) TearDownTest(c *check.C) { + s.composeStop(c, "tempo") +} - file := s.adaptFile(c, "fixtures/tracing/simple-zipkin.toml", TracingTemplate{ +func (s *TracingSuite) TestOpentelemetryBasic_HTTP(c *check.C) { + file := s.adaptFile(c, "fixtures/tracing/simple-opentelemetry.toml", TracingTemplate{ WhoamiIP: s.whoamiIP, WhoamiPort: s.whoamiPort, - IP: s.tracerIP, + IP: s.otelCollectorIP, + IsHTTP: true, }) defer os.Remove(file) cmd, display := s.traefikCmd(withConfigFile(file)) defer display(c) + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer s.killCmd(cmd) + // wait for traefik + err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth")) + c.Assert(err, checker.IsNil) + + err = try.GetRequest("http://127.0.0.1:8000/basic", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK)) + c.Assert(err, checker.IsNil) + + contains := []map[string]string{ + { + "batches.0.scopeSpans.0.scope.name": "github.com/traefik/traefik", + + "batches.0.scopeSpans.0.spans.0.name": "EntryPoint", + "batches.0.scopeSpans.0.spans.0.kind": "SPAN_KIND_SERVER", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.request.method\").value.stringValue": "GET", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"entry_point\").value.stringValue": "web", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"url.path\").value.stringValue": "/basic", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.response.status_code\").value.intValue": "200", + + "batches.0.scopeSpans.0.spans.1.name": "Router", + "batches.0.scopeSpans.0.spans.1.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.router.name\").value.stringValue": "router0@file", + "batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.service.name\").value.stringValue": "service0@file", + + "batches.0.scopeSpans.0.spans.2.name": "Service", + "batches.0.scopeSpans.0.spans.2.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.2.attributes.#(key=\"traefik.service.name\").value.stringValue": "service0@file", + + "batches.0.scopeSpans.0.spans.3.name": "ReverseProxy", + "batches.0.scopeSpans.0.spans.3.kind": "SPAN_KIND_CLIENT", + "batches.0.scopeSpans.0.spans.3.attributes.#(key=\"url.scheme\").value.stringValue": "http", + "batches.0.scopeSpans.0.spans.3.attributes.#(key=\"http.response.status_code\").value.intValue": "200", + "batches.0.scopeSpans.0.spans.3.attributes.#(key=\"user_agent.original\").value.stringValue": "Go-http-client/1.1", + }, + } + + checkTraceContent(c, s.tempoIP, contains) +} + +func (s *TracingSuite) TestOpentelemetryBasic_gRPC(c *check.C) { + file := s.adaptFile(c, "fixtures/tracing/simple-opentelemetry.toml", TracingTemplate{ + WhoamiIP: s.whoamiIP, + WhoamiPort: s.whoamiPort, + IP: s.otelCollectorIP, + IsHTTP: false, + }) + defer os.Remove(file) + + cmd, display := s.traefikCmd(withConfigFile(file)) + defer display(c) + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer s.killCmd(cmd) + + // wait for traefik + err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth")) + c.Assert(err, checker.IsNil) + + err = try.GetRequest("http://127.0.0.1:8000/basic", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK)) + c.Assert(err, checker.IsNil) + + contains := []map[string]string{ + { + "batches.0.scopeSpans.0.scope.name": "github.com/traefik/traefik", + + "batches.0.scopeSpans.0.spans.0.name": "EntryPoint", + "batches.0.scopeSpans.0.spans.0.kind": "SPAN_KIND_SERVER", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.request.method\").value.stringValue": "GET", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"entry_point\").value.stringValue": "web", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"url.path\").value.stringValue": "/basic", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.response.status_code\").value.intValue": "200", + + "batches.0.scopeSpans.0.spans.1.name": "Router", + "batches.0.scopeSpans.0.spans.1.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.router.name\").value.stringValue": "router0@file", + "batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.service.name\").value.stringValue": "service0@file", + + "batches.0.scopeSpans.0.spans.2.name": "Service", + "batches.0.scopeSpans.0.spans.2.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.2.attributes.#(key=\"traefik.service.name\").value.stringValue": "service0@file", + + "batches.0.scopeSpans.0.spans.3.name": "ReverseProxy", + "batches.0.scopeSpans.0.spans.3.kind": "SPAN_KIND_CLIENT", + "batches.0.scopeSpans.0.spans.3.attributes.#(key=\"url.scheme\").value.stringValue": "http", + "batches.0.scopeSpans.0.spans.3.attributes.#(key=\"http.response.status_code\").value.intValue": "200", + "batches.0.scopeSpans.0.spans.3.attributes.#(key=\"user_agent.original\").value.stringValue": "Go-http-client/1.1", + }, + } + + checkTraceContent(c, s.tempoIP, contains) +} + +func (s *TracingSuite) TestOpentelemetryRateLimit(c *check.C) { + file := s.adaptFile(c, "fixtures/tracing/simple-opentelemetry.toml", TracingTemplate{ + WhoamiIP: s.whoamiIP, + WhoamiPort: s.whoamiPort, + IP: s.otelCollectorIP, + }) + defer os.Remove(file) + + cmd, display := s.traefikCmd(withConfigFile(file)) + defer display(c) err := cmd.Start() c.Assert(err, checker.IsNil) defer s.killCmd(cmd) @@ -85,22 +209,94 @@ func (s *TracingSuite) TestZipkinRateLimit(c *check.C) { err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK)) c.Assert(err, checker.IsNil) - time.Sleep(3 * time.Second) err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests)) c.Assert(err, checker.IsNil) - err = try.GetRequest("http://"+s.tracerIP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("forward service1/router1@file", "ratelimit-1@file")) - c.Assert(err, checker.IsNil) + contains := []map[string]string{ + { + "batches.0.scopeSpans.0.scope.name": "github.com/traefik/traefik", + + "batches.0.scopeSpans.0.spans.0.name": "EntryPoint", + "batches.0.scopeSpans.0.spans.0.kind": "SPAN_KIND_SERVER", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.request.method\").value.stringValue": "GET", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"entry_point\").value.stringValue": "web", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"url.path\").value.stringValue": "/ratelimit", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.response.status_code\").value.intValue": "200", + + "batches.0.scopeSpans.0.spans.1.name": "Router", + "batches.0.scopeSpans.0.spans.1.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.router.name\").value.stringValue": "router1@file", + "batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.service.name\").value.stringValue": "service1@file", + + "batches.0.scopeSpans.0.spans.2.name": "Retry", + "batches.0.scopeSpans.0.spans.2.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.2.attributes.#(key=\"traefik.middleware.name\").value.stringValue": "retry@file", + + "batches.0.scopeSpans.0.spans.3.name": "RateLimiter", + "batches.0.scopeSpans.0.spans.3.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.3.attributes.#(key=\"traefik.middleware.name\").value.stringValue": "ratelimit-1@file", + + "batches.0.scopeSpans.0.spans.4.name": "Service", + "batches.0.scopeSpans.0.spans.4.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.4.attributes.#(key=\"traefik.service.name\").value.stringValue": "service1@file", + + "batches.0.scopeSpans.0.spans.5.name": "ReverseProxy", + "batches.0.scopeSpans.0.spans.5.kind": "SPAN_KIND_CLIENT", + "batches.0.scopeSpans.0.spans.5.attributes.#(key=\"url.scheme\").value.stringValue": "http", + "batches.0.scopeSpans.0.spans.5.attributes.#(key=\"http.response.status_code\").value.intValue": "200", + "batches.0.scopeSpans.0.spans.5.attributes.#(key=\"user_agent.original\").value.stringValue": "Go-http-client/1.1", + }, + { + "batches.0.scopeSpans.0.scope.name": "github.com/traefik/traefik", + + "batches.0.scopeSpans.0.spans.0.name": "EntryPoint", + "batches.0.scopeSpans.0.spans.0.kind": "SPAN_KIND_SERVER", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.request.method\").value.stringValue": "GET", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"entry_point\").value.stringValue": "web", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"url.path\").value.stringValue": "/ratelimit", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.response.status_code\").value.intValue": "429", + + "batches.0.scopeSpans.0.spans.1.name": "Router", + "batches.0.scopeSpans.0.spans.1.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.router.name\").value.stringValue": "router1@file", + "batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.service.name\").value.stringValue": "service1@file", + + "batches.0.scopeSpans.0.spans.2.name": "Retry", + "batches.0.scopeSpans.0.spans.2.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.2.attributes.#(key=\"traefik.middleware.name\").value.stringValue": "retry@file", + + "batches.0.scopeSpans.0.spans.3.name": "RateLimiter", + "batches.0.scopeSpans.0.spans.3.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.3.attributes.#(key=\"traefik.middleware.name\").value.stringValue": "ratelimit-1@file", + + "batches.0.scopeSpans.0.spans.4.name": "Retry", + "batches.0.scopeSpans.0.spans.4.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.4.attributes.#(key=\"traefik.middleware.name\").value.stringValue": "retry@file", + "batches.0.scopeSpans.0.spans.4.attributes.#(key=\"http.resend_count\").value.intValue": "1", + + "batches.0.scopeSpans.0.spans.5.name": "RateLimiter", + "batches.0.scopeSpans.0.spans.5.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.5.attributes.#(key=\"traefik.middleware.name\").value.stringValue": "ratelimit-1@file", + + "batches.0.scopeSpans.0.spans.6.name": "Retry", + "batches.0.scopeSpans.0.spans.6.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.6.attributes.#(key=\"traefik.middleware.name\").value.stringValue": "retry@file", + "batches.0.scopeSpans.0.spans.6.attributes.#(key=\"http.resend_count\").value.intValue": "2", + + "batches.0.scopeSpans.0.spans.7.name": "RateLimiter", + "batches.0.scopeSpans.0.spans.7.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.7.attributes.#(key=\"traefik.middleware.name\").value.stringValue": "ratelimit-1@file", + }, + } + + checkTraceContent(c, s.tempoIP, contains) } -func (s *TracingSuite) TestZipkinRetry(c *check.C) { - s.startZipkin(c) - defer s.composeStop(c, "zipkin") - - file := s.adaptFile(c, "fixtures/tracing/simple-zipkin.toml", TracingTemplate{ +func (s *TracingSuite) TestOpentelemetryRetry(c *check.C) { + file := s.adaptFile(c, "fixtures/tracing/simple-opentelemetry.toml", TracingTemplate{ WhoamiIP: s.whoamiIP, WhoamiPort: 81, - IP: s.tracerIP, + IP: s.otelCollectorIP, }) defer os.Remove(file) @@ -117,18 +313,75 @@ func (s *TracingSuite) TestZipkinRetry(c *check.C) { err = try.GetRequest("http://127.0.0.1:8000/retry", 500*time.Millisecond, try.StatusCodeIs(http.StatusBadGateway)) c.Assert(err, checker.IsNil) - err = try.GetRequest("http://"+s.tracerIP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("forward service2/router2@file", "retry@file")) - c.Assert(err, checker.IsNil) + contains := []map[string]string{ + { + "batches.0.scopeSpans.0.scope.name": "github.com/traefik/traefik", + + "batches.0.scopeSpans.0.spans.0.name": "EntryPoint", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.request.method\").value.stringValue": "GET", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"url.path\").value.stringValue": "/retry", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.response.status_code\").value.intValue": "502", + "batches.0.scopeSpans.0.spans.0.status.code": "STATUS_CODE_ERROR", + + "batches.0.scopeSpans.0.spans.1.name": "Router", + "batches.0.scopeSpans.0.spans.1.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.service.name\").value.stringValue": "service2@file", + "batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.router.name\").value.stringValue": "router2@file", + + "batches.0.scopeSpans.0.spans.2.name": "Retry", + "batches.0.scopeSpans.0.spans.2.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.2.attributes.#(key=\"traefik.middleware.name\").value.stringValue": "retry@file", + + "batches.0.scopeSpans.0.spans.3.name": "Service", + "batches.0.scopeSpans.0.spans.3.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.3.attributes.#(key=\"traefik.service.name\").value.stringValue": "service2@file", + + "batches.0.scopeSpans.0.spans.4.name": "ReverseProxy", + "batches.0.scopeSpans.0.spans.4.kind": "SPAN_KIND_CLIENT", + "batches.0.scopeSpans.0.spans.4.attributes.#(key=\"url.scheme\").value.stringValue": "http", + "batches.0.scopeSpans.0.spans.4.attributes.#(key=\"http.response.status_code\").value.intValue": "502", + "batches.0.scopeSpans.0.spans.4.attributes.#(key=\"user_agent.original\").value.stringValue": "Go-http-client/1.1", + + "batches.0.scopeSpans.0.spans.5.name": "Retry", + "batches.0.scopeSpans.0.spans.5.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.5.attributes.#(key=\"traefik.middleware.name\").value.stringValue": "retry@file", + "batches.0.scopeSpans.0.spans.5.attributes.#(key=\"http.resend_count\").value.intValue": "1", + + "batches.0.scopeSpans.0.spans.6.name": "Service", + "batches.0.scopeSpans.0.spans.6.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.6.attributes.#(key=\"traefik.service.name\").value.stringValue": "service2@file", + + "batches.0.scopeSpans.0.spans.7.name": "ReverseProxy", + "batches.0.scopeSpans.0.spans.7.kind": "SPAN_KIND_CLIENT", + "batches.0.scopeSpans.0.spans.7.attributes.#(key=\"url.scheme\").value.stringValue": "http", + "batches.0.scopeSpans.0.spans.7.attributes.#(key=\"http.response.status_code\").value.intValue": "502", + "batches.0.scopeSpans.0.spans.7.attributes.#(key=\"user_agent.original\").value.stringValue": "Go-http-client/1.1", + + "batches.0.scopeSpans.0.spans.8.name": "Retry", + "batches.0.scopeSpans.0.spans.8.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.8.attributes.#(key=\"traefik.middleware.name\").value.stringValue": "retry@file", + "batches.0.scopeSpans.0.spans.8.attributes.#(key=\"http.resend_count\").value.intValue": "2", + + "batches.0.scopeSpans.0.spans.9.name": "Service", + "batches.0.scopeSpans.0.spans.9.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.9.attributes.#(key=\"traefik.service.name\").value.stringValue": "service2@file", + + "batches.0.scopeSpans.0.spans.10.name": "ReverseProxy", + "batches.0.scopeSpans.0.spans.10.kind": "SPAN_KIND_CLIENT", + "batches.0.scopeSpans.0.spans.10.attributes.#(key=\"url.scheme\").value.stringValue": "http", + "batches.0.scopeSpans.0.spans.10.attributes.#(key=\"http.response.status_code\").value.intValue": "502", + "batches.0.scopeSpans.0.spans.10.attributes.#(key=\"user_agent.original\").value.stringValue": "Go-http-client/1.1", + }, + } + + checkTraceContent(c, s.tempoIP, contains) } -func (s *TracingSuite) TestZipkinAuth(c *check.C) { - s.startZipkin(c) - defer s.composeStop(c, "zipkin") - - file := s.adaptFile(c, "fixtures/tracing/simple-zipkin.toml", TracingTemplate{ +func (s *TracingSuite) TestOpentelemetryAuth(c *check.C) { + file := s.adaptFile(c, "fixtures/tracing/simple-opentelemetry.toml", TracingTemplate{ WhoamiIP: s.whoamiIP, WhoamiPort: s.whoamiPort, - IP: s.tracerIP, + IP: s.otelCollectorIP, }) defer os.Remove(file) @@ -145,181 +398,101 @@ func (s *TracingSuite) TestZipkinAuth(c *check.C) { err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized)) c.Assert(err, checker.IsNil) - err = try.GetRequest("http://"+s.tracerIP+":9411/api/v2/spans?serviceName=tracing", 20*time.Second, try.BodyContains("entrypoint web", "basic-auth@file")) - c.Assert(err, checker.IsNil) + contains := []map[string]string{ + { + "batches.0.scopeSpans.0.scope.name": "github.com/traefik/traefik", + + "batches.0.scopeSpans.0.spans.0.name": "EntryPoint", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.request.method\").value.stringValue": "GET", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"url.path\").value.stringValue": "/auth", + "batches.0.scopeSpans.0.spans.0.attributes.#(key=\"http.response.status_code\").value.intValue": "401", + + "batches.0.scopeSpans.0.spans.1.name": "Router", + "batches.0.scopeSpans.0.spans.1.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.router.name\").value.stringValue": "router3@file", + "batches.0.scopeSpans.0.spans.1.attributes.#(key=\"traefik.service.name\").value.stringValue": "service3@file", + + "batches.0.scopeSpans.0.spans.2.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.2.attributes.#(key=\"traefik.middleware.name\").value.stringValue": "retry@file", + + "batches.0.scopeSpans.0.spans.3.kind": "SPAN_KIND_INTERNAL", + "batches.0.scopeSpans.0.spans.3.attributes.#(key=\"traefik.middleware.name\").value.stringValue": "basic-auth@file", + }, + } + + checkTraceContent(c, s.tempoIP, contains) } -func (s *TracingSuite) startJaeger(c *check.C) { - s.composeUp(c, "jaeger", "whoami") - s.tracerIP = s.getComposeServiceIP(c, "jaeger") - - // Wait for Jaeger to turn ready. - err := try.GetRequest("http://"+s.tracerIP+":16686/api/services", 20*time.Second, try.StatusCodeIs(http.StatusOK)) +func checkTraceContent(c *check.C, tempoIP string, expectedJSON []map[string]string) { + baseURL, err := url.Parse("http://" + tempoIP + ":3200/api/search") c.Assert(err, checker.IsNil) + + req := &http.Request{ + Method: http.MethodGet, + URL: baseURL, + } + // Wait for traces to be available. + time.Sleep(10 * time.Second) + resp, err := try.Response(req, 5*time.Second) + c.Assert(err, checker.IsNil) + + out := &TraceResponse{} + content, err := io.ReadAll(resp.Body) + c.Assert(err, checker.IsNil) + err = json.Unmarshal(content, &out) + c.Assert(err, checker.IsNil) + + if len(out.Traces) == 0 { + c.Fatalf("expected at least one trace, got %d (%s)", len(out.Traces), string(content)) + } + + var contents []string + for _, t := range out.Traces { + baseURL, err := url.Parse("http://" + tempoIP + ":3200/api/traces/" + t.TraceID) + c.Assert(err, checker.IsNil) + + req := &http.Request{ + Method: http.MethodGet, + URL: baseURL, + } + + resp, err := try.Response(req, 5*time.Second) + c.Assert(err, checker.IsNil) + + content, err := io.ReadAll(resp.Body) + c.Assert(err, checker.IsNil) + + contents = append(contents, string(content)) + } + + for _, expected := range expectedJSON { + containsAll(c, expected, contents) + } } -func (s *TracingSuite) TestJaegerRateLimit(c *check.C) { - s.startJaeger(c) - defer s.composeStop(c, "jaeger") +func containsAll(c *check.C, expectedJSON map[string]string, contents []string) { + for k, v := range expectedJSON { + found := false + for _, content := range contents { + if gjson.Get(content, k).String() == v { + found = true + break + } + } - file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{ - WhoamiIP: s.whoamiIP, - WhoamiPort: s.whoamiPort, - IP: s.tracerIP, - TraceContextHeaderName: "uber-trace-id", - }) - defer os.Remove(file) - - cmd, display := s.traefikCmd(withConfigFile(file)) - defer display(c) - err := cmd.Start() - c.Assert(err, checker.IsNil) - defer s.killCmd(cmd) - - // wait for traefik - err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth")) - c.Assert(err, checker.IsNil) - - err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) - err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) - err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests)) - c.Assert(err, checker.IsNil) - - // sleep for 4 seconds to be certain the configured time period has elapsed - // then test another request and verify a 200 status code - time.Sleep(4 * time.Second) - err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) - - // continue requests at 3 second intervals to test the other rate limit time period - time.Sleep(3 * time.Second) - err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) - - time.Sleep(3 * time.Second) - err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK)) - c.Assert(err, checker.IsNil) - - err = try.GetRequest("http://127.0.0.1:8000/ratelimit", 500*time.Millisecond, try.StatusCodeIs(http.StatusTooManyRequests)) - c.Assert(err, checker.IsNil) - - err = try.GetRequest("http://"+s.tracerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("forward service1/router1@file", "ratelimit-1@file")) - c.Assert(err, checker.IsNil) + if !found { + c.Log("[" + strings.Join(contents, ",") + "]") + c.Errorf("missing element: \nKey: %q\nValue: %q ", k, v) + } + } } -func (s *TracingSuite) TestJaegerRetry(c *check.C) { - s.startJaeger(c) - defer s.composeStop(c, "jaeger") - - file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{ - WhoamiIP: s.whoamiIP, - WhoamiPort: 81, - IP: s.tracerIP, - TraceContextHeaderName: "uber-trace-id", - }) - defer os.Remove(file) - - cmd, display := s.traefikCmd(withConfigFile(file)) - defer display(c) - err := cmd.Start() - c.Assert(err, checker.IsNil) - defer s.killCmd(cmd) - - // wait for traefik - err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth")) - c.Assert(err, checker.IsNil) - - err = try.GetRequest("http://127.0.0.1:8000/retry", 500*time.Millisecond, try.StatusCodeIs(http.StatusBadGateway)) - c.Assert(err, checker.IsNil) - - err = try.GetRequest("http://"+s.tracerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("forward service2/router2@file", "retry@file")) - c.Assert(err, checker.IsNil) +// TraceResponse contains a list of traces. +type TraceResponse struct { + Traces []Trace `json:"traces"` } -func (s *TracingSuite) TestJaegerAuth(c *check.C) { - s.startJaeger(c) - defer s.composeStop(c, "jaeger") - - file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{ - WhoamiIP: s.whoamiIP, - WhoamiPort: s.whoamiPort, - IP: s.tracerIP, - TraceContextHeaderName: "uber-trace-id", - }) - defer os.Remove(file) - - cmd, display := s.traefikCmd(withConfigFile(file)) - defer display(c) - err := cmd.Start() - c.Assert(err, checker.IsNil) - defer s.killCmd(cmd) - - // wait for traefik - err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth")) - c.Assert(err, checker.IsNil) - - err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized)) - c.Assert(err, checker.IsNil) - - err = try.GetRequest("http://"+s.tracerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file")) - c.Assert(err, checker.IsNil) -} - -func (s *TracingSuite) TestJaegerCustomHeader(c *check.C) { - s.startJaeger(c) - defer s.composeStop(c, "jaeger") - - file := s.adaptFile(c, "fixtures/tracing/simple-jaeger.toml", TracingTemplate{ - WhoamiIP: s.whoamiIP, - WhoamiPort: s.whoamiPort, - IP: s.tracerIP, - TraceContextHeaderName: "powpow", - }) - defer os.Remove(file) - - cmd, display := s.traefikCmd(withConfigFile(file)) - defer display(c) - err := cmd.Start() - c.Assert(err, checker.IsNil) - defer s.killCmd(cmd) - - // wait for traefik - err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth")) - c.Assert(err, checker.IsNil) - - err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized)) - c.Assert(err, checker.IsNil) - - err = try.GetRequest("http://"+s.tracerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file")) - c.Assert(err, checker.IsNil) -} - -func (s *TracingSuite) TestJaegerAuthCollector(c *check.C) { - s.startJaeger(c) - defer s.composeStop(c, "jaeger") - - file := s.adaptFile(c, "fixtures/tracing/simple-jaeger-collector.toml", TracingTemplate{ - WhoamiIP: s.whoamiIP, - WhoamiPort: s.whoamiPort, - IP: s.tracerIP, - }) - defer os.Remove(file) - - cmd, display := s.traefikCmd(withConfigFile(file)) - defer display(c) - err := cmd.Start() - c.Assert(err, checker.IsNil) - defer s.killCmd(cmd) - - // wait for traefik - err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", time.Second, try.BodyContains("basic-auth")) - c.Assert(err, checker.IsNil) - - err = try.GetRequest("http://127.0.0.1:8000/auth", 500*time.Millisecond, try.StatusCodeIs(http.StatusUnauthorized)) - c.Assert(err, checker.IsNil) - - err = try.GetRequest("http://"+s.tracerIP+":16686/api/traces?service=tracing", 20*time.Second, try.BodyContains("EntryPoint web", "basic-auth@file")) - c.Assert(err, checker.IsNil) +// Trace represents a simplified grafana tempo trace. +type Trace struct { + TraceID string `json:"traceID"` } diff --git a/pkg/api/handler_overview_test.go b/pkg/api/handler_overview_test.go index 0e0165904..3e8743a81 100644 --- a/pkg/api/handler_overview_test.go +++ b/pkg/api/handler_overview_test.go @@ -18,7 +18,6 @@ import ( "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd" "github.com/traefik/traefik/v3/pkg/provider/kubernetes/ingress" "github.com/traefik/traefik/v3/pkg/provider/rest" - "github.com/traefik/traefik/v3/pkg/tracing/jaeger" "github.com/traefik/traefik/v3/pkg/types" ) @@ -259,9 +258,7 @@ func TestHandler_Overview(t *testing.T) { Metrics: &types.Metrics{ Prometheus: &types.Prometheus{}, }, - Tracing: &static.Tracing{ - Jaeger: &jaeger.Config{}, - }, + Tracing: &static.Tracing{}, }, confDyn: runtime.Configuration{}, expected: expected{ diff --git a/pkg/api/testdata/overview-features.json b/pkg/api/testdata/overview-features.json index 5df280da0..a3db11a75 100644 --- a/pkg/api/testdata/overview-features.json +++ b/pkg/api/testdata/overview-features.json @@ -2,7 +2,7 @@ "features": { "accessLog": false, "metrics": "Prometheus", - "tracing": "Jaeger" + "tracing": "" }, "http": { "middlewares": { diff --git a/pkg/config/dynamic/fixtures/sample.toml b/pkg/config/dynamic/fixtures/sample.toml index 86242772c..f6ab56cf1 100644 --- a/pkg/config/dynamic/fixtures/sample.toml +++ b/pkg/config/dynamic/fixtures/sample.toml @@ -122,41 +122,29 @@ [tracing] serviceName = "foobar" - spanNameLimit = 42 - [tracing.jaeger] - samplingServerURL = "foobar" - samplingType = "foobar" - samplingParam = 42.0 - localAgentHostPort = "foobar" - gen128Bit = true - propagation = "foobar" - traceContextHeaderName = "foobar" - [tracing.zipkin] - httpEndpoint = "foobar" - sameSpan = true - id128Bit = true - debug = true - sampleRate = 42.0 - [tracing.datadog] - localAgentHostPort = "foobar" - localAgentSocket = "foobar" - debug = true - prioritySampling = true - traceIDHeaderName = "foobar" - parentIDHeaderName = "foobar" - samplingPriorityHeaderName = "foobar" - bagagePrefixHeaderName = "foobar" - [tracing.instana] - localAgentHost = "foobar" - localAgentPort = 42 - logLevel = "foobar" - [tracing.haystack] - localAgentHost = "foobar" - localAgentPort = 42 - globalTag = "foobar" - traceIDHeaderName = "foobar" - parentIDHeaderName = "foobar" - spanIDHeaderName = "foobar" + sampleRate = 42 + [tracing.headers] + header1 = "foobar" + header2 = "foobar" + [tracing.globalAttributes] + attr1 = "foobar" + attr2 = "foobar" + [tracing.otlp.grpc] + endpoint = "foobar" + insecure = true + [tracing.otlp.grpc.tls] + ca = "foobar" + cert = "foobar" + key = "foobar" + insecureSkipVerify = true + [tracing.otlp.http] + endpoint = "foobar" + insecure = true + [tracing.otlp.http.tls] + ca = "foobar" + cert = "foobar" + key = "foobar" + insecureSkipVerify = true [hostResolver] cnameFlattening = true diff --git a/pkg/config/static/static_config.go b/pkg/config/static/static_config.go index 01a28d7c0..1c141a5a8 100644 --- a/pkg/config/static/static_config.go +++ b/pkg/config/static/static_config.go @@ -1,6 +1,7 @@ package static import ( + "errors" "fmt" "strings" "time" @@ -27,13 +28,7 @@ import ( "github.com/traefik/traefik/v3/pkg/provider/nomad" "github.com/traefik/traefik/v3/pkg/provider/rest" "github.com/traefik/traefik/v3/pkg/tls" - "github.com/traefik/traefik/v3/pkg/tracing/datadog" - "github.com/traefik/traefik/v3/pkg/tracing/elastic" - "github.com/traefik/traefik/v3/pkg/tracing/haystack" - "github.com/traefik/traefik/v3/pkg/tracing/instana" - "github.com/traefik/traefik/v3/pkg/tracing/jaeger" "github.com/traefik/traefik/v3/pkg/tracing/opentelemetry" - "github.com/traefik/traefik/v3/pkg/tracing/zipkin" "github.com/traefik/traefik/v3/pkg/types" ) @@ -187,21 +182,18 @@ func (a *LifeCycle) SetDefaults() { // Tracing holds the tracing configuration. type Tracing struct { - ServiceName string `description:"Set the name for this service." json:"serviceName,omitempty" toml:"serviceName,omitempty" yaml:"serviceName,omitempty" export:"true"` - SpanNameLimit int `description:"Set the maximum character limit for Span names (default 0 = no limit)." json:"spanNameLimit,omitempty" toml:"spanNameLimit,omitempty" yaml:"spanNameLimit,omitempty" export:"true"` - Jaeger *jaeger.Config `description:"Settings for Jaeger." json:"jaeger,omitempty" toml:"jaeger,omitempty" yaml:"jaeger,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` - Zipkin *zipkin.Config `description:"Settings for Zipkin." json:"zipkin,omitempty" toml:"zipkin,omitempty" yaml:"zipkin,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` - Datadog *datadog.Config `description:"Settings for Datadog." json:"datadog,omitempty" toml:"datadog,omitempty" yaml:"datadog,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` - Instana *instana.Config `description:"Settings for Instana." json:"instana,omitempty" toml:"instana,omitempty" yaml:"instana,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` - Haystack *haystack.Config `description:"Settings for Haystack." json:"haystack,omitempty" toml:"haystack,omitempty" yaml:"haystack,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` - Elastic *elastic.Config `description:"Settings for Elastic." json:"elastic,omitempty" toml:"elastic,omitempty" yaml:"elastic,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` - OpenTelemetry *opentelemetry.Config `description:"Settings for OpenTelemetry." json:"openTelemetry,omitempty" toml:"openTelemetry,omitempty" yaml:"openTelemetry,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` + ServiceName string `description:"Set the name for this service." json:"serviceName,omitempty" toml:"serviceName,omitempty" yaml:"serviceName,omitempty" export:"true"` + Headers map[string]string `description:"Defines additional headers to be sent with the payloads." json:"headers,omitempty" toml:"headers,omitempty" yaml:"headers,omitempty" export:"true"` + GlobalAttributes map[string]string `description:"Defines additional attributes (key:value) on all spans." json:"globalAttributes,omitempty" toml:"globalAttributes,omitempty" yaml:"globalAttributes,omitempty" export:"true"` + SampleRate float64 `description:"Sets the rate between 0.0 and 1.0 of requests to trace." json:"sampleRate,omitempty" toml:"sampleRate,omitempty" yaml:"sampleRate,omitempty" export:"true"` + + OTLP *opentelemetry.Config `description:"Settings for OpenTelemetry." json:"otlp,omitempty" toml:"otlp,omitempty" yaml:"otlp,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` } // SetDefaults sets the default values. func (t *Tracing) SetDefaults() { t.ServiceName = "traefik" - t.SpanNameLimit = 0 + t.SampleRate = 1.0 } // Providers contains providers configuration. @@ -326,6 +318,20 @@ func (c *Configuration) ValidateConfiguration() error { acmeEmail = resolver.ACME.Email } + if c.Tracing != nil && c.Tracing.OTLP != nil { + if c.Tracing.OTLP.HTTP == nil && c.Tracing.OTLP.GRPC == nil { + return errors.New("tracing OTLP: at least one of HTTP and gRPC options should be defined") + } + + if c.Tracing.OTLP.HTTP != nil && c.Tracing.OTLP.GRPC != nil { + return errors.New("tracing OTLP: HTTP and gRPC options are mutually exclusive") + } + + if c.Tracing.OTLP.GRPC != nil && c.Tracing.OTLP.GRPC.TLS != nil && c.Tracing.OTLP.GRPC.Insecure { + return errors.New("tracing OTLP GRPC: TLS and Insecure options are mutually exclusive") + } + } + return nil } diff --git a/pkg/logs/haystack.go b/pkg/logs/haystack.go deleted file mode 100644 index 6f3db7361..000000000 --- a/pkg/logs/haystack.go +++ /dev/null @@ -1,28 +0,0 @@ -package logs - -import ( - "github.com/rs/zerolog" -) - -type HaystackLogger struct { - logger zerolog.Logger -} - -func NewHaystackLogger(logger zerolog.Logger) *HaystackLogger { - return &HaystackLogger{logger: logger} -} - -// Error prints the error message. -func (l HaystackLogger) Error(format string, v ...interface{}) { - l.logger.Error().CallerSkipFrame(1).Msgf(format, v...) -} - -// Info prints the info message. -func (l HaystackLogger) Info(format string, v ...interface{}) { - l.logger.Info().CallerSkipFrame(1).Msgf(format, v...) -} - -// Debug prints the info message. -func (l HaystackLogger) Debug(format string, v ...interface{}) { - l.logger.Debug().CallerSkipFrame(1).Msgf(format, v...) -} diff --git a/pkg/logs/haystack_test.go b/pkg/logs/haystack_test.go deleted file mode 100644 index a6342bd99..000000000 --- a/pkg/logs/haystack_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package logs - -import ( - "bytes" - "os" - "testing" - "time" - - "github.com/rs/zerolog" - "github.com/stretchr/testify/assert" -) - -func TestNewHaystackLogger(t *testing.T) { - buf := bytes.NewBuffer(nil) - cwb := zerolog.ConsoleWriter{Out: buf, TimeFormat: time.RFC3339, NoColor: true} - - out := zerolog.MultiLevelWriter(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}, cwb) - - logger := NewHaystackLogger(zerolog.New(out).With().Caller().Logger()) - - logger.Info("foo") - - assert.Equal(t, " INF haystack_test.go:21 > foo\n", buf.String()) -} diff --git a/pkg/logs/jaeger.go b/pkg/logs/jaeger.go deleted file mode 100644 index 2faedc2fb..000000000 --- a/pkg/logs/jaeger.go +++ /dev/null @@ -1,23 +0,0 @@ -package logs - -import ( - "github.com/rs/zerolog" -) - -// JaegerLogger is an implementation of the Logger interface that delegates to traefik log. -type JaegerLogger struct { - logger zerolog.Logger -} - -func NewJaegerLogger(logger zerolog.Logger) *JaegerLogger { - return &JaegerLogger{logger: logger} -} - -func (l *JaegerLogger) Error(msg string) { - l.logger.Error().CallerSkipFrame(1).Msg(msg) -} - -// Infof logs a message at debug priority. -func (l *JaegerLogger) Infof(msg string, args ...interface{}) { - l.logger.Debug().CallerSkipFrame(1).Msgf(msg, args...) -} diff --git a/pkg/logs/jaeger_test.go b/pkg/logs/jaeger_test.go deleted file mode 100644 index 7ab6fe53d..000000000 --- a/pkg/logs/jaeger_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package logs - -import ( - "bytes" - "os" - "testing" - "time" - - "github.com/rs/zerolog" - "github.com/stretchr/testify/assert" -) - -func TestNewJaegerLogger(t *testing.T) { - buf := bytes.NewBuffer(nil) - cwb := zerolog.ConsoleWriter{Out: buf, TimeFormat: time.RFC3339, NoColor: true} - - out := zerolog.MultiLevelWriter(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}, cwb) - - logger := NewJaegerLogger(zerolog.New(out).With().Caller().Logger()) - - logger.Infof("foo") - - assert.Equal(t, " DBG jaeger_test.go:21 > foo\n", buf.String()) -} diff --git a/pkg/metrics/opentelemetry.go b/pkg/metrics/opentelemetry.go index a6c0c43e0..e866ff5e0 100644 --- a/pkg/metrics/opentelemetry.go +++ b/pkg/metrics/opentelemetry.go @@ -19,7 +19,7 @@ import ( "go.opentelemetry.io/otel/metric" sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" - semconv "go.opentelemetry.io/otel/semconv/v1.12.0" + semconv "go.opentelemetry.io/otel/semconv/v1.21.0" "google.golang.org/grpc/credentials" "google.golang.org/grpc/encoding/gzip" ) diff --git a/pkg/middlewares/addprefix/add_prefix.go b/pkg/middlewares/addprefix/add_prefix.go index 4363da9b9..e91facaf9 100644 --- a/pkg/middlewares/addprefix/add_prefix.go +++ b/pkg/middlewares/addprefix/add_prefix.go @@ -5,10 +5,9 @@ import ( "fmt" "net/http" - "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/middlewares" - "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/trace" ) const ( @@ -40,8 +39,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.AddPrefix, name return result, nil } -func (a *addPrefix) GetTracingInformation() (string, ext.SpanKindEnum) { - return a.name, tracing.SpanKindNoneEnum +func (a *addPrefix) GetTracingInformation() (string, string, trace.SpanKind) { + return a.name, typeName, trace.SpanKindInternal } func (a *addPrefix) ServeHTTP(rw http.ResponseWriter, req *http.Request) { diff --git a/pkg/middlewares/auth/basic_auth.go b/pkg/middlewares/auth/basic_auth.go index 70e25d3a1..5a3caa26d 100644 --- a/pkg/middlewares/auth/basic_auth.go +++ b/pkg/middlewares/auth/basic_auth.go @@ -8,15 +8,15 @@ import ( "strings" goauth "github.com/abbot/go-http-auth" - "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/middlewares" "github.com/traefik/traefik/v3/pkg/middlewares/accesslog" "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/trace" ) const ( - basicTypeName = "BasicAuth" + typeNameBasic = "BasicAuth" ) type basicAuth struct { @@ -30,7 +30,7 @@ type basicAuth struct { // NewBasic creates a basicAuth middleware. func NewBasic(ctx context.Context, next http.Handler, authConfig dynamic.BasicAuth, name string) (http.Handler, error) { - middlewares.GetLogger(ctx, name, basicTypeName).Debug().Msg("Creating middleware") + middlewares.GetLogger(ctx, name, typeNameBasic).Debug().Msg("Creating middleware") users, err := getUsers(authConfig.UsersFile, authConfig.Users, basicUserParser) if err != nil { @@ -55,12 +55,12 @@ func NewBasic(ctx context.Context, next http.Handler, authConfig dynamic.BasicAu return ba, nil } -func (b *basicAuth) GetTracingInformation() (string, ext.SpanKindEnum) { - return b.name, tracing.SpanKindNoneEnum +func (b *basicAuth) GetTracingInformation() (string, string, trace.SpanKind) { + return b.name, typeNameBasic, trace.SpanKindInternal } func (b *basicAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - logger := middlewares.GetLogger(req.Context(), b.name, basicTypeName) + logger := middlewares.GetLogger(req.Context(), b.name, typeNameBasic) user, password, ok := req.BasicAuth() if ok { @@ -77,7 +77,7 @@ func (b *basicAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if !ok { logger.Debug().Msg("Authentication failed") - tracing.SetErrorWithEvent(req, "Authentication failed") + tracing.SetStatusErrorf(req.Context(), "Authentication failed") b.auth.RequireAuth(rw, req) return diff --git a/pkg/middlewares/auth/digest_auth.go b/pkg/middlewares/auth/digest_auth.go index ea772aeb5..e02bc5883 100644 --- a/pkg/middlewares/auth/digest_auth.go +++ b/pkg/middlewares/auth/digest_auth.go @@ -8,15 +8,15 @@ import ( "strings" goauth "github.com/abbot/go-http-auth" - "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/middlewares" "github.com/traefik/traefik/v3/pkg/middlewares/accesslog" "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/trace" ) const ( - digestTypeName = "digestAuth" + typeNameDigest = "digestAuth" ) type digestAuth struct { @@ -30,7 +30,7 @@ type digestAuth struct { // NewDigest creates a digest auth middleware. func NewDigest(ctx context.Context, next http.Handler, authConfig dynamic.DigestAuth, name string) (http.Handler, error) { - middlewares.GetLogger(ctx, name, digestTypeName).Debug().Msg("Creating middleware") + middlewares.GetLogger(ctx, name, typeNameDigest).Debug().Msg("Creating middleware") users, err := getUsers(authConfig.UsersFile, authConfig.Users, digestUserParser) if err != nil { @@ -54,12 +54,12 @@ func NewDigest(ctx context.Context, next http.Handler, authConfig dynamic.Digest return da, nil } -func (d *digestAuth) GetTracingInformation() (string, ext.SpanKindEnum) { - return d.name, tracing.SpanKindNoneEnum +func (d *digestAuth) GetTracingInformation() (string, string, trace.SpanKind) { + return d.name, typeNameDigest, trace.SpanKindInternal } func (d *digestAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - logger := middlewares.GetLogger(req.Context(), d.name, digestTypeName) + logger := middlewares.GetLogger(req.Context(), d.name, typeNameDigest) username, authinfo := d.auth.CheckAuth(req) if username == "" { @@ -78,13 +78,13 @@ func (d *digestAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if authinfo != nil && *authinfo == "stale" { logger.Debug().Msg("Digest authentication failed, possibly because out of order requests") - tracing.SetErrorWithEvent(req, "Digest authentication failed, possibly because out of order requests") + tracing.SetStatusErrorf(req.Context(), "Digest authentication failed, possibly because out of order requests") d.auth.RequireAuthStale(rw, req) return } logger.Debug().Msg("Digest authentication failed") - tracing.SetErrorWithEvent(req, "Digest authentication failed") + tracing.SetStatusErrorf(req.Context(), "Digest authentication failed") d.auth.RequireAuth(rw, req) return } diff --git a/pkg/middlewares/auth/forward.go b/pkg/middlewares/auth/forward.go index b19e37a6f..f93137469 100644 --- a/pkg/middlewares/auth/forward.go +++ b/pkg/middlewares/auth/forward.go @@ -11,21 +11,22 @@ import ( "strings" "time" - "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/middlewares" "github.com/traefik/traefik/v3/pkg/middlewares/connectionheader" "github.com/traefik/traefik/v3/pkg/tracing" "github.com/vulcand/oxy/v2/forward" "github.com/vulcand/oxy/v2/utils" + "go.opentelemetry.io/otel/trace" ) const ( - xForwardedURI = "X-Forwarded-Uri" - xForwardedMethod = "X-Forwarded-Method" - forwardedTypeName = "ForwardedAuthType" + xForwardedURI = "X-Forwarded-Uri" + xForwardedMethod = "X-Forwarded-Method" ) +const typeNameForward = "ForwardAuth" + // hopHeaders Hop-by-hop headers to be removed in the authentication request. // http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html // Proxy-Authorization header is forwarded to the authentication server (see https://tools.ietf.org/html/rfc7235#section-4.4). @@ -51,7 +52,7 @@ type forwardAuth struct { // NewForward creates a forward auth middleware. func NewForward(ctx context.Context, next http.Handler, config dynamic.ForwardAuth, name string) (http.Handler, error) { - middlewares.GetLogger(ctx, name, forwardedTypeName).Debug().Msg("Creating middleware") + middlewares.GetLogger(ctx, name, typeNameForward).Debug().Msg("Creating middleware") fa := &forwardAuth{ address: config.Address, @@ -89,30 +90,38 @@ func NewForward(ctx context.Context, next http.Handler, config dynamic.ForwardAu fa.authResponseHeadersRegex = re } - return connectionheader.Remover(fa), nil + return fa, nil } -func (fa *forwardAuth) GetTracingInformation() (string, ext.SpanKindEnum) { - return fa.name, ext.SpanKindRPCClientEnum +func (fa *forwardAuth) GetTracingInformation() (string, string, trace.SpanKind) { + return fa.name, typeNameForward, trace.SpanKindInternal } func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - logger := middlewares.GetLogger(req.Context(), fa.name, forwardedTypeName) + logger := middlewares.GetLogger(req.Context(), fa.name, typeNameForward) - forwardReq, err := http.NewRequest(http.MethodGet, fa.address, nil) - tracing.LogRequest(tracing.GetSpan(req), forwardReq) + req = connectionheader.Remove(req) + + forwardReq, err := http.NewRequestWithContext(req.Context(), http.MethodGet, fa.address, nil) if err != nil { logMessage := fmt.Sprintf("Error calling %s. Cause %s", fa.address, err) logger.Debug().Msg(logMessage) - tracing.SetErrorWithEvent(req, logMessage) - + tracing.SetStatusErrorf(req.Context(), logMessage) rw.WriteHeader(http.StatusInternalServerError) return } - // Ensure tracing headers are in the request before we copy the headers to the - // forwardReq. - tracing.InjectRequestHeaders(req) + var forwardSpan trace.Span + if tracer := tracing.TracerFromContext(req.Context()); tracer != nil { + var tracingCtx context.Context + tracingCtx, forwardSpan = tracer.Start(req.Context(), "AuthRequest", trace.WithSpanKind(trace.SpanKindClient)) + defer forwardSpan.End() + + forwardReq = forwardReq.WithContext(tracingCtx) + + tracing.InjectContextIntoCarrier(forwardReq) + tracing.LogClientRequest(forwardSpan, forwardReq) + } writeHeader(req, forwardReq, fa.trustForwardHeader, fa.authRequestHeaders) @@ -120,7 +129,7 @@ func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if forwardErr != nil { logMessage := fmt.Sprintf("Error calling %s. Cause: %s", fa.address, forwardErr) logger.Debug().Msg(logMessage) - tracing.SetErrorWithEvent(req, logMessage) + tracing.SetStatusErrorf(forwardReq.Context(), logMessage) rw.WriteHeader(http.StatusInternalServerError) return @@ -131,12 +140,18 @@ func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if readError != nil { logMessage := fmt.Sprintf("Error reading body %s. Cause: %s", fa.address, readError) logger.Debug().Msg(logMessage) - tracing.SetErrorWithEvent(req, logMessage) + tracing.SetStatusErrorf(forwardReq.Context(), logMessage) rw.WriteHeader(http.StatusInternalServerError) return } + // Ending the forward request span as soon as the response is handled. + // If any errors happen earlier, this span will be close by the defer instruction. + if forwardSpan != nil { + forwardSpan.End() + } + // Pass the forward response's body and selected headers if it // didn't return a response within the range of [200, 300). if forwardResponse.StatusCode < http.StatusOK || forwardResponse.StatusCode >= http.StatusMultipleChoices { @@ -152,7 +167,7 @@ func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if !errors.Is(err, http.ErrNoLocation) { logMessage := fmt.Sprintf("Error reading response location header %s. Cause: %s", fa.address, err) logger.Debug().Msg(logMessage) - tracing.SetErrorWithEvent(req, logMessage) + tracing.SetStatusErrorf(forwardReq.Context(), logMessage) rw.WriteHeader(http.StatusInternalServerError) return @@ -162,7 +177,7 @@ func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { rw.Header().Set("Location", redirectURL.String()) } - tracing.LogResponseCode(tracing.GetSpan(req), forwardResponse.StatusCode) + tracing.LogResponseCode(forwardSpan, forwardResponse.StatusCode, trace.SpanKindClient) rw.WriteHeader(forwardResponse.StatusCode) if _, err = rw.Write(body); err != nil { @@ -193,6 +208,8 @@ func (fa *forwardAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } } + tracing.LogResponseCode(forwardSpan, forwardResponse.StatusCode, trace.SpanKindClient) + req.RequestURI = req.URL.RequestURI() fa.next.ServeHTTP(rw, req) } diff --git a/pkg/middlewares/auth/forward_test.go b/pkg/middlewares/auth/forward_test.go index 0f300fc71..e3afd6882 100644 --- a/pkg/middlewares/auth/forward_test.go +++ b/pkg/middlewares/auth/forward_test.go @@ -8,15 +8,22 @@ import ( "net/http/httptest" "testing" - "github.com/opentracing/opentracing-go" - "github.com/opentracing/opentracing-go/mocktracer" + "github.com/containous/alice" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/traefik/traefik/v3/pkg/config/dynamic" + "github.com/traefik/traefik/v3/pkg/config/static" tracingMiddleware "github.com/traefik/traefik/v3/pkg/middlewares/tracing" "github.com/traefik/traefik/v3/pkg/testhelpers" "github.com/traefik/traefik/v3/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/tracing/opentelemetry" + "github.com/traefik/traefik/v3/pkg/version" "github.com/vulcand/oxy/v2/forward" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + "go.opentelemetry.io/otel/sdk/trace/tracetest" + semconv "go.opentelemetry.io/otel/semconv/v1.21.0" ) func TestForwardAuthFail(t *testing.T) { @@ -452,8 +459,8 @@ func Test_writeHeader(t *testing.T) { func TestForwardAuthUsesTracing(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Header.Get("Mockpfx-Ids-Traceid") == "" { - t.Errorf("expected Mockpfx-Ids-Traceid header to be present in request") + if r.Header.Get("Traceparent") == "" { + t.Errorf("expected Traceparent header to be present in request") } })) t.Cleanup(server.Close) @@ -464,15 +471,44 @@ func TestForwardAuthUsesTracing(t *testing.T) { Address: server.URL, } - tracer := mocktracer.New() - opentracing.SetGlobalTracer(tracer) + exporter := tracetest.NewInMemoryExporter() - tr, _ := tracing.NewTracing("testApp", 100, &mockBackend{tracer}) - - next, err := NewForward(context.Background(), next, auth, "authTest") + tres, err := resource.New(context.Background(), + resource.WithAttributes(semconv.ServiceNameKey.String("traefik")), + resource.WithAttributes(semconv.ServiceVersionKey.String(version.Version)), + resource.WithFromEnv(), + resource.WithTelemetrySDK(), + ) require.NoError(t, err) - next = tracingMiddleware.NewEntryPoint(context.Background(), tr, "tracingTest", next) + tracerProvider := sdktrace.NewTracerProvider( + sdktrace.WithSampler(sdktrace.AlwaysSample()), + sdktrace.WithResource(tres), + sdktrace.WithBatcher(exporter), + ) + otel.SetTracerProvider(tracerProvider) + + config := &static.Tracing{ + ServiceName: "testApp", + SampleRate: 1, + OTLP: &opentelemetry.Config{ + HTTP: &opentelemetry.HTTP{ + Endpoint: "http://127.0.0.1:8080", + }, + }, + } + tr, closer, err := tracing.NewTracing(config) + require.NoError(t, err) + t.Cleanup(func() { + _ = closer.Close() + }) + + next, err = NewForward(context.Background(), next, auth, "authTest") + require.NoError(t, err) + + chain := alice.New(tracingMiddleware.WrapEntryPointHandler(context.Background(), tr, "tracingTest")) + next, err = chain.Then(next) + require.NoError(t, err) ts := httptest.NewServer(next) t.Cleanup(ts.Close) @@ -482,11 +518,3 @@ func TestForwardAuthUsesTracing(t *testing.T) { require.NoError(t, err) assert.Equal(t, http.StatusOK, res.StatusCode) } - -type mockBackend struct { - opentracing.Tracer -} - -func (b *mockBackend) Setup(componentName string) (opentracing.Tracer, io.Closer, error) { - return b.Tracer, io.NopCloser(nil), nil -} diff --git a/pkg/middlewares/buffering/buffering.go b/pkg/middlewares/buffering/buffering.go index 6aa2ed562..ec9100a98 100644 --- a/pkg/middlewares/buffering/buffering.go +++ b/pkg/middlewares/buffering/buffering.go @@ -4,13 +4,12 @@ import ( "context" "net/http" - "github.com/opentracing/opentracing-go/ext" "github.com/rs/zerolog" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/logs" "github.com/traefik/traefik/v3/pkg/middlewares" - "github.com/traefik/traefik/v3/pkg/tracing" oxybuffer "github.com/vulcand/oxy/v2/buffer" + "go.opentelemetry.io/otel/trace" ) const ( @@ -49,8 +48,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.Buffering, name }, nil } -func (b *buffer) GetTracingInformation() (string, ext.SpanKindEnum) { - return b.name, tracing.SpanKindNoneEnum +func (b *buffer) GetTracingInformation() (string, string, trace.SpanKind) { + return b.name, typeName, trace.SpanKindInternal } func (b *buffer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { diff --git a/pkg/middlewares/circuitbreaker/circuit_breaker.go b/pkg/middlewares/circuitbreaker/circuit_breaker.go index 8445b45b8..3fa06ba23 100644 --- a/pkg/middlewares/circuitbreaker/circuit_breaker.go +++ b/pkg/middlewares/circuitbreaker/circuit_breaker.go @@ -5,7 +5,6 @@ import ( "net/http" "time" - "github.com/opentracing/opentracing-go/ext" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/traefik/traefik/v3/pkg/config/dynamic" @@ -13,6 +12,7 @@ import ( "github.com/traefik/traefik/v3/pkg/middlewares" "github.com/traefik/traefik/v3/pkg/tracing" "github.com/vulcand/oxy/v2/cbreaker" + "go.opentelemetry.io/otel/trace" ) const typeName = "CircuitBreaker" @@ -32,7 +32,7 @@ func New(ctx context.Context, next http.Handler, confCircuitBreaker dynamic.Circ cbOpts := []cbreaker.Option{ cbreaker.Fallback(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - tracing.SetErrorWithEvent(req, "blocked by circuit-breaker (%q)", expression) + tracing.SetStatusErrorf(req.Context(), "blocked by circuit-breaker (%q)", expression) rw.WriteHeader(http.StatusServiceUnavailable) if _, err := rw.Write([]byte(http.StatusText(http.StatusServiceUnavailable))); err != nil { @@ -66,8 +66,8 @@ func New(ctx context.Context, next http.Handler, confCircuitBreaker dynamic.Circ }, nil } -func (c *circuitBreaker) GetTracingInformation() (string, ext.SpanKindEnum) { - return c.name, tracing.SpanKindNoneEnum +func (c *circuitBreaker) GetTracingInformation() (string, string, trace.SpanKind) { + return c.name, typeName, trace.SpanKindInternal } func (c *circuitBreaker) ServeHTTP(rw http.ResponseWriter, req *http.Request) { diff --git a/pkg/middlewares/compress/compress.go b/pkg/middlewares/compress/compress.go index adc346237..b7ae85b4d 100644 --- a/pkg/middlewares/compress/compress.go +++ b/pkg/middlewares/compress/compress.go @@ -9,11 +9,10 @@ import ( "strings" "github.com/klauspost/compress/gzhttp" - "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/middlewares" "github.com/traefik/traefik/v3/pkg/middlewares/compress/brotli" - "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/trace" ) const typeName = "Compress" @@ -114,8 +113,8 @@ func (c *compress) ServeHTTP(rw http.ResponseWriter, req *http.Request) { c.next.ServeHTTP(rw, req) } -func (c *compress) GetTracingInformation() (string, ext.SpanKindEnum) { - return c.name, tracing.SpanKindNoneEnum +func (c *compress) GetTracingInformation() (string, string, trace.SpanKind) { + return c.name, typeName, trace.SpanKindInternal } func (c *compress) newGzipHandler() (http.Handler, error) { diff --git a/pkg/middlewares/connectionheader/connectionheader.go b/pkg/middlewares/connectionheader/connectionheader.go index b7a64910a..12a994f17 100644 --- a/pkg/middlewares/connectionheader/connectionheader.go +++ b/pkg/middlewares/connectionheader/connectionheader.go @@ -17,24 +17,29 @@ const ( // See RFC 7230, section 6.1. func Remover(next http.Handler) http.HandlerFunc { return func(rw http.ResponseWriter, req *http.Request) { - var reqUpType string - if httpguts.HeaderValuesContainsToken(req.Header[connectionHeader], upgradeHeader) { - reqUpType = req.Header.Get(upgradeHeader) - } - - removeConnectionHeaders(req.Header) - - if reqUpType != "" { - req.Header.Set(connectionHeader, upgradeHeader) - req.Header.Set(upgradeHeader, reqUpType) - } else { - req.Header.Del(connectionHeader) - } - - next.ServeHTTP(rw, req) + next.ServeHTTP(rw, Remove(req)) } } +// Remove removes hop-by-hop header on the request. +func Remove(req *http.Request) *http.Request { + var reqUpType string + if httpguts.HeaderValuesContainsToken(req.Header[connectionHeader], upgradeHeader) { + reqUpType = req.Header.Get(upgradeHeader) + } + + removeConnectionHeaders(req.Header) + + if reqUpType != "" { + req.Header.Set(connectionHeader, upgradeHeader) + req.Header.Set(upgradeHeader, reqUpType) + } else { + req.Header.Del(connectionHeader) + } + + return req +} + func removeConnectionHeaders(h http.Header) { for _, f := range h[connectionHeader] { for _, sf := range strings.Split(f, ",") { diff --git a/pkg/middlewares/customerrors/custom_errors.go b/pkg/middlewares/customerrors/custom_errors.go index 2d71e751d..dd1f77e33 100644 --- a/pkg/middlewares/customerrors/custom_errors.go +++ b/pkg/middlewares/customerrors/custom_errors.go @@ -10,12 +10,12 @@ import ( "strconv" "strings" - "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/middlewares" "github.com/traefik/traefik/v3/pkg/tracing" "github.com/traefik/traefik/v3/pkg/types" "github.com/vulcand/oxy/v2/utils" + "go.opentelemetry.io/otel/trace" ) // Compile time validation that the response recorder implements http interfaces correctly. @@ -24,7 +24,7 @@ var ( _ middlewares.Stateful = &codeCatcher{} ) -const typeName = "customError" +const typeName = "CustomError" type serviceBuilder interface { BuildHTTP(ctx context.Context, serviceName string) (http.Handler, error) @@ -62,8 +62,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.ErrorPage, servi }, nil } -func (c *customErrors) GetTracingInformation() (string, ext.SpanKindEnum) { - return c.name, tracing.SpanKindNoneEnum +func (c *customErrors) GetTracingInformation() (string, string, trace.SpanKind) { + return c.name, typeName, trace.SpanKindInternal } func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) { @@ -71,7 +71,7 @@ func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if c.backendHandler == nil { logger.Error().Msg("Error pages: no backend handler.") - tracing.SetErrorWithEvent(req, "Error pages: no backend handler.") + tracing.SetStatusErrorf(req.Context(), "Error pages: no backend handler.") c.next.ServeHTTP(rw, req) return } @@ -96,12 +96,12 @@ func (c *customErrors) ServeHTTP(rw http.ResponseWriter, req *http.Request) { pageReq, err := newRequest("http://" + req.Host + query) if err != nil { logger.Error().Err(err).Send() + tracing.SetStatusErrorf(req.Context(), err.Error()) http.Error(rw, http.StatusText(code), code) return } utils.CopyHeaders(pageReq.Header, req.Header) - c.backendHandler.ServeHTTP(newCodeModifier(rw, code), pageReq.WithContext(req.Context())) } diff --git a/pkg/middlewares/grpcweb/grpcweb.go b/pkg/middlewares/grpcweb/grpcweb.go index 18fe108eb..1d32b5273 100644 --- a/pkg/middlewares/grpcweb/grpcweb.go +++ b/pkg/middlewares/grpcweb/grpcweb.go @@ -9,7 +9,7 @@ import ( "github.com/traefik/traefik/v3/pkg/middlewares" ) -const typeName = "grpc-web" +const typeName = "GRPCWeb" // New builds a new gRPC web request converter. func New(ctx context.Context, next http.Handler, config dynamic.GrpcWeb, name string) http.Handler { diff --git a/pkg/middlewares/headers/headers.go b/pkg/middlewares/headers/headers.go index 1210f6711..e393aa1a6 100644 --- a/pkg/middlewares/headers/headers.go +++ b/pkg/middlewares/headers/headers.go @@ -6,11 +6,10 @@ import ( "errors" "net/http" - "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/middlewares" "github.com/traefik/traefik/v3/pkg/middlewares/connectionheader" - "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/trace" ) const ( @@ -61,8 +60,8 @@ func New(ctx context.Context, next http.Handler, cfg dynamic.Headers, name strin }, nil } -func (h *headers) GetTracingInformation() (string, ext.SpanKindEnum) { - return h.name, tracing.SpanKindNoneEnum +func (h *headers) GetTracingInformation() (string, string, trace.SpanKind) { + return h.name, typeName, trace.SpanKindInternal } func (h *headers) ServeHTTP(rw http.ResponseWriter, req *http.Request) { diff --git a/pkg/middlewares/headers/headers_test.go b/pkg/middlewares/headers/headers_test.go index 61cf3779a..8e365ab54 100644 --- a/pkg/middlewares/headers/headers_test.go +++ b/pkg/middlewares/headers/headers_test.go @@ -14,7 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/traefik/traefik/v3/pkg/config/dynamic" - "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/trace" ) func TestNew_withoutOptions(t *testing.T) { @@ -109,10 +109,11 @@ func Test_headers_getTracingInformation(t *testing.T) { name: "testing", } - name, trace := mid.GetTracingInformation() + name, typeName, spanKind := mid.GetTracingInformation() assert.Equal(t, "testing", name) - assert.Equal(t, tracing.SpanKindNoneEnum, trace) + assert.Equal(t, "Headers", typeName) + assert.Equal(t, trace.SpanKindInternal, spanKind) } // This test is an adapted version of net/http/httputil.Test1xxResponses test. diff --git a/pkg/middlewares/inflightreq/inflight_req.go b/pkg/middlewares/inflightreq/inflight_req.go index a6fcdf101..c05193607 100644 --- a/pkg/middlewares/inflightreq/inflight_req.go +++ b/pkg/middlewares/inflightreq/inflight_req.go @@ -5,13 +5,12 @@ import ( "fmt" "net/http" - "github.com/opentracing/opentracing-go/ext" "github.com/rs/zerolog" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/logs" "github.com/traefik/traefik/v3/pkg/middlewares" - "github.com/traefik/traefik/v3/pkg/tracing" "github.com/vulcand/oxy/v2/connlimit" + "go.opentelemetry.io/otel/trace" ) const ( @@ -54,8 +53,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.InFlightReq, nam return &inFlightReq{handler: handler, name: name}, nil } -func (i *inFlightReq) GetTracingInformation() (string, ext.SpanKindEnum) { - return i.name, tracing.SpanKindNoneEnum +func (i *inFlightReq) GetTracingInformation() (string, string, trace.SpanKind) { + return i.name, typeName, trace.SpanKindInternal } func (i *inFlightReq) ServeHTTP(rw http.ResponseWriter, req *http.Request) { diff --git a/pkg/middlewares/ipallowlist/ip_allowlist.go b/pkg/middlewares/ipallowlist/ip_allowlist.go index e888d5d92..ddd7bfe47 100644 --- a/pkg/middlewares/ipallowlist/ip_allowlist.go +++ b/pkg/middlewares/ipallowlist/ip_allowlist.go @@ -6,12 +6,12 @@ import ( "fmt" "net/http" - "github.com/opentracing/opentracing-go/ext" "github.com/rs/zerolog/log" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/ip" "github.com/traefik/traefik/v3/pkg/middlewares" "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/trace" ) const ( @@ -55,8 +55,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.IPAllowList, nam }, nil } -func (al *ipAllowLister) GetTracingInformation() (string, ext.SpanKindEnum) { - return al.name, tracing.SpanKindNoneEnum +func (al *ipAllowLister) GetTracingInformation() (string, string, trace.SpanKind) { + return al.name, typeName, trace.SpanKindInternal } func (al *ipAllowLister) ServeHTTP(rw http.ResponseWriter, req *http.Request) { @@ -68,7 +68,7 @@ func (al *ipAllowLister) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if err != nil { msg := fmt.Sprintf("Rejecting IP %s: %v", clientIP, err) logger.Debug().Msg(msg) - tracing.SetErrorWithEvent(req, msg) + tracing.SetStatusErrorf(req.Context(), msg) reject(ctx, rw) return } diff --git a/pkg/middlewares/metrics/metrics.go b/pkg/middlewares/metrics/metrics.go index 64a09db17..a61da207e 100644 --- a/pkg/middlewares/metrics/metrics.go +++ b/pkg/middlewares/metrics/metrics.go @@ -16,6 +16,8 @@ import ( "github.com/traefik/traefik/v3/pkg/middlewares/capture" "github.com/traefik/traefik/v3/pkg/middlewares/retry" traefiktls "github.com/traefik/traefik/v3/pkg/tls" + "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/trace" "google.golang.org/grpc/codes" ) @@ -39,6 +41,7 @@ type metricsMiddleware struct { reqsBytesCounter gokitmetrics.Counter respsBytesCounter gokitmetrics.Counter baseLabels []string + name string } // NewEntryPointMiddleware creates a new metrics middleware for an Entrypoint. @@ -53,6 +56,7 @@ func NewEntryPointMiddleware(ctx context.Context, next http.Handler, registry me reqsBytesCounter: registry.EntryPointReqsBytesCounter(), respsBytesCounter: registry.EntryPointRespsBytesCounter(), baseLabels: []string{"entrypoint", entryPointName}, + name: nameEntrypoint, } } @@ -68,6 +72,7 @@ func NewRouterMiddleware(ctx context.Context, next http.Handler, registry metric reqsBytesCounter: registry.RouterReqsBytesCounter(), respsBytesCounter: registry.RouterRespsBytesCounter(), baseLabels: []string{"router", routerName, "service", serviceName}, + name: nameRouter, } } @@ -83,6 +88,7 @@ func NewServiceMiddleware(ctx context.Context, next http.Handler, registry metri reqsBytesCounter: registry.ServiceReqsBytesCounter(), respsBytesCounter: registry.ServiceRespsBytesCounter(), baseLabels: []string{"service", serviceName}, + name: nameService, } } @@ -100,6 +106,17 @@ func WrapRouterHandler(ctx context.Context, registry metrics.Registry, routerNam } } +// WrapServiceHandler Wraps metrics service to alice.Constructor. +func WrapServiceHandler(ctx context.Context, registry metrics.Registry, serviceName string) alice.Constructor { + return func(next http.Handler) (http.Handler, error) { + return NewServiceMiddleware(ctx, next, registry, serviceName), nil + } +} + +func (m *metricsMiddleware) GetTracingInformation() (string, string, trace.SpanKind) { + return m.name, typeName, trace.SpanKindInternal +} + func (m *metricsMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Request) { proto := getRequestProtocol(req) @@ -127,6 +144,7 @@ func (m *metricsMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Request) } logger := with.Logger() logger.Error().Err(err).Msg("Could not get Capture") + tracing.SetStatusErrorf(req.Context(), "Could not get Capture") return } diff --git a/pkg/middlewares/passtlsclientcert/pass_tls_client_cert.go b/pkg/middlewares/passtlsclientcert/pass_tls_client_cert.go index 94367ce28..77f1cd09d 100644 --- a/pkg/middlewares/passtlsclientcert/pass_tls_client_cert.go +++ b/pkg/middlewares/passtlsclientcert/pass_tls_client_cert.go @@ -11,11 +11,10 @@ import ( "net/url" "strings" - "github.com/opentracing/opentracing-go/ext" "github.com/rs/zerolog/log" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/middlewares" - "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/trace" ) const typeName = "PassClientTLSCert" @@ -140,8 +139,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.PassTLSClientCer }, nil } -func (p *passTLSClientCert) GetTracingInformation() (string, ext.SpanKindEnum) { - return p.name, tracing.SpanKindNoneEnum +func (p *passTLSClientCert) GetTracingInformation() (string, string, trace.SpanKind) { + return p.name, typeName, trace.SpanKindInternal } func (p *passTLSClientCert) ServeHTTP(rw http.ResponseWriter, req *http.Request) { diff --git a/pkg/middlewares/ratelimiter/rate_limiter.go b/pkg/middlewares/ratelimiter/rate_limiter.go index 1c3582c4e..fcede7dce 100644 --- a/pkg/middlewares/ratelimiter/rate_limiter.go +++ b/pkg/middlewares/ratelimiter/rate_limiter.go @@ -9,17 +9,17 @@ import ( "time" "github.com/mailgun/ttlmap" - "github.com/opentracing/opentracing-go/ext" "github.com/rs/zerolog/log" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/middlewares" "github.com/traefik/traefik/v3/pkg/tracing" "github.com/vulcand/oxy/v2/utils" + "go.opentelemetry.io/otel/trace" "golang.org/x/time/rate" ) const ( - typeName = "RateLimiterType" + typeName = "RateLimiter" maxSources = 65536 ) @@ -122,8 +122,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.RateLimit, name }, nil } -func (rl *rateLimiter) GetTracingInformation() (string, ext.SpanKindEnum) { - return rl.name, tracing.SpanKindNoneEnum +func (rl *rateLimiter) GetTracingInformation() (string, string, trace.SpanKind) { + return rl.name, typeName, trace.SpanKindInternal } func (rl *rateLimiter) ServeHTTP(rw http.ResponseWriter, req *http.Request) { @@ -153,12 +153,14 @@ func (rl *rateLimiter) ServeHTTP(rw http.ResponseWriter, req *http.Request) { // as the expiryTime is supposed to reflect the activity (or lack thereof) on that source. if err := rl.buckets.Set(source, bucket, rl.ttl); err != nil { logger.Error().Err(err).Msg("Could not insert/update bucket") + tracing.SetStatusErrorf(req.Context(), "Could not insert/update bucket") http.Error(rw, "could not insert/update bucket", http.StatusInternalServerError) return } res := bucket.Reserve() if !res.OK() { + tracing.SetStatusErrorf(req.Context(), "No bursty traffic allowed") http.Error(rw, "No bursty traffic allowed", http.StatusTooManyRequests) return } diff --git a/pkg/middlewares/redirect/redirect.go b/pkg/middlewares/redirect/redirect.go index d64d8cd70..25ca6a2ac 100644 --- a/pkg/middlewares/redirect/redirect.go +++ b/pkg/middlewares/redirect/redirect.go @@ -5,9 +5,8 @@ import ( "net/url" "regexp" - "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v3/pkg/tracing" "github.com/vulcand/oxy/v2/utils" + "go.opentelemetry.io/otel/trace" ) const ( @@ -15,6 +14,8 @@ const ( schemeHTTPS = "https" ) +const typeName = "Redirect" + var uriRegexp = regexp.MustCompile(`^(https?):\/\/(\[[\w:.]+\]|[\w\._-]+)?(:\d+)?(.*)$`) type redirect struct { @@ -45,8 +46,8 @@ func newRedirect(next http.Handler, regex, replacement string, permanent bool, r }, nil } -func (r *redirect) GetTracingInformation() (string, ext.SpanKindEnum) { - return r.name, tracing.SpanKindNoneEnum +func (r *redirect) GetTracingInformation() (string, string, trace.SpanKind) { + return r.name, typeName, trace.SpanKindInternal } func (r *redirect) ServeHTTP(rw http.ResponseWriter, req *http.Request) { diff --git a/pkg/middlewares/replacepath/replace_path.go b/pkg/middlewares/replacepath/replace_path.go index 9f6fea443..3419d7b83 100644 --- a/pkg/middlewares/replacepath/replace_path.go +++ b/pkg/middlewares/replacepath/replace_path.go @@ -5,10 +5,10 @@ import ( "net/http" "net/url" - "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/middlewares" "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/trace" ) const ( @@ -35,8 +35,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.ReplacePath, nam }, nil } -func (r *replacePath) GetTracingInformation() (string, ext.SpanKindEnum) { - return r.name, tracing.SpanKindNoneEnum +func (r *replacePath) GetTracingInformation() (string, string, trace.SpanKind) { + return r.name, typeName, trace.SpanKindInternal } func (r *replacePath) ServeHTTP(rw http.ResponseWriter, req *http.Request) { @@ -52,6 +52,7 @@ func (r *replacePath) ServeHTTP(rw http.ResponseWriter, req *http.Request) { req.URL.Path, err = url.PathUnescape(req.URL.RawPath) if err != nil { middlewares.GetLogger(context.Background(), r.name, typeName).Error().Err(err).Send() + tracing.SetStatusErrorf(req.Context(), err.Error()) http.Error(rw, err.Error(), http.StatusInternalServerError) return } diff --git a/pkg/middlewares/replacepathregex/replace_path_regex.go b/pkg/middlewares/replacepathregex/replace_path_regex.go index 1fffb6bd4..ff800d354 100644 --- a/pkg/middlewares/replacepathregex/replace_path_regex.go +++ b/pkg/middlewares/replacepathregex/replace_path_regex.go @@ -8,11 +8,11 @@ import ( "regexp" "strings" - "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/middlewares" "github.com/traefik/traefik/v3/pkg/middlewares/replacepath" "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/trace" ) const typeName = "ReplacePathRegex" @@ -42,8 +42,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.ReplacePathRegex }, nil } -func (rp *replacePathRegex) GetTracingInformation() (string, ext.SpanKindEnum) { - return rp.name, tracing.SpanKindNoneEnum +func (rp *replacePathRegex) GetTracingInformation() (string, string, trace.SpanKind) { + return rp.name, typeName, trace.SpanKindInternal } func (rp *replacePathRegex) ServeHTTP(rw http.ResponseWriter, req *http.Request) { @@ -63,6 +63,7 @@ func (rp *replacePathRegex) ServeHTTP(rw http.ResponseWriter, req *http.Request) req.URL.Path, err = url.PathUnescape(req.URL.RawPath) if err != nil { middlewares.GetLogger(context.Background(), rp.name, typeName).Error().Err(err).Send() + tracing.SetStatusErrorf(req.Context(), err.Error()) http.Error(rw, err.Error(), http.StatusInternalServerError) return } diff --git a/pkg/middlewares/retry/retry.go b/pkg/middlewares/retry/retry.go index 68bfdadd4..f8945a989 100644 --- a/pkg/middlewares/retry/retry.go +++ b/pkg/middlewares/retry/retry.go @@ -12,10 +12,12 @@ import ( "time" "github.com/cenkalti/backoff/v4" - "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/middlewares" "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/attribute" + semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + "go.opentelemetry.io/otel/trace" ) // Compile time validation that the response writer implements http interfaces correctly. @@ -60,10 +62,6 @@ func New(ctx context.Context, next http.Handler, config dynamic.Retry, listener }, nil } -func (r *retry) GetTracingInformation() (string, ext.SpanKindEnum) { - return r.name, tracing.SpanKindNoneEnum -} - func (r *retry) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if r.attempts == 1 { r.next.ServeHTTP(rw, req) @@ -79,12 +77,35 @@ func (r *retry) ServeHTTP(rw http.ResponseWriter, req *http.Request) { attempts := 1 + initialCtx := req.Context() + tracer := tracing.TracerFromContext(initialCtx) + + var currentSpan trace.Span operation := func() error { + if tracer != nil { + if currentSpan != nil { + currentSpan.End() + } + // Because multiple tracing spans may need to be created, + // the Retry middleware does not implement trace.Traceable, + // and creates directly a new span for each retry operation. + var tracingCtx context.Context + tracingCtx, currentSpan = tracer.Start(initialCtx, typeName, trace.WithSpanKind(trace.SpanKindInternal)) + + currentSpan.SetAttributes(attribute.String("traefik.middleware.name", r.name)) + // Only add the attribute "http.resend_count" defined by semantic conventions starting from second attempt. + if attempts > 1 { + currentSpan.SetAttributes(semconv.HTTPResendCount(attempts - 1)) + } + + req = req.WithContext(tracingCtx) + } + shouldRetry := attempts < r.attempts retryResponseWriter := newResponseWriter(rw, shouldRetry) // Disable retries when the backend already received request data - trace := &httptrace.ClientTrace{ + clientTrace := &httptrace.ClientTrace{ WroteHeaders: func() { retryResponseWriter.DisableRetries() }, @@ -92,7 +113,7 @@ func (r *retry) ServeHTTP(rw http.ResponseWriter, req *http.Request) { retryResponseWriter.DisableRetries() }, } - newCtx := httptrace.WithClientTrace(req.Context(), trace) + newCtx := httptrace.WithClientTrace(req.Context(), clientTrace) r.next.ServeHTTP(retryResponseWriter, req.Clone(newCtx)) @@ -119,6 +140,10 @@ func (r *retry) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if err != nil { logger.Debug().Err(err).Msg("Final retry attempt failed") } + + if currentSpan != nil { + currentSpan.End() + } } func (r *retry) newBackOff() backoff.BackOff { diff --git a/pkg/middlewares/stripprefix/strip_prefix.go b/pkg/middlewares/stripprefix/strip_prefix.go index a017c051f..18717875e 100644 --- a/pkg/middlewares/stripprefix/strip_prefix.go +++ b/pkg/middlewares/stripprefix/strip_prefix.go @@ -5,10 +5,9 @@ import ( "net/http" "strings" - "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/middlewares" - "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/trace" ) const ( @@ -34,8 +33,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.StripPrefix, nam }, nil } -func (s *stripPrefix) GetTracingInformation() (string, ext.SpanKindEnum) { - return s.name, tracing.SpanKindNoneEnum +func (s *stripPrefix) GetTracingInformation() (string, string, trace.SpanKind) { + return s.name, typeName, trace.SpanKindUnspecified } func (s *stripPrefix) ServeHTTP(rw http.ResponseWriter, req *http.Request) { diff --git a/pkg/middlewares/stripprefixregex/strip_prefix_regex.go b/pkg/middlewares/stripprefixregex/strip_prefix_regex.go index 383ce1f01..71de1ad28 100644 --- a/pkg/middlewares/stripprefixregex/strip_prefix_regex.go +++ b/pkg/middlewares/stripprefixregex/strip_prefix_regex.go @@ -6,11 +6,10 @@ import ( "regexp" "strings" - "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/middlewares" "github.com/traefik/traefik/v3/pkg/middlewares/stripprefix" - "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/trace" ) const ( @@ -44,8 +43,8 @@ func New(ctx context.Context, next http.Handler, config dynamic.StripPrefixRegex return &stripPrefix, nil } -func (s *stripPrefixRegex) GetTracingInformation() (string, ext.SpanKindEnum) { - return s.name, tracing.SpanKindNoneEnum +func (s *stripPrefixRegex) GetTracingInformation() (string, string, trace.SpanKind) { + return s.name, typeName, trace.SpanKindInternal } func (s *stripPrefixRegex) ServeHTTP(rw http.ResponseWriter, req *http.Request) { diff --git a/pkg/middlewares/tracing/entrypoint.go b/pkg/middlewares/tracing/entrypoint.go index b17d8c2ce..5ea32ee8f 100644 --- a/pkg/middlewares/tracing/entrypoint.go +++ b/pkg/middlewares/tracing/entrypoint.go @@ -5,57 +5,53 @@ import ( "net/http" "github.com/containous/alice" - "github.com/opentracing/opentracing-go" - "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v3/pkg/middlewares" "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" ) const ( entryPointTypeName = "TracingEntryPoint" ) -// NewEntryPoint creates a new middleware that the incoming request. -func NewEntryPoint(ctx context.Context, t *tracing.Tracing, entryPointName string, next http.Handler) http.Handler { - middlewares.GetLogger(ctx, "tracing", entryPointTypeName).Debug().Msg("Creating middleware") - - return &entryPointMiddleware{ - entryPoint: entryPointName, - Tracing: t, - next: next, - } -} - -type entryPointMiddleware struct { - *tracing.Tracing +type entryPointTracing struct { + tracer trace.Tracer entryPoint string next http.Handler } -func (e *entryPointMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - spanCtx, err := e.Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(req.Header)) - if err != nil { - middlewares.GetLogger(req.Context(), "tracing", entryPointTypeName). - Debug().Err(err).Msg("Failed to extract the context") +// WrapEntryPointHandler Wraps tracing to alice.Constructor. +func WrapEntryPointHandler(ctx context.Context, tracer trace.Tracer, entryPointName string) alice.Constructor { + return func(next http.Handler) (http.Handler, error) { + return newEntryPoint(ctx, tracer, entryPointName, next), nil } +} - span, req, finish := e.StartSpanf(req, ext.SpanKindRPCServerEnum, "EntryPoint", []string{e.entryPoint, req.Host}, " ", ext.RPCServerOption(spanCtx)) - defer finish() +// newEntryPoint creates a new tracing middleware for incoming requests. +func newEntryPoint(ctx context.Context, tracer trace.Tracer, entryPointName string, next http.Handler) http.Handler { + middlewares.GetLogger(ctx, "tracing", entryPointTypeName).Debug().Msg("Creating middleware") - ext.Component.Set(span, e.ServiceName) - tracing.LogRequest(span, req) + return &entryPointTracing{ + entryPoint: entryPointName, + tracer: tracer, + next: next, + } +} - req = req.WithContext(tracing.WithTracing(req.Context(), e.Tracing)) +func (e *entryPointTracing) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + tracingCtx := tracing.ExtractCarrierIntoContext(req.Context(), req.Header) + tracingCtx, span := e.tracer.Start(tracingCtx, "EntryPoint", trace.WithSpanKind(trace.SpanKindServer)) + defer span.End() + + req = req.WithContext(tracingCtx) + + span.SetAttributes(attribute.String("entry_point", e.entryPoint)) + + tracing.LogServerRequest(span, req) recorder := newStatusCodeRecorder(rw, http.StatusOK) e.next.ServeHTTP(recorder, req) - tracing.LogResponseCode(span, recorder.Status()) -} - -// WrapEntryPointHandler Wraps tracing to alice.Constructor. -func WrapEntryPointHandler(ctx context.Context, tracer *tracing.Tracing, entryPointName string) alice.Constructor { - return func(next http.Handler) (http.Handler, error) { - return NewEntryPoint(ctx, tracer, entryPointName, next), nil - } + tracing.LogResponseCode(span, recorder.Status(), trace.SpanKindServer) } diff --git a/pkg/middlewares/tracing/entrypoint_test.go b/pkg/middlewares/tracing/entrypoint_test.go index e8528e048..b3cb60d67 100644 --- a/pkg/middlewares/tracing/entrypoint_test.go +++ b/pkg/middlewares/tracing/entrypoint_test.go @@ -6,81 +6,69 @@ import ( "net/http/httptest" "testing" - "github.com/opentracing/opentracing-go/ext" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/attribute" ) func TestEntryPointMiddleware(t *testing.T) { type expected struct { - Tags map[string]interface{} - OperationName string + name string + attributes []attribute.KeyValue } testCases := []struct { - desc string - entryPoint string - spanNameLimit int - tracing *trackingBackenMock - expected expected + desc string + entryPoint string + expected expected }{ { - desc: "no truncation test", - entryPoint: "test", - spanNameLimit: 0, - tracing: &trackingBackenMock{ - tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}}, - }, + desc: "basic test", + entryPoint: "test", expected: expected{ - Tags: map[string]interface{}{ - "span.kind": ext.SpanKindRPCServerEnum, - "http.method": http.MethodGet, - "component": "", - "http.url": "http://www.test.com", - "http.host": "www.test.com", + name: "EntryPoint", + attributes: []attribute.KeyValue{ + attribute.String("span.kind", "server"), + attribute.String("entry_point", "test"), + attribute.String("http.request.method", "GET"), + attribute.String("network.protocol.version", "1.1"), + attribute.Int64("http.request.body.size", int64(0)), + attribute.String("url.path", "/search"), + attribute.String("url.query", "q=Opentelemetry"), + attribute.String("url.scheme", "http"), + attribute.String("user_agent.original", "entrypoint-test"), + attribute.String("server.address", "www.test.com"), + attribute.String("network.peer.address", "10.0.0.1"), + attribute.String("network.peer.port", "1234"), + attribute.String("client.address", "10.0.0.1"), + attribute.Int64("client.port", int64(1234)), + attribute.String("client.socket.address", ""), + attribute.Int64("http.response.status_code", int64(404)), }, - OperationName: "EntryPoint test www.test.com", - }, - }, - { - desc: "basic test", - entryPoint: "test", - spanNameLimit: 25, - tracing: &trackingBackenMock{ - tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}}, - }, - expected: expected{ - Tags: map[string]interface{}{ - "span.kind": ext.SpanKindRPCServerEnum, - "http.method": http.MethodGet, - "component": "", - "http.url": "http://www.test.com", - "http.host": "www.test.com", - }, - OperationName: "EntryPoint te... ww... 0c15301b", }, }, } for _, test := range testCases { t.Run(test.desc, func(t *testing.T) { - newTracing, err := tracing.NewTracing("", test.spanNameLimit, test.tracing) - require.NoError(t, err) - - req := httptest.NewRequest(http.MethodGet, "http://www.test.com", nil) + req := httptest.NewRequest(http.MethodGet, "http://www.test.com/search?q=Opentelemetry", nil) rw := httptest.NewRecorder() + req.RemoteAddr = "10.0.0.1:1234" + req.Header.Set("User-Agent", "entrypoint-test") + req.Header.Set("X-Forwarded-Proto", "http") - next := http.HandlerFunc(func(http.ResponseWriter, *http.Request) { - span := test.tracing.tracer.(*MockTracer).Span - - tags := span.Tags - assert.Equal(t, test.expected.Tags, tags) - assert.Equal(t, test.expected.OperationName, span.OpName) + next := http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { + rw.WriteHeader(http.StatusNotFound) }) - handler := NewEntryPoint(context.Background(), newTracing, test.entryPoint, next) + tracer := &mockTracer{} + + handler := newEntryPoint(context.Background(), tracer, test.entryPoint, next) handler.ServeHTTP(rw, req) + + for _, span := range tracer.spans { + assert.Equal(t, test.expected.name, span.name) + assert.Equal(t, test.expected.attributes, span.attributes) + } }) } } diff --git a/pkg/middlewares/tracing/forwarder.go b/pkg/middlewares/tracing/forwarder.go deleted file mode 100644 index e2ee76a10..000000000 --- a/pkg/middlewares/tracing/forwarder.go +++ /dev/null @@ -1,59 +0,0 @@ -package tracing - -import ( - "context" - "net/http" - - "github.com/opentracing/opentracing-go/ext" - "github.com/traefik/traefik/v3/pkg/logs" - "github.com/traefik/traefik/v3/pkg/middlewares" - "github.com/traefik/traefik/v3/pkg/tracing" -) - -const ( - forwarderTypeName = "TracingForwarder" -) - -type forwarderMiddleware struct { - router string - service string - next http.Handler -} - -// NewForwarder creates a new forwarder middleware that traces the outgoing request. -func NewForwarder(ctx context.Context, router, service string, next http.Handler) http.Handler { - middlewares.GetLogger(ctx, "tracing", forwarderTypeName). - Debug().Str(logs.ServiceName, service).Msg("Added outgoing tracing middleware") - - return &forwarderMiddleware{ - router: router, - service: service, - next: next, - } -} - -func (f *forwarderMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - tr, err := tracing.FromContext(req.Context()) - if err != nil { - f.next.ServeHTTP(rw, req) - return - } - - opParts := []string{f.service, f.router} - span, req, finish := tr.StartSpanf(req, ext.SpanKindRPCClientEnum, "forward", opParts, "/") - defer finish() - - span.SetTag("traefik.service.name", f.service) - span.SetTag("traefik.router.name", f.router) - ext.HTTPMethod.Set(span, req.Method) - ext.HTTPUrl.Set(span, req.URL.String()) - span.SetTag("http.host", req.Host) - - tracing.InjectRequestHeaders(req) - - recorder := newStatusCodeRecorder(rw, 200) - - f.next.ServeHTTP(recorder, req) - - tracing.LogResponseCode(span, recorder.Status()) -} diff --git a/pkg/middlewares/tracing/forwarder_test.go b/pkg/middlewares/tracing/forwarder_test.go deleted file mode 100644 index e56c47502..000000000 --- a/pkg/middlewares/tracing/forwarder_test.go +++ /dev/null @@ -1,136 +0,0 @@ -package tracing - -import ( - "context" - "net/http" - "net/http/httptest" - "testing" - - "github.com/opentracing/opentracing-go/ext" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/traefik/traefik/v3/pkg/tracing" -) - -func TestNewForwarder(t *testing.T) { - type expected struct { - Tags map[string]interface{} - OperationName string - } - - testCases := []struct { - desc string - spanNameLimit int - tracing *trackingBackenMock - service string - router string - expected expected - }{ - { - desc: "Simple Forward Tracer without truncation and hashing", - spanNameLimit: 101, - tracing: &trackingBackenMock{ - tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}}, - }, - service: "some-service.domain.tld", - router: "some-service.domain.tld", - expected: expected{ - Tags: map[string]interface{}{ - "http.host": "www.test.com", - "http.method": "GET", - "http.url": "http://www.test.com/toto", - "traefik.service.name": "some-service.domain.tld", - "traefik.router.name": "some-service.domain.tld", - "span.kind": ext.SpanKindRPCClientEnum, - }, - OperationName: "forward some-service.domain.tld/some-service.domain.tld", - }, - }, - { - desc: "Simple Forward Tracer with truncation and hashing", - spanNameLimit: 101, - tracing: &trackingBackenMock{ - tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}}, - }, - service: "some-service-100.slug.namespace.environment.domain.tld", - router: "some-service-100.slug.namespace.environment.domain.tld", - expected: expected{ - Tags: map[string]interface{}{ - "http.host": "www.test.com", - "http.method": "GET", - "http.url": "http://www.test.com/toto", - "traefik.service.name": "some-service-100.slug.namespace.environment.domain.tld", - "traefik.router.name": "some-service-100.slug.namespace.environment.domain.tld", - "span.kind": ext.SpanKindRPCClientEnum, - }, - OperationName: "forward some-service-100.slug.namespace.enviro.../some-service-100.slug.namespace.enviro.../bc4a0d48", - }, - }, - { - desc: "Exactly 101 chars", - spanNameLimit: 101, - tracing: &trackingBackenMock{ - tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}}, - }, - service: "some-service1.namespace.environment.domain.tld", - router: "some-service1.namespace.environment.domain.tld", - expected: expected{ - Tags: map[string]interface{}{ - "http.host": "www.test.com", - "http.method": "GET", - "http.url": "http://www.test.com/toto", - "traefik.service.name": "some-service1.namespace.environment.domain.tld", - "traefik.router.name": "some-service1.namespace.environment.domain.tld", - "span.kind": ext.SpanKindRPCClientEnum, - }, - OperationName: "forward some-service1.namespace.environment.domain.tld/some-service1.namespace.environment.domain.tld", - }, - }, - { - desc: "More than 101 chars", - spanNameLimit: 101, - tracing: &trackingBackenMock{ - tracer: &MockTracer{Span: &MockSpan{Tags: make(map[string]interface{})}}, - }, - service: "some-service1.frontend.namespace.environment.domain.tld", - router: "some-service1.backend.namespace.environment.domain.tld", - expected: expected{ - Tags: map[string]interface{}{ - "http.host": "www.test.com", - "http.method": "GET", - "http.url": "http://www.test.com/toto", - "traefik.service.name": "some-service1.frontend.namespace.environment.domain.tld", - "traefik.router.name": "some-service1.backend.namespace.environment.domain.tld", - "span.kind": ext.SpanKindRPCClientEnum, - }, - OperationName: "forward some-service1.frontend.namespace.envir.../some-service1.backend.namespace.enviro.../fa49dd23", - }, - }, - } - - for _, test := range testCases { - t.Run(test.desc, func(t *testing.T) { - newTracing, err := tracing.NewTracing("", test.spanNameLimit, test.tracing) - require.NoError(t, err) - - req := httptest.NewRequest(http.MethodGet, "http://www.test.com/toto", nil) - req = req.WithContext(tracing.WithTracing(req.Context(), newTracing)) - - rw := httptest.NewRecorder() - - next := http.HandlerFunc(func(http.ResponseWriter, *http.Request) { - span := test.tracing.tracer.(*MockTracer).Span - - tags := span.Tags - assert.Equal(t, test.expected.Tags, tags) - assert.LessOrEqual(t, len(test.expected.OperationName), test.spanNameLimit, - "the len of the operation name %q [len: %d] doesn't respect limit %d", - test.expected.OperationName, len(test.expected.OperationName), test.spanNameLimit) - assert.Equal(t, test.expected.OperationName, span.OpName) - }) - - handler := NewForwarder(context.Background(), test.router, test.service, next) - handler.ServeHTTP(rw, req) - }) - } -} diff --git a/pkg/middlewares/tracing/middleware.go b/pkg/middlewares/tracing/middleware.go new file mode 100644 index 000000000..47a6af502 --- /dev/null +++ b/pkg/middlewares/tracing/middleware.go @@ -0,0 +1,71 @@ +package tracing + +import ( + "context" + "net/http" + + "github.com/containous/alice" + "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" +) + +// Traceable embeds tracing information. +type Traceable interface { + GetTracingInformation() (name string, typeName string, spanKind trace.SpanKind) +} + +// WrapMiddleware adds traceability to an alice.Constructor. +func WrapMiddleware(ctx context.Context, constructor alice.Constructor) alice.Constructor { + return func(next http.Handler) (http.Handler, error) { + if constructor == nil { + return nil, nil + } + handler, err := constructor(next) + if err != nil { + return nil, err + } + + if traceableHandler, ok := handler.(Traceable); ok { + name, typeName, spanKind := traceableHandler.GetTracingInformation() + log.Ctx(ctx).Debug().Str(logs.MiddlewareName, name).Msg("Adding tracing to middleware") + return NewMiddleware(handler, name, typeName, spanKind), nil + } + return handler, nil + } +} + +// NewMiddleware returns a http.Handler struct. +func NewMiddleware(next http.Handler, name string, typeName string, spanKind trace.SpanKind) http.Handler { + return &middlewareTracing{ + next: next, + name: name, + typeName: typeName, + spanKind: spanKind, + } +} + +// middlewareTracing is used to wrap http handler middleware. +type middlewareTracing struct { + next http.Handler + name string + typeName string + spanKind trace.SpanKind +} + +func (w *middlewareTracing) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + if tracer := tracing.TracerFromContext(req.Context()); tracer != nil { + tracingCtx, span := tracer.Start(req.Context(), w.typeName, trace.WithSpanKind(w.spanKind)) + defer span.End() + + req = req.WithContext(tracingCtx) + + span.SetAttributes(attribute.String("traefik.middleware.name", w.name)) + } + + if w.next != nil { + w.next.ServeHTTP(rw, req) + } +} diff --git a/pkg/middlewares/tracing/mock_tracing_test.go b/pkg/middlewares/tracing/mock_tracing_test.go index 33aac1ee6..a44345f6a 100644 --- a/pkg/middlewares/tracing/mock_tracing_test.go +++ b/pkg/middlewares/tracing/mock_tracing_test.go @@ -1,70 +1,62 @@ package tracing import ( - "io" + "context" - "github.com/opentracing/opentracing-go" - "github.com/opentracing/opentracing-go/log" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/trace" + "go.opentelemetry.io/otel/trace/embedded" ) -type MockTracer struct { - Span *MockSpan +type mockTracerProvider struct { + embedded.TracerProvider } -// StartSpan belongs to the Tracer interface. -func (n MockTracer) StartSpan(operationName string, opts ...opentracing.StartSpanOption) opentracing.Span { - n.Span.OpName = operationName - return n.Span +var _ trace.TracerProvider = mockTracerProvider{} + +func (p mockTracerProvider) Tracer(string, ...trace.TracerOption) trace.Tracer { + return &mockTracer{} } -// Inject belongs to the Tracer interface. -func (n MockTracer) Inject(sp opentracing.SpanContext, format, carrier interface{}) error { - return nil +type mockTracer struct { + embedded.Tracer + + spans []*mockSpan } -// Extract belongs to the Tracer interface. -func (n MockTracer) Extract(format, carrier interface{}) (opentracing.SpanContext, error) { - return nil, opentracing.ErrSpanContextNotFound +var _ trace.Tracer = &mockTracer{} + +func (t *mockTracer) Start(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { + config := trace.NewSpanStartConfig(opts...) + span := &mockSpan{} + span.SetName(name) + span.SetAttributes(attribute.String("span.kind", config.SpanKind().String())) + span.SetAttributes(config.Attributes()...) + t.spans = append(t.spans, span) + return trace.ContextWithSpan(ctx, span), span } -// MockSpanContext a span context mock. -type MockSpanContext struct{} +// mockSpan is an implementation of Span that preforms no operations. +type mockSpan struct { + embedded.Span -func (n MockSpanContext) ForeachBaggageItem(handler func(k, v string) bool) {} - -// MockSpan a span mock. -type MockSpan struct { - OpName string - Tags map[string]interface{} + name string + attributes []attribute.KeyValue } -func (n MockSpan) Context() opentracing.SpanContext { return MockSpanContext{} } -func (n MockSpan) SetBaggageItem(key, val string) opentracing.Span { - return MockSpan{Tags: make(map[string]interface{})} -} -func (n MockSpan) BaggageItem(key string) string { return "" } -func (n MockSpan) SetTag(key string, value interface{}) opentracing.Span { - n.Tags[key] = value - return n -} -func (n MockSpan) LogFields(fields ...log.Field) {} -func (n MockSpan) LogKV(keyVals ...interface{}) {} -func (n MockSpan) Finish() {} -func (n MockSpan) FinishWithOptions(opts opentracing.FinishOptions) {} -func (n MockSpan) SetOperationName(operationName string) opentracing.Span { return n } -func (n MockSpan) Tracer() opentracing.Tracer { return MockTracer{} } -func (n MockSpan) LogEvent(event string) {} -func (n MockSpan) LogEventWithPayload(event string, payload interface{}) {} -func (n MockSpan) Log(data opentracing.LogData) {} -func (n *MockSpan) Reset() { - n.Tags = make(map[string]interface{}) -} +var _ trace.Span = &mockSpan{} -type trackingBackenMock struct { - tracer opentracing.Tracer +func (*mockSpan) SpanContext() trace.SpanContext { return trace.SpanContext{} } +func (*mockSpan) IsRecording() bool { return false } +func (s *mockSpan) SetStatus(_ codes.Code, _ string) {} +func (s *mockSpan) SetAttributes(kv ...attribute.KeyValue) { + s.attributes = append(s.attributes, kv...) } +func (s *mockSpan) End(...trace.SpanEndOption) {} +func (s *mockSpan) RecordError(_ error, _ ...trace.EventOption) {} +func (s *mockSpan) AddEvent(_ string, _ ...trace.EventOption) {} -func (t *trackingBackenMock) Setup(componentName string) (opentracing.Tracer, io.Closer, error) { - opentracing.SetGlobalTracer(t.tracer) - return t.tracer, nil, nil -} +func (s *mockSpan) SetName(name string) { s.name = name } + +func (*mockSpan) TracerProvider() trace.TracerProvider { return mockTracerProvider{} } diff --git a/pkg/middlewares/tracing/router.go b/pkg/middlewares/tracing/router.go new file mode 100644 index 000000000..e964be12c --- /dev/null +++ b/pkg/middlewares/tracing/router.go @@ -0,0 +1,60 @@ +package tracing + +import ( + "context" + "net/http" + + "github.com/containous/alice" + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/attribute" + semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + "go.opentelemetry.io/otel/trace" +) + +const ( + routerTypeName = "TracingRouter" +) + +type routerTracing struct { + router string + routerRule string + service string + next http.Handler +} + +// WrapRouterHandler Wraps tracing to alice.Constructor. +func WrapRouterHandler(ctx context.Context, router, routerRule, service string) alice.Constructor { + return func(next http.Handler) (http.Handler, error) { + return newRouter(ctx, router, routerRule, service, next), nil + } +} + +// newRouter creates a new tracing middleware that traces the internal requests. +func newRouter(ctx context.Context, router, routerRule, service string, next http.Handler) http.Handler { + middlewares.GetLogger(ctx, "tracing", routerTypeName). + Debug().Str(logs.RouterName, router).Str(logs.ServiceName, service).Msg("Added outgoing tracing middleware") + + return &routerTracing{ + router: router, + routerRule: routerRule, + service: service, + next: next, + } +} + +func (f *routerTracing) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + if tracer := tracing.TracerFromContext(req.Context()); tracer != nil { + tracingCtx, span := tracer.Start(req.Context(), "Router", trace.WithSpanKind(trace.SpanKindInternal)) + defer span.End() + + req = req.WithContext(tracingCtx) + + span.SetAttributes(attribute.String("traefik.service.name", f.service)) + span.SetAttributes(attribute.String("traefik.router.name", f.router)) + span.SetAttributes(semconv.HTTPRoute(f.routerRule)) + } + + f.next.ServeHTTP(rw, req) +} diff --git a/pkg/middlewares/tracing/router_test.go b/pkg/middlewares/tracing/router_test.go new file mode 100644 index 000000000..b220cdabe --- /dev/null +++ b/pkg/middlewares/tracing/router_test.go @@ -0,0 +1,86 @@ +package tracing + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" +) + +func TestNewRouter(t *testing.T) { + type expected struct { + attributes []attribute.KeyValue + name string + } + + testCases := []struct { + desc string + service string + router string + routerRule string + expected []expected + }{ + { + desc: "base", + service: "myService", + router: "myRouter", + routerRule: "Path(`/`)", + expected: []expected{ + { + name: "EntryPoint", + attributes: []attribute.KeyValue{ + attribute.String("span.kind", "server"), + }, + }, + { + name: "Router", + attributes: []attribute.KeyValue{ + attribute.String("span.kind", "internal"), + attribute.String("http.request.method", "GET"), + attribute.Int64("http.response.status_code", int64(404)), + attribute.String("network.protocol.version", "1.1"), + attribute.String("server.address", "www.test.com"), + attribute.Int64("server.port", int64(80)), + attribute.String("url.full", "http://www.test.com/traces?p=OpenTelemetry"), + attribute.String("url.scheme", "http"), + attribute.String("traefik.service.name", "myService"), + attribute.String("traefik.router.name", "myRouter"), + attribute.String("http.route", "Path(`/`)"), + attribute.String("user_agent.original", "router-test"), + }, + }, + }, + }, + } + + for _, test := range testCases { + t.Run(test.desc, func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "http://www.test.com/traces?p=OpenTelemetry", nil) + req.RemoteAddr = "10.0.0.1:1234" + req.Header.Set("User-Agent", "router-test") + + tracer := &mockTracer{} + tracingCtx, entryPointSpan := tracer.Start(req.Context(), "EntryPoint", trace.WithSpanKind(trace.SpanKindServer)) + defer entryPointSpan.End() + + req = req.WithContext(tracingCtx) + + rw := httptest.NewRecorder() + next := http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { + rw.WriteHeader(http.StatusNotFound) + }) + + handler := newRouter(context.Background(), test.router, test.routerRule, test.service, next) + handler.ServeHTTP(rw, req) + + for i, span := range tracer.spans { + assert.Equal(t, test.expected[i].name, span.name) + assert.Equal(t, test.expected[i].attributes, span.attributes) + } + }) + } +} diff --git a/pkg/middlewares/tracing/service.go b/pkg/middlewares/tracing/service.go new file mode 100644 index 000000000..9cc5bd1ca --- /dev/null +++ b/pkg/middlewares/tracing/service.go @@ -0,0 +1,45 @@ +package tracing + +import ( + "context" + "net/http" + + "github.com/traefik/traefik/v3/pkg/logs" + "github.com/traefik/traefik/v3/pkg/middlewares" + "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" +) + +const ( + serviceTypeName = "TracingService" +) + +type serviceTracing struct { + service string + next http.Handler +} + +// NewService creates a new tracing middleware that traces the outgoing requests. +func NewService(ctx context.Context, service string, next http.Handler) http.Handler { + middlewares.GetLogger(ctx, "tracing", serviceTypeName). + Debug().Str(logs.ServiceName, service).Msg("Added outgoing tracing middleware") + + return &serviceTracing{ + service: service, + next: next, + } +} + +func (t *serviceTracing) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + if tracer := tracing.TracerFromContext(req.Context()); tracer != nil { + tracingCtx, span := tracer.Start(req.Context(), "Service", trace.WithSpanKind(trace.SpanKindInternal)) + defer span.End() + + req = req.WithContext(tracingCtx) + + span.SetAttributes(attribute.String("traefik.service.name", t.service)) + } + + t.next.ServeHTTP(rw, req) +} diff --git a/pkg/middlewares/tracing/service_test.go b/pkg/middlewares/tracing/service_test.go new file mode 100644 index 000000000..c78510faf --- /dev/null +++ b/pkg/middlewares/tracing/service_test.go @@ -0,0 +1,80 @@ +package tracing + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" +) + +func TestNewService(t *testing.T) { + type expected struct { + attributes []attribute.KeyValue + name string + } + + testCases := []struct { + desc string + service string + expected []expected + }{ + { + desc: "base", + service: "myService", + expected: []expected{ + { + name: "EntryPoint", + attributes: []attribute.KeyValue{ + attribute.String("span.kind", "server"), + }, + }, + { + name: "Service", + attributes: []attribute.KeyValue{ + attribute.String("span.kind", "internal"), + attribute.String("http.request.method", "GET"), + attribute.Int64("http.response.status_code", int64(404)), + attribute.String("network.protocol.version", "1.1"), + attribute.String("server.address", "www.test.com"), + attribute.Int64("server.port", int64(80)), + attribute.String("url.full", "http://www.test.com/traces?p=OpenTelemetry"), + attribute.String("url.scheme", "http"), + attribute.String("traefik.service.name", "myService"), + attribute.String("user_agent.original", "service-test"), + }, + }, + }, + }, + } + + for _, test := range testCases { + t.Run(test.desc, func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "http://www.test.com/traces?p=OpenTelemetry", nil) + req.RemoteAddr = "10.0.0.1:1234" + req.Header.Set("User-Agent", "service-test") + + tracer := &mockTracer{} + tracingCtx, entryPointSpan := tracer.Start(req.Context(), "EntryPoint", trace.WithSpanKind(trace.SpanKindServer)) + defer entryPointSpan.End() + + req = req.WithContext(tracingCtx) + + rw := httptest.NewRecorder() + next := http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { + rw.WriteHeader(http.StatusNotFound) + }) + + handler := NewService(context.Background(), test.service, next) + handler.ServeHTTP(rw, req) + + for i, span := range tracer.spans { + assert.Equal(t, test.expected[i].name, span.name) + assert.Equal(t, test.expected[i].attributes, span.attributes) + } + }) + } +} diff --git a/pkg/middlewares/tracing/wrapper.go b/pkg/middlewares/tracing/wrapper.go deleted file mode 100644 index 1fa3cfcdd..000000000 --- a/pkg/middlewares/tracing/wrapper.go +++ /dev/null @@ -1,69 +0,0 @@ -package tracing - -import ( - "context" - "net/http" - - "github.com/containous/alice" - "github.com/opentracing/opentracing-go/ext" - "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v3/pkg/logs" - "github.com/traefik/traefik/v3/pkg/tracing" -) - -// Traceable embeds tracing information. -type Traceable interface { - GetTracingInformation() (name string, spanKind ext.SpanKindEnum) -} - -// Wrap adds traceability to an alice.Constructor. -func Wrap(ctx context.Context, constructor alice.Constructor) alice.Constructor { - return func(next http.Handler) (http.Handler, error) { - if constructor == nil { - return nil, nil - } - handler, err := constructor(next) - if err != nil { - return nil, err - } - - if traceableHandler, ok := handler.(Traceable); ok { - name, spanKind := traceableHandler.GetTracingInformation() - log.Ctx(ctx).Debug().Str(logs.MiddlewareName, name).Msg("Adding tracing to middleware") - return NewWrapper(handler, name, spanKind), nil - } - return handler, nil - } -} - -// NewWrapper returns a http.Handler struct. -func NewWrapper(next http.Handler, name string, spanKind ext.SpanKindEnum) http.Handler { - return &Wrapper{ - next: next, - name: name, - spanKind: spanKind, - } -} - -// Wrapper is used to wrap http handler middleware. -type Wrapper struct { - next http.Handler - name string - spanKind ext.SpanKindEnum -} - -func (w *Wrapper) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - _, err := tracing.FromContext(req.Context()) - if err != nil { - w.next.ServeHTTP(rw, req) - return - } - - var finish func() - _, req, finish = tracing.StartSpan(req, w.name, w.spanKind) - defer finish() - - if w.next != nil { - w.next.ServeHTTP(rw, req) - } -} diff --git a/pkg/redactor/redactor_config_test.go b/pkg/redactor/redactor_config_test.go index f785ec72d..0a6b174e9 100644 --- a/pkg/redactor/redactor_config_test.go +++ b/pkg/redactor/redactor_config_test.go @@ -30,12 +30,7 @@ import ( "github.com/traefik/traefik/v3/pkg/provider/kv/zk" "github.com/traefik/traefik/v3/pkg/provider/rest" traefiktls "github.com/traefik/traefik/v3/pkg/tls" - "github.com/traefik/traefik/v3/pkg/tracing/datadog" - "github.com/traefik/traefik/v3/pkg/tracing/elastic" - "github.com/traefik/traefik/v3/pkg/tracing/haystack" - "github.com/traefik/traefik/v3/pkg/tracing/instana" - "github.com/traefik/traefik/v3/pkg/tracing/jaeger" - "github.com/traefik/traefik/v3/pkg/tracing/zipkin" + "github.com/traefik/traefik/v3/pkg/tracing/opentelemetry" "github.com/traefik/traefik/v3/pkg/types" ) @@ -850,58 +845,19 @@ func TestDo_staticConfiguration(t *testing.T) { } config.Tracing = &static.Tracing{ - ServiceName: "myServiceName", - SpanNameLimit: 42, - Jaeger: &jaeger.Config{ - SamplingServerURL: "foobar", - SamplingType: "foobar", - SamplingParam: 42, - LocalAgentHostPort: "foobar", - Gen128Bit: true, - Propagation: "foobar", - TraceContextHeaderName: "foobar", - Collector: &jaeger.Collector{ + ServiceName: "myServiceName", + Headers: map[string]string{ + "foobar": "foobar", + }, + GlobalAttributes: map[string]string{ + "foobar": "foobar", + }, + SampleRate: 42, + OTLP: &opentelemetry.Config{ + HTTP: &opentelemetry.HTTP{ Endpoint: "foobar", - User: "foobar", - Password: "foobar", + TLS: nil, }, - DisableAttemptReconnecting: true, - }, - Zipkin: &zipkin.Config{ - HTTPEndpoint: "foobar", - SameSpan: true, - ID128Bit: true, - SampleRate: 42, - }, - Datadog: &datadog.Config{ - LocalAgentHostPort: "foobar", - LocalAgentSocket: "foobar", - GlobalTags: map[string]string{"foobar": "foobar"}, - Debug: true, - PrioritySampling: true, - TraceIDHeaderName: "foobar", - ParentIDHeaderName: "foobar", - SamplingPriorityHeaderName: "foobar", - BagagePrefixHeaderName: "foobar", - }, - Instana: &instana.Config{ - LocalAgentHost: "foobar", - LocalAgentPort: 4242, - LogLevel: "foobar", - }, - Haystack: &haystack.Config{ - LocalAgentHost: "foobar", - LocalAgentPort: 42, - GlobalTag: "foobar", - TraceIDHeaderName: "foobar", - ParentIDHeaderName: "foobar", - SpanIDHeaderName: "foobar", - BaggagePrefixHeaderName: "foobar", - }, - Elastic: &elastic.Config{ - ServerURL: "foobar", - SecretToken: "foobar", - ServiceEnvironment: "foobar", }, } diff --git a/pkg/redactor/testdata/anonymized-static-config.json b/pkg/redactor/testdata/anonymized-static-config.json index a8db72460..97e678c85 100644 --- a/pkg/redactor/testdata/anonymized-static-config.json +++ b/pkg/redactor/testdata/anonymized-static-config.json @@ -344,57 +344,17 @@ }, "tracing": { "serviceName": "myServiceName", - "spanNameLimit": 42, - "jaeger": { - "samplingServerURL": "xxxx", - "samplingType": "foobar", - "samplingParam": 42, - "localAgentHostPort": "xxxx", - "gen128Bit": true, - "propagation": "foobar", - "traceContextHeaderName": "foobar", - "collector": { - "endpoint": "xxxx", - "user": "xxxx", - "password": "xxxx" - }, - "disableAttemptReconnecting": true + "headers": { + "foobar": "foobar" }, - "zipkin": { - "httpEndpoint": "xxxx", - "sameSpan": true, - "id128Bit": true, - "sampleRate": 42 + "globalAttributes": { + "foobar": "foobar" }, - "datadog": { - "localAgentHostPort": "xxxx", - "localAgentSocket": "xxxx", - "globalTags": { - "foobar": "foobar" - }, - "debug": true, - "prioritySampling": true, - "traceIDHeaderName": "foobar", - "parentIDHeaderName": "foobar", - "samplingPriorityHeaderName": "foobar", - "bagagePrefixHeaderName": "foobar" - }, - "instana": { - "localAgentHost": "xxxx", - "logLevel": "foobar" - }, - "haystack": { - "localAgentHost": "xxxx", - "globalTag": "foobar", - "traceIDHeaderName": "foobar", - "parentIDHeaderName": "foobar", - "spanIDHeaderName": "foobar", - "baggagePrefixHeaderName": "foobar" - }, - "elastic": { - "serverURL": "xxxx", - "secretToken": "xxxx", - "serviceEnvironment": "foobar" + "sampleRate": 42, + "otlp": { + "http": { + "endpoint": "xxxx" + } } }, "hostResolver": { @@ -447,4 +407,4 @@ } } } -} \ No newline at end of file +} diff --git a/pkg/server/middleware/chainbuilder.go b/pkg/server/middleware/chainbuilder.go index 864e7e68b..980d7a2b5 100644 --- a/pkg/server/middleware/chainbuilder.go +++ b/pkg/server/middleware/chainbuilder.go @@ -8,20 +8,20 @@ import ( "github.com/traefik/traefik/v3/pkg/metrics" "github.com/traefik/traefik/v3/pkg/middlewares/accesslog" "github.com/traefik/traefik/v3/pkg/middlewares/capture" - metricsmiddleware "github.com/traefik/traefik/v3/pkg/middlewares/metrics" - mTracing "github.com/traefik/traefik/v3/pkg/middlewares/tracing" - "github.com/traefik/traefik/v3/pkg/tracing" + metricsMiddle "github.com/traefik/traefik/v3/pkg/middlewares/metrics" + tracingMiddle "github.com/traefik/traefik/v3/pkg/middlewares/tracing" + "go.opentelemetry.io/otel/trace" ) // ChainBuilder Creates a middleware chain by entry point. It is used for middlewares that are created almost systematically and that need to be created before all others. type ChainBuilder struct { metricsRegistry metrics.Registry accessLoggerMiddleware *accesslog.Handler - tracer *tracing.Tracing + tracer trace.Tracer } // NewChainBuilder Creates a new ChainBuilder. -func NewChainBuilder(metricsRegistry metrics.Registry, accessLoggerMiddleware *accesslog.Handler, tracer *tracing.Tracing) *ChainBuilder { +func NewChainBuilder(metricsRegistry metrics.Registry, accessLoggerMiddleware *accesslog.Handler, tracer trace.Tracer) *ChainBuilder { return &ChainBuilder{ metricsRegistry: metricsRegistry, accessLoggerMiddleware: accessLoggerMiddleware, @@ -42,11 +42,12 @@ func (c *ChainBuilder) Build(ctx context.Context, entryPointName string) alice.C } if c.tracer != nil { - chain = chain.Append(mTracing.WrapEntryPointHandler(ctx, c.tracer, entryPointName)) + chain = chain.Append(tracingMiddle.WrapEntryPointHandler(ctx, c.tracer, entryPointName)) } if c.metricsRegistry != nil && c.metricsRegistry.IsEpEnabled() { - chain = chain.Append(metricsmiddleware.WrapEntryPointHandler(ctx, c.metricsRegistry, entryPointName)) + metricsHandler := metricsMiddle.WrapEntryPointHandler(ctx, c.metricsRegistry, entryPointName) + chain = chain.Append(tracingMiddle.WrapMiddleware(ctx, metricsHandler)) } return chain @@ -59,8 +60,4 @@ func (c *ChainBuilder) Close() { log.Error().Err(err).Msg("Could not close the access log file") } } - - if c.tracer != nil { - c.tracer.Close() - } } diff --git a/pkg/server/middleware/middlewares.go b/pkg/server/middleware/middlewares.go index afeab88e4..fe2fd23a9 100644 --- a/pkg/server/middleware/middlewares.go +++ b/pkg/server/middleware/middlewares.go @@ -372,7 +372,7 @@ func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) ( return nil, fmt.Errorf("invalid middleware %q configuration: invalid middleware type or middleware does not exist", middlewareName) } - return tracing.Wrap(ctx, middleware), nil + return tracing.WrapMiddleware(ctx, middleware), nil } func inSlice(element string, stack []string) bool { diff --git a/pkg/server/middleware/plugins.go b/pkg/server/middleware/plugins.go index 80253b05b..eacf8fba1 100644 --- a/pkg/server/middleware/plugins.go +++ b/pkg/server/middleware/plugins.go @@ -5,12 +5,13 @@ import ( "errors" "net/http" - "github.com/opentracing/opentracing-go/ext" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/plugins" - "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/trace" ) +const typeName = "Plugin" + // PluginsBuilder the plugin's builder interface. type PluginsBuilder interface { Build(pName string, config map[string]interface{}, middlewareName string) (plugins.Constructor, error) @@ -54,6 +55,6 @@ func (s *traceablePlugin) ServeHTTP(rw http.ResponseWriter, req *http.Request) { s.h.ServeHTTP(rw, req) } -func (s *traceablePlugin) GetTracingInformation() (string, ext.SpanKindEnum) { - return s.name, tracing.SpanKindNoneEnum +func (s *traceablePlugin) GetTracingInformation() (string, string, trace.SpanKind) { + return s.name, typeName, trace.SpanKindInternal } diff --git a/pkg/server/router/router.go b/pkg/server/router/router.go index 5e4aa043b..4b383e076 100644 --- a/pkg/server/router/router.go +++ b/pkg/server/router/router.go @@ -198,21 +198,20 @@ func (m *Manager) buildHTTPHandler(ctx context.Context, router *runtime.RouterIn mHandler := m.middlewaresBuilder.BuildChain(ctx, router.Middlewares) - tHandler := func(next http.Handler) (http.Handler, error) { - return tracing.NewForwarder(ctx, routerName, router.Service, next), nil - } - chain := alice.New() + chain = chain.Append(tracing.WrapRouterHandler(ctx, routerName, router.Rule, provider.GetQualifiedName(ctx, router.Service))) + if m.metricsRegistry != nil && m.metricsRegistry.IsRouterEnabled() { - chain = chain.Append(metricsMiddle.WrapRouterHandler(ctx, m.metricsRegistry, routerName, provider.GetQualifiedName(ctx, router.Service))) + metricsHandler := metricsMiddle.WrapRouterHandler(ctx, m.metricsRegistry, routerName, provider.GetQualifiedName(ctx, router.Service)) + chain = chain.Append(tracing.WrapMiddleware(ctx, metricsHandler)) } if router.DefaultRule { chain = chain.Append(denyrouterrecursion.WrapHandler(routerName)) } - return chain.Extend(*mHandler).Append(tHandler).Then(sHandler) + return chain.Extend(*mHandler).Then(sHandler) } // BuildDefaultHTTPRouter creates a default HTTP router. diff --git a/pkg/server/server.go b/pkg/server/server.go index c17464621..0f4379f04 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -3,6 +3,7 @@ package server import ( "context" "errors" + "io" "os" "os/signal" "time" @@ -27,12 +28,12 @@ type Server struct { stopChan chan bool routinesPool *safe.Pool + + tracerCloser io.Closer } // NewServer returns an initialized Server. -func NewServer(routinesPool *safe.Pool, entryPoints TCPEntryPoints, entryPointsUDP UDPEntryPoints, watcher *ConfigurationWatcher, - chainBuilder *middleware.ChainBuilder, accessLoggerMiddleware *accesslog.Handler, -) *Server { +func NewServer(routinesPool *safe.Pool, entryPoints TCPEntryPoints, entryPointsUDP UDPEntryPoints, watcher *ConfigurationWatcher, chainBuilder *middleware.ChainBuilder, accessLoggerMiddleware *accesslog.Handler, tracerCloser io.Closer) *Server { srv := &Server{ watcher: watcher, tcpEntryPoints: entryPoints, @@ -42,6 +43,7 @@ func NewServer(routinesPool *safe.Pool, entryPoints TCPEntryPoints, entryPointsU stopChan: make(chan bool, 1), routinesPool: routinesPool, udpEntryPoints: entryPointsUDP, + tracerCloser: tracerCloser, } srv.configureSignals() @@ -105,6 +107,12 @@ func (s *Server) Close() { s.chainBuilder.Close() + if s.tracerCloser != nil { + if err := s.tracerCloser.Close(); err != nil { + log.Error().Err(err).Msg("Could not close the tracer") + } + } + cancel() } diff --git a/pkg/server/service/proxy.go b/pkg/server/service/proxy.go index 413a97a6c..083875f9e 100644 --- a/pkg/server/service/proxy.go +++ b/pkg/server/service/proxy.go @@ -22,9 +22,13 @@ const StatusClientClosedRequest = 499 const StatusClientClosedRequestText = "Client Closed Request" func buildSingleHostProxy(target *url.URL, passHostHeader bool, flushInterval time.Duration, roundTripper http.RoundTripper, bufferPool httputil.BufferPool) http.Handler { + // Wrapping the roundTripper with the Tracing roundTripper, + // to handle the reverseProxy client span creation. + tracingRoundTripper := newTracingRoundTripper(roundTripper) + return &httputil.ReverseProxy{ Director: directorBuilder(target, passHostHeader), - Transport: roundTripper, + Transport: tracingRoundTripper, FlushInterval: flushInterval, BufferPool: bufferPool, ErrorHandler: errorHandler, @@ -94,23 +98,7 @@ func isWebSocketUpgrade(req *http.Request) bool { } func errorHandler(w http.ResponseWriter, req *http.Request, err error) { - statusCode := http.StatusInternalServerError - - switch { - case errors.Is(err, io.EOF): - statusCode = http.StatusBadGateway - case errors.Is(err, context.Canceled): - statusCode = StatusClientClosedRequest - default: - var netErr net.Error - if errors.As(err, &netErr) { - if netErr.Timeout() { - statusCode = http.StatusGatewayTimeout - } else { - statusCode = http.StatusBadGateway - } - } - } + statusCode := computeStatusCode(err) logger := log.Ctx(req.Context()) logger.Debug().Err(err).Msgf("%d %s", statusCode, statusText(statusCode)) @@ -121,6 +109,26 @@ func errorHandler(w http.ResponseWriter, req *http.Request, err error) { } } +func computeStatusCode(err error) int { + switch { + case errors.Is(err, io.EOF): + return http.StatusBadGateway + case errors.Is(err, context.Canceled): + return StatusClientClosedRequest + default: + var netErr net.Error + if errors.As(err, &netErr) { + if netErr.Timeout() { + return http.StatusGatewayTimeout + } + + return http.StatusBadGateway + } + } + + return http.StatusInternalServerError +} + func statusText(statusCode int) string { if statusCode == StatusClientClosedRequest { return StatusClientClosedRequestText diff --git a/pkg/server/service/service.go b/pkg/server/service/service.go index 61f6859f4..55fcb9fa2 100644 --- a/pkg/server/service/service.go +++ b/pkg/server/service/service.go @@ -14,6 +14,7 @@ import ( "strings" "time" + "github.com/containous/alice" "github.com/rs/zerolog/log" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/config/runtime" @@ -22,6 +23,7 @@ import ( "github.com/traefik/traefik/v3/pkg/metrics" "github.com/traefik/traefik/v3/pkg/middlewares/accesslog" metricsMiddle "github.com/traefik/traefik/v3/pkg/middlewares/metrics" + tracingMiddle "github.com/traefik/traefik/v3/pkg/middlewares/tracing" "github.com/traefik/traefik/v3/pkg/safe" "github.com/traefik/traefik/v3/pkg/server/cookie" "github.com/traefik/traefik/v3/pkg/server/provider" @@ -305,9 +307,18 @@ func (m *Manager) getLoadBalancerServiceHandler(ctx context.Context, serviceName proxy = accesslog.NewFieldHandler(proxy, accesslog.ServiceName, serviceName, accesslog.AddServiceFields) if m.metricsRegistry != nil && m.metricsRegistry.IsSvcEnabled() { - proxy = metricsMiddle.NewServiceMiddleware(ctx, proxy, m.metricsRegistry, serviceName) + metricsHandler := metricsMiddle.WrapServiceHandler(ctx, m.metricsRegistry, serviceName) + + proxy, err = alice.New(). + Append(tracingMiddle.WrapMiddleware(ctx, metricsHandler)). + Then(proxy) + if err != nil { + return nil, fmt.Errorf("error wrapping metrics handler: %w", err) + } } + proxy = tracingMiddle.NewService(ctx, serviceName, proxy) + lb.Add(proxyName, proxy, nil) // servers are considered UP by default. diff --git a/pkg/server/service/tracing_roundtripper.go b/pkg/server/service/tracing_roundtripper.go new file mode 100644 index 000000000..bdb2ab4f3 --- /dev/null +++ b/pkg/server/service/tracing_roundtripper.go @@ -0,0 +1,42 @@ +package service + +import ( + "context" + "net/http" + + "github.com/traefik/traefik/v3/pkg/tracing" + "go.opentelemetry.io/otel/trace" +) + +type wrapper struct { + rt http.RoundTripper +} + +func (t *wrapper) RoundTrip(req *http.Request) (*http.Response, error) { + var span trace.Span + if tracer := tracing.TracerFromContext(req.Context()); tracer != nil { + var tracingCtx context.Context + tracingCtx, span = tracer.Start(req.Context(), "ReverseProxy", trace.WithSpanKind(trace.SpanKindClient)) + defer span.End() + + req = req.WithContext(tracingCtx) + + tracing.LogClientRequest(span, req) + tracing.InjectContextIntoCarrier(req) + } + + response, err := t.rt.RoundTrip(req) + if err != nil { + statusCode := computeStatusCode(err) + tracing.LogResponseCode(span, statusCode, trace.SpanKindClient) + return response, err + } + + tracing.LogResponseCode(span, response.StatusCode, trace.SpanKindClient) + + return response, nil +} + +func newTracingRoundTripper(rt http.RoundTripper) http.RoundTripper { + return &wrapper{rt: rt} +} diff --git a/pkg/tracing/datadog/datadog.go b/pkg/tracing/datadog/datadog.go deleted file mode 100644 index 0bdacff7b..000000000 --- a/pkg/tracing/datadog/datadog.go +++ /dev/null @@ -1,84 +0,0 @@ -package datadog - -import ( - "io" - "net" - "os" - - "github.com/opentracing/opentracing-go" - "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v3/pkg/logs" - ddtracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentracer" - datadog "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" -) - -// Name sets the name of this tracer. -const Name = "datadog" - -// Config provides configuration settings for a datadog tracer. -type Config struct { - LocalAgentHostPort string `description:"Sets the Datadog Agent host:port." json:"localAgentHostPort,omitempty" toml:"localAgentHostPort,omitempty" yaml:"localAgentHostPort,omitempty"` - LocalAgentSocket string `description:"Sets the socket for the Datadog Agent." json:"localAgentSocket,omitempty" toml:"localAgentSocket,omitempty" yaml:"localAgentSocket,omitempty"` - GlobalTags map[string]string `description:"Sets a list of key:value tags on all spans." json:"globalTags,omitempty" toml:"globalTags,omitempty" yaml:"globalTags,omitempty" export:"true"` - Debug bool `description:"Enables Datadog debug." json:"debug,omitempty" toml:"debug,omitempty" yaml:"debug,omitempty" export:"true"` - PrioritySampling bool `description:"Enables priority sampling. When using distributed tracing, this option must be enabled in order to get all the parts of a distributed trace sampled." json:"prioritySampling,omitempty" toml:"prioritySampling,omitempty" yaml:"prioritySampling,omitempty" export:"true"` - TraceIDHeaderName string `description:"Sets the header name used to store the trace ID." json:"traceIDHeaderName,omitempty" toml:"traceIDHeaderName,omitempty" yaml:"traceIDHeaderName,omitempty" export:"true"` - ParentIDHeaderName string `description:"Sets the header name used to store the parent ID." json:"parentIDHeaderName,omitempty" toml:"parentIDHeaderName,omitempty" yaml:"parentIDHeaderName,omitempty" export:"true"` - SamplingPriorityHeaderName string `description:"Sets the header name used to store the sampling priority." json:"samplingPriorityHeaderName,omitempty" toml:"samplingPriorityHeaderName,omitempty" yaml:"samplingPriorityHeaderName,omitempty" export:"true"` - BagagePrefixHeaderName string `description:"Sets the header name prefix used to store baggage items in a map." json:"bagagePrefixHeaderName,omitempty" toml:"bagagePrefixHeaderName,omitempty" yaml:"bagagePrefixHeaderName,omitempty" export:"true"` -} - -// SetDefaults sets the default values. -func (c *Config) SetDefaults() { - host, ok := os.LookupEnv("DD_AGENT_HOST") - if !ok { - host = "localhost" - } - - port, ok := os.LookupEnv("DD_TRACE_AGENT_PORT") - if !ok { - port = "8126" - } - - c.LocalAgentHostPort = net.JoinHostPort(host, port) -} - -// Setup sets up the tracer. -func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error) { - logger := log.With().Str(logs.TracingProviderName, Name).Logger() - - opts := []datadog.StartOption{ - datadog.WithService(serviceName), - datadog.WithDebugMode(c.Debug), - datadog.WithPropagator(datadog.NewPropagator(&datadog.PropagatorConfig{ - TraceHeader: c.TraceIDHeaderName, - ParentHeader: c.ParentIDHeaderName, - PriorityHeader: c.SamplingPriorityHeaderName, - BaggagePrefix: c.BagagePrefixHeaderName, - })), - datadog.WithLogger(logs.NewDatadogLogger(logger)), - } - - if c.LocalAgentSocket != "" { - opts = append(opts, datadog.WithUDS(c.LocalAgentSocket)) - } else { - opts = append(opts, datadog.WithAgentAddr(c.LocalAgentHostPort)) - } - - for k, v := range c.GlobalTags { - opts = append(opts, datadog.WithGlobalTag(k, v)) - } - - if c.PrioritySampling { - opts = append(opts, datadog.WithPrioritySampling()) - } - - tracer := ddtracer.New(opts...) - - // Without this, child spans are getting the NOOP tracer - opentracing.SetGlobalTracer(tracer) - - logger.Debug().Msg("Datadog tracer configured") - - return tracer, nil, nil -} diff --git a/pkg/tracing/elastic/elastic.go b/pkg/tracing/elastic/elastic.go deleted file mode 100644 index 383cca2bd..000000000 --- a/pkg/tracing/elastic/elastic.go +++ /dev/null @@ -1,74 +0,0 @@ -package elastic - -import ( - "io" - "net/url" - - "github.com/opentracing/opentracing-go" - "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v3/pkg/logs" - "github.com/traefik/traefik/v3/pkg/version" - "go.elastic.co/apm" - "go.elastic.co/apm/module/apmot" - "go.elastic.co/apm/transport" -) - -// Name sets the name of this tracer. -const Name = "elastic" - -func init() { - // The APM lib uses the init() function to create a default tracer. - // So this default tracer must be disabled. - // https://github.com/elastic/apm-agent-go/blob/8dd383d0d21776faad8841fe110f35633d199a03/tracer.go#L61-L65 - apm.DefaultTracer.Close() -} - -// Config provides configuration settings for a elastic.co tracer. -type Config struct { - ServerURL string `description:"Sets the URL of the Elastic APM server." json:"serverURL,omitempty" toml:"serverURL,omitempty" yaml:"serverURL,omitempty"` - SecretToken string `description:"Sets the token used to connect to Elastic APM Server." json:"secretToken,omitempty" toml:"secretToken,omitempty" yaml:"secretToken,omitempty" loggable:"false"` - ServiceEnvironment string `description:"Sets the name of the environment Traefik is deployed in, e.g. 'production' or 'staging'." json:"serviceEnvironment,omitempty" toml:"serviceEnvironment,omitempty" yaml:"serviceEnvironment,omitempty" export:"true"` -} - -// Setup sets up the tracer. -func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error) { - // Create default transport. - tr, err := transport.NewHTTPTransport() - if err != nil { - return nil, nil, err - } - - if c.ServerURL != "" { - serverURL, err := url.Parse(c.ServerURL) - if err != nil { - return nil, nil, err - } - tr.SetServerURL(serverURL) - } - - if c.SecretToken != "" { - tr.SetSecretToken(c.SecretToken) - } - - tracer, err := apm.NewTracerOptions(apm.TracerOptions{ - ServiceName: serviceName, - ServiceVersion: version.Version, - ServiceEnvironment: c.ServiceEnvironment, - Transport: tr, - }) - if err != nil { - return nil, nil, err - } - - logger := log.With().Str(logs.TracingProviderName, Name).Logger() - tracer.SetLogger(logs.NewElasticLogger(logger)) - - otTracer := apmot.New(apmot.WithTracer(tracer)) - - // Without this, child spans are getting the NOOP tracer - opentracing.SetGlobalTracer(otTracer) - - log.Debug().Msg("Elastic tracer configured") - - return otTracer, nil, nil -} diff --git a/pkg/tracing/haystack/haystack.go b/pkg/tracing/haystack/haystack.go deleted file mode 100644 index 6e460dcfb..000000000 --- a/pkg/tracing/haystack/haystack.go +++ /dev/null @@ -1,72 +0,0 @@ -package haystack - -import ( - "io" - "strings" - "time" - - "github.com/ExpediaDotCom/haystack-client-go" - "github.com/opentracing/opentracing-go" - "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v3/pkg/logs" -) - -// Name sets the name of this tracer. -const Name = "haystack" - -// Config provides configuration settings for a haystack tracer. -type Config struct { - LocalAgentHost string `description:"Sets the Haystack Agent host." json:"localAgentHost,omitempty" toml:"localAgentHost,omitempty" yaml:"localAgentHost,omitempty"` - LocalAgentPort int `description:"Sets the Haystack Agent port." json:"localAgentPort,omitempty" toml:"localAgentPort,omitempty" yaml:"localAgentPort,omitempty"` - GlobalTag string `description:"Sets a key:value tag on all spans." json:"globalTag,omitempty" toml:"globalTag,omitempty" yaml:"globalTag,omitempty" export:"true"` - TraceIDHeaderName string `description:"Sets the header name used to store the trace ID." json:"traceIDHeaderName,omitempty" toml:"traceIDHeaderName,omitempty" yaml:"traceIDHeaderName,omitempty" export:"true"` - ParentIDHeaderName string `description:"Sets the header name used to store the parent ID." json:"parentIDHeaderName,omitempty" toml:"parentIDHeaderName,omitempty" yaml:"parentIDHeaderName,omitempty" export:"true"` - SpanIDHeaderName string `description:"Sets the header name used to store the span ID." json:"spanIDHeaderName,omitempty" toml:"spanIDHeaderName,omitempty" yaml:"spanIDHeaderName,omitempty" export:"true"` - BaggagePrefixHeaderName string `description:"Sets the header name prefix used to store baggage items in a map." json:"baggagePrefixHeaderName,omitempty" toml:"baggagePrefixHeaderName,omitempty" yaml:"baggagePrefixHeaderName,omitempty" export:"true"` -} - -// SetDefaults sets the default values. -func (c *Config) SetDefaults() { - c.LocalAgentHost = "127.0.0.1" - c.LocalAgentPort = 35000 -} - -// Setup sets up the tracer. -func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error) { - tag := strings.SplitN(c.GlobalTag, ":", 2) - - value := "" - if len(tag) == 2 { - value = tag[1] - } - - host := "localhost" - port := 35000 - if len(c.LocalAgentHost) > 0 { - host = c.LocalAgentHost - } - if c.LocalAgentPort > 0 { - port = c.LocalAgentPort - } - - logger := log.With().Str(logs.TracingProviderName, Name).Logger() - - tracer, closer := haystack.NewTracer(serviceName, haystack.NewAgentDispatcher(host, port, 3*time.Second, 1000), - haystack.TracerOptionsFactory.Tag(tag[0], value), - haystack.TracerOptionsFactory.Propagator(opentracing.HTTPHeaders, - haystack.NewTextMapPropagator(haystack.PropagatorOpts{ - TraceIDKEYName: c.TraceIDHeaderName, - ParentSpanIDKEYName: c.ParentIDHeaderName, - SpanIDKEYName: c.SpanIDHeaderName, - BaggagePrefixKEYName: c.BaggagePrefixHeaderName, - }, haystack.DefaultCodex{})), - haystack.TracerOptionsFactory.Logger(logs.NewHaystackLogger(logger)), - ) - - // Without this, child spans are getting the NOOP tracer - opentracing.SetGlobalTracer(tracer) - - log.Debug().Msg("haystack tracer configured") - - return tracer, closer, nil -} diff --git a/pkg/tracing/instana/instana.go b/pkg/tracing/instana/instana.go deleted file mode 100644 index edb2ee14e..000000000 --- a/pkg/tracing/instana/instana.go +++ /dev/null @@ -1,61 +0,0 @@ -package instana - -import ( - "io" - - instana "github.com/instana/go-sensor" - "github.com/opentracing/opentracing-go" - "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v3/pkg/logs" -) - -// Name sets the name of this tracer. -const Name = "instana" - -// Config provides configuration settings for an instana tracer. -type Config struct { - LocalAgentHost string `description:"Sets the Instana Agent host." json:"localAgentHost,omitempty" toml:"localAgentHost,omitempty" yaml:"localAgentHost,omitempty"` - LocalAgentPort int `description:"Sets the Instana Agent port." json:"localAgentPort,omitempty" toml:"localAgentPort,omitempty" yaml:"localAgentPort,omitempty"` - LogLevel string `description:"Sets the log level for the Instana tracer. ('error','warn','info','debug')" json:"logLevel,omitempty" toml:"logLevel,omitempty" yaml:"logLevel,omitempty" export:"true"` - EnableAutoProfile bool `description:"Enables automatic profiling for the Traefik process." json:"enableAutoProfile,omitempty" toml:"enableAutoProfile,omitempty" yaml:"enableAutoProfile,omitempty" export:"true"` -} - -// SetDefaults sets the default values. -func (c *Config) SetDefaults() { - c.LocalAgentPort = 42699 - c.LogLevel = "info" -} - -// Setup sets up the tracer. -func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error) { - // set default logLevel - logLevel := instana.Info - - // check/set logLevel overrides - switch c.LogLevel { - case "error": - logLevel = instana.Error - case "warn": - logLevel = instana.Warn - case "debug": - logLevel = instana.Debug - } - - logger := log.With().Str(logs.TracingProviderName, Name).Logger() - instana.SetLogger(logs.NewInstanaLogger(logger)) - - tracer := instana.NewTracerWithOptions(&instana.Options{ - Service: serviceName, - LogLevel: logLevel, - AgentPort: c.LocalAgentPort, - AgentHost: c.LocalAgentHost, - EnableAutoProfile: c.EnableAutoProfile, - }) - - // Without this, child spans are getting the NOOP tracer - opentracing.SetGlobalTracer(tracer) - - logger.Debug().Msg("Instana tracer configured") - - return tracer, nil, nil -} diff --git a/pkg/tracing/jaeger/jaeger.go b/pkg/tracing/jaeger/jaeger.go deleted file mode 100644 index 64eeb8e18..000000000 --- a/pkg/tracing/jaeger/jaeger.go +++ /dev/null @@ -1,124 +0,0 @@ -package jaeger - -import ( - "fmt" - "io" - - "github.com/opentracing/opentracing-go" - "github.com/rs/zerolog/log" - "github.com/traefik/traefik/v3/pkg/logs" - jaegercli "github.com/uber/jaeger-client-go" - jaegercfg "github.com/uber/jaeger-client-go/config" - "github.com/uber/jaeger-client-go/zipkin" - jaegermet "github.com/uber/jaeger-lib/metrics" -) - -// Name sets the name of this tracer. -const Name = "jaeger" - -// Config provides configuration settings for a jaeger tracer. -type Config struct { - SamplingServerURL string `description:"Sets the sampling server URL." json:"samplingServerURL,omitempty" toml:"samplingServerURL,omitempty" yaml:"samplingServerURL,omitempty"` - SamplingType string `description:"Sets the sampling type." json:"samplingType,omitempty" toml:"samplingType,omitempty" yaml:"samplingType,omitempty" export:"true"` - SamplingParam float64 `description:"Sets the sampling parameter." json:"samplingParam,omitempty" toml:"samplingParam,omitempty" yaml:"samplingParam,omitempty" export:"true"` - LocalAgentHostPort string `description:"Sets the Jaeger Agent host:port." json:"localAgentHostPort,omitempty" toml:"localAgentHostPort,omitempty" yaml:"localAgentHostPort,omitempty"` - Gen128Bit bool `description:"Generates 128 bits span IDs." json:"gen128Bit,omitempty" toml:"gen128Bit,omitempty" yaml:"gen128Bit,omitempty" export:"true"` - Propagation string `description:"Sets the propagation format (jaeger/b3)." json:"propagation,omitempty" toml:"propagation,omitempty" yaml:"propagation,omitempty" export:"true"` - TraceContextHeaderName string `description:"Sets the header name used to store the trace ID." json:"traceContextHeaderName,omitempty" toml:"traceContextHeaderName,omitempty" yaml:"traceContextHeaderName,omitempty" export:"true"` - Collector *Collector `description:"Defines the collector information." json:"collector,omitempty" toml:"collector,omitempty" yaml:"collector,omitempty" export:"true"` - DisableAttemptReconnecting bool `description:"Disables the periodic re-resolution of the agent's hostname and reconnection if there was a change." json:"disableAttemptReconnecting,omitempty" toml:"disableAttemptReconnecting,omitempty" yaml:"disableAttemptReconnecting,omitempty" export:"true"` -} - -// SetDefaults sets the default values. -func (c *Config) SetDefaults() { - c.SamplingServerURL = "http://localhost:5778/sampling" - c.SamplingType = "const" - c.SamplingParam = 1.0 - c.LocalAgentHostPort = "127.0.0.1:6831" - c.Propagation = "jaeger" - c.Gen128Bit = false - c.TraceContextHeaderName = jaegercli.TraceContextHeaderName - c.DisableAttemptReconnecting = true -} - -// Collector provides configuration settings for jaeger collector. -type Collector struct { - Endpoint string `description:"Instructs reporter to send spans to jaeger-collector at this URL." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"` - User string `description:"User for basic http authentication when sending spans to jaeger-collector." json:"user,omitempty" toml:"user,omitempty" yaml:"user,omitempty" loggable:"false"` - Password string `description:"Password for basic http authentication when sending spans to jaeger-collector." json:"password,omitempty" toml:"password,omitempty" yaml:"password,omitempty" loggable:"false"` -} - -// SetDefaults sets the default values. -func (c *Collector) SetDefaults() { - c.Endpoint = "" - c.User = "" - c.Password = "" -} - -// Setup sets up the tracer. -func (c *Config) Setup(componentName string) (opentracing.Tracer, io.Closer, error) { - reporter := &jaegercfg.ReporterConfig{ - LogSpans: true, - LocalAgentHostPort: c.LocalAgentHostPort, - DisableAttemptReconnecting: c.DisableAttemptReconnecting, - } - - if c.Collector != nil { - reporter.CollectorEndpoint = c.Collector.Endpoint - reporter.User = c.Collector.User - reporter.Password = c.Collector.Password - } - - jcfg := &jaegercfg.Configuration{ - Sampler: &jaegercfg.SamplerConfig{ - SamplingServerURL: c.SamplingServerURL, - Type: c.SamplingType, - Param: c.SamplingParam, - }, - Reporter: reporter, - Headers: &jaegercli.HeadersConfig{ - TraceContextHeaderName: c.TraceContextHeaderName, - }, - } - - // Overrides existing tracer's Configuration with environment variables. - _, err := jcfg.FromEnv() - if err != nil { - return nil, nil, err - } - - jMetricsFactory := jaegermet.NullFactory - - logger := log.With().Str(logs.TracingProviderName, Name).Logger() - - opts := []jaegercfg.Option{ - jaegercfg.Logger(logs.NewJaegerLogger(logger)), - jaegercfg.Metrics(jMetricsFactory), - jaegercfg.Gen128Bit(c.Gen128Bit), - } - - switch c.Propagation { - case "b3": - p := zipkin.NewZipkinB3HTTPHeaderPropagator() - opts = append(opts, - jaegercfg.Injector(opentracing.HTTPHeaders, p), - jaegercfg.Extractor(opentracing.HTTPHeaders, p), - ) - case "jaeger", "": - default: - return nil, nil, fmt.Errorf("unknown propagation format: %s", c.Propagation) - } - - // Initialize tracer with a logger and a metrics factory - closer, err := jcfg.InitGlobalTracer( - componentName, - opts..., - ) - if err != nil { - logger.Warn().Err(err).Msg("Could not initialize jaeger tracer") - return nil, nil, err - } - logger.Debug().Msg("Jaeger tracer configured") - - return opentracing.GlobalTracer(), closer, nil -} diff --git a/pkg/tracing/opentelemetry/opentelemetry.go b/pkg/tracing/opentelemetry/opentelemetry.go index c59fbd410..2e13bc20c 100644 --- a/pkg/tracing/opentelemetry/opentelemetry.go +++ b/pkg/tracing/opentelemetry/opentelemetry.go @@ -5,20 +5,21 @@ import ( "fmt" "io" "net" + "net/url" + "time" - "github.com/opentracing/opentracing-go" "github.com/rs/zerolog/log" "github.com/traefik/traefik/v3/pkg/types" "github.com/traefik/traefik/v3/pkg/version" "go.opentelemetry.io/otel" - oteltracer "go.opentelemetry.io/otel/bridge/opentracing" + "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/exporters/otlp/otlptrace" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.12.0" + semconv "go.opentelemetry.io/otel/semconv/v1.21.0" "go.opentelemetry.io/otel/trace" "google.golang.org/grpc/credentials" "google.golang.org/grpc/encoding/gzip" @@ -26,85 +27,108 @@ import ( // Config provides configuration settings for the open-telemetry tracer. type Config struct { - // NOTE: as no gRPC option is implemented yet, the type is empty and is used as a boolean for upward compatibility purposes. - GRPC *struct{} `description:"gRPC specific configuration for the OpenTelemetry collector." json:"grpc,omitempty" toml:"grpc,omitempty" yaml:"grpc,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` + GRPC *GRPC `description:"gRPC configuration for the OpenTelemetry collector." json:"grpc,omitempty" toml:"grpc,omitempty" yaml:"grpc,omitempty" export:"true"` + HTTP *HTTP `description:"HTTP configuration for the OpenTelemetry collector." json:"http,omitempty" toml:"http,omitempty" yaml:"http,omitempty" export:"true"` +} - Address string `description:"Sets the address (host:port) of the collector endpoint." json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"` - Path string `description:"Sets the URL path of the collector endpoint." json:"path,omitempty" toml:"path,omitempty" yaml:"path,omitempty" export:"true"` - Insecure bool `description:"Disables client transport security for the exporter." json:"insecure,omitempty" toml:"insecure,omitempty" yaml:"insecure,omitempty" export:"true"` - Headers map[string]string `description:"Defines additional headers to be sent with the payloads." json:"headers,omitempty" toml:"headers,omitempty" yaml:"headers,omitempty" export:"true"` - TLS *types.ClientTLS `description:"Defines client transport security parameters." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"` +// GRPC provides configuration settings for the gRPC open-telemetry tracer. +type GRPC struct { + Endpoint string `description:"Sets the gRPC endpoint (host:port) of the collector." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"` + + Insecure bool `description:"Disables client transport security for the exporter." json:"insecure,omitempty" toml:"insecure,omitempty" yaml:"insecure,omitempty" export:"true"` + TLS *types.ClientTLS `description:"Defines client transport security parameters." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"` } // SetDefaults sets the default values. -func (c *Config) SetDefaults() { - c.Address = "localhost:4318" +func (c *GRPC) SetDefaults() { + c.Endpoint = "localhost:4317" +} + +// HTTP provides configuration settings for the HTTP open-telemetry tracer. +type HTTP struct { + Endpoint string `description:"Sets the HTTP endpoint (scheme://host:port/v1/traces) of the collector." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"` + TLS *types.ClientTLS `description:"Defines client transport security parameters." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"` +} + +// SetDefaults sets the default values. +func (c *HTTP) SetDefaults() { + c.Endpoint = "localhost:4318" } // Setup sets up the tracer. -func (c *Config) Setup(componentName string) (opentracing.Tracer, io.Closer, error) { +func (c *Config) Setup(serviceName string, sampleRate float64, globalAttributes map[string]string, headers map[string]string) (trace.Tracer, io.Closer, error) { var ( err error exporter *otlptrace.Exporter ) if c.GRPC != nil { - exporter, err = c.setupGRPCExporter() + exporter, err = c.setupGRPCExporter(headers) } else { - exporter, err = c.setupHTTPExporter() + exporter, err = c.setupHTTPExporter(headers) } if err != nil { return nil, nil, fmt.Errorf("setting up exporter: %w", err) } - bt := oteltracer.NewBridgeTracer() - bt.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) + attr := []attribute.KeyValue{ + semconv.ServiceNameKey.String(serviceName), + semconv.ServiceVersionKey.String(version.Version), + } - bt.SetOpenTelemetryTracer(otel.Tracer(componentName, trace.WithInstrumentationVersion(version.Version))) - opentracing.SetGlobalTracer(bt) + for k, v := range globalAttributes { + attr = append(attr, attribute.String(k, v)) + } res, err := resource.New(context.Background(), - resource.WithAttributes(semconv.ServiceNameKey.String("traefik")), - resource.WithAttributes(semconv.ServiceVersionKey.String(version.Version)), + resource.WithAttributes(attr...), resource.WithFromEnv(), resource.WithTelemetrySDK(), + resource.WithOSType(), + resource.WithProcessCommandArgs(), ) if err != nil { return nil, nil, fmt.Errorf("building resource: %w", err) } + // Register the trace exporter with a TracerProvider, using a batch + // span processor to aggregate spans before export. + bsp := sdktrace.NewBatchSpanProcessor(exporter) tracerProvider := sdktrace.NewTracerProvider( + sdktrace.WithSampler(sdktrace.TraceIDRatioBased(sampleRate)), sdktrace.WithResource(res), - sdktrace.WithBatcher(exporter), + sdktrace.WithSpanProcessor(bsp), ) + otel.SetTracerProvider(tracerProvider) + otel.SetTextMapPropagator(propagation.TraceContext{}) log.Debug().Msg("OpenTelemetry tracer configured") - return bt, tpCloser{provider: tracerProvider}, err + return tracerProvider.Tracer("github.com/traefik/traefik"), &tpCloser{provider: tracerProvider}, err } -func (c *Config) setupHTTPExporter() (*otlptrace.Exporter, error) { - host, port, err := net.SplitHostPort(c.Address) +func (c *Config) setupHTTPExporter(headers map[string]string) (*otlptrace.Exporter, error) { + endpoint, err := url.Parse(c.HTTP.Endpoint) if err != nil { - return nil, fmt.Errorf("invalid collector address %q: %w", c.Address, err) + return nil, fmt.Errorf("invalid collector endpoint %q: %w", c.HTTP.Endpoint, err) } opts := []otlptracehttp.Option{ - otlptracehttp.WithEndpoint(fmt.Sprintf("%s:%s", host, port)), - otlptracehttp.WithHeaders(c.Headers), + otlptracehttp.WithEndpoint(endpoint.Host), + otlptracehttp.WithHeaders(headers), otlptracehttp.WithCompression(otlptracehttp.GzipCompression), } - if c.Insecure { + if endpoint.Scheme == "http" { opts = append(opts, otlptracehttp.WithInsecure()) } - if c.Path != "" { - opts = append(opts, otlptracehttp.WithURLPath(c.Path)) + if endpoint.Path != "" { + opts = append(opts, otlptracehttp.WithURLPath(endpoint.Path)) } - if c.TLS != nil { - tlsConfig, err := c.TLS.CreateTLSConfig(context.Background()) + if c.HTTP.TLS != nil { + tlsConfig, err := c.HTTP.TLS.CreateTLSConfig(context.Background()) if err != nil { return nil, fmt.Errorf("creating TLS client config: %w", err) } @@ -115,24 +139,24 @@ func (c *Config) setupHTTPExporter() (*otlptrace.Exporter, error) { return otlptrace.New(context.Background(), otlptracehttp.NewClient(opts...)) } -func (c *Config) setupGRPCExporter() (*otlptrace.Exporter, error) { - host, port, err := net.SplitHostPort(c.Address) +func (c *Config) setupGRPCExporter(headers map[string]string) (*otlptrace.Exporter, error) { + host, port, err := net.SplitHostPort(c.GRPC.Endpoint) if err != nil { - return nil, fmt.Errorf("invalid collector address %q: %w", c.Address, err) + return nil, fmt.Errorf("invalid collector address %q: %w", c.GRPC.Endpoint, err) } opts := []otlptracegrpc.Option{ otlptracegrpc.WithEndpoint(fmt.Sprintf("%s:%s", host, port)), - otlptracegrpc.WithHeaders(c.Headers), + otlptracegrpc.WithHeaders(headers), otlptracegrpc.WithCompressor(gzip.Name), } - if c.Insecure { + if c.GRPC.Insecure { opts = append(opts, otlptracegrpc.WithInsecure()) } - if c.TLS != nil { - tlsConfig, err := c.TLS.CreateTLSConfig(context.Background()) + if c.GRPC.TLS != nil { + tlsConfig, err := c.GRPC.TLS.CreateTLSConfig(context.Background()) if err != nil { return nil, fmt.Errorf("creating TLS client config: %w", err) } @@ -148,6 +172,13 @@ type tpCloser struct { provider *sdktrace.TracerProvider } -func (t tpCloser) Close() error { - return t.provider.Shutdown(context.Background()) +func (t *tpCloser) Close() error { + if t == nil { + return nil + } + + ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(5*time.Second)) + defer cancel() + + return t.provider.Shutdown(ctx) } diff --git a/pkg/tracing/opentelemetry/opentelemetry_test.go b/pkg/tracing/opentelemetry/opentelemetry_test.go index 40fcca159..ad7f13a4d 100644 --- a/pkg/tracing/opentelemetry/opentelemetry_test.go +++ b/pkg/tracing/opentelemetry/opentelemetry_test.go @@ -1,4 +1,4 @@ -package opentelemetry +package opentelemetry_test import ( "compress/gzip" @@ -7,14 +7,16 @@ import ( "io" "net/http" "net/http/httptest" - "strings" "testing" "time" + "github.com/containous/alice" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - mtracing "github.com/traefik/traefik/v3/pkg/middlewares/tracing" + "github.com/traefik/traefik/v3/pkg/config/static" + tracingMiddle "github.com/traefik/traefik/v3/pkg/middlewares/tracing" "github.com/traefik/traefik/v3/pkg/tracing" + "github.com/traefik/traefik/v3/pkg/tracing/opentelemetry" "go.opentelemetry.io/collector/pdata/ptrace/ptraceotlp" ) @@ -68,14 +70,25 @@ func TestTracing(t *testing.T) { })) t.Cleanup(collector.Close) - newTracing, err := tracing.NewTracing("", 0, &Config{ - Insecure: true, - Address: strings.TrimPrefix(collector.URL, "http://"), - }) - require.NoError(t, err) - t.Cleanup(newTracing.Close) + tracingConfig := &static.Tracing{ + ServiceName: "traefik", + SampleRate: 1.0, + OTLP: &opentelemetry.Config{ + HTTP: &opentelemetry.HTTP{ + Endpoint: collector.URL, + }, + }, + } - epHandler := mtracing.NewEntryPoint(context.Background(), newTracing, "test", http.NotFoundHandler()) + newTracing, closer, err := tracing.NewTracing(tracingConfig) + require.NoError(t, err) + t.Cleanup(func() { + _ = closer.Close() + }) + + chain := alice.New(tracingMiddle.WrapEntryPointHandler(context.Background(), newTracing, "test")) + epHandler, err := chain.Then(http.NotFoundHandler()) + require.NoError(t, err) for _, test := range tests { t.Run(test.desc, func(t *testing.T) { diff --git a/pkg/tracing/operation_name.go b/pkg/tracing/operation_name.go deleted file mode 100644 index 54e875569..000000000 --- a/pkg/tracing/operation_name.go +++ /dev/null @@ -1,65 +0,0 @@ -package tracing - -import ( - "crypto/sha256" - "encoding/hex" - "strings" - - "github.com/rs/zerolog/log" -) - -// TraceNameHashLength defines the number of characters to use from the head of the generated hash. -const TraceNameHashLength = 8 - -// OperationNameMaxLengthNumber defines the number of static characters in a Span Trace name: -// 8 chars for hash + 2 chars for '_'. -const OperationNameMaxLengthNumber = 10 - -func generateOperationName(prefix string, parts []string, sep string, spanLimit int) string { - name := prefix + " " + strings.Join(parts, sep) - - maxLength := OperationNameMaxLengthNumber + len(prefix) + 1 - - if spanLimit > 0 && len(name) > spanLimit { - if spanLimit < maxLength { - log.Warn().Msgf("SpanNameLimit cannot be lesser than %d: falling back on %d", maxLength, maxLength+3) - spanLimit = maxLength + 3 - } - - limit := (spanLimit - maxLength) / 2 - - var fragments []string - for _, value := range parts { - fragments = append(fragments, truncateString(value, limit)) - } - fragments = append(fragments, computeHash(name)) - - name = prefix + " " + strings.Join(fragments, sep) - } - - return name -} - -// truncateString reduces the length of the 'str' argument to 'num' - 3 and adds a '...' suffix to the tail. -func truncateString(str string, num int) string { - text := str - if len(str) > num { - if num > 3 { - num -= 3 - } - text = str[0:num] + "..." - } - return text -} - -// computeHash returns the first TraceNameHashLength character of the sha256 hash for 'name' argument. -func computeHash(name string) string { - data := []byte(name) - hash := sha256.New() - if _, err := hash.Write(data); err != nil { - // Impossible case - log.Error().Str("OperationName", name).Err(err).Msgf("Failed to create Span name hash for %s", name) - } - - return hex.EncodeToString(hash.Sum(nil))[:TraceNameHashLength] -} diff --git a/pkg/tracing/operation_name_test.go b/pkg/tracing/operation_name_test.go deleted file mode 100644 index 4c9c746bd..000000000 --- a/pkg/tracing/operation_name_test.go +++ /dev/null @@ -1,135 +0,0 @@ -package tracing - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func Test_generateOperationName(t *testing.T) { - testCases := []struct { - desc string - prefix string - parts []string - sep string - spanLimit int - expected string - }{ - { - desc: "empty", - expected: " ", - }, - { - desc: "with prefix, without parts", - prefix: "foo", - parts: []string{}, - sep: "-", - spanLimit: 0, - expected: "foo ", - }, - { - desc: "with prefix, without parts, too small span limit", - prefix: "foo", - parts: []string{}, - sep: "-", - spanLimit: 1, - expected: "foo 6c2d2c76", - }, - { - desc: "with prefix, with parts", - prefix: "foo", - parts: []string{"fii", "fuu", "fee", "faa"}, - sep: "-", - spanLimit: 0, - expected: "foo fii-fuu-fee-faa", - }, - { - desc: "with prefix, with parts, with span limit", - prefix: "foo", - parts: []string{"fff", "ooo", "ooo", "bbb", "aaa", "rrr"}, - sep: "-", - spanLimit: 20, - expected: "foo fff-ooo-ooo-bbb-aaa-rrr-1a8e8ac1", - }, - } - - for _, test := range testCases { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - - opName := generateOperationName(test.prefix, test.parts, test.sep, test.spanLimit) - assert.Equal(t, test.expected, opName) - }) - } -} - -func TestComputeHash(t *testing.T) { - testCases := []struct { - desc string - text string - expected string - }{ - { - desc: "hashing", - text: "some very long piece of text", - expected: "0c6e798b", - }, - { - desc: "short text less than limit 10", - text: "short", - expected: "f9b0078b", - }, - } - - for _, test := range testCases { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - - actual := computeHash(test.text) - - assert.Equal(t, test.expected, actual) - }) - } -} - -func TestTruncateString(t *testing.T) { - testCases := []struct { - desc string - text string - limit int - expected string - }{ - { - desc: "short text less than limit 10", - text: "short", - limit: 10, - expected: "short", - }, - { - desc: "basic truncate with limit 10", - text: "some very long piece of text", - limit: 10, - expected: "some ve...", - }, - { - desc: "truncate long FQDN to 39 chars", - text: "some-service-100.slug.namespace.environment.domain.tld", - limit: 39, - expected: "some-service-100.slug.namespace.envi...", - }, - } - - for _, test := range testCases { - test := test - t.Run(test.desc, func(t *testing.T) { - t.Parallel() - - actual := truncateString(test.text, test.limit) - - assert.Equal(t, test.expected, actual) - assert.LessOrEqual(t, len(actual), test.limit) - }) - } -} diff --git a/pkg/tracing/tracing.go b/pkg/tracing/tracing.go index d8923f510..6bb382920 100644 --- a/pkg/tracing/tracing.go +++ b/pkg/tracing/tracing.go @@ -2,182 +2,213 @@ package tracing import ( "context" - "errors" "fmt" "io" + "net" "net/http" + "strconv" - "github.com/opentracing/opentracing-go" - "github.com/opentracing/opentracing-go/ext" "github.com/rs/zerolog/log" + "github.com/traefik/traefik/v3/pkg/config/static" + "github.com/traefik/traefik/v3/pkg/tracing/opentelemetry" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/propagation" + semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + "go.opentelemetry.io/otel/trace" ) -type contextKey int - -const ( - // SpanKindNoneEnum Span kind enum none. - SpanKindNoneEnum ext.SpanKindEnum = "none" - tracingKey contextKey = iota -) - -// WithTracing Adds Tracing into the context. -func WithTracing(ctx context.Context, tracing *Tracing) context.Context { - return context.WithValue(ctx, tracingKey, tracing) -} - -// FromContext Gets Tracing from context. -func FromContext(ctx context.Context) (*Tracing, error) { - if ctx == nil { - panic("nil context") - } - - tracer, ok := ctx.Value(tracingKey).(*Tracing) - if !ok { - return nil, errors.New("unable to find tracing in the context") - } - return tracer, nil -} - -// Backend is an abstraction for tracking backend (Jaeger, Zipkin, ...). +// Backend is an abstraction for tracking backend (OpenTelemetry, ...). type Backend interface { - Setup(componentName string) (opentracing.Tracer, io.Closer, error) -} - -// Tracing middleware. -type Tracing struct { - ServiceName string `description:"Sets the name for this service" export:"true"` - SpanNameLimit int `description:"Sets the maximum character limit for span names (default 0 = no limit)" export:"true"` - - tracer opentracing.Tracer - closer io.Closer + Setup(serviceName string, sampleRate float64, globalAttributes map[string]string, headers map[string]string) (trace.Tracer, io.Closer, error) } // NewTracing Creates a Tracing. -func NewTracing(serviceName string, spanNameLimit int, tracingBackend Backend) (*Tracing, error) { - tracing := &Tracing{ - ServiceName: serviceName, - SpanNameLimit: spanNameLimit, +func NewTracing(conf *static.Tracing) (trace.Tracer, io.Closer, error) { + var backend Backend + + if conf.OTLP != nil { + backend = conf.OTLP } - var err error - tracing.tracer, tracing.closer, err = tracingBackend.Setup(serviceName) + if backend == nil { + log.Debug().Msg("Could not initialize tracing, using OpenTelemetry by default") + defaultBackend := &opentelemetry.Config{} + backend = defaultBackend + } + + return backend.Setup(conf.ServiceName, conf.SampleRate, conf.GlobalAttributes, conf.Headers) +} + +// TracerFromContext extracts the trace.Tracer from the given context. +func TracerFromContext(ctx context.Context) trace.Tracer { + span := trace.SpanFromContext(ctx) + if span != nil && span.TracerProvider() != nil { + return span.TracerProvider().Tracer("github.com/traefik/traefik") + } + + return nil +} + +// ExtractCarrierIntoContext reads cross-cutting concerns from the carrier into a Context. +func ExtractCarrierIntoContext(ctx context.Context, headers http.Header) context.Context { + propagator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}) + return propagator.Extract(ctx, propagation.HeaderCarrier(headers)) +} + +// InjectContextIntoCarrier sets cross-cutting concerns from the request context into the request headers. +func InjectContextIntoCarrier(req *http.Request) { + propagator := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}) + propagator.Inject(req.Context(), propagation.HeaderCarrier(req.Header)) +} + +// SetStatusErrorf flags the span as in error and log an event. +func SetStatusErrorf(ctx context.Context, format string, args ...interface{}) { + if span := trace.SpanFromContext(ctx); span != nil { + span.SetStatus(codes.Error, fmt.Sprintf(format, args...)) + } +} + +// LogClientRequest used to add span attributes from the request as a Client. +// TODO: the semconv does not implement Semantic Convention v1.23.0. +func LogClientRequest(span trace.Span, r *http.Request) { + if r == nil || span == nil { + return + } + + // Common attributes https://github.com/open-telemetry/semantic-conventions/blob/v1.23.0/docs/http/http-spans.md#common-attributes + span.SetAttributes(semconv.HTTPRequestMethodKey.String(r.Method)) + span.SetAttributes(semconv.NetworkProtocolVersion(proto(r.Proto))) + + // Client attributes https://github.com/open-telemetry/semantic-conventions/blob/v1.23.0/docs/http/http-spans.md#http-client + span.SetAttributes(semconv.URLFull(r.URL.String())) + span.SetAttributes(semconv.URLScheme(r.URL.Scheme)) + span.SetAttributes(semconv.UserAgentOriginal(r.UserAgent())) + + host, port, err := net.SplitHostPort(r.URL.Host) if err != nil { - return nil, err - } - return tracing, nil -} - -// StartSpan delegates to opentracing.Tracer. -func (t *Tracing) StartSpan(operationName string, opts ...opentracing.StartSpanOption) opentracing.Span { - return t.tracer.StartSpan(operationName, opts...) -} - -// StartSpanf delegates to StartSpan. -func (t *Tracing) StartSpanf(r *http.Request, spanKind ext.SpanKindEnum, opPrefix string, opParts []string, separator string, opts ...opentracing.StartSpanOption) (opentracing.Span, *http.Request, func()) { - operationName := generateOperationName(opPrefix, opParts, separator, t.SpanNameLimit) - - return StartSpan(r, operationName, spanKind, opts...) -} - -// Inject delegates to opentracing.Tracer. -func (t *Tracing) Inject(sm opentracing.SpanContext, format, carrier interface{}) error { - return t.tracer.Inject(sm, format, carrier) -} - -// Extract delegates to opentracing.Tracer. -func (t *Tracing) Extract(format, carrier interface{}) (opentracing.SpanContext, error) { - return t.tracer.Extract(format, carrier) -} - -// IsEnabled determines if tracing was successfully activated. -func (t *Tracing) IsEnabled() bool { - return t != nil && t.tracer != nil -} - -// Close tracer. -func (t *Tracing) Close() { - if t.closer != nil { - err := t.closer.Close() - if err != nil { - log.Warn().Err(err).Send() + span.SetAttributes(attribute.String("network.peer.address", host)) + span.SetAttributes(semconv.ServerAddress(r.URL.Host)) + switch r.URL.Scheme { + case "http": + span.SetAttributes(attribute.String("network.peer.port", "80")) + span.SetAttributes(semconv.ServerPort(80)) + case "https": + span.SetAttributes(attribute.String("network.peer.port", "443")) + span.SetAttributes(semconv.ServerPort(443)) } + } else { + span.SetAttributes(attribute.String("network.peer.address", host)) + span.SetAttributes(attribute.String("network.peer.port", port)) + intPort, _ := strconv.Atoi(port) + span.SetAttributes(semconv.ServerAddress(host)) + span.SetAttributes(semconv.ServerPort(intPort)) } } -// LogRequest used to create span tags from the request. -func LogRequest(span opentracing.Span, r *http.Request) { - if span != nil && r != nil { - ext.HTTPMethod.Set(span, r.Method) - ext.HTTPUrl.Set(span, r.URL.String()) - span.SetTag("http.host", r.Host) +// LogServerRequest used to add span attributes from the request as a Server. +// TODO: the semconv does not implement Semantic Convention v1.23.0. +func LogServerRequest(span trace.Span, r *http.Request) { + if r == nil { + return + } + + // Common attributes https://github.com/open-telemetry/semantic-conventions/blob/v1.23.0/docs/http/http-spans.md#common-attributes + span.SetAttributes(semconv.HTTPRequestMethodKey.String(r.Method)) + span.SetAttributes(semconv.NetworkProtocolVersion(proto(r.Proto))) + + // Server attributes https://github.com/open-telemetry/semantic-conventions/blob/v1.23.0/docs/http/http-spans.md#http-server-semantic-conventions + span.SetAttributes(semconv.HTTPRequestBodySize(int(r.ContentLength))) + span.SetAttributes(semconv.URLPath(r.URL.Path)) + span.SetAttributes(semconv.URLQuery(r.URL.RawQuery)) + span.SetAttributes(semconv.URLScheme(r.Header.Get("X-Forwarded-Proto"))) + span.SetAttributes(semconv.UserAgentOriginal(r.UserAgent())) + span.SetAttributes(semconv.ServerAddress(r.Host)) + + host, port, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + span.SetAttributes(semconv.ClientAddress(r.RemoteAddr)) + span.SetAttributes(attribute.String("network.peer.address", r.RemoteAddr)) + } else { + span.SetAttributes(attribute.String("network.peer.address", host)) + span.SetAttributes(attribute.String("network.peer.port", port)) + span.SetAttributes(semconv.ClientAddress(host)) + intPort, _ := strconv.Atoi(port) + span.SetAttributes(semconv.ClientPort(intPort)) + } + + span.SetAttributes(semconv.ClientSocketAddress(r.Header.Get("X-Forwarded-For"))) +} + +func proto(proto string) string { + switch proto { + case "HTTP/1.0": + return "1.0" + case "HTTP/1.1": + return "1.1" + case "HTTP/2": + return "2" + case "HTTP/3": + return "3" + default: + return proto } } // LogResponseCode used to log response code in span. -func LogResponseCode(span opentracing.Span, code int) { +func LogResponseCode(span trace.Span, code int, spanKind trace.SpanKind) { if span != nil { - ext.HTTPStatusCode.Set(span, uint16(code)) - if code >= http.StatusInternalServerError { - ext.Error.Set(span, true) + var status codes.Code + var desc string + switch spanKind { + case trace.SpanKindServer: + status, desc = ServerStatus(code) + case trace.SpanKindClient: + status, desc = ClientStatus(code) + default: + status, desc = DefaultStatus(code) + } + span.SetStatus(status, desc) + if code > 0 { + span.SetAttributes(semconv.HTTPResponseStatusCode(code)) } } } -// GetSpan used to retrieve span from request context. -func GetSpan(r *http.Request) opentracing.Span { - return opentracing.SpanFromContext(r.Context()) -} - -// InjectRequestHeaders used to inject OpenTracing headers into the request. -func InjectRequestHeaders(r *http.Request) { - if span := GetSpan(r); span != nil { - err := opentracing.GlobalTracer().Inject( - span.Context(), - opentracing.HTTPHeaders, - opentracing.HTTPHeadersCarrier(r.Header)) - if err != nil { - log.Ctx(r.Context()).Error().Err(err).Send() - } +// ServerStatus returns a span status code and message for an HTTP status code +// value returned by a server. Status codes in the 400-499 range are not +// returned as errors. +func ServerStatus(code int) (codes.Code, string) { + if code < 100 || code >= 600 { + return codes.Error, fmt.Sprintf("Invalid HTTP status code %d", code) } -} - -// LogEventf logs an event to the span in the request context. -func LogEventf(r *http.Request, format string, args ...interface{}) { - if span := GetSpan(r); span != nil { - span.LogKV("event", fmt.Sprintf(format, args...)) + if code >= 500 { + return codes.Error, "" } + return codes.Unset, "" } -// StartSpan starts a new span from the one in the request context. -func StartSpan(r *http.Request, operationName string, spanKind ext.SpanKindEnum, opts ...opentracing.StartSpanOption) (opentracing.Span, *http.Request, func()) { - span, ctx := opentracing.StartSpanFromContext(r.Context(), operationName, opts...) - - switch spanKind { - case ext.SpanKindRPCClientEnum: - ext.SpanKindRPCClient.Set(span) - case ext.SpanKindRPCServerEnum: - ext.SpanKindRPCServer.Set(span) - case ext.SpanKindProducerEnum: - ext.SpanKindProducer.Set(span) - case ext.SpanKindConsumerEnum: - ext.SpanKindConsumer.Set(span) - default: - // noop +// ClientStatus returns a span status code and message for an HTTP status code +// value returned by a server. Status codes in the 400-499 range are not +// returned as errors. +func ClientStatus(code int) (codes.Code, string) { + if code < 100 || code >= 600 { + return codes.Error, fmt.Sprintf("Invalid HTTP status code %d", code) } - - r = r.WithContext(ctx) - return span, r, func() { span.Finish() } -} - -// SetError flags the span associated with this request as in error. -func SetError(r *http.Request) { - if span := GetSpan(r); span != nil { - ext.Error.Set(span, true) + if code >= 400 { + return codes.Error, "" } + return codes.Unset, "" } -// SetErrorWithEvent flags the span associated with this request as in error and log an event. -func SetErrorWithEvent(r *http.Request, format string, args ...interface{}) { - SetError(r) - LogEventf(r, format, args...) +// DefaultStatus returns a span status code and message for an HTTP status code +// value generated internally. +func DefaultStatus(code int) (codes.Code, string) { + if code < 100 || code >= 600 { + return codes.Error, fmt.Sprintf("Invalid HTTP status code %d", code) + } + if code >= 500 { + return codes.Error, "" + } + return codes.Unset, "" } diff --git a/pkg/tracing/zipkin/zipkin.go b/pkg/tracing/zipkin/zipkin.go deleted file mode 100644 index 598f38037..000000000 --- a/pkg/tracing/zipkin/zipkin.go +++ /dev/null @@ -1,71 +0,0 @@ -package zipkin - -import ( - "io" - "time" - - "github.com/opentracing/opentracing-go" - zipkinot "github.com/openzipkin-contrib/zipkin-go-opentracing" - "github.com/openzipkin/zipkin-go" - "github.com/openzipkin/zipkin-go/reporter/http" - "github.com/rs/zerolog/log" -) - -// Name sets the name of this tracer. -const Name = "zipkin" - -// Config provides configuration settings for a zipkin tracer. -type Config struct { - HTTPEndpoint string `description:"Sets the HTTP Endpoint to report traces to." json:"httpEndpoint,omitempty" toml:"httpEndpoint,omitempty" yaml:"httpEndpoint,omitempty"` - SameSpan bool `description:"Uses SameSpan RPC style traces." json:"sameSpan,omitempty" toml:"sameSpan,omitempty" yaml:"sameSpan,omitempty" export:"true"` - ID128Bit bool `description:"Uses 128 bits root span IDs." json:"id128Bit,omitempty" toml:"id128Bit,omitempty" yaml:"id128Bit,omitempty" export:"true"` - SampleRate float64 `description:"Sets the rate between 0.0 and 1.0 of requests to trace." json:"sampleRate,omitempty" toml:"sampleRate,omitempty" yaml:"sampleRate,omitempty" export:"true"` -} - -// SetDefaults sets the default values. -func (c *Config) SetDefaults() { - c.HTTPEndpoint = "http://localhost:9411/api/v2/spans" - c.SameSpan = false - c.ID128Bit = true - c.SampleRate = 1.0 -} - -// Setup sets up the tracer. -func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error) { - // create our local endpoint - endpoint, err := zipkin.NewEndpoint(serviceName, "0.0.0.0:0") - if err != nil { - return nil, nil, err - } - - // create our sampler - sampler, err := zipkin.NewBoundarySampler(c.SampleRate, time.Now().Unix()) - if err != nil { - return nil, nil, err - } - - // create the span reporter - reporter := http.NewReporter(c.HTTPEndpoint) - - // create the native Zipkin tracer - nativeTracer, err := zipkin.NewTracer( - reporter, - zipkin.WithLocalEndpoint(endpoint), - zipkin.WithSharedSpans(c.SameSpan), - zipkin.WithTraceID128Bit(c.ID128Bit), - zipkin.WithSampler(sampler), - ) - if err != nil { - return nil, nil, err - } - - // wrap the Zipkin native tracer with the OpenTracing Bridge - tracer := zipkinot.Wrap(nativeTracer) - - // Without this, child spans are getting the NOOP tracer - opentracing.SetGlobalTracer(tracer) - - log.Debug().Msg("Zipkin tracer configured") - - return tracer, reporter, nil -} From fea94a3393eeb07bd6bec7426cf5ff49c65b53c4 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 9 Jan 2024 10:28:05 +0100 Subject: [PATCH 20/21] feat: upgrade gateway api to v1.0.0 --- docs/content/providers/kubernetes-gateway.md | 12 +- ....networking.k8s.io_backendtlspolicies.yaml | 281 + ...eway.networking.k8s.io_gatewayclasses.yaml | 549 +- .../gateway.networking.k8s.io_gateways.yaml | 1710 +-- .../gateway.networking.k8s.io_grpcroutes.yaml | 819 ++ .../gateway.networking.k8s.io_httproutes.yaml | 3351 +++--- ...way.networking.k8s.io_referencegrants.yaml | 205 + .../gateway.networking.k8s.io_tcproutes.yaml | 619 +- .../gateway.networking.k8s.io_tlsroutes.yaml | 678 +- .../gateway.networking.k8s.io_udproutes.yaml | 284 + .../kubernetes-gateway-resource.yml | 6 +- .../kubernetes-gateway-simple-https.yml | 6 +- .../kubernetes-gateway.md | 4 + .../routing/providers/kubernetes-gateway.md | 32 +- go.mod | 74 +- go.sum | 224 +- .../fixtures/k8s/01-gateway-api-crd.yml | 9486 +++++++++++++++-- integration/fixtures/k8s/03-gateway.yml | 12 +- pkg/provider/kubernetes/gateway/client.go | 51 +- .../kubernetes/gateway/client_mock_test.go | 32 +- .../kubernetes/gateway/client_test.go | 70 +- .../httproute/filter_http_to_https.yml | 6 +- ...r_http_to_https_with_hostname_and_port.yml | 6 +- .../gatewayclass_with_unknown_controller.yml | 6 +- .../httproute/one_rule_two_targets.yml | 6 +- .../gateway/fixtures/httproute/simple.yml | 6 +- .../httproute/simple_cross_provider.yml | 6 +- .../httproute/simple_to_api_internal.yml | 6 +- .../httproute/simple_with_bad_rule.yml | 6 +- .../httproute/simple_with_tls_entrypoint.yml | 6 +- .../gateway/fixtures/httproute/two_rules.yml | 6 +- .../fixtures/httproute/with_multiple_host.yml | 6 +- .../fixtures/httproute/with_namespace_all.yml | 8 +- .../httproute/with_namespace_same.yml | 8 +- .../httproute/with_namespace_selector.yml | 8 +- .../httproute/with_protocol_https.yml | 6 +- ...th_protocol_https_with_tls_passthrough.yml | 6 +- .../with_protocol_https_without_tls.yml | 6 +- .../fixtures/httproute/with_protocol_tcp.yml | 6 +- .../fixtures/httproute/with_protocol_tls.yml | 6 +- .../fixtures/httproute/with_several_rules.yml | 6 +- .../httproute/with_tls_configuration.yml | 4 +- .../with_two_gateways_one_httproute.yml | 8 +- .../with_two_listeners_one_httproute.yml | 6 +- .../httproute/with_wrong_service_port.yml | 6 +- .../httproute/without_gatewayclass.yml | 4 +- .../fixtures/httproute/without_httproute.yml | 4 +- .../gateway/fixtures/mixed/simple.yml | 6 +- .../mixed/with_bad_listener_protocol.yml | 6 +- .../mixed/with_bad_listener_route_kind.yml | 6 +- .../fixtures/mixed/with_core_group.yml | 6 +- ...h_incompatible_protocol_and_route_kind.yml | 6 +- ...ners_using_same_hostname_port_protocol.yml | 12 +- .../fixtures/mixed/with_namespace_all.yml | 8 +- .../fixtures/mixed/with_namespace_same.yml | 8 +- .../mixed/with_namespace_selector.yml | 8 +- .../mixed/with_wrong_routes_selector.yml | 6 +- .../gatewayclass_with_unknown_controller.yml | 4 +- .../gateway/fixtures/tcproute/simple.yml | 4 +- .../tcproute/simple_cross_provider.yml | 4 +- .../tcproute/with_multiple_routes.yml | 4 +- .../fixtures/tcproute/with_multiple_rules.yml | 4 +- .../fixtures/tcproute/with_namespace_all.yml | 4 +- .../fixtures/tcproute/with_namespace_same.yml | 4 +- .../tcproute/with_namespace_selector.yml | 4 +- .../fixtures/tcproute/with_protocol_http.yml | 4 +- .../fixtures/tcproute/with_protocol_https.yml | 4 +- .../fixtures/tcproute/with_protocol_tls.yml | 4 +- .../tcproute/with_tls_configuration.yml | 4 +- .../tcproute/with_wrong_service_port.yml | 4 +- .../tcproute/without_gatewayclass.yml | 2 +- .../fixtures/tcproute/without_tcproute.yml | 4 +- .../without_tcproute_tls_protocol.yml | 4 +- .../gatewayclass_with_unknown_controller.yml | 4 +- .../tlsroute/simple_TLS_to_TCPRoute.yml | 4 +- .../simple_TLS_to_TCPRoute_passthrough.yml | 4 +- .../tlsroute/simple_TLS_to_TLSRoute.yml | 4 +- .../tlsroute/simple_cross_provider.yml | 4 +- .../fixtures/tlsroute/with_SNI_matching.yml | 4 +- .../tlsroute/with_invalid_SNI_matching.yml | 4 +- .../tlsroute/with_multiple_SNI_matching.yml | 4 +- .../tlsroute/with_multiple_routes_kind.yml | 4 +- .../fixtures/tlsroute/with_multiple_rules.yml | 4 +- .../fixtures/tlsroute/with_namespace_all.yml | 4 +- .../fixtures/tlsroute/with_namespace_same.yml | 4 +- .../tlsroute/with_namespace_selector.yml | 4 +- .../fixtures/tlsroute/with_passthrough.yml | 4 +- .../tlsroute/with_passthrough_tls.yml | 4 +- .../fixtures/tlsroute/with_protocol_http.yml | 4 +- .../fixtures/tlsroute/with_protocol_https.yml | 4 +- .../fixtures/tlsroute/with_protocol_tcp.yml | 4 +- .../tlsroute/with_wrong_service_port.yml | 4 +- .../tlsroute/without_gatewayclass.yml | 2 +- .../fixtures/tlsroute/without_tlsroute.yml | 4 +- .../fixtures/with_two_hosts_one_wildcard.yml | 6 +- .../fixtures/with_two_hosts_wildcard.yml | 6 +- pkg/provider/kubernetes/gateway/kubernetes.go | 288 +- .../kubernetes/gateway/kubernetes_test.go | 514 +- pkg/provider/kubernetes/k8s/event_handler.go | 2 +- 99 files changed, 15229 insertions(+), 4466 deletions(-) create mode 100644 docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_backendtlspolicies.yaml create mode 100644 docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_grpcroutes.yaml create mode 100644 docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_referencegrants.yaml create mode 100644 docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_udproutes.yaml diff --git a/docs/content/providers/kubernetes-gateway.md b/docs/content/providers/kubernetes-gateway.md index 6f371c6c7..e23fef820 100644 --- a/docs/content/providers/kubernetes-gateway.md +++ b/docs/content/providers/kubernetes-gateway.md @@ -80,17 +80,13 @@ This provider is proposed as an experimental feature and partially supports the The Kubernetes Gateway API project provides several guides on how to use the APIs. These guides can help you to go further than the example above. -The [getting started guide](https://gateway-api.sigs.k8s.io/v1alpha2/guides/) details how to install the CRDs from their repository. - -!!! note "" - - Keep in mind that the Traefik Gateway provider only supports the `v0.4.0` (v1alpha2). +The [getting started guide](https://gateway-api.sigs.k8s.io/guides/) details how to install the CRDs from their repository. For now, the Traefik Gateway Provider can be used while following the below guides: -* [Simple Gateway](https://gateway-api.sigs.k8s.io/v1alpha2/guides/simple-gateway/) -* [HTTP routing](https://gateway-api.sigs.k8s.io/v1alpha2/guides/http-routing/) -* [TLS](https://gateway-api.sigs.k8s.io/v1alpha2/guides/tls/) +* [Simple Gateway](https://gateway-api.sigs.k8s.io/guides/simple-gateway/) +* [HTTP routing](https://gateway-api.sigs.k8s.io/guides/http-routing/) +* [TLS](https://gateway-api.sigs.k8s.io/guides/tls/) ## Resource Configuration diff --git a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_backendtlspolicies.yaml b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_backendtlspolicies.yaml new file mode 100644 index 000000000..bb90c54d0 --- /dev/null +++ b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -0,0 +1,281 @@ +# Copyright 2023 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. + +# +# Gateway API Experimental channel install +# +# +# config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml +# +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + labels: + gateway.networking.k8s.io/policy: Direct + name: backendtlspolicies.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: BackendTLSPolicy + listKind: BackendTLSPolicyList + plural: backendtlspolicies + shortNames: + - btlspolicy + singular: backendtlspolicy + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: BackendTLSPolicy provides a way to configure how a Gateway connects to a Backend via TLS. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of BackendTLSPolicy. + properties: + targetRef: + description: "TargetRef identifies an API object to apply the policy to. Only Services have Extended support. Implementations MAY support additional objects, with Implementation Specific support. Note that this config applies to the entire referenced resource by default, but this default may change in the future to provide a more granular application of the policy. \n Support: Extended for Kubernetes Service \n Support: Implementation-specific for any other resource" + properties: + group: + description: Group is the group of the target resource. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the target resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the target resource. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace is the namespace of the referent. When unspecified, the local namespace is inferred. Even when policy targets a resource in a different namespace, it MUST only apply to traffic originating from the same namespace as the policy. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within the target resource. When unspecified, this targetRef targets the entire resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name * Service: Port Name \n If a SectionName is specified, but does not exist on the targeted object, the Policy must fail to attach, and the policy implementation should record a `ResolvedRefs` or similar Condition in the Policy's status." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - group + - kind + - name + type: object + tls: + description: TLS contains backend TLS policy configuration. + properties: + caCertRefs: + description: "CACertRefs contains one or more references to Kubernetes objects that contain a PEM-encoded TLS CA certificate bundle, which is used to validate a TLS handshake between the Gateway and backend Pod. \n If CACertRefs is empty or unspecified, then WellKnownCACerts must be specified. Only one of CACertRefs or WellKnownCACerts may be specified, not both. If CACertRefs is empty or unspecified, the configuration for WellKnownCACerts MUST be honored instead. \n References to a resource in a different namespace are invalid for the moment, although we will revisit this in the future. \n A single CACertRef to a Kubernetes ConfigMap kind has \"Core\" support. Implementations MAY choose to support attaching multiple certificates to a backend, but this behavior is implementation-specific. \n Support: Core - An optional single reference to a Kubernetes ConfigMap, with the CA certificate in a key named `ca.crt`. \n Support: Implementation-specific (More than one reference, or other kinds of resources)." + items: + description: "LocalObjectReference identifies an API object within the namespace of the referrer. The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid. \n References to objects with invalid Group and Kind are not valid, and must be rejected by the implementation, with appropriate Conditions set on the containing object." + properties: + group: + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + maxItems: 8 + type: array + hostname: + description: "Hostname is used for two purposes in the connection between Gateways and backends: \n 1. Hostname MUST be used as the SNI to connect to the backend (RFC 6066). 2. Hostname MUST be used for authentication and MUST match the certificate served by the matching backend. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + wellKnownCACerts: + description: "WellKnownCACerts specifies whether system CA certificates may be used in the TLS handshake between the gateway and backend pod. \n If WellKnownCACerts is unspecified or empty (\"\"), then CACertRefs must be specified with at least one entry for a valid configuration. Only one of CACertRefs or WellKnownCACerts may be specified, not both. \n Support: Core for \"System\"" + enum: + - System + type: string + required: + - hostname + type: object + x-kubernetes-validations: + - message: must not contain both CACertRefs and WellKnownCACerts + rule: '!(has(self.caCertRefs) && size(self.caCertRefs) > 0 && has(self.wellKnownCACerts) && self.wellKnownCACerts != "")' + - message: must specify either CACertRefs or WellKnownCACerts + rule: (has(self.caCertRefs) && size(self.caCertRefs) > 0 || has(self.wellKnownCACerts) && self.wellKnownCACerts != "") + required: + - targetRef + - tls + type: object + status: + description: Status defines the current state of BackendTLSPolicy. + properties: + ancestors: + description: "Ancestors is a list of ancestor resources (usually Gateways) that are associated with the policy, and the status of the policy with respect to each ancestor. When this policy attaches to a parent, the controller that manages the parent and the ancestors MUST add an entry to this list when the controller first sees the policy and SHOULD update the entry as appropriate when the relevant ancestor is modified. \n Note that choosing the relevant ancestor is left to the Policy designers; an important part of Policy design is designing the right object level at which to namespace this status. \n Note also that implementations MUST ONLY populate ancestor status for the Ancestor resources they are responsible for. Implementations MUST use the ControllerName field to uniquely identify the entries in this list that they are responsible for. \n Note that to achieve this, the list of PolicyAncestorStatus structs MUST be treated as a map with a composite key, made up of the AncestorRef and ControllerName fields combined. \n A maximum of 16 ancestors will be represented in this list. An empty list means the Policy is not relevant for any ancestors. \n If this slice is full, implementations MUST NOT add further entries. Instead they MUST consider the policy unimplementable and signal that on any related resources such as the ancestor that would be referenced here. For example, if this list was full on BackendTLSPolicy, no additional Gateways would be able to reference the Service targeted by the BackendTLSPolicy." + items: + description: "PolicyAncestorStatus describes the status of a route with respect to an associated Ancestor. \n Ancestors refer to objects that are either the Target of a policy or above it in terms of object hierarchy. For example, if a policy targets a Service, the Policy's Ancestors are, in order, the Service, the HTTPRoute, the Gateway, and the GatewayClass. Almost always, in this hierarchy, the Gateway will be the most useful object to place Policy status on, so we recommend that implementations SHOULD use Gateway as the PolicyAncestorStatus object unless the designers have a _very_ good reason otherwise. \n In the context of policy attachment, the Ancestor is used to distinguish which resource results in a distinct application of this policy. For example, if a policy targets a Service, it may have a distinct result per attached Gateway. \n Policies targeting the same resource may have different effects depending on the ancestors of those resources. For example, different Gateways targeting the same Service may have different capabilities, especially if they have different underlying implementations. \n For example, in BackendTLSPolicy, the Policy attaches to a Service that is used as a backend in a HTTPRoute that is itself attached to a Gateway. In this case, the relevant object for status is the Gateway, and that is the ancestor object referred to in this status. \n Note that a parent is also an ancestor, so for objects where the parent is the relevant object for status, this struct SHOULD still be used. \n This struct is intended to be used in a slice that's effectively a map, with a composite key made up of the AncestorRef and the ControllerName." + properties: + ancestorRef: + description: AncestorRef corresponds with a ParentRef in the spec that this PolicyAncestorStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + conditions: + description: Conditions describes the status of the Policy with respect to the given Ancestor. + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates the name of the controller that wrote this status. This corresponds with the controllerName field on GatewayClass. \n Example: \"example.net/gateway-controller\". \n The format of this field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). \n Controllers MUST populate this field when writing status. Controllers should ensure that entries to status populated with their ControllerName are cleaned up when they are no longer necessary." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + required: + - ancestorRef + - controllerName + type: object + maxItems: 16 + type: array + required: + - ancestors + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_gatewayclasses.yaml b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_gatewayclasses.yaml index cac5b0ee7..7ebf7c706 100644 --- a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_gatewayclasses.yaml +++ b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_gatewayclasses.yaml @@ -1,226 +1,381 @@ - ---- +# +# config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml +# apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: gatewayclasses.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io names: categories: - - gateway-api + - gateway-api kind: GatewayClass listKind: GatewayClassList plural: gatewayclasses shortNames: - - gc + - gc singular: gatewayclass scope: Cluster versions: - - additionalPrinterColumns: - - jsonPath: .spec.controller - name: Controller - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - - jsonPath: .spec.description - name: Description - priority: 1 - type: string - name: v1alpha2 - schema: - openAPIV3Schema: - description: "GatewayClass describes a class of Gateways available to the - user for creating Gateway resources. \n It is recommended that this resource - be used as a template for Gateways. This means that a Gateway is based on - the state of the GatewayClass at the time it was created and changes to - the GatewayClass or associated parameters are not propagated down to existing - Gateways. This recommendation is intended to limit the blast radius of changes - to GatewayClass or associated parameters. If implementations choose to propagate - GatewayClass changes to existing Gateways, that MUST be clearly documented - by the implementation. \n Whenever one or more Gateways are using a GatewayClass, - implementations MUST add the `gateway-exists-finalizer.gateway.networking.k8s.io` - finalizer on the associated GatewayClass. This ensures that a GatewayClass - associated with a Gateway is not deleted while in use. \n GatewayClass is - a Cluster level resource." - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Spec defines the desired state of GatewayClass. - properties: - controllerName: - description: "ControllerName is the name of the controller that is - managing Gateways of this class. The value of this field MUST be - a domain prefixed path. \n Example: \"example.net/gateway-controller\". - \n This field is not mutable and cannot be empty. \n Support: Core" - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ - type: string - description: - description: Description helps describe a GatewayClass with more details. - maxLength: 64 - type: string - parametersRef: - description: "ParametersRef is a reference to a resource that contains - the configuration parameters corresponding to the GatewayClass. - This is optional if the controller does not require any additional - configuration. \n ParametersRef can reference a standard Kubernetes - resource, i.e. ConfigMap, or an implementation-specific custom resource. - The resource can be cluster-scoped or namespace-scoped. \n If the - referent cannot be found, the GatewayClass's \"InvalidParameters\" - status condition will be true. \n Support: Custom" - properties: - group: - description: Group is the group of the referent. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - description: Kind is kind of the referent. - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: Namespace is the namespace of the referent. This - field is required when referring to a Namespace-scoped resource - and MUST be unset when referring to a Cluster-scoped resource. - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - required: - - group - - kind - - name - type: object - required: - - controllerName - type: object - status: - default: - conditions: - - lastTransitionTime: "1970-01-01T00:00:00Z" - message: Waiting for controller - reason: Waiting - status: Unknown - type: Accepted - description: Status defines the current state of GatewayClass. - properties: - conditions: - default: - - lastTransitionTime: "1970-01-01T00:00:00Z" - message: Waiting for controller - reason: Waiting - status: Unknown - type: Accepted - description: "Conditions is the current status from the controller - for this GatewayClass. \n Controllers should prefer to publish conditions - using values of GatewayClassConditionType for the type of each Condition." - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: - \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // +listMapKey=type - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" + - additionalPrinterColumns: + - jsonPath: .spec.controllerName + name: Controller + type: string + - jsonPath: .status.conditions[?(@.type=="Accepted")].status + name: Accepted + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.description + name: Description + priority: 1 + type: string + name: v1 + schema: + openAPIV3Schema: + description: "GatewayClass describes a class of Gateways available to the user for creating Gateway resources. \n It is recommended that this resource be used as a template for Gateways. This means that a Gateway is based on the state of the GatewayClass at the time it was created and changes to the GatewayClass or associated parameters are not propagated down to existing Gateways. This recommendation is intended to limit the blast radius of changes to GatewayClass or associated parameters. If implementations choose to propagate GatewayClass changes to existing Gateways, that MUST be clearly documented by the implementation. \n Whenever one or more Gateways are using a GatewayClass, implementations SHOULD add the `gateway-exists-finalizer.gateway.networking.k8s.io` finalizer on the associated GatewayClass. This ensures that a GatewayClass associated with a Gateway is not deleted while in use. \n GatewayClass is a Cluster level resource." + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of GatewayClass. + properties: + controllerName: + description: "ControllerName is the name of the controller that is managing Gateways of this class. The value of this field MUST be a domain prefixed path. \n Example: \"example.net/gateway-controller\". \n This field is not mutable and cannot be empty. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + description: + description: Description helps describe a GatewayClass with more details. + maxLength: 64 + type: string + parametersRef: + description: "ParametersRef is a reference to a resource that contains the configuration parameters corresponding to the GatewayClass. This is optional if the controller does not require any additional configuration. \n ParametersRef can reference a standard Kubernetes resource, i.e. ConfigMap, or an implementation-specific custom resource. The resource can be cluster-scoped or namespace-scoped. \n If the referent cannot be found, the GatewayClass's \"InvalidParameters\" status condition will be true. \n Support: Implementation-specific" properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time + group: + description: Group is the group of the referent. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 + kind: + description: Kind is kind of the referent. + maxLength: 63 minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + namespace: + description: Namespace is the namespace of the referent. This field is required when referring to a Namespace-scoped resource and MUST be unset when referring to a Cluster-scoped resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string required: - - lastTransitionTime - - message - - reason - - status - - type + - group + - kind + - name type: object - maxItems: 8 - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} + required: + - controllerName + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Waiting + status: Unknown + type: Accepted + description: "Status defines the current state of GatewayClass. \n Implementations MUST populate status on all GatewayClass resources which specify their controller name." + properties: + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + description: "Conditions is the current status from the controller for this GatewayClass. \n Controllers should prefer to publish conditions using values of GatewayClassConditionType for the type of each Condition." + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + supportedFeatures: + description: 'SupportedFeatures is the set of features the GatewayClass support. It MUST be sorted in ascending alphabetical order. ' + items: + description: SupportedFeature is used to describe distinct features that are covered by conformance tests. + enum: + - Gateway + - GatewayPort8080 + - GatewayStaticAddresses + - HTTPRoute + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + - Mesh + - ReferenceGrant + - TLSRoute + type: string + maxItems: 64 + type: array + x-kubernetes-list-type: set + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.controllerName + name: Controller + type: string + - jsonPath: .status.conditions[?(@.type=="Accepted")].status + name: Accepted + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.description + name: Description + priority: 1 + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: "GatewayClass describes a class of Gateways available to the user for creating Gateway resources. \n It is recommended that this resource be used as a template for Gateways. This means that a Gateway is based on the state of the GatewayClass at the time it was created and changes to the GatewayClass or associated parameters are not propagated down to existing Gateways. This recommendation is intended to limit the blast radius of changes to GatewayClass or associated parameters. If implementations choose to propagate GatewayClass changes to existing Gateways, that MUST be clearly documented by the implementation. \n Whenever one or more Gateways are using a GatewayClass, implementations SHOULD add the `gateway-exists-finalizer.gateway.networking.k8s.io` finalizer on the associated GatewayClass. This ensures that a GatewayClass associated with a Gateway is not deleted while in use. \n GatewayClass is a Cluster level resource." + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of GatewayClass. + properties: + controllerName: + description: "ControllerName is the name of the controller that is managing Gateways of this class. The value of this field MUST be a domain prefixed path. \n Example: \"example.net/gateway-controller\". \n This field is not mutable and cannot be empty. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + description: + description: Description helps describe a GatewayClass with more details. + maxLength: 64 + type: string + parametersRef: + description: "ParametersRef is a reference to a resource that contains the configuration parameters corresponding to the GatewayClass. This is optional if the controller does not require any additional configuration. \n ParametersRef can reference a standard Kubernetes resource, i.e. ConfigMap, or an implementation-specific custom resource. The resource can be cluster-scoped or namespace-scoped. \n If the referent cannot be found, the GatewayClass's \"InvalidParameters\" status condition will be true. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace is the namespace of the referent. This field is required when referring to a Namespace-scoped resource and MUST be unset when referring to a Cluster-scoped resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + required: + - controllerName + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Waiting + status: Unknown + type: Accepted + description: "Status defines the current state of GatewayClass. \n Implementations MUST populate status on all GatewayClass resources which specify their controller name." + properties: + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + description: "Conditions is the current status from the controller for this GatewayClass. \n Controllers should prefer to publish conditions using values of GatewayClassConditionType for the type of each Condition." + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + supportedFeatures: + description: 'SupportedFeatures is the set of features the GatewayClass support. It MUST be sorted in ascending alphabetical order. ' + items: + description: SupportedFeature is used to describe distinct features that are covered by conformance tests. + enum: + - Gateway + - GatewayPort8080 + - GatewayStaticAddresses + - HTTPRoute + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + - Mesh + - ReferenceGrant + - TLSRoute + type: string + maxItems: 64 + type: array + x-kubernetes-list-type: set + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} status: acceptedNames: kind: "" plural: "" - conditions: [] - storedVersions: [] + conditions: null + storedVersions: null diff --git a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_gateways.yaml b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_gateways.yaml index 486471336..2a4b26f58 100644 --- a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_gateways.yaml +++ b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_gateways.yaml @@ -1,719 +1,1037 @@ - ---- +# +# config/crd/experimental/gateway.networking.k8s.io_gateways.yaml +# apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: gateways.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io names: categories: - - gateway-api + - gateway-api kind: Gateway listKind: GatewayList plural: gateways shortNames: - - gtw + - gtw singular: gateway scope: Namespaced versions: - - additionalPrinterColumns: - - jsonPath: .spec.gatewayClassName - name: Class - type: string - - jsonPath: .status.addresses[*].value - name: Address - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha2 - schema: - openAPIV3Schema: - description: Gateway represents an instance of a service-traffic handling - infrastructure by binding Listeners to a set of IP addresses. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Spec defines the desired state of Gateway. - properties: - addresses: - description: "Addresses requested for this Gateway. This is optional - and behavior can depend on the implementation. If a value is set - in the spec and the requested address is invalid or unavailable, - the implementation MUST indicate this in the associated entry in - GatewayStatus.Addresses. \n The Addresses field represents a request - for the address(es) on the \"outside of the Gateway\", that traffic - bound for this Gateway will use. This could be the IP address or - hostname of an external load balancer or other networking infrastructure, - or some other address that traffic will be sent to. \n The .listener.hostname - field is used to route traffic that has already arrived at the Gateway - to the correct in-cluster destination. \n If no Addresses are specified, - the implementation MAY schedule the Gateway in an implementation-specific - manner, assigning an appropriate set of Addresses. \n The implementation - MUST bind all Listeners to every GatewayAddress that it assigns - to the Gateway and add a corresponding entry in GatewayStatus.Addresses. - \n Support: Core" - items: - description: GatewayAddress describes an address that can be bound - to a Gateway. - properties: - type: - default: IPAddress - description: Type of the address. - enum: - - IPAddress - - Hostname - - NamedAddress - type: string - value: - description: "Value of the address. The validity of the values - will depend on the type and support by the controller. \n - Examples: `1.2.3.4`, `128::1`, `my-ip-address`." - maxLength: 253 - minLength: 1 - type: string - required: - - value - type: object - maxItems: 16 - type: array - gatewayClassName: - description: GatewayClassName used for this Gateway. This is the name - of a GatewayClass resource. - maxLength: 253 - minLength: 1 - type: string - listeners: - description: "Listeners associated with this Gateway. Listeners define - logical endpoints that are bound on this Gateway's addresses. At - least one Listener MUST be specified. \n Each listener in a Gateway - must have a unique combination of Hostname, Port, and Protocol. - \n An implementation MAY group Listeners by Port and then collapse - each group of Listeners into a single Listener if the implementation - determines that the Listeners in the group are \"compatible\". An - implementation MAY also group together and collapse compatible Listeners - belonging to different Gateways. \n For example, an implementation - might consider Listeners to be compatible with each other if all - of the following conditions are met: \n 1. Either each Listener - within the group specifies the \"HTTP\" Protocol or each Listener - within the group specifies either the \"HTTPS\" or \"TLS\" Protocol. - \n 2. Each Listener within the group specifies a Hostname that is - unique within the group. \n 3. As a special case, one Listener - within a group may omit Hostname, in which case this Listener - matches when no other Listener matches. \n If the implementation - does collapse compatible Listeners, the hostname provided in the - incoming client request MUST be matched to a Listener to find the - correct set of Routes. The incoming hostname MUST be matched using - the Hostname field for each Listener in order of most to least specific. - That is, exact matches must be processed before wildcard matches. - \n If this field specifies multiple Listeners that have the same - Port value but are not compatible, the implementation must raise - a \"Conflicted\" condition in the Listener status. \n Support: Core" - items: - description: Listener embodies the concept of a logical endpoint - where a Gateway accepts network connections. - properties: - allowedRoutes: - default: - namespaces: - from: Same - description: "AllowedRoutes defines the types of routes that - MAY be attached to a Listener and the trusted namespaces where - those Route resources MAY be present. \n Although a client - request may match multiple route rules, only one rule may - ultimately receive the request. Matching precedence MUST be - determined in order of the following criteria: \n * The most - specific match as defined by the Route type. * The oldest - Route based on creation timestamp. For example, a Route with - \ a creation timestamp of \"2020-09-08 01:02:03\" is given - precedence over a Route with a creation timestamp of \"2020-09-08 - 01:02:04\". * If everything else is equivalent, the Route - appearing first in alphabetical order (namespace/name) should - be given precedence. For example, foo/bar is given precedence - over foo/baz. \n All valid rules within a Route attached to - this Listener should be implemented. Invalid Route rules can - be ignored (sometimes that will mean the full Route). If a - Route rule transitions from valid to invalid, support for - that Route rule should be dropped to ensure consistency. For - example, even if a filter specified by a Route rule is invalid, - the rest of the rules within that Route should still be supported. - \n Support: Core" - properties: - kinds: - description: "Kinds specifies the groups and kinds of Routes - that are allowed to bind to this Gateway Listener. When - unspecified or empty, the kinds of Routes selected are - determined using the Listener protocol. \n A RouteGroupKind - MUST correspond to kinds of Routes that are compatible - with the application protocol specified in the Listener's - Protocol field. If an implementation does not support - or recognize this resource type, it MUST set the \"ResolvedRefs\" - condition to False for this Listener with the \"InvalidRoutesRef\" - reason. \n Support: Core" - items: - description: RouteGroupKind indicates the group and kind - of a Route resource. - properties: - group: - default: gateway.networking.k8s.io - description: Group is the group of the Route. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - description: Kind is the kind of the Route. - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - required: - - kind - type: object - maxItems: 8 - type: array - namespaces: - default: - from: Same - description: "Namespaces indicates namespaces from which - Routes may be attached to this Listener. This is restricted - to the namespace of this Gateway by default. \n Support: - Core" - properties: - from: - default: Same - description: "From indicates where Routes will be selected - for this Gateway. Possible values are: * All: Routes - in all namespaces may be used by this Gateway. * Selector: - Routes in namespaces selected by the selector may - be used by this Gateway. * Same: Only Routes in - the same namespace may be used by this Gateway. \n - Support: Core" - enum: - - All - - Selector - - Same - type: string - selector: - description: "Selector must be specified when From is - set to \"Selector\". In that case, only Routes in - Namespaces matching this Selector will be selected - by this Gateway. This field is ignored for other values - of \"From\". \n Support: Core" - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: A label selector requirement is a - selector that contains values, a key, and an - operator that relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are - In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. If the - operator is Exists or DoesNotExist, the - values array must be empty. This array is - replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is "In", - and the values array contains only "value". The - requirements are ANDed. - type: object - type: object - type: object - type: object - hostname: - description: "Hostname specifies the virtual hostname to match - for protocol types that define this concept. When unspecified, - all hostnames are matched. This field is ignored for protocols - that don't require hostname based matching. \n Implementations - MUST apply Hostname matching appropriately for each of the - following protocols: \n * TLS: The Listener Hostname MUST - match the SNI. * HTTP: The Listener Hostname MUST match the - Host header of the request. * HTTPS: The Listener Hostname - SHOULD match at both the TLS and HTTP protocol layers as - described above. If an implementation does not ensure that - both the SNI and Host header match the Listener hostname, - \ it MUST clearly document that. \n For HTTPRoute and TLSRoute - resources, there is an interaction with the `spec.hostnames` - array. When both listener and route specify hostnames, there - MUST be an intersection between the values for a Route to - be accepted. For more information, refer to the Route specific - Hostnames documentation. \n Support: Core" - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - name: - description: "Name is the name of the Listener. \n Support: - Core" - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - port: - description: "Port is the network port. Multiple listeners may - use the same port, subject to the Listener compatibility rules. - \n Support: Core" - format: int32 - maximum: 65535 - minimum: 1 - type: integer - protocol: - description: "Protocol specifies the network protocol this listener - expects to receive. \n Support: Core" - maxLength: 255 - minLength: 1 - pattern: ^[a-zA-Z0-9]([-a-zSA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$ - type: string - tls: - description: "TLS is the TLS configuration for the Listener. - This field is required if the Protocol field is \"HTTPS\" - or \"TLS\". It is invalid to set this field if the Protocol - field is \"HTTP\", \"TCP\", or \"UDP\". \n The association - of SNIs to Certificate defined in GatewayTLSConfig is defined - based on the Hostname field for this listener. \n The GatewayClass - MUST use the longest matching SNI out of all available certificates - for any TLS handshake. \n Support: Core" - properties: - certificateRefs: - description: "CertificateRefs contains a series of references - to Kubernetes objects that contains TLS certificates and - private keys. These certificates are used to establish - a TLS handshake for requests that match the hostname of - the associated listener. \n A single CertificateRef to - a Kubernetes Secret has \"Core\" support. Implementations - MAY choose to support attaching multiple certificates - to a Listener, but this behavior is implementation-specific. - \n References to a resource in different namespace are - invalid UNLESS there is a ReferencePolicy in the target - namespace that allows the certificate to be attached. - If a ReferencePolicy does not allow this reference, the - \"ResolvedRefs\" condition MUST be set to False for this - listener with the \"InvalidCertificateRef\" reason. \n - This field is required to have at least one element when - the mode is set to \"Terminate\" (default) and is optional - otherwise. \n CertificateRefs can reference to standard - Kubernetes resources, i.e. Secret, or implementation-specific - custom resources. \n Support: Core - A single reference - to a Kubernetes Secret \n Support: Implementation-specific - (More than one reference or other resource types)" - items: - description: "SecretObjectReference identifies an API - object including its namespace, defaulting to Secret. - \n The API object must be valid in the cluster; the - Group and Kind must be registered in the cluster for - this reference to be valid. \n References to objects - with invalid Group and Kind are not valid, and must - be rejected by the implementation, with appropriate - Conditions set on the containing object." - properties: - group: - default: "" - description: Group is the group of the referent. For - example, "networking.k8s.io". When unspecified (empty - string), core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Secret - description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: "Namespace is the namespace of the backend. - When unspecified, the local namespace is inferred. - \n Note that when a namespace is specified, a ReferencePolicy - object is required in the referent namespace to - allow that namespace's owner to accept the reference. - See the ReferencePolicy documentation for details. - \n Support: Core" - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - required: - - name - type: object - maxItems: 64 - type: array - mode: - default: Terminate - description: "Mode defines the TLS behavior for the TLS - session initiated by the client. There are two possible - modes: \n - Terminate: The TLS session between the downstream - client and the Gateway is terminated at the Gateway. - This mode requires certificateRefs to be set and contain - at least one element. - Passthrough: The TLS session is - NOT terminated by the Gateway. This implies that the - Gateway can't decipher the TLS stream except for the - ClientHello message of the TLS protocol. CertificateRefs - field is ignored in this mode. \n Support: Core" - enum: - - Terminate - - Passthrough - type: string - options: - additionalProperties: - description: AnnotationValue is the value of an annotation - in Gateway API. This is used for validation of maps - such as TLS options. This roughly matches Kubernetes - annotation validation, although the length validation - in that case is based on the entire size of the annotations - struct. - maxLength: 4096 - minLength: 0 - type: string - description: "Options are a list of key/value pairs to enable - extended TLS configuration for each implementation. For - example, configuring the minimum TLS version or supported - cipher suites. \n A set of common keys MAY be defined - by the API in the future. To avoid any ambiguity, implementation-specific - definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`. - Un-prefixed names are reserved for key names defined by - Gateway API. \n Support: Implementation-specific" - maxProperties: 16 - type: object - type: object - required: - - name - - port - - protocol - type: object - maxItems: 64 - minItems: 1 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - required: - - gatewayClassName - - listeners - type: object - status: - default: - conditions: - - lastTransitionTime: "1970-01-01T00:00:00Z" - message: Waiting for controller - reason: NotReconciled - status: Unknown - type: Scheduled - description: Status defines the current state of Gateway. - properties: - addresses: - description: Addresses lists the IP addresses that have actually been - bound to the Gateway. These addresses may differ from the addresses - in the Spec, e.g. if the Gateway automatically assigns an address - from a reserved pool. - items: - description: GatewayAddress describes an address that can be bound - to a Gateway. - properties: - type: - default: IPAddress - description: Type of the address. - enum: - - IPAddress - - Hostname - - NamedAddress - type: string - value: - description: "Value of the address. The validity of the values - will depend on the type and support by the controller. \n - Examples: `1.2.3.4`, `128::1`, `my-ip-address`." - maxLength: 253 - minLength: 1 - type: string - required: - - value - type: object - maxItems: 16 - type: array - conditions: - default: - - lastTransitionTime: "1970-01-01T00:00:00Z" - message: Waiting for controller - reason: NotReconciled - status: Unknown - type: Scheduled - description: "Conditions describe the current conditions of the Gateway. - \n Implementations should prefer to express Gateway conditions using - the `GatewayConditionType` and `GatewayConditionReason` constants - so that operators and tools can converge on a common vocabulary - to describe Gateway state. \n Known condition types are: \n * \"Scheduled\" - * \"Ready\"" - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: - \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // +listMapKey=type - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - maxItems: 8 - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - listeners: - description: Listeners provide status for each unique listener port - defined in the Spec. - items: - description: ListenerStatus is the status associated with a Listener. - properties: - attachedRoutes: - description: AttachedRoutes represents the total number of Routes - that have been successfully attached to this Listener. - format: int32 - type: integer - conditions: - description: Conditions describe the current condition of this - listener. - items: - description: "Condition contains details for one aspect of - the current state of this API Resource. --- This struct - is intended for direct use as an array at the field path - .status.conditions. For example, type FooStatus struct{ - \ // Represents the observations of a foo's current state. - \ // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // - +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should - be when the underlying condition changed. If that is - not known, then using the time when the API field changed - is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, - if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the - current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier - indicating the reason for the condition's last transition. - Producers of specific condition types may define expected - values and meanings for this field, and whether the - values are considered a guaranteed API. The value should - be a CamelCase string. This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string + - additionalPrinterColumns: + - jsonPath: .spec.gatewayClassName + name: Class + type: string + - jsonPath: .status.addresses[*].value + name: Address + type: string + - jsonPath: .status.conditions[?(@.type=="Programmed")].status + name: Programmed + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: Gateway represents an instance of a service-traffic handling infrastructure by binding Listeners to a set of IP addresses. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of Gateway. + properties: + addresses: + description: "Addresses requested for this Gateway. This is optional and behavior can depend on the implementation. If a value is set in the spec and the requested address is invalid or unavailable, the implementation MUST indicate this in the associated entry in GatewayStatus.Addresses. \n The Addresses field represents a request for the address(es) on the \"outside of the Gateway\", that traffic bound for this Gateway will use. This could be the IP address or hostname of an external load balancer or other networking infrastructure, or some other address that traffic will be sent to. \n If no Addresses are specified, the implementation MAY schedule the Gateway in an implementation-specific manner, assigning an appropriate set of Addresses. \n The implementation MUST bind all Listeners to every GatewayAddress that it assigns to the Gateway and add a corresponding entry in GatewayStatus.Addresses. \n Support: Extended \n " + items: + description: GatewayAddress describes an address that can be bound to a Gateway. + oneOf: + - properties: type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across - resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability - to deconflict is important. The regex it matches is - (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - maxItems: 8 - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - name: - description: Name is the name of the Listener that this status - corresponds to. - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - supportedKinds: - description: "SupportedKinds is the list indicating the Kinds - supported by this listener. This MUST represent the kinds - an implementation supports for that Listener configuration. - \n If kinds are specified in Spec that are not supported, - they MUST NOT appear in this list and an implementation MUST - set the \"ResolvedRefs\" condition to \"False\" with the \"InvalidRouteKinds\" - reason. If both valid and invalid Route kinds are specified, - the implementation MUST reference the valid Route kinds that - have been specified." - items: - description: RouteGroupKind indicates the group and kind of - a Route resource. - properties: - group: - default: gateway.networking.k8s.io - description: Group is the group of the Route. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - description: Kind is the kind of the Route. - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - required: - - kind - type: object - maxItems: 8 - type: array - required: - - attachedRoutes - - conditions - - name - - supportedKinds + enum: + - IPAddress + value: + anyOf: + - format: ipv4 + - format: ipv6 + - properties: + type: + not: + enum: + - IPAddress + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: "Value of the address. The validity of the values will depend on the type and support by the controller. \n Examples: `1.2.3.4`, `128::1`, `my-ip-address`." + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + x-kubernetes-validations: + - message: Hostname value must only contain valid characters (matching ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): true' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: IPAddress values must be unique + rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2, a2.type == a1.type && a2.value == a1.value) : true )' + - message: Hostname values must be unique + rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2, a2.type == a1.type && a2.value == a1.value) : true )' + gatewayClassName: + description: GatewayClassName used for this Gateway. This is the name of a GatewayClass resource. + maxLength: 253 + minLength: 1 + type: string + infrastructure: + description: "Infrastructure defines infrastructure level attributes about this Gateway instance. \n Support: Core \n " + properties: + annotations: + additionalProperties: + description: AnnotationValue is the value of an annotation in Gateway API. This is used for validation of maps such as TLS options. This roughly matches Kubernetes annotation validation, although the length validation in that case is based on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: "Annotations that SHOULD be applied to any resources created in response to this Gateway. \n For implementations creating other Kubernetes objects, this should be the `metadata.annotations` field on resources. For other implementations, this refers to any relevant (implementation specific) \"annotations\" concepts. \n An implementation may chose to add additional implementation-specific annotations as they see fit. \n Support: Extended" + maxProperties: 8 + type: object + labels: + additionalProperties: + description: AnnotationValue is the value of an annotation in Gateway API. This is used for validation of maps such as TLS options. This roughly matches Kubernetes annotation validation, although the length validation in that case is based on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: "Labels that SHOULD be applied to any resources created in response to this Gateway. \n For implementations creating other Kubernetes objects, this should be the `metadata.labels` field on resources. For other implementations, this refers to any relevant (implementation specific) \"labels\" concepts. \n An implementation may chose to add additional implementation-specific labels as they see fit. \n Support: Extended" + maxProperties: 8 + type: object type: object - maxItems: 64 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} + listeners: + description: "Listeners associated with this Gateway. Listeners define logical endpoints that are bound on this Gateway's addresses. At least one Listener MUST be specified. \n Each Listener in a set of Listeners (for example, in a single Gateway) MUST be _distinct_, in that a traffic flow MUST be able to be assigned to exactly one listener. (This section uses \"set of Listeners\" rather than \"Listeners in a single Gateway\" because implementations MAY merge configuration from multiple Gateways onto a single data plane, and these rules _also_ apply in that case). \n Practically, this means that each listener in a set MUST have a unique combination of Port, Protocol, and, if supported by the protocol, Hostname. \n Some combinations of port, protocol, and TLS settings are considered Core support and MUST be supported by implementations based on their targeted conformance profile: \n HTTP Profile \n 1. HTTPRoute, Port: 80, Protocol: HTTP 2. HTTPRoute, Port: 443, Protocol: HTTPS, TLS Mode: Terminate, TLS keypair provided \n TLS Profile \n 1. TLSRoute, Port: 443, Protocol: TLS, TLS Mode: Passthrough \n \"Distinct\" Listeners have the following property: \n The implementation can match inbound requests to a single distinct Listener. When multiple Listeners share values for fields (for example, two Listeners with the same Port value), the implementation can match requests to only one of the Listeners using other Listener fields. \n For example, the following Listener scenarios are distinct: \n 1. Multiple Listeners with the same Port that all use the \"HTTP\" Protocol that all have unique Hostname values. 2. Multiple Listeners with the same Port that use either the \"HTTPS\" or \"TLS\" Protocol that all have unique Hostname values. 3. A mixture of \"TCP\" and \"UDP\" Protocol Listeners, where no Listener with the same Protocol has the same Port value. \n Some fields in the Listener struct have possible values that affect whether the Listener is distinct. Hostname is particularly relevant for HTTP or HTTPS protocols. \n When using the Hostname value to select between same-Port, same-Protocol Listeners, the Hostname value must be different on each Listener for the Listener to be distinct. \n When the Listeners are distinct based on Hostname, inbound request hostnames MUST match from the most specific to least specific Hostname values to choose the correct Listener and its associated set of Routes. \n Exact matches must be processed before wildcard matches, and wildcard matches must be processed before fallback (empty Hostname value) matches. For example, `\"foo.example.com\"` takes precedence over `\"*.example.com\"`, and `\"*.example.com\"` takes precedence over `\"\"`. \n Additionally, if there are multiple wildcard entries, more specific wildcard entries must be processed before less specific wildcard entries. For example, `\"*.foo.example.com\"` takes precedence over `\"*.example.com\"`. The precise definition here is that the higher the number of dots in the hostname to the right of the wildcard character, the higher the precedence. \n The wildcard character will match any number of characters _and dots_ to the left, however, so `\"*.example.com\"` will match both `\"foo.bar.example.com\"` _and_ `\"bar.example.com\"`. \n If a set of Listeners contains Listeners that are not distinct, then those Listeners are Conflicted, and the implementation MUST set the \"Conflicted\" condition in the Listener Status to \"True\". \n Implementations MAY choose to accept a Gateway with some Conflicted Listeners only if they only accept the partial Listener set that contains no Conflicted Listeners. To put this another way, implementations may accept a partial Listener set only if they throw out *all* the conflicting Listeners. No picking one of the conflicting listeners as the winner. This also means that the Gateway must have at least one non-conflicting Listener in this case, otherwise it violates the requirement that at least one Listener must be present. \n The implementation MUST set a \"ListenersNotValid\" condition on the Gateway Status when the Gateway contains Conflicted Listeners whether or not they accept the Gateway. That Condition SHOULD clearly indicate in the Message which Listeners are conflicted, and which are Accepted. Additionally, the Listener status for those listeners SHOULD indicate which Listeners are conflicted and not Accepted. \n A Gateway's Listeners are considered \"compatible\" if: \n 1. They are distinct. 2. The implementation can serve them in compliance with the Addresses requirement that all Listeners are available on all assigned addresses. \n Compatible combinations in Extended support are expected to vary across implementations. A combination that is compatible for one implementation may not be compatible for another. \n For example, an implementation that cannot serve both TCP and UDP listeners on the same address, or cannot mix HTTPS and generic TLS listens on the same port would not consider those cases compatible, even though they are distinct. \n Note that requests SHOULD match at most one Listener. For example, if Listeners are defined for \"foo.example.com\" and \"*.example.com\", a request to \"foo.example.com\" SHOULD only be routed using routes attached to the \"foo.example.com\" Listener (and not the \"*.example.com\" Listener). This concept is known as \"Listener Isolation\". Implementations that do not support Listener Isolation MUST clearly document this. \n Implementations MAY merge separate Gateways onto a single set of Addresses if all Listeners across all Gateways are compatible. \n Support: Core" + items: + description: Listener embodies the concept of a logical endpoint where a Gateway accepts network connections. + properties: + allowedRoutes: + default: + namespaces: + from: Same + description: "AllowedRoutes defines the types of routes that MAY be attached to a Listener and the trusted namespaces where those Route resources MAY be present. \n Although a client request may match multiple route rules, only one rule may ultimately receive the request. Matching precedence MUST be determined in order of the following criteria: \n * The most specific match as defined by the Route type. * The oldest Route based on creation timestamp. For example, a Route with a creation timestamp of \"2020-09-08 01:02:03\" is given precedence over a Route with a creation timestamp of \"2020-09-08 01:02:04\". * If everything else is equivalent, the Route appearing first in alphabetical order (namespace/name) should be given precedence. For example, foo/bar is given precedence over foo/baz. \n All valid rules within a Route attached to this Listener should be implemented. Invalid Route rules can be ignored (sometimes that will mean the full Route). If a Route rule transitions from valid to invalid, support for that Route rule should be dropped to ensure consistency. For example, even if a filter specified by a Route rule is invalid, the rest of the rules within that Route should still be supported. \n Support: Core" + properties: + kinds: + description: "Kinds specifies the groups and kinds of Routes that are allowed to bind to this Gateway Listener. When unspecified or empty, the kinds of Routes selected are determined using the Listener protocol. \n A RouteGroupKind MUST correspond to kinds of Routes that are compatible with the application protocol specified in the Listener's Protocol field. If an implementation does not support or recognize this resource type, it MUST set the \"ResolvedRefs\" condition to False for this Listener with the \"InvalidRouteKinds\" reason. \n Support: Core" + items: + description: RouteGroupKind indicates the group and kind of a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + namespaces: + default: + from: Same + description: "Namespaces indicates namespaces from which Routes may be attached to this Listener. This is restricted to the namespace of this Gateway by default. \n Support: Core" + properties: + from: + default: Same + description: "From indicates where Routes will be selected for this Gateway. Possible values are: \n * All: Routes in all namespaces may be used by this Gateway. * Selector: Routes in namespaces selected by the selector may be used by this Gateway. * Same: Only Routes in the same namespace may be used by this Gateway. \n Support: Core" + enum: + - All + - Selector + - Same + type: string + selector: + description: "Selector must be specified when From is set to \"Selector\". In that case, only Routes in Namespaces matching this Selector will be selected by this Gateway. This field is ignored for other values of \"From\". \n Support: Core" + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: object + type: object + hostname: + description: "Hostname specifies the virtual hostname to match for protocol types that define this concept. When unspecified, all hostnames are matched. This field is ignored for protocols that don't require hostname based matching. \n Implementations MUST apply Hostname matching appropriately for each of the following protocols: \n * TLS: The Listener Hostname MUST match the SNI. * HTTP: The Listener Hostname MUST match the Host header of the request. * HTTPS: The Listener Hostname SHOULD match at both the TLS and HTTP protocol layers as described above. If an implementation does not ensure that both the SNI and Host header match the Listener hostname, it MUST clearly document that. \n For HTTPRoute and TLSRoute resources, there is an interaction with the `spec.hostnames` array. When both listener and route specify hostnames, there MUST be an intersection between the values for a Route to be accepted. For more information, refer to the Route specific Hostnames documentation. \n Hostnames that are prefixed with a wildcard label (`*.`) are interpreted as a suffix match. That means that a match for `*.example.com` would match both `test.example.com`, and `foo.test.example.com`, but not `example.com`. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + name: + description: "Name is the name of the Listener. This name MUST be unique within a Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + port: + description: "Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules. \n Support: Core" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + description: "Protocol specifies the network protocol this listener expects to receive. \n Support: Core" + maxLength: 255 + minLength: 1 + pattern: ^[a-zA-Z0-9]([-a-zSA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$ + type: string + tls: + description: "TLS is the TLS configuration for the Listener. This field is required if the Protocol field is \"HTTPS\" or \"TLS\". It is invalid to set this field if the Protocol field is \"HTTP\", \"TCP\", or \"UDP\". \n The association of SNIs to Certificate defined in GatewayTLSConfig is defined based on the Hostname field for this listener. \n The GatewayClass MUST use the longest matching SNI out of all available certificates for any TLS handshake. \n Support: Core" + properties: + certificateRefs: + description: "CertificateRefs contains a series of references to Kubernetes objects that contains TLS certificates and private keys. These certificates are used to establish a TLS handshake for requests that match the hostname of the associated listener. \n A single CertificateRef to a Kubernetes Secret has \"Core\" support. Implementations MAY choose to support attaching multiple certificates to a Listener, but this behavior is implementation-specific. \n References to a resource in different namespace are invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. If a ReferenceGrant does not allow this reference, the \"ResolvedRefs\" condition MUST be set to False for this listener with the \"RefNotPermitted\" reason. \n This field is required to have at least one element when the mode is set to \"Terminate\" (default) and is optional otherwise. \n CertificateRefs can reference to standard Kubernetes resources, i.e. Secret, or implementation-specific custom resources. \n Support: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls \n Support: Implementation-specific (More than one reference or other resource types)" + items: + description: "SecretObjectReference identifies an API object including its namespace, defaulting to Secret. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid. \n References to objects with invalid Group and Kind are not valid, and must be rejected by the implementation, with appropriate Conditions set on the containing object." + properties: + group: + default: "" + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Secret + description: Kind is kind of the referent. For example "Secret". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referenced object. When unspecified, the local namespace is inferred. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - name + type: object + maxItems: 64 + type: array + mode: + default: Terminate + description: "Mode defines the TLS behavior for the TLS session initiated by the client. There are two possible modes: \n - Terminate: The TLS session between the downstream client and the Gateway is terminated at the Gateway. This mode requires certificateRefs to be set and contain at least one element. - Passthrough: The TLS session is NOT terminated by the Gateway. This implies that the Gateway can't decipher the TLS stream except for the ClientHello message of the TLS protocol. CertificateRefs field is ignored in this mode. \n Support: Core" + enum: + - Terminate + - Passthrough + type: string + options: + additionalProperties: + description: AnnotationValue is the value of an annotation in Gateway API. This is used for validation of maps such as TLS options. This roughly matches Kubernetes annotation validation, although the length validation in that case is based on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: "Options are a list of key/value pairs to enable extended TLS configuration for each implementation. For example, configuring the minimum TLS version or supported cipher suites. \n A set of common keys MAY be defined by the API in the future. To avoid any ambiguity, implementation-specific definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`. Un-prefixed names are reserved for key names defined by Gateway API. \n Support: Implementation-specific" + maxProperties: 16 + type: object + type: object + x-kubernetes-validations: + - message: certificateRefs must be specified when TLSModeType is Terminate + rule: 'self.mode == ''Terminate'' ? size(self.certificateRefs) > 0 : true' + required: + - name + - port + - protocol + type: object + maxItems: 64 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + x-kubernetes-validations: + - message: tls must be specified for protocols ['HTTPS', 'TLS'] + rule: 'self.all(l, l.protocol in [''HTTPS'', ''TLS''] ? has(l.tls) : true)' + - message: tls must not be specified for protocols ['HTTP', 'TCP', 'UDP'] + rule: 'self.all(l, l.protocol in [''HTTP'', ''TCP'', ''UDP''] ? !has(l.tls) : true)' + - message: hostname must not be specified for protocols ['TCP', 'UDP'] + rule: 'self.all(l, l.protocol in [''TCP'', ''UDP''] ? (!has(l.hostname) || l.hostname == '''') : true)' + - message: Listener name must be unique within the Gateway + rule: self.all(l1, self.exists_one(l2, l1.name == l2.name)) + - message: Combination of port, protocol and hostname must be unique for each listener + rule: 'self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))' + required: + - gatewayClassName + - listeners + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed + description: Status defines the current state of Gateway. + properties: + addresses: + description: "Addresses lists the network addresses that have been bound to the Gateway. \n This list may differ from the addresses provided in the spec under some conditions: \n * no addresses are specified, all addresses are dynamically assigned * a combination of specified and dynamic addresses are assigned * a specified address was unusable (e.g. already in use) \n " + items: + description: GatewayStatusAddress describes a network address that is bound to a Gateway. + oneOf: + - properties: + type: + enum: + - IPAddress + value: + anyOf: + - format: ipv4 + - format: ipv6 + - properties: + type: + not: + enum: + - IPAddress + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: "Value of the address. The validity of the values will depend on the type and support by the controller. \n Examples: `1.2.3.4`, `128::1`, `my-ip-address`." + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + x-kubernetes-validations: + - message: Hostname value must only contain valid characters (matching ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): true' + maxItems: 16 + type: array + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed + description: "Conditions describe the current conditions of the Gateway. \n Implementations should prefer to express Gateway conditions using the `GatewayConditionType` and `GatewayConditionReason` constants so that operators and tools can converge on a common vocabulary to describe Gateway state. \n Known condition types are: \n * \"Accepted\" * \"Programmed\" * \"Ready\"" + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + listeners: + description: Listeners provide status for each unique listener port defined in the Spec. + items: + description: ListenerStatus is the status associated with a Listener. + properties: + attachedRoutes: + description: "AttachedRoutes represents the total number of Routes that have been successfully attached to this Listener. \n Successful attachment of a Route to a Listener is based solely on the combination of the AllowedRoutes field on the corresponding Listener and the Route's ParentRefs field. A Route is successfully attached to a Listener when it is selected by the Listener's AllowedRoutes field AND the Route has a valid ParentRef selecting the whole Gateway resource or a specific Listener as a parent resource (more detail on attachment semantics can be found in the documentation on the various Route kinds ParentRefs fields). Listener or Route status does not impact successful attachment, i.e. the AttachedRoutes field count MUST be set for Listeners with condition Accepted: false and MUST count successfully attached Routes that may themselves have Accepted: false conditions. \n Uses for this field include troubleshooting Route attachment and measuring blast radius/impact of changes to a Listener." + format: int32 + type: integer + conditions: + description: Conditions describe the current condition of this listener. + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + name: + description: Name is the name of the Listener that this status corresponds to. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + supportedKinds: + description: "SupportedKinds is the list indicating the Kinds supported by this listener. This MUST represent the kinds an implementation supports for that Listener configuration. \n If kinds are specified in Spec that are not supported, they MUST NOT appear in this list and an implementation MUST set the \"ResolvedRefs\" condition to \"False\" with the \"InvalidRouteKinds\" reason. If both valid and invalid Route kinds are specified, the implementation MUST reference the valid Route kinds that have been specified." + items: + description: RouteGroupKind indicates the group and kind of a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + required: + - attachedRoutes + - conditions + - name + - supportedKinds + type: object + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.gatewayClassName + name: Class + type: string + - jsonPath: .status.addresses[*].value + name: Address + type: string + - jsonPath: .status.conditions[?(@.type=="Programmed")].status + name: Programmed + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: Gateway represents an instance of a service-traffic handling infrastructure by binding Listeners to a set of IP addresses. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of Gateway. + properties: + addresses: + description: "Addresses requested for this Gateway. This is optional and behavior can depend on the implementation. If a value is set in the spec and the requested address is invalid or unavailable, the implementation MUST indicate this in the associated entry in GatewayStatus.Addresses. \n The Addresses field represents a request for the address(es) on the \"outside of the Gateway\", that traffic bound for this Gateway will use. This could be the IP address or hostname of an external load balancer or other networking infrastructure, or some other address that traffic will be sent to. \n If no Addresses are specified, the implementation MAY schedule the Gateway in an implementation-specific manner, assigning an appropriate set of Addresses. \n The implementation MUST bind all Listeners to every GatewayAddress that it assigns to the Gateway and add a corresponding entry in GatewayStatus.Addresses. \n Support: Extended \n " + items: + description: GatewayAddress describes an address that can be bound to a Gateway. + oneOf: + - properties: + type: + enum: + - IPAddress + value: + anyOf: + - format: ipv4 + - format: ipv6 + - properties: + type: + not: + enum: + - IPAddress + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: "Value of the address. The validity of the values will depend on the type and support by the controller. \n Examples: `1.2.3.4`, `128::1`, `my-ip-address`." + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + x-kubernetes-validations: + - message: Hostname value must only contain valid characters (matching ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): true' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: IPAddress values must be unique + rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2, a2.type == a1.type && a2.value == a1.value) : true )' + - message: Hostname values must be unique + rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2, a2.type == a1.type && a2.value == a1.value) : true )' + gatewayClassName: + description: GatewayClassName used for this Gateway. This is the name of a GatewayClass resource. + maxLength: 253 + minLength: 1 + type: string + infrastructure: + description: "Infrastructure defines infrastructure level attributes about this Gateway instance. \n Support: Core \n " + properties: + annotations: + additionalProperties: + description: AnnotationValue is the value of an annotation in Gateway API. This is used for validation of maps such as TLS options. This roughly matches Kubernetes annotation validation, although the length validation in that case is based on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: "Annotations that SHOULD be applied to any resources created in response to this Gateway. \n For implementations creating other Kubernetes objects, this should be the `metadata.annotations` field on resources. For other implementations, this refers to any relevant (implementation specific) \"annotations\" concepts. \n An implementation may chose to add additional implementation-specific annotations as they see fit. \n Support: Extended" + maxProperties: 8 + type: object + labels: + additionalProperties: + description: AnnotationValue is the value of an annotation in Gateway API. This is used for validation of maps such as TLS options. This roughly matches Kubernetes annotation validation, although the length validation in that case is based on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: "Labels that SHOULD be applied to any resources created in response to this Gateway. \n For implementations creating other Kubernetes objects, this should be the `metadata.labels` field on resources. For other implementations, this refers to any relevant (implementation specific) \"labels\" concepts. \n An implementation may chose to add additional implementation-specific labels as they see fit. \n Support: Extended" + maxProperties: 8 + type: object + type: object + listeners: + description: "Listeners associated with this Gateway. Listeners define logical endpoints that are bound on this Gateway's addresses. At least one Listener MUST be specified. \n Each Listener in a set of Listeners (for example, in a single Gateway) MUST be _distinct_, in that a traffic flow MUST be able to be assigned to exactly one listener. (This section uses \"set of Listeners\" rather than \"Listeners in a single Gateway\" because implementations MAY merge configuration from multiple Gateways onto a single data plane, and these rules _also_ apply in that case). \n Practically, this means that each listener in a set MUST have a unique combination of Port, Protocol, and, if supported by the protocol, Hostname. \n Some combinations of port, protocol, and TLS settings are considered Core support and MUST be supported by implementations based on their targeted conformance profile: \n HTTP Profile \n 1. HTTPRoute, Port: 80, Protocol: HTTP 2. HTTPRoute, Port: 443, Protocol: HTTPS, TLS Mode: Terminate, TLS keypair provided \n TLS Profile \n 1. TLSRoute, Port: 443, Protocol: TLS, TLS Mode: Passthrough \n \"Distinct\" Listeners have the following property: \n The implementation can match inbound requests to a single distinct Listener. When multiple Listeners share values for fields (for example, two Listeners with the same Port value), the implementation can match requests to only one of the Listeners using other Listener fields. \n For example, the following Listener scenarios are distinct: \n 1. Multiple Listeners with the same Port that all use the \"HTTP\" Protocol that all have unique Hostname values. 2. Multiple Listeners with the same Port that use either the \"HTTPS\" or \"TLS\" Protocol that all have unique Hostname values. 3. A mixture of \"TCP\" and \"UDP\" Protocol Listeners, where no Listener with the same Protocol has the same Port value. \n Some fields in the Listener struct have possible values that affect whether the Listener is distinct. Hostname is particularly relevant for HTTP or HTTPS protocols. \n When using the Hostname value to select between same-Port, same-Protocol Listeners, the Hostname value must be different on each Listener for the Listener to be distinct. \n When the Listeners are distinct based on Hostname, inbound request hostnames MUST match from the most specific to least specific Hostname values to choose the correct Listener and its associated set of Routes. \n Exact matches must be processed before wildcard matches, and wildcard matches must be processed before fallback (empty Hostname value) matches. For example, `\"foo.example.com\"` takes precedence over `\"*.example.com\"`, and `\"*.example.com\"` takes precedence over `\"\"`. \n Additionally, if there are multiple wildcard entries, more specific wildcard entries must be processed before less specific wildcard entries. For example, `\"*.foo.example.com\"` takes precedence over `\"*.example.com\"`. The precise definition here is that the higher the number of dots in the hostname to the right of the wildcard character, the higher the precedence. \n The wildcard character will match any number of characters _and dots_ to the left, however, so `\"*.example.com\"` will match both `\"foo.bar.example.com\"` _and_ `\"bar.example.com\"`. \n If a set of Listeners contains Listeners that are not distinct, then those Listeners are Conflicted, and the implementation MUST set the \"Conflicted\" condition in the Listener Status to \"True\". \n Implementations MAY choose to accept a Gateway with some Conflicted Listeners only if they only accept the partial Listener set that contains no Conflicted Listeners. To put this another way, implementations may accept a partial Listener set only if they throw out *all* the conflicting Listeners. No picking one of the conflicting listeners as the winner. This also means that the Gateway must have at least one non-conflicting Listener in this case, otherwise it violates the requirement that at least one Listener must be present. \n The implementation MUST set a \"ListenersNotValid\" condition on the Gateway Status when the Gateway contains Conflicted Listeners whether or not they accept the Gateway. That Condition SHOULD clearly indicate in the Message which Listeners are conflicted, and which are Accepted. Additionally, the Listener status for those listeners SHOULD indicate which Listeners are conflicted and not Accepted. \n A Gateway's Listeners are considered \"compatible\" if: \n 1. They are distinct. 2. The implementation can serve them in compliance with the Addresses requirement that all Listeners are available on all assigned addresses. \n Compatible combinations in Extended support are expected to vary across implementations. A combination that is compatible for one implementation may not be compatible for another. \n For example, an implementation that cannot serve both TCP and UDP listeners on the same address, or cannot mix HTTPS and generic TLS listens on the same port would not consider those cases compatible, even though they are distinct. \n Note that requests SHOULD match at most one Listener. For example, if Listeners are defined for \"foo.example.com\" and \"*.example.com\", a request to \"foo.example.com\" SHOULD only be routed using routes attached to the \"foo.example.com\" Listener (and not the \"*.example.com\" Listener). This concept is known as \"Listener Isolation\". Implementations that do not support Listener Isolation MUST clearly document this. \n Implementations MAY merge separate Gateways onto a single set of Addresses if all Listeners across all Gateways are compatible. \n Support: Core" + items: + description: Listener embodies the concept of a logical endpoint where a Gateway accepts network connections. + properties: + allowedRoutes: + default: + namespaces: + from: Same + description: "AllowedRoutes defines the types of routes that MAY be attached to a Listener and the trusted namespaces where those Route resources MAY be present. \n Although a client request may match multiple route rules, only one rule may ultimately receive the request. Matching precedence MUST be determined in order of the following criteria: \n * The most specific match as defined by the Route type. * The oldest Route based on creation timestamp. For example, a Route with a creation timestamp of \"2020-09-08 01:02:03\" is given precedence over a Route with a creation timestamp of \"2020-09-08 01:02:04\". * If everything else is equivalent, the Route appearing first in alphabetical order (namespace/name) should be given precedence. For example, foo/bar is given precedence over foo/baz. \n All valid rules within a Route attached to this Listener should be implemented. Invalid Route rules can be ignored (sometimes that will mean the full Route). If a Route rule transitions from valid to invalid, support for that Route rule should be dropped to ensure consistency. For example, even if a filter specified by a Route rule is invalid, the rest of the rules within that Route should still be supported. \n Support: Core" + properties: + kinds: + description: "Kinds specifies the groups and kinds of Routes that are allowed to bind to this Gateway Listener. When unspecified or empty, the kinds of Routes selected are determined using the Listener protocol. \n A RouteGroupKind MUST correspond to kinds of Routes that are compatible with the application protocol specified in the Listener's Protocol field. If an implementation does not support or recognize this resource type, it MUST set the \"ResolvedRefs\" condition to False for this Listener with the \"InvalidRouteKinds\" reason. \n Support: Core" + items: + description: RouteGroupKind indicates the group and kind of a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + namespaces: + default: + from: Same + description: "Namespaces indicates namespaces from which Routes may be attached to this Listener. This is restricted to the namespace of this Gateway by default. \n Support: Core" + properties: + from: + default: Same + description: "From indicates where Routes will be selected for this Gateway. Possible values are: \n * All: Routes in all namespaces may be used by this Gateway. * Selector: Routes in namespaces selected by the selector may be used by this Gateway. * Same: Only Routes in the same namespace may be used by this Gateway. \n Support: Core" + enum: + - All + - Selector + - Same + type: string + selector: + description: "Selector must be specified when From is set to \"Selector\". In that case, only Routes in Namespaces matching this Selector will be selected by this Gateway. This field is ignored for other values of \"From\". \n Support: Core" + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: object + type: object + hostname: + description: "Hostname specifies the virtual hostname to match for protocol types that define this concept. When unspecified, all hostnames are matched. This field is ignored for protocols that don't require hostname based matching. \n Implementations MUST apply Hostname matching appropriately for each of the following protocols: \n * TLS: The Listener Hostname MUST match the SNI. * HTTP: The Listener Hostname MUST match the Host header of the request. * HTTPS: The Listener Hostname SHOULD match at both the TLS and HTTP protocol layers as described above. If an implementation does not ensure that both the SNI and Host header match the Listener hostname, it MUST clearly document that. \n For HTTPRoute and TLSRoute resources, there is an interaction with the `spec.hostnames` array. When both listener and route specify hostnames, there MUST be an intersection between the values for a Route to be accepted. For more information, refer to the Route specific Hostnames documentation. \n Hostnames that are prefixed with a wildcard label (`*.`) are interpreted as a suffix match. That means that a match for `*.example.com` would match both `test.example.com`, and `foo.test.example.com`, but not `example.com`. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + name: + description: "Name is the name of the Listener. This name MUST be unique within a Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + port: + description: "Port is the network port. Multiple listeners may use the same port, subject to the Listener compatibility rules. \n Support: Core" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + description: "Protocol specifies the network protocol this listener expects to receive. \n Support: Core" + maxLength: 255 + minLength: 1 + pattern: ^[a-zA-Z0-9]([-a-zSA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$ + type: string + tls: + description: "TLS is the TLS configuration for the Listener. This field is required if the Protocol field is \"HTTPS\" or \"TLS\". It is invalid to set this field if the Protocol field is \"HTTP\", \"TCP\", or \"UDP\". \n The association of SNIs to Certificate defined in GatewayTLSConfig is defined based on the Hostname field for this listener. \n The GatewayClass MUST use the longest matching SNI out of all available certificates for any TLS handshake. \n Support: Core" + properties: + certificateRefs: + description: "CertificateRefs contains a series of references to Kubernetes objects that contains TLS certificates and private keys. These certificates are used to establish a TLS handshake for requests that match the hostname of the associated listener. \n A single CertificateRef to a Kubernetes Secret has \"Core\" support. Implementations MAY choose to support attaching multiple certificates to a Listener, but this behavior is implementation-specific. \n References to a resource in different namespace are invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. If a ReferenceGrant does not allow this reference, the \"ResolvedRefs\" condition MUST be set to False for this listener with the \"RefNotPermitted\" reason. \n This field is required to have at least one element when the mode is set to \"Terminate\" (default) and is optional otherwise. \n CertificateRefs can reference to standard Kubernetes resources, i.e. Secret, or implementation-specific custom resources. \n Support: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls \n Support: Implementation-specific (More than one reference or other resource types)" + items: + description: "SecretObjectReference identifies an API object including its namespace, defaulting to Secret. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid. \n References to objects with invalid Group and Kind are not valid, and must be rejected by the implementation, with appropriate Conditions set on the containing object." + properties: + group: + default: "" + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Secret + description: Kind is kind of the referent. For example "Secret". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referenced object. When unspecified, the local namespace is inferred. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - name + type: object + maxItems: 64 + type: array + mode: + default: Terminate + description: "Mode defines the TLS behavior for the TLS session initiated by the client. There are two possible modes: \n - Terminate: The TLS session between the downstream client and the Gateway is terminated at the Gateway. This mode requires certificateRefs to be set and contain at least one element. - Passthrough: The TLS session is NOT terminated by the Gateway. This implies that the Gateway can't decipher the TLS stream except for the ClientHello message of the TLS protocol. CertificateRefs field is ignored in this mode. \n Support: Core" + enum: + - Terminate + - Passthrough + type: string + options: + additionalProperties: + description: AnnotationValue is the value of an annotation in Gateway API. This is used for validation of maps such as TLS options. This roughly matches Kubernetes annotation validation, although the length validation in that case is based on the entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: "Options are a list of key/value pairs to enable extended TLS configuration for each implementation. For example, configuring the minimum TLS version or supported cipher suites. \n A set of common keys MAY be defined by the API in the future. To avoid any ambiguity, implementation-specific definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`. Un-prefixed names are reserved for key names defined by Gateway API. \n Support: Implementation-specific" + maxProperties: 16 + type: object + type: object + x-kubernetes-validations: + - message: certificateRefs must be specified when TLSModeType is Terminate + rule: 'self.mode == ''Terminate'' ? size(self.certificateRefs) > 0 : true' + required: + - name + - port + - protocol + type: object + maxItems: 64 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + x-kubernetes-validations: + - message: tls must be specified for protocols ['HTTPS', 'TLS'] + rule: 'self.all(l, l.protocol in [''HTTPS'', ''TLS''] ? has(l.tls) : true)' + - message: tls must not be specified for protocols ['HTTP', 'TCP', 'UDP'] + rule: 'self.all(l, l.protocol in [''HTTP'', ''TCP'', ''UDP''] ? !has(l.tls) : true)' + - message: hostname must not be specified for protocols ['TCP', 'UDP'] + rule: 'self.all(l, l.protocol in [''TCP'', ''UDP''] ? (!has(l.hostname) || l.hostname == '''') : true)' + - message: Listener name must be unique within the Gateway + rule: self.all(l1, self.exists_one(l2, l1.name == l2.name)) + - message: Combination of port, protocol and hostname must be unique for each listener + rule: 'self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))' + required: + - gatewayClassName + - listeners + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed + description: Status defines the current state of Gateway. + properties: + addresses: + description: "Addresses lists the network addresses that have been bound to the Gateway. \n This list may differ from the addresses provided in the spec under some conditions: \n * no addresses are specified, all addresses are dynamically assigned * a combination of specified and dynamic addresses are assigned * a specified address was unusable (e.g. already in use) \n " + items: + description: GatewayStatusAddress describes a network address that is bound to a Gateway. + oneOf: + - properties: + type: + enum: + - IPAddress + value: + anyOf: + - format: ipv4 + - format: ipv6 + - properties: + type: + not: + enum: + - IPAddress + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: "Value of the address. The validity of the values will depend on the type and support by the controller. \n Examples: `1.2.3.4`, `128::1`, `my-ip-address`." + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + x-kubernetes-validations: + - message: Hostname value must only contain valid characters (matching ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): true' + maxItems: 16 + type: array + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed + description: "Conditions describe the current conditions of the Gateway. \n Implementations should prefer to express Gateway conditions using the `GatewayConditionType` and `GatewayConditionReason` constants so that operators and tools can converge on a common vocabulary to describe Gateway state. \n Known condition types are: \n * \"Accepted\" * \"Programmed\" * \"Ready\"" + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + listeners: + description: Listeners provide status for each unique listener port defined in the Spec. + items: + description: ListenerStatus is the status associated with a Listener. + properties: + attachedRoutes: + description: "AttachedRoutes represents the total number of Routes that have been successfully attached to this Listener. \n Successful attachment of a Route to a Listener is based solely on the combination of the AllowedRoutes field on the corresponding Listener and the Route's ParentRefs field. A Route is successfully attached to a Listener when it is selected by the Listener's AllowedRoutes field AND the Route has a valid ParentRef selecting the whole Gateway resource or a specific Listener as a parent resource (more detail on attachment semantics can be found in the documentation on the various Route kinds ParentRefs fields). Listener or Route status does not impact successful attachment, i.e. the AttachedRoutes field count MUST be set for Listeners with condition Accepted: false and MUST count successfully attached Routes that may themselves have Accepted: false conditions. \n Uses for this field include troubleshooting Route attachment and measuring blast radius/impact of changes to a Listener." + format: int32 + type: integer + conditions: + description: Conditions describe the current condition of this listener. + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + name: + description: Name is the name of the Listener that this status corresponds to. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + supportedKinds: + description: "SupportedKinds is the list indicating the Kinds supported by this listener. This MUST represent the kinds an implementation supports for that Listener configuration. \n If kinds are specified in Spec that are not supported, they MUST NOT appear in this list and an implementation MUST set the \"ResolvedRefs\" condition to \"False\" with the \"InvalidRouteKinds\" reason. If both valid and invalid Route kinds are specified, the implementation MUST reference the valid Route kinds that have been specified." + items: + description: RouteGroupKind indicates the group and kind of a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + required: + - attachedRoutes + - conditions + - name + - supportedKinds + type: object + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} status: acceptedNames: kind: "" plural: "" - conditions: [] - storedVersions: [] + conditions: null + storedVersions: null diff --git a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_grpcroutes.yaml b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_grpcroutes.yaml new file mode 100644 index 000000000..1d2964156 --- /dev/null +++ b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_grpcroutes.yaml @@ -0,0 +1,819 @@ +# +# config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml +# +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + name: grpcroutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: GRPCRoute + listKind: GRPCRouteList + plural: grpcroutes + singular: grpcroute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.hostnames + name: Hostnames + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: "GRPCRoute provides a way to route gRPC requests. This includes the capability to match requests by hostname, gRPC service, gRPC method, or HTTP/2 header. Filters can be used to specify additional processing steps. Backends specify where matching requests will be routed. \n GRPCRoute falls under extended support within the Gateway API. Within the following specification, the word \"MUST\" indicates that an implementation supporting GRPCRoute must conform to the indicated requirement, but an implementation not supporting this route type need not follow the requirement unless explicitly indicated. \n Implementations supporting `GRPCRoute` with the `HTTPS` `ProtocolType` MUST accept HTTP/2 connections without an initial upgrade from HTTP/1.1, i.e. via ALPN. If the implementation does not support this, then it MUST set the \"Accepted\" condition to \"False\" for the affected listener with a reason of \"UnsupportedProtocol\". Implementations MAY also accept HTTP/2 connections with an upgrade from HTTP/1. \n Implementations supporting `GRPCRoute` with the `HTTP` `ProtocolType` MUST support HTTP/2 over cleartext TCP (h2c, https://www.rfc-editor.org/rfc/rfc7540#section-3.1) without an initial upgrade from HTTP/1.1, i.e. with prior knowledge (https://www.rfc-editor.org/rfc/rfc7540#section-3.4). If the implementation does not support this, then it MUST set the \"Accepted\" condition to \"False\" for the affected listener with a reason of \"UnsupportedProtocol\". Implementations MAY also accept HTTP/2 connections with an upgrade from HTTP/1, i.e. without prior knowledge." + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of GRPCRoute. + properties: + hostnames: + description: "Hostnames defines a set of hostnames to match against the GRPC Host header to select a GRPCRoute to process the request. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard label MUST appear by itself as the first label. \n If a hostname is specified by both the Listener and GRPCRoute, there MUST be at least one intersecting hostname for the GRPCRoute to be attached to the Listener. For example: \n * A Listener with `test.example.com` as the hostname matches GRPCRoutes that have either not specified any hostnames, or have specified at least one of `test.example.com` or `*.example.com`. * A Listener with `*.example.com` as the hostname matches GRPCRoutes that have either not specified any hostnames or have specified at least one hostname that matches the Listener hostname. For example, `test.example.com` and `*.example.com` would both match. On the other hand, `example.com` and `test.example.net` would not match. \n Hostnames that are prefixed with a wildcard label (`*.`) are interpreted as a suffix match. That means that a match for `*.example.com` would match both `test.example.com`, and `foo.test.example.com`, but not `example.com`. \n If both the Listener and GRPCRoute have specified hostnames, any GRPCRoute hostnames that do not match the Listener hostname MUST be ignored. For example, if a Listener specified `*.example.com`, and the GRPCRoute specified `test.example.com` and `test.example.net`, `test.example.net` MUST NOT be considered for a match. \n If both the Listener and GRPCRoute have specified hostnames, and none match with the criteria above, then the GRPCRoute MUST NOT be accepted by the implementation. The implementation MUST raise an 'Accepted' Condition with a status of `False` in the corresponding RouteParentStatus. \n If a Route (A) of type HTTPRoute or GRPCRoute is attached to a Listener and that listener already has another Route (B) of the other type attached and the intersection of the hostnames of A and B is non-empty, then the implementation MUST accept exactly one of these two routes, determined by the following criteria, in order: \n * The oldest Route based on creation timestamp. * The Route appearing first in alphabetical order by \"{namespace}/{name}\". \n The rejected Route MUST raise an 'Accepted' condition with a status of 'False' in the corresponding RouteParentStatus. \n Support: Core" + items: + description: "Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard label must appear by itself as the first label. \n Hostname can be \"precise\" which is a domain name without the terminating dot of a network host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain name prefixed with a single wildcard label (e.g. `*.example.com`). \n Note that as per RFC1035 and RFC1123, a *label* must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character. No other punctuation is allowed." + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + description: "ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a \"producer\" route, or the mesh implementation must support and allow \"consumer\" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a \"producer\" route for a Service in a different namespace from the Route. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) This API may be extended in the future to support additional kinds of parent resources. \n ParentRefs must be _distinct_. This means either that: \n * They select different objects. If this is the case, then parentRef entries are distinct. In terms of fields, this means that the multi-part key defined by `group`, `kind`, `namespace`, and `name` must be unique across all parentRef entries in the Route. * They do not select different objects, but for each optional field used, each ParentRef that selects the same object must set the same set of optional fields to different values. If one ParentRef sets a combination of optional fields, all must set the same combination. \n Some examples: \n * If one ParentRef sets `sectionName`, all ParentRefs referencing the same object must also set `sectionName`. * If one ParentRef sets `port`, all ParentRefs referencing the same object must also set `port`. * If one ParentRef sets `sectionName` and `port`, all ParentRefs referencing the same object must also set `sectionName` and `port`. \n It is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged. \n Note that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n " + items: + description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n This API may be extended in the future to support additional kinds of parent resources. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + x-kubernetes-validations: + - message: sectionName or port must be specified when parentRefs includes 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__)) ? ((!has(p1.sectionName) || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) || p2.port == 0)): true))' + - message: sectionName or port must be unique when parentRefs includes 2 or more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName == '')) || ( has(p1.sectionName) && has(p2.sectionName) && p1.sectionName == p2.sectionName)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port == p2.port)))) + rules: + description: Rules are a list of GRPC matchers, filters and actions. + items: + description: GRPCRouteRule defines the semantics for matching a gRPC request based on conditions (matches), processing it (filters), and forwarding the request to an API object (backendRefs). + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching requests should be sent. \n Failure behavior here depends on how many BackendRefs are specified and how many are invalid. \n If *all* entries in BackendRefs are invalid, and there are also no filters specified in this route rule, *all* traffic which matches this rule MUST receive an `UNAVAILABLE` status. \n See the GRPCBackendRef definition for the rules about what makes a single GRPCBackendRef invalid. \n When a GRPCBackendRef is invalid, `UNAVAILABLE` statuses MUST be returned for requests that would have otherwise been routed to an invalid backend. If multiple backends are specified, and some are invalid, the proportion of requests that would otherwise have been routed to an invalid backend MUST receive an `UNAVAILABLE` status. \n For example, if two backends are specified with equal weights, and one is invalid, 50 percent of traffic MUST receive an `UNAVAILABLE` status. Implementations may choose how that 50 percent is determined. \n Support: Core for Kubernetes Service \n Support: Implementation-specific for any other resource \n Support for weight: Core" + items: + description: "GRPCBackendRef defines how a GRPCRoute forwards a gRPC request. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n \n When the BackendRef points to a Kubernetes Service, implementations SHOULD honor the appProtocol field if it is set for the target Service Port. \n Implementations supporting appProtocol SHOULD recognize the Kubernetes Standard Application Protocols defined in KEP-3726. \n If a Service appProtocol isn't specified, an implementation MAY infer the backend protocol through its own means. Implementations MAY infer the protocol from the Route type referring to the backend Service. \n If a Route is not able to send traffic to the backend using the specified protocol then the backend is considered invalid. Implementations MUST set the \"ResolvedRefs\" condition to \"False\" with the \"UnsupportedProtocol\" reason. \n " + properties: + filters: + description: "Filters defined at this level MUST be executed if and only if the request is being forwarded to the backend defined here. \n Support: Implementation-specific (For broader support of filters, use the Filters field in GRPCRouteRule.)" + items: + description: GRPCRouteFilter defines processing steps that must be completed during the request or response lifecycle. GRPCRouteFilters are meant as an extension point to express processing that may be done in Gateway implementations. Some examples include request or response modification, implementing authentication strategies, rate-limiting, and traffic shaping. API guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: "ExtensionRef is an optional, implementation-specific extension to the \"filter\" behavior. For example, resource \"myroutefilter\" in group \"networking.example.net\"). ExtensionRef MUST NOT be used for core and extended filters. \n Support: Implementation-specific \n This filter can be used multiple times within the same rule." + properties: + group: + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema for a filter that modifies request headers. \n Support: Core" + properties: + add: + description: "Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: add: - name: \"my-header\" value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz \n Config: remove: [\"my-header1\", \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the given header (name, value) before the action. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: set: - name: \"my-header\" value: \"bar\" \n Output: GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: "RequestMirror defines a schema for a filter that mirrors requests. Requests are sent to the specified destination, but responses from that destination are ignored. \n This filter can be used multiple times within the same rule. Note that not all implementations will be able to support mirroring to multiple backends. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource where mirrored requests are sent. \n Mirrored requests must be sent only to a single destination endpoint within this BackendRef, irrespective of how many endpoints are present within this BackendRef. \n If the referent cannot be found, this BackendRef is invalid and must be dropped from the Gateway. The controller must ensure the \"ResolvedRefs\" condition on the Route status is set to `status: False` and not configure this backend in the underlying implementation. \n If there is a cross-namespace reference to an *existing* object that is not allowed by a ReferenceGrant, the controller must ensure the \"ResolvedRefs\" condition on the Route is set to `status: False`, with the \"RefNotPermitted\" reason and not configure this backend in the underlying implementation. \n In either error case, the Message of the `ResolvedRefs` Condition should be used to provide more detail about the problem. \n Support: Extended for Kubernetes Service \n Support: Implementation-specific for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource kind of the referent. For example \"Service\". \n Defaults to \"Service\" when not specified. \n ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. \n Support: Core (Services with a type other than ExternalName) \n Support: Implementation-specific (Services with type ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + required: + - backendRef + type: object + responseHeaderModifier: + description: "ResponseHeaderModifier defines a schema for a filter that modifies response headers. \n Support: Extended" + properties: + add: + description: "Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: add: - name: \"my-header\" value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz \n Config: remove: [\"my-header1\", \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the given header (name, value) before the action. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: set: - name: \"my-header\" value: \"bar\" \n Output: GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: "Type identifies the type of filter to apply. As with other API fields, types are classified into three conformance levels: \n - Core: Filter types and their corresponding configuration defined by \"Support: Core\" in this package, e.g. \"RequestHeaderModifier\". All implementations supporting GRPCRoute MUST support core filters. \n - Extended: Filter types and their corresponding configuration defined by \"Support: Extended\" in this package, e.g. \"RequestMirror\". Implementers are encouraged to support extended filters. \n - Implementation-specific: Filters that are defined and supported by specific vendors. In the future, filters showing convergence in behavior across multiple implementations will be considered for inclusion in extended or core conformance levels. Filter-specific configuration for such filters is specified using the ExtensionRef field. `Type` MUST be set to \"ExtensionRef\" for custom filters. \n Implementers are encouraged to define custom implementation types to extend the core API with implementation-specific behavior. \n If a reference to a custom filter type cannot be resolved, the filter MUST NOT be skipped. Instead, requests that would have been processed by that filter MUST receive a HTTP error response. \n " + enum: + - ResponseHeaderModifier + - RequestHeaderModifier + - RequestMirror + - ExtensionRef + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.extensionRef must be nil if the filter.type is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1 + group: + default: "" + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource kind of the referent. For example \"Service\". \n Defaults to \"Service\" when not specified. \n ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. \n Support: Core (Services with a type other than ExternalName) \n Support: Implementation-specific (Services with type ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests forwarded to the referenced backend. This is computed as weight/(sum of all weights in this BackendRefs list). For non-zero values, there may be some epsilon from the exact proportion defined here depending on the precision an implementation supports. Weight is not a percentage and the sum of weights does not need to equal 100. \n If only one backend is specified and it has a weight greater than 0, 100% of the traffic is forwarded to that backend. If weight is set to 0, no traffic should be forwarded for this entry. If unspecified, weight defaults to 1. \n Support for this field varies based on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + maxItems: 16 + type: array + filters: + description: "Filters define the filters that are applied to requests that match this rule. \n The effects of ordering of multiple behaviors are currently unspecified. This can change in the future based on feedback during the alpha stage. \n Conformance-levels at this level are defined based on the type of filter: \n - ALL core filters MUST be supported by all implementations that support GRPCRoute. - Implementers are encouraged to support extended filters. - Implementation-specific custom filters have no API guarantees across implementations. \n Specifying the same filter multiple times is not supported unless explicitly indicated in the filter. \n If an implementation can not support a combination of filters, it must clearly document that limitation. In cases where incompatible or unsupported filters are specified and cause the `Accepted` condition to be set to status `False`, implementations may use the `IncompatibleFilters` reason to specify this configuration error. \n Support: Core" + items: + description: GRPCRouteFilter defines processing steps that must be completed during the request or response lifecycle. GRPCRouteFilters are meant as an extension point to express processing that may be done in Gateway implementations. Some examples include request or response modification, implementing authentication strategies, rate-limiting, and traffic shaping. API guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: "ExtensionRef is an optional, implementation-specific extension to the \"filter\" behavior. For example, resource \"myroutefilter\" in group \"networking.example.net\"). ExtensionRef MUST NOT be used for core and extended filters. \n Support: Implementation-specific \n This filter can be used multiple times within the same rule." + properties: + group: + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema for a filter that modifies request headers. \n Support: Core" + properties: + add: + description: "Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: add: - name: \"my-header\" value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz \n Config: remove: [\"my-header1\", \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the given header (name, value) before the action. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: set: - name: \"my-header\" value: \"bar\" \n Output: GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: "RequestMirror defines a schema for a filter that mirrors requests. Requests are sent to the specified destination, but responses from that destination are ignored. \n This filter can be used multiple times within the same rule. Note that not all implementations will be able to support mirroring to multiple backends. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource where mirrored requests are sent. \n Mirrored requests must be sent only to a single destination endpoint within this BackendRef, irrespective of how many endpoints are present within this BackendRef. \n If the referent cannot be found, this BackendRef is invalid and must be dropped from the Gateway. The controller must ensure the \"ResolvedRefs\" condition on the Route status is set to `status: False` and not configure this backend in the underlying implementation. \n If there is a cross-namespace reference to an *existing* object that is not allowed by a ReferenceGrant, the controller must ensure the \"ResolvedRefs\" condition on the Route is set to `status: False`, with the \"RefNotPermitted\" reason and not configure this backend in the underlying implementation. \n In either error case, the Message of the `ResolvedRefs` Condition should be used to provide more detail about the problem. \n Support: Extended for Kubernetes Service \n Support: Implementation-specific for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource kind of the referent. For example \"Service\". \n Defaults to \"Service\" when not specified. \n ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. \n Support: Core (Services with a type other than ExternalName) \n Support: Implementation-specific (Services with type ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + required: + - backendRef + type: object + responseHeaderModifier: + description: "ResponseHeaderModifier defines a schema for a filter that modifies response headers. \n Support: Extended" + properties: + add: + description: "Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: add: - name: \"my-header\" value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz \n Config: remove: [\"my-header1\", \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the given header (name, value) before the action. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: set: - name: \"my-header\" value: \"bar\" \n Output: GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: "Type identifies the type of filter to apply. As with other API fields, types are classified into three conformance levels: \n - Core: Filter types and their corresponding configuration defined by \"Support: Core\" in this package, e.g. \"RequestHeaderModifier\". All implementations supporting GRPCRoute MUST support core filters. \n - Extended: Filter types and their corresponding configuration defined by \"Support: Extended\" in this package, e.g. \"RequestMirror\". Implementers are encouraged to support extended filters. \n - Implementation-specific: Filters that are defined and supported by specific vendors. In the future, filters showing convergence in behavior across multiple implementations will be considered for inclusion in extended or core conformance levels. Filter-specific configuration for such filters is specified using the ExtensionRef field. `Type` MUST be set to \"ExtensionRef\" for custom filters. \n Implementers are encouraged to define custom implementation types to extend the core API with implementation-specific behavior. \n If a reference to a custom filter type cannot be resolved, the filter MUST NOT be skipped. Instead, requests that would have been processed by that filter MUST receive a HTTP error response. \n " + enum: + - ResponseHeaderModifier + - RequestHeaderModifier + - RequestMirror + - ExtensionRef + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.extensionRef must be nil if the filter.type is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1 + matches: + description: "Matches define conditions used for matching the rule against incoming gRPC requests. Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied. \n For example, take the following matches configuration: \n ``` matches: - method: service: foo.bar headers: values: version: 2 - method: service: foo.bar.v2 ``` \n For a request to match against this rule, it MUST satisfy EITHER of the two conditions: \n - service of foo.bar AND contains the header `version: 2` - service of foo.bar.v2 \n See the documentation for GRPCRouteMatch on how to specify multiple match conditions to be ANDed together. \n If no matches are specified, the implementation MUST match every gRPC request. \n Proxy or Load Balancer routing configuration generated from GRPCRoutes MUST prioritize rules based on the following criteria, continuing on ties. Merging MUST not be done between GRPCRoutes and HTTPRoutes. Precedence MUST be given to the rule with the largest number of: \n * Characters in a matching non-wildcard hostname. * Characters in a matching hostname. * Characters in a matching service. * Characters in a matching method. * Header matches. \n If ties still exist across multiple Routes, matching precedence MUST be determined in order of the following criteria, continuing on ties: \n * The oldest Route based on creation timestamp. * The Route appearing first in alphabetical order by \"{namespace}/{name}\". \n If ties still exist within the Route that has been given precedence, matching precedence MUST be granted to the first matching rule meeting the above criteria." + items: + description: "GRPCRouteMatch defines the predicate used to match requests to a given action. Multiple match types are ANDed together, i.e. the match will evaluate to true only if all conditions are satisfied. \n For example, the match below will match a gRPC request only if its service is `foo` AND it contains the `version: v1` header: \n ``` matches: - method: type: Exact service: \"foo\" headers: - name: \"version\" value \"v1\" \n ```" + properties: + headers: + description: Headers specifies gRPC request header matchers. Multiple match values are ANDed together, meaning, a request MUST match all the specified headers to select the route. + items: + description: GRPCHeaderMatch describes how to select a gRPC route by matching gRPC request headers. + properties: + name: + description: "Name is the name of the gRPC Header to be matched. \n If multiple entries specify equivalent header names, only the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: Type specifies how to match against the value of the header. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of the gRPC Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + description: Method specifies a gRPC request service/method matcher. If this field is not specified, all services and methods will match. + properties: + method: + description: "Value of the method to match against. If left empty or omitted, will match all services. \n At least one of Service and Method MUST be a non-empty string." + maxLength: 1024 + type: string + service: + description: "Value of the service to match against. If left empty or omitted, will match any service. \n At least one of Service and Method MUST be a non-empty string." + maxLength: 1024 + type: string + type: + default: Exact + description: "Type specifies how to match against the service and/or method. Support: Core (Exact with service and method specified) \n Support: Implementation-specific (Exact with method specified but no service specified) \n Support: Implementation-specific (RegularExpression)" + enum: + - Exact + - RegularExpression + type: string + type: object + x-kubernetes-validations: + - message: One or both of 'service' or 'method' must be specified + rule: 'has(self.type) ? has(self.service) || has(self.method) : true' + - message: service must only contain valid characters (matching ^(?i)\.?[a-z_][a-z_0-9]*(\.[a-z_][a-z_0-9]*)*$) + rule: '(!has(self.type) || self.type == ''Exact'') && has(self.service) ? self.service.matches(r"""^(?i)\.?[a-z_][a-z_0-9]*(\.[a-z_][a-z_0-9]*)*$"""): true' + - message: method must only contain valid characters (matching ^[A-Za-z_][A-Za-z_0-9]*$) + rule: '(!has(self.type) || self.type == ''Exact'') && has(self.method) ? self.method.matches(r"""^[A-Za-z_][A-Za-z_0-9]*$"""): true' + type: object + maxItems: 8 + type: array + type: object + maxItems: 16 + type: array + type: object + status: + description: Status defines the current state of GRPCRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified. \n Note that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for. \n A maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway." + items: + description: RouteParentStatus describes the status of a route with respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with respect to the Gateway. Note that the route's availability is also subject to the Gateway's own status conditions and listener status. \n If the Route's ParentRef specifies an existing Gateway that supports Routes of this kind AND that Gateway's controller has sufficient access, then that Gateway's controller MUST set the \"Accepted\" condition on the Route, to indicate whether the route has been accepted or rejected by the Gateway, and why. \n A Route MUST be considered \"Accepted\" if at least one of the Route's rules is implemented by the Gateway. \n There are a number of cases where the \"Accepted\" condition may not be set due to lack of controller visibility, that includes when: \n * The Route refers to a non-existent parent. * The Route is of a type that the controller does not support. * The Route is in a namespace the controller does not have access to." + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates the name of the controller that wrote this status. This corresponds with the controllerName field on GatewayClass. \n Example: \"example.net/gateway-controller\". \n The format of this field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). \n Controllers MUST populate this field when writing status. Controllers should ensure that entries to status populated with their ControllerName are cleaned up when they are no longer necessary." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec that this RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_httproutes.yaml b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_httproutes.yaml index fc574151a..5ce7697b4 100644 --- a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_httproutes.yaml +++ b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_httproutes.yaml @@ -1,240 +1,621 @@ - ---- +# +# config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml +# apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: httproutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io names: categories: - - gateway-api + - gateway-api kind: HTTPRoute listKind: HTTPRouteList plural: httproutes singular: httproute scope: Namespaced versions: - - additionalPrinterColumns: - - jsonPath: .spec.hostnames - name: Hostnames - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha2 - schema: - openAPIV3Schema: - description: HTTPRoute provides a way to route HTTP requests. This includes - the capability to match requests by hostname, path, header, or query param. - Filters can be used to specify additional processing steps. Backends specify - where matching requests should be routed. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Spec defines the desired state of HTTPRoute. - properties: - hostnames: - description: "Hostnames defines a set of hostname that should match - against the HTTP Host header to select a HTTPRoute to process the - request. This matches the RFC 1123 definition of a hostname with - 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname may - be prefixed with a wildcard label (`*.`). The wildcard label - must appear by itself as the first label. \n If a hostname is specified - by both the Listener and HTTPRoute, there must be at least one intersecting - hostname for the HTTPRoute to be attached to the Listener. For example: - \n * A Listener with `test.example.com` as the hostname matches - HTTPRoutes that have either not specified any hostnames, or have - specified at least one of `test.example.com` or `*.example.com`. - * A Listener with `*.example.com` as the hostname matches HTTPRoutes - \ that have either not specified any hostnames or have specified - at least one hostname that matches the Listener hostname. For - example, `test.example.com` and `*.example.com` would both match. - On the other hand, `example.com` and `test.example.net` would - not match. \n If both the Listener and HTTPRoute have specified - hostnames, any HTTPRoute hostnames that do not match the Listener - hostname MUST be ignored. For example, if a Listener specified `*.example.com`, - and the HTTPRoute specified `test.example.com` and `test.example.net`, - `test.example.net` must not be considered for a match. \n If both - the Listener and HTTPRoute have specified hostnames, and none match - with the criteria above, then the HTTPRoute is not accepted. The - implementation must raise an 'Accepted' Condition with a status - of `False` in the corresponding RouteParentStatus. \n Support: Core" - items: - description: "Hostname is the fully qualified domain name of a network - host. This matches the RFC 1123 definition of a hostname with - 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname - may be prefixed with a wildcard label (`*.`). The wildcard label - must appear by itself as the first label. \n Hostname can be \"precise\" - which is a domain name without the terminating dot of a network - host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain - name prefixed with a single wildcard label (e.g. `*.example.com`). - \n Note that as per RFC1035 and RFC1123, a *label* must consist - of lower case alphanumeric characters or '-', and must start and - end with an alphanumeric character. No other punctuation is allowed." - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - maxItems: 16 - type: array - parentRefs: - description: "ParentRefs references the resources (usually Gateways) - that a Route wants to be attached to. Note that the referenced parent - resource needs to allow this for the attachment to be complete. - For Gateways, that means the Gateway needs to allow attachment from - Routes of this kind and namespace. \n The only kind of parent resource - with \"Core\" support is Gateway. This API may be extended in the - future to support additional kinds of parent resources such as one - of the route kinds. \n It is invalid to reference an identical parent - more than once. It is valid to reference multiple distinct sections - within the same parent resource, such as 2 Listeners within a Gateway. - \n It is possible to separately reference multiple distinct objects - that may be collapsed by an implementation. For example, some implementations - may choose to merge compatible Gateway Listeners together. If that - is the case, the list of routes attached to those resources should - also be merged." - items: - description: "ParentRef identifies an API object (usually a Gateway) - that can be considered a parent of this resource (usually a route). - The only kind of parent resource with \"Core\" support is Gateway. - This API may be extended in the future to support additional kinds - of parent resources, such as HTTPRoute. \n The API object must - be valid in the cluster; the Group and Kind must be registered - in the cluster for this reference to be valid. \n References to - objects with invalid Group and Kind are not valid, and must be - rejected by the implementation, with appropriate Conditions set - on the containing object." - properties: - group: - default: gateway.networking.k8s.io - description: "Group is the group of the referent. \n Support: - Core" - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Gateway - description: "Kind is kind of the referent. \n Support: Core - (Gateway) Support: Custom (Other Resources)" - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: "Name is the name of the referent. \n Support: - Core" - maxLength: 253 - minLength: 1 - type: string - namespace: - description: "Namespace is the namespace of the referent. When - unspecified (or empty string), this refers to the local namespace - of the Route. \n Support: Core" - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - sectionName: - description: "SectionName is the name of a section within the - target resource. In the following resources, SectionName is - interpreted as the following: \n * Gateway: Listener Name - \n Implementations MAY choose to support attaching Routes - to other resources. If that is the case, they MUST clearly - document how SectionName is interpreted. \n When unspecified - (empty string), this will reference the entire resource. For - the purpose of status, an attachment is considered successful - if at least one section in the parent resource accepts it. - For example, Gateway listeners can restrict which Routes can - attach to them by Route kind, namespace, or hostname. If 1 - of 2 Gateway listeners accept attachment from the referencing - Route, the Route MUST be considered successfully attached. - If no Gateway listeners accept attachment from this Route, - the Route MUST be considered detached from the Gateway. \n - Support: Core" - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - required: - - name - type: object - maxItems: 32 - type: array - rules: - default: - - matches: - - path: - type: PathPrefix - value: / - description: Rules are a list of HTTP matchers, filters and actions. - items: - description: HTTPRouteRule defines semantics for matching an HTTP - request based on conditions (matches), processing it (filters), - and forwarding the request to an API object (backendRefs). - properties: - backendRefs: - description: "If unspecified or invalid (refers to a non-existent - resource or a Service with no endpoints), the rule performs - no forwarding. If there are also no filters specified that - would result in a response being sent, a HTTP 503 status code - is returned. 503 responses must be sent so that the overall - weight is respected; if an invalid backend is requested to - have 80% of requests, then 80% of requests must get a 503 - instead. \n Support: Core for Kubernetes Service Support: - Custom for any other resource \n Support for weight: Core" - items: - description: HTTPBackendRef defines how a HTTPRoute should - forward an HTTP request. - properties: - filters: - description: "Filters defined at this level should be - executed if and only if the request is being forwarded - to the backend defined here. \n Support: Custom (For - broader support of filters, use the Filters field in - HTTPRouteRule.)" - items: - description: HTTPRouteFilter defines processing steps - that must be completed during the request or response - lifecycle. HTTPRouteFilters are meant as an extension - point to express processing that may be done in Gateway - implementations. Some examples include request or - response modification, implementing authentication - strategies, rate-limiting, and traffic shaping. API - guarantee/conformance is defined based on the type - of the filter. + - additionalPrinterColumns: + - jsonPath: .spec.hostnames + name: Hostnames + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: HTTPRoute provides a way to route HTTP requests. This includes the capability to match requests by hostname, path, header, or query param. Filters can be used to specify additional processing steps. Backends specify where matching requests should be routed. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of HTTPRoute. + properties: + hostnames: + description: "Hostnames defines a set of hostnames that should match against the HTTP Host header to select a HTTPRoute used to process the request. Implementations MUST ignore any port value specified in the HTTP Host header while performing a match and (absent of any applicable header modification configuration) MUST forward this header unmodified to the backend. \n Valid values for Hostnames are determined by RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard label must appear by itself as the first label. \n If a hostname is specified by both the Listener and HTTPRoute, there must be at least one intersecting hostname for the HTTPRoute to be attached to the Listener. For example: \n * A Listener with `test.example.com` as the hostname matches HTTPRoutes that have either not specified any hostnames, or have specified at least one of `test.example.com` or `*.example.com`. * A Listener with `*.example.com` as the hostname matches HTTPRoutes that have either not specified any hostnames or have specified at least one hostname that matches the Listener hostname. For example, `*.example.com`, `test.example.com`, and `foo.test.example.com` would all match. On the other hand, `example.com` and `test.example.net` would not match. \n Hostnames that are prefixed with a wildcard label (`*.`) are interpreted as a suffix match. That means that a match for `*.example.com` would match both `test.example.com`, and `foo.test.example.com`, but not `example.com`. \n If both the Listener and HTTPRoute have specified hostnames, any HTTPRoute hostnames that do not match the Listener hostname MUST be ignored. For example, if a Listener specified `*.example.com`, and the HTTPRoute specified `test.example.com` and `test.example.net`, `test.example.net` must not be considered for a match. \n If both the Listener and HTTPRoute have specified hostnames, and none match with the criteria above, then the HTTPRoute is not accepted. The implementation must raise an 'Accepted' Condition with a status of `False` in the corresponding RouteParentStatus. \n In the event that multiple HTTPRoutes specify intersecting hostnames (e.g. overlapping wildcard matching and exact matching hostnames), precedence must be given to rules from the HTTPRoute with the largest number of: \n * Characters in a matching non-wildcard hostname. * Characters in a matching hostname. \n If ties exist across multiple Routes, the matching precedence rules for HTTPRouteMatches takes over. \n Support: Core" + items: + description: "Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard label must appear by itself as the first label. \n Hostname can be \"precise\" which is a domain name without the terminating dot of a network host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain name prefixed with a single wildcard label (e.g. `*.example.com`). \n Note that as per RFC1035 and RFC1123, a *label* must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character. No other punctuation is allowed." + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + description: "ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a \"producer\" route, or the mesh implementation must support and allow \"consumer\" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a \"producer\" route for a Service in a different namespace from the Route. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) This API may be extended in the future to support additional kinds of parent resources. \n ParentRefs must be _distinct_. This means either that: \n * They select different objects. If this is the case, then parentRef entries are distinct. In terms of fields, this means that the multi-part key defined by `group`, `kind`, `namespace`, and `name` must be unique across all parentRef entries in the Route. * They do not select different objects, but for each optional field used, each ParentRef that selects the same object must set the same set of optional fields to different values. If one ParentRef sets a combination of optional fields, all must set the same combination. \n Some examples: \n * If one ParentRef sets `sectionName`, all ParentRefs referencing the same object must also set `sectionName`. * If one ParentRef sets `port`, all ParentRefs referencing the same object must also set `port`. * If one ParentRef sets `sectionName` and `port`, all ParentRefs referencing the same object must also set `sectionName` and `port`. \n It is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged. \n Note that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n " + items: + description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n This API may be extended in the future to support additional kinds of parent resources. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + x-kubernetes-validations: + - message: sectionName or port must be specified when parentRefs includes 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__)) ? ((!has(p1.sectionName) || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) || p2.port == 0)): true))' + - message: sectionName or port must be unique when parentRefs includes 2 or more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName == '')) || ( has(p1.sectionName) && has(p2.sectionName) && p1.sectionName == p2.sectionName)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port == p2.port)))) + rules: + default: + - matches: + - path: + type: PathPrefix + value: / + description: Rules are a list of HTTP matchers, filters and actions. + items: + description: HTTPRouteRule defines semantics for matching an HTTP request based on conditions (matches), processing it (filters), and forwarding the request to an API object (backendRefs). + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching requests should be sent. \n Failure behavior here depends on how many BackendRefs are specified and how many are invalid. \n If *all* entries in BackendRefs are invalid, and there are also no filters specified in this route rule, *all* traffic which matches this rule MUST receive a 500 status code. \n See the HTTPBackendRef definition for the rules about what makes a single HTTPBackendRef invalid. \n When a HTTPBackendRef is invalid, 500 status codes MUST be returned for requests that would have otherwise been routed to an invalid backend. If multiple backends are specified, and some are invalid, the proportion of requests that would otherwise have been routed to an invalid backend MUST receive a 500 status code. \n For example, if two backends are specified with equal weights, and one is invalid, 50 percent of traffic must receive a 500. Implementations may choose how that 50 percent is determined. \n Support: Core for Kubernetes Service \n Support: Extended for Kubernetes ServiceImport \n Support: Implementation-specific for any other resource \n Support for weight: Core" + items: + description: "HTTPBackendRef defines how a HTTPRoute forwards a HTTP request. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n \n When the BackendRef points to a Kubernetes Service, implementations SHOULD honor the appProtocol field if it is set for the target Service Port. \n Implementations supporting appProtocol SHOULD recognize the Kubernetes Standard Application Protocols defined in KEP-3726. \n If a Service appProtocol isn't specified, an implementation MAY infer the backend protocol through its own means. Implementations MAY infer the protocol from the Route type referring to the backend Service. \n If a Route is not able to send traffic to the backend using the specified protocol then the backend is considered invalid. Implementations MUST set the \"ResolvedRefs\" condition to \"False\" with the \"UnsupportedProtocol\" reason. \n " + properties: + filters: + description: "Filters defined at this level should be executed if and only if the request is being forwarded to the backend defined here. \n Support: Implementation-specific (For broader support of filters, use the Filters field in HTTPRouteRule.)" + items: + description: HTTPRouteFilter defines processing steps that must be completed during the request or response lifecycle. HTTPRouteFilters are meant as an extension point to express processing that may be done in Gateway implementations. Some examples include request or response modification, implementing authentication strategies, rate-limiting, and traffic shaping. API guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: "ExtensionRef is an optional, implementation-specific extension to the \"filter\" behavior. For example, resource \"myroutefilter\" in group \"networking.example.net\"). ExtensionRef MUST NOT be used for core and extended filters. \n This filter can be used multiple times within the same rule. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema for a filter that modifies request headers. \n Support: Core" + properties: + add: + description: "Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: add: - name: \"my-header\" value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz \n Config: remove: [\"my-header1\", \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the given header (name, value) before the action. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: set: - name: \"my-header\" value: \"bar\" \n Output: GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: "RequestMirror defines a schema for a filter that mirrors requests. Requests are sent to the specified destination, but responses from that destination are ignored. \n This filter can be used multiple times within the same rule. Note that not all implementations will be able to support mirroring to multiple backends. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource where mirrored requests are sent. \n Mirrored requests must be sent only to a single destination endpoint within this BackendRef, irrespective of how many endpoints are present within this BackendRef. \n If the referent cannot be found, this BackendRef is invalid and must be dropped from the Gateway. The controller must ensure the \"ResolvedRefs\" condition on the Route status is set to `status: False` and not configure this backend in the underlying implementation. \n If there is a cross-namespace reference to an *existing* object that is not allowed by a ReferenceGrant, the controller must ensure the \"ResolvedRefs\" condition on the Route is set to `status: False`, with the \"RefNotPermitted\" reason and not configure this backend in the underlying implementation. \n In either error case, the Message of the `ResolvedRefs` Condition should be used to provide more detail about the problem. \n Support: Extended for Kubernetes Service \n Support: Implementation-specific for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource kind of the referent. For example \"Service\". \n Defaults to \"Service\" when not specified. \n ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. \n Support: Core (Services with a type other than ExternalName) \n Support: Implementation-specific (Services with type ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + required: + - backendRef + type: object + requestRedirect: + description: "RequestRedirect defines a schema for a filter that responds to the request with an HTTP redirection. \n Support: Core" + properties: + hostname: + description: "Hostname is the hostname to be used in the value of the `Location` header in the response. When empty, the hostname in the `Host` header of the request is used. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines parameters used to modify the path of the incoming request. The modified path is then used to construct the `Location` header. When empty, the request path is used as-is. \n Support: Extended" + properties: + replaceFullPath: + description: ReplaceFullPath specifies the value with which to replace the full path of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the value with which to replace the prefix match of a request during a rewrite or redirect. For example, a request to \"/foo/bar\" with a prefix match of \"/foo\" and a ReplacePrefixMatch of \"/xyz\" would be modified to \"/xyz/bar\". \n Note that this matches the behavior of the PathPrefix match type. This matches full path elements. A path element refers to the list of labels in the path split by the `/` separator. When specified, a trailing `/` is ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match the prefix `/abc`, but the path `/abcd` would not. \n ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in the implementation setting the Accepted Condition for the Route to `status: False`. \n Request Path | Prefix Match | Replace Prefix | Modified Path -------------|--------------|----------------|---------- /foo/bar | /foo | /xyz | /xyz/bar /foo/bar | /foo | /xyz/ | /xyz/bar /foo/bar | /foo/ | /xyz | /xyz/bar /foo/bar | /foo/ | /xyz/ | /xyz/bar /foo | /foo | /xyz | /xyz /foo/ | /foo | /xyz | /xyz/ /foo/bar | /foo | | /bar /foo/ | /foo | | / /foo | /foo | | / /foo/ | /foo | / | / /foo | /foo | / | /" + maxLength: 1024 + type: string + type: + description: "Type defines the type of path modifier. Additional types may be added in a future release of the API. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type == ''ReplacePrefixMatch'' : true' + port: + description: "Port is the port to be used in the value of the `Location` header in the response. \n If no port is specified, the redirect port MUST be derived using the following rules: \n * If redirect scheme is not-empty, the redirect port MUST be the well-known port associated with the redirect scheme. Specifically \"http\" to port 80 and \"https\" to port 443. If the redirect scheme does not have a well-known port, the listener port of the Gateway SHOULD be used. * If redirect scheme is empty, the redirect port MUST be the Gateway Listener port. \n Implementations SHOULD NOT add the port number in the 'Location' header in the following cases: \n * A Location header that will use HTTP (whether that is determined via the Listener protocol or the Scheme field) _and_ use port 80. * A Location header that will use HTTPS (whether that is determined via the Listener protocol or the Scheme field) _and_ use port 443. \n Support: Extended" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: "Scheme is the scheme to be used in the value of the `Location` header in the response. When empty, the scheme of the request is used. \n Scheme redirects can affect the port of the redirect, for more information, refer to the documentation for the port field of this filter. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. \n Support: Extended" + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status code to be used in response. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. \n Support: Core" + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: "ResponseHeaderModifier defines a schema for a filter that modifies response headers. \n Support: Extended" + properties: + add: + description: "Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: add: - name: \"my-header\" value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz \n Config: remove: [\"my-header1\", \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the given header (name, value) before the action. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: set: - name: \"my-header\" value: \"bar\" \n Output: GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: "Type identifies the type of filter to apply. As with other API fields, types are classified into three conformance levels: \n - Core: Filter types and their corresponding configuration defined by \"Support: Core\" in this package, e.g. \"RequestHeaderModifier\". All implementations must support core filters. \n - Extended: Filter types and their corresponding configuration defined by \"Support: Extended\" in this package, e.g. \"RequestMirror\". Implementers are encouraged to support extended filters. \n - Implementation-specific: Filters that are defined and supported by specific vendors. In the future, filters showing convergence in behavior across multiple implementations will be considered for inclusion in extended or core conformance levels. Filter-specific configuration for such filters is specified using the ExtensionRef field. `Type` should be set to \"ExtensionRef\" for custom filters. \n Implementers are encouraged to define custom implementation types to extend the core API with implementation-specific behavior. \n If a reference to a custom filter type cannot be resolved, the filter MUST NOT be skipped. Instead, requests that would have been processed by that filter MUST receive a HTTP error response. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: "URLRewrite defines a schema for a filter that modifies a request during forwarding. \n Support: Extended" + properties: + hostname: + description: "Hostname is the value to be used to replace the Host header value during forwarding. \n Support: Extended" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines a path rewrite. \n Support: Extended" + properties: + replaceFullPath: + description: ReplaceFullPath specifies the value with which to replace the full path of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the value with which to replace the prefix match of a request during a rewrite or redirect. For example, a request to \"/foo/bar\" with a prefix match of \"/foo\" and a ReplacePrefixMatch of \"/xyz\" would be modified to \"/xyz/bar\". \n Note that this matches the behavior of the PathPrefix match type. This matches full path elements. A path element refers to the list of labels in the path split by the `/` separator. When specified, a trailing `/` is ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match the prefix `/abc`, but the path `/abcd` would not. \n ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in the implementation setting the Accepted Condition for the Route to `status: False`. \n Request Path | Prefix Match | Replace Prefix | Modified Path -------------|--------------|----------------|---------- /foo/bar | /foo | /xyz | /xyz/bar /foo/bar | /foo | /xyz/ | /xyz/bar /foo/bar | /foo/ | /xyz | /xyz/bar /foo/bar | /foo/ | /xyz/ | /xyz/bar /foo | /foo | /xyz | /xyz /foo/ | /foo | /xyz | /xyz/ /foo/bar | /foo | | /bar /foo/ | /foo | | / /foo | /foo | | / /foo/ | /foo | / | / /foo | /foo | / | /" + maxLength: 1024 + type: string + type: + description: "Type defines the type of path modifier. Additional types may be added in a future release of the API. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the filter.type is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != ''RequestRedirect'')' + - message: filter.requestRedirect must be specified for RequestRedirect filter.type + rule: '!(!has(self.requestRedirect) && self.type == ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && self.exists(f, f.type == ''URLRewrite''))' + - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() <= 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 + group: + default: "" + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource kind of the referent. For example \"Service\". \n Defaults to \"Service\" when not specified. \n ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. \n Support: Core (Services with a type other than ExternalName) \n Support: Implementation-specific (Services with type ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests forwarded to the referenced backend. This is computed as weight/(sum of all weights in this BackendRefs list). For non-zero values, there may be some epsilon from the exact proportion defined here depending on the precision an implementation supports. Weight is not a percentage and the sum of weights does not need to equal 100. \n If only one backend is specified and it has a weight greater than 0, 100% of the traffic is forwarded to that backend. If weight is set to 0, no traffic should be forwarded for this entry. If unspecified, weight defaults to 1. \n Support for this field varies based on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + maxItems: 16 + type: array + filters: + description: "Filters define the filters that are applied to requests that match this rule. \n The effects of ordering of multiple behaviors are currently unspecified. This can change in the future based on feedback during the alpha stage. \n Conformance-levels at this level are defined based on the type of filter: \n - ALL core filters MUST be supported by all implementations. - Implementers are encouraged to support extended filters. - Implementation-specific custom filters have no API guarantees across implementations. \n Specifying the same filter multiple times is not supported unless explicitly indicated in the filter. \n All filters are expected to be compatible with each other except for the URLRewrite and RequestRedirect filters, which may not be combined. If an implementation can not support other combinations of filters, they must clearly document that limitation. In cases where incompatible or unsupported filters are specified and cause the `Accepted` condition to be set to status `False`, implementations may use the `IncompatibleFilters` reason to specify this configuration error. \n Support: Core" + items: + description: HTTPRouteFilter defines processing steps that must be completed during the request or response lifecycle. HTTPRouteFilters are meant as an extension point to express processing that may be done in Gateway implementations. Some examples include request or response modification, implementing authentication strategies, rate-limiting, and traffic shaping. API guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: "ExtensionRef is an optional, implementation-specific extension to the \"filter\" behavior. For example, resource \"myroutefilter\" in group \"networking.example.net\"). ExtensionRef MUST NOT be used for core and extended filters. \n This filter can be used multiple times within the same rule. \n Support: Implementation-specific" properties: - extensionRef: - description: "ExtensionRef is an optional, implementation-specific - extension to the \"filter\" behavior. For example, - resource \"myroutefilter\" in group \"networking.example.net\"). - ExtensionRef MUST NOT be used for core and extended - filters. \n Support: Implementation-specific" + group: + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema for a filter that modifies request headers. \n Support: Core" + properties: + add: + description: "Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: add: - name: \"my-header\" value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz \n Config: remove: [\"my-header1\", \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the given header (name, value) before the action. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: set: - name: \"my-header\" value: \"bar\" \n Output: GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: "RequestMirror defines a schema for a filter that mirrors requests. Requests are sent to the specified destination, but responses from that destination are ignored. \n This filter can be used multiple times within the same rule. Note that not all implementations will be able to support mirroring to multiple backends. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource where mirrored requests are sent. \n Mirrored requests must be sent only to a single destination endpoint within this BackendRef, irrespective of how many endpoints are present within this BackendRef. \n If the referent cannot be found, this BackendRef is invalid and must be dropped from the Gateway. The controller must ensure the \"ResolvedRefs\" condition on the Route status is set to `status: False` and not configure this backend in the underlying implementation. \n If there is a cross-namespace reference to an *existing* object that is not allowed by a ReferenceGrant, the controller must ensure the \"ResolvedRefs\" condition on the Route is set to `status: False`, with the \"RefNotPermitted\" reason and not configure this backend in the underlying implementation. \n In either error case, the Message of the `ResolvedRefs` Condition should be used to provide more detail about the problem. \n Support: Extended for Kubernetes Service \n Support: Implementation-specific for any other resource" properties: group: - description: Group is the group of the referent. - For example, "networking.k8s.io". When unspecified - (empty string), core API group is inferred. + default: "" + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: - description: Kind is kind of the referent. For - example "HTTPRoute" or "Service". + default: Service + description: "Kind is the Kubernetes resource kind of the referent. For example \"Service\". \n Defaults to \"Service\" when not specified. \n ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. \n Support: Core (Services with a type other than ExternalName) \n Support: Implementation-specific (Services with type ExternalName)" maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ @@ -244,1041 +625,1639 @@ spec: maxLength: 253 minLength: 1 type: string - required: - - group - - kind - - name - type: object - requestHeaderModifier: - description: "RequestHeaderModifier defines a schema - for a filter that modifies request headers. \n - Support: Core" - properties: - add: - description: "Add adds the given header(s) (name, - value) to the request before the action. It - appends to any existing values associated - with the header name. \n Input: GET /foo - HTTP/1.1 my-header: foo \n Config: add: - \ - name: \"my-header\" value: \"bar\" - \n Output: GET /foo HTTP/1.1 my-header: - foo my-header: bar" - items: - description: HTTPHeader represents an HTTP - Header name and value as defined by RFC - 7230. - properties: - name: - description: "Name is the name of the - HTTP Header to be matched. Name matching - MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - \n If multiple entries specify equivalent - header names, the first entry with an - equivalent name MUST be considered for - a match. Subsequent entries with an - equivalent header name MUST be ignored. - Due to the case-insensitivity of header - names, \"foo\" and \"Foo\" are considered - equivalent." - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - value: - description: Value is the value of HTTP - Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - remove: - description: "Remove the given header(s) from - the HTTP request before the action. The value - of Remove is a list of HTTP header names. - Note that the header names are case-insensitive - (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - \n Input: GET /foo HTTP/1.1 my-header1: - foo my-header2: bar my-header3: baz \n - Config: remove: [\"my-header1\", \"my-header3\"] - \n Output: GET /foo HTTP/1.1 my-header2: - bar" - items: - type: string - maxItems: 16 - type: array - set: - description: "Set overwrites the request with - the given header (name, value) before the - action. \n Input: GET /foo HTTP/1.1 my-header: - foo \n Config: set: - name: \"my-header\" - \ value: \"bar\" \n Output: GET /foo - HTTP/1.1 my-header: bar" - items: - description: HTTPHeader represents an HTTP - Header name and value as defined by RFC - 7230. - properties: - name: - description: "Name is the name of the - HTTP Header to be matched. Name matching - MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - \n If multiple entries specify equivalent - header names, the first entry with an - equivalent name MUST be considered for - a match. Subsequent entries with an - equivalent header name MUST be ignored. - Due to the case-insensitivity of header - names, \"foo\" and \"Foo\" are considered - equivalent." - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - value: - description: Value is the value of HTTP - Header to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - requestMirror: - description: "RequestMirror defines a schema for - a filter that mirrors requests. Requests are sent - to the specified destination, but responses from - that destination are ignored. \n Support: Extended" - properties: - backendRef: - description: "BackendRef references a resource - where mirrored requests are sent. \n If the - referent cannot be found, this BackendRef - is invalid and must be dropped from the Gateway. - The controller must ensure the \"ResolvedRefs\" - condition on the Route status is set to `status: - False` and not configure this backend in the - underlying implementation. \n If there is - a cross-namespace reference to an *existing* - object that is not allowed by a ReferencePolicy, - the controller must ensure the \"ResolvedRefs\" - \ condition on the Route is set to `status: - False`, with the \"RefNotPermitted\" reason - and not configure this backend in the underlying - implementation. \n In either error case, the - Message of the `ResolvedRefs` Condition should - be used to provide more detail about the problem. - \n Support: Extended for Kubernetes Service - Support: Custom for any other resource" - properties: - group: - default: "" - description: Group is the group of the referent. - For example, "networking.k8s.io". When - unspecified (empty string), core API group - is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Service - description: Kind is kind of the referent. - For example "HTTPRoute" or "Service". - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: "Namespace is the namespace - of the backend. When unspecified, the - local namespace is inferred. \n Note that - when a namespace is specified, a ReferencePolicy - object is required in the referent namespace - to allow that namespace's owner to accept - the reference. See the ReferencePolicy - documentation for details. \n Support: - Core" - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - port: - description: Port specifies the destination - port number to use for this resource. - Port is required when the referent is - a Kubernetes Service. For other resources, - destination port might be derived from - the referent resource or this field. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - required: - - name - type: object - required: - - backendRef - type: object - requestRedirect: - description: "RequestRedirect defines a schema for - a filter that responds to the request with an - HTTP redirection. \n Support: Core" - properties: - hostname: - description: "Hostname is the hostname to be - used in the value of the `Location` header - in the response. When empty, the hostname - of the request is used. \n Support: Core" - maxLength: 253 + namespace: + description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n Support: Core" + maxLength: 63 minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: - description: "Port is the port to be used in - the value of the `Location` header in the - response. When empty, port (if specified) - of the request is used. \n Support: Extended" + description: Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. format: int32 maximum: 65535 minimum: 1 type: integer - scheme: - description: "Scheme is the scheme to be used - in the value of the `Location` header in the - response. When empty, the scheme of the request - is used. \n Support: Extended" - enum: - - http - - https - type: string - statusCode: - default: 302 - description: "StatusCode is the HTTP status - code to be used in response. \n Support: Core" - enum: - - 301 - - 302 - type: integer + required: + - name type: object - type: - description: "Type identifies the type of filter - to apply. As with other API fields, types are - classified into three conformance levels: \n - - Core: Filter types and their corresponding configuration - defined by \"Support: Core\" in this package, - e.g. \"RequestHeaderModifier\". All implementations - must support core filters. \n - Extended: Filter - types and their corresponding configuration defined - by \"Support: Extended\" in this package, e.g. - \"RequestMirror\". Implementers are encouraged - to support extended filters. \n - Custom: Filters - that are defined and supported by specific vendors. - \ In the future, filters showing convergence - in behavior across multiple implementations - will be considered for inclusion in extended or - core conformance levels. Filter-specific configuration - for such filters is specified using the ExtensionRef - field. `Type` should be set to \"ExtensionRef\" - for custom filters. \n Implementers are encouraged - to define custom implementation types to extend - the core API with implementation-specific behavior. - \n If a reference to a custom filter type cannot - be resolved, the filter MUST NOT be skipped. Instead, - requests that would have been processed by that - filter MUST receive a HTTP error response." - enum: - - RequestHeaderModifier - - RequestMirror - - RequestRedirect - - ExtensionRef - type: string + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' required: - - type + - backendRef type: object - maxItems: 16 - type: array + requestRedirect: + description: "RequestRedirect defines a schema for a filter that responds to the request with an HTTP redirection. \n Support: Core" + properties: + hostname: + description: "Hostname is the hostname to be used in the value of the `Location` header in the response. When empty, the hostname in the `Host` header of the request is used. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines parameters used to modify the path of the incoming request. The modified path is then used to construct the `Location` header. When empty, the request path is used as-is. \n Support: Extended" + properties: + replaceFullPath: + description: ReplaceFullPath specifies the value with which to replace the full path of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the value with which to replace the prefix match of a request during a rewrite or redirect. For example, a request to \"/foo/bar\" with a prefix match of \"/foo\" and a ReplacePrefixMatch of \"/xyz\" would be modified to \"/xyz/bar\". \n Note that this matches the behavior of the PathPrefix match type. This matches full path elements. A path element refers to the list of labels in the path split by the `/` separator. When specified, a trailing `/` is ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match the prefix `/abc`, but the path `/abcd` would not. \n ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in the implementation setting the Accepted Condition for the Route to `status: False`. \n Request Path | Prefix Match | Replace Prefix | Modified Path -------------|--------------|----------------|---------- /foo/bar | /foo | /xyz | /xyz/bar /foo/bar | /foo | /xyz/ | /xyz/bar /foo/bar | /foo/ | /xyz | /xyz/bar /foo/bar | /foo/ | /xyz/ | /xyz/bar /foo | /foo | /xyz | /xyz /foo/ | /foo | /xyz | /xyz/ /foo/bar | /foo | | /bar /foo/ | /foo | | / /foo | /foo | | / /foo/ | /foo | / | / /foo | /foo | / | /" + maxLength: 1024 + type: string + type: + description: "Type defines the type of path modifier. Additional types may be added in a future release of the API. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type == ''ReplacePrefixMatch'' : true' + port: + description: "Port is the port to be used in the value of the `Location` header in the response. \n If no port is specified, the redirect port MUST be derived using the following rules: \n * If redirect scheme is not-empty, the redirect port MUST be the well-known port associated with the redirect scheme. Specifically \"http\" to port 80 and \"https\" to port 443. If the redirect scheme does not have a well-known port, the listener port of the Gateway SHOULD be used. * If redirect scheme is empty, the redirect port MUST be the Gateway Listener port. \n Implementations SHOULD NOT add the port number in the 'Location' header in the following cases: \n * A Location header that will use HTTP (whether that is determined via the Listener protocol or the Scheme field) _and_ use port 80. * A Location header that will use HTTPS (whether that is determined via the Listener protocol or the Scheme field) _and_ use port 443. \n Support: Extended" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: "Scheme is the scheme to be used in the value of the `Location` header in the response. When empty, the scheme of the request is used. \n Scheme redirects can affect the port of the redirect, for more information, refer to the documentation for the port field of this filter. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. \n Support: Extended" + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status code to be used in response. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. \n Support: Core" + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: "ResponseHeaderModifier defines a schema for a filter that modifies response headers. \n Support: Extended" + properties: + add: + description: "Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: add: - name: \"my-header\" value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz \n Config: remove: [\"my-header1\", \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the given header (name, value) before the action. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: set: - name: \"my-header\" value: \"bar\" \n Output: GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: "Type identifies the type of filter to apply. As with other API fields, types are classified into three conformance levels: \n - Core: Filter types and their corresponding configuration defined by \"Support: Core\" in this package, e.g. \"RequestHeaderModifier\". All implementations must support core filters. \n - Extended: Filter types and their corresponding configuration defined by \"Support: Extended\" in this package, e.g. \"RequestMirror\". Implementers are encouraged to support extended filters. \n - Implementation-specific: Filters that are defined and supported by specific vendors. In the future, filters showing convergence in behavior across multiple implementations will be considered for inclusion in extended or core conformance levels. Filter-specific configuration for such filters is specified using the ExtensionRef field. `Type` should be set to \"ExtensionRef\" for custom filters. \n Implementers are encouraged to define custom implementation types to extend the core API with implementation-specific behavior. \n If a reference to a custom filter type cannot be resolved, the filter MUST NOT be skipped. Instead, requests that would have been processed by that filter MUST receive a HTTP error response. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: "URLRewrite defines a schema for a filter that modifies a request during forwarding. \n Support: Extended" + properties: + hostname: + description: "Hostname is the value to be used to replace the Host header value during forwarding. \n Support: Extended" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines a path rewrite. \n Support: Extended" + properties: + replaceFullPath: + description: ReplaceFullPath specifies the value with which to replace the full path of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the value with which to replace the prefix match of a request during a rewrite or redirect. For example, a request to \"/foo/bar\" with a prefix match of \"/foo\" and a ReplacePrefixMatch of \"/xyz\" would be modified to \"/xyz/bar\". \n Note that this matches the behavior of the PathPrefix match type. This matches full path elements. A path element refers to the list of labels in the path split by the `/` separator. When specified, a trailing `/` is ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match the prefix `/abc`, but the path `/abcd` would not. \n ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in the implementation setting the Accepted Condition for the Route to `status: False`. \n Request Path | Prefix Match | Replace Prefix | Modified Path -------------|--------------|----------------|---------- /foo/bar | /foo | /xyz | /xyz/bar /foo/bar | /foo | /xyz/ | /xyz/bar /foo/bar | /foo/ | /xyz | /xyz/bar /foo/bar | /foo/ | /xyz/ | /xyz/bar /foo | /foo | /xyz | /xyz /foo/ | /foo | /xyz | /xyz/ /foo/bar | /foo | | /bar /foo/ | /foo | | / /foo | /foo | | / /foo/ | /foo | / | / /foo | /foo | / | /" + maxLength: 1024 + type: string + type: + description: "Type defines the type of path modifier. Additional types may be added in a future release of the API. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the filter.type is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != ''RequestRedirect'')' + - message: filter.requestRedirect must be specified for RequestRedirect filter.type + rule: '!(!has(self.requestRedirect) && self.type == ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() <= 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 + matches: + default: + - path: + type: PathPrefix + value: / + description: "Matches define conditions used for matching the rule against incoming HTTP requests. Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied. \n For example, take the following matches configuration: \n ``` matches: - path: value: \"/foo\" headers: - name: \"version\" value: \"v2\" - path: value: \"/v2/foo\" ``` \n For a request to match against this rule, a request must satisfy EITHER of the two conditions: \n - path prefixed with `/foo` AND contains the header `version: v2` - path prefix of `/v2/foo` \n See the documentation for HTTPRouteMatch on how to specify multiple match conditions that should be ANDed together. \n If no matches are specified, the default is a prefix path match on \"/\", which has the effect of matching every HTTP request. \n Proxy or Load Balancer routing configuration generated from HTTPRoutes MUST prioritize matches based on the following criteria, continuing on ties. Across all rules specified on applicable Routes, precedence must be given to the match having: \n * \"Exact\" path match. * \"Prefix\" path match with largest number of characters. * Method match. * Largest number of header matches. * Largest number of query param matches. \n Note: The precedence of RegularExpression path matches are implementation-specific. \n If ties still exist across multiple Routes, matching precedence MUST be determined in order of the following criteria, continuing on ties: \n * The oldest Route based on creation timestamp. * The Route appearing first in alphabetical order by \"{namespace}/{name}\". \n If ties still exist within an HTTPRoute, matching precedence MUST be granted to the FIRST matching rule (in list order) with a match meeting the above criteria. \n When no rules matching a request have been successfully attached to the parent a request is coming from, a HTTP 404 status code MUST be returned." + items: + description: "HTTPRouteMatch defines the predicate used to match requests to a given action. Multiple match types are ANDed together, i.e. the match will evaluate to true only if all conditions are satisfied. \n For example, the match below will match a HTTP request only if its path starts with `/foo` AND it contains the `version: v1` header: \n ``` match: \n path: value: \"/foo\" headers: - name: \"version\" value \"v1\" \n ```" + properties: + headers: + description: Headers specifies HTTP request header matchers. Multiple match values are ANDed together, meaning, a request must match all the specified headers to select the route. + items: + description: HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request headers. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, only the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent. \n When a header is repeated in an HTTP request, it is implementation-specific behavior as to how this is represented. Generally, proxies should follow the guidance from the RFC: https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding processing a repeated header, with special handling for \"Set-Cookie\"." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: "Type specifies how to match against the value of the header. \n Support: Core (Exact) \n Support: Implementation-specific (RegularExpression) \n Since RegularExpression HeaderMatchType has implementation-specific conformance, implementations can support POSIX, PCRE or any other dialects of regular expressions. Please read the implementation's documentation to determine the supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + description: "Method specifies HTTP method matcher. When specified, this route will be matched only if the request has the specified method. \n Support: Extended" + enum: + - GET + - HEAD + - POST + - PUT + - DELETE + - CONNECT + - OPTIONS + - TRACE + - PATCH + type: string + path: + default: + type: PathPrefix + value: / + description: Path specifies a HTTP request path matcher. If this field is not specified, a default prefix match on the "/" path is provided. + properties: + type: + default: PathPrefix + description: "Type specifies how to match against the path Value. \n Support: Core (Exact, PathPrefix) \n Support: Implementation-specific (RegularExpression)" + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + x-kubernetes-validations: + - message: value must be an absolute path and start with '/' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.startsWith(''/'') : true' + - message: must not contain '//' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''//'') : true' + - message: must not contain '/./' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/./'') : true' + - message: must not contain '/../' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/../'') : true' + - message: must not contain '%2f' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2f'') : true' + - message: must not contain '%2F' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2F'') : true' + - message: must not contain '#' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''#'') : true' + - message: must not end with '/..' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/..'') : true' + - message: must not end with '/.' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/.'') : true' + - message: type must be one of ['Exact', 'PathPrefix', 'RegularExpression'] + rule: self.type in ['Exact','PathPrefix'] || self.type == 'RegularExpression' + - message: must only contain valid characters (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) for types ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") : true' + queryParams: + description: "QueryParams specifies HTTP query parameter matchers. Multiple match values are ANDed together, meaning, a request must match all the specified query parameters to select the route. \n Support: Extended" + items: + description: HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP query parameters. + properties: + name: + description: "Name is the name of the HTTP query param to be matched. This must be an exact string match. (See https://tools.ietf.org/html/rfc7230#section-2.7.3). \n If multiple entries specify equivalent query param names, only the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent query param name MUST be ignored. \n If a query param is repeated in an HTTP request, the behavior is purposely left undefined, since different data planes have different capabilities. However, it is *recommended* that implementations should match against the first value of the param if the data plane supports it, as this behavior is expected in other load balancing contexts outside of the Gateway API. \n Users SHOULD NOT route traffic based on repeated query params to guard themselves against potential differences in the implementations." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: "Type specifies how to match against the value of the query parameter. \n Support: Extended (Exact) \n Support: Implementation-specific (RegularExpression) \n Since RegularExpression QueryParamMatchType has Implementation-specific conformance, implementations can support POSIX, PCRE or any other dialects of regular expressions. Please read the implementation's documentation to determine the supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 8 + type: array + timeouts: + description: "Timeouts defines the timeouts that can be configured for an HTTP request. \n Support: Extended \n " + properties: + backendRequest: + description: "BackendRequest specifies a timeout for an individual request from the gateway to a backend. This covers the time from when the request first starts being sent from the gateway to when the full response has been received from the backend. \n An entire client HTTP transaction with a gateway, covered by the Request timeout, may result in more than one call from the gateway to the destination backend, for example, if automatic retries are supported. \n Because the Request timeout encompasses the BackendRequest timeout, the value of BackendRequest must be <= the value of Request timeout. \n Support: Extended" + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + request: + description: "Request specifies the maximum duration for a gateway to respond to an HTTP request. If the gateway has not been able to respond before this deadline is met, the gateway MUST return a timeout error. \n For example, setting the `rules.timeouts.request` field to the value `10s` in an `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds to complete. \n This timeout is intended to cover as close to the whole request-response transaction as possible although an implementation MAY choose to start the timeout after the entire request stream has been received instead of immediately after the transaction is initiated by the client. \n When this field is unspecified, request timeout behavior is implementation-specific. \n Support: Extended" + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + type: object + x-kubernetes-validations: + - message: backendRequest timeout cannot be longer than request timeout + rule: '!(has(self.request) && has(self.backendRequest) && duration(self.request) != duration(''0s'') && duration(self.backendRequest) > duration(self.request))' + type: object + x-kubernetes-validations: + - message: RequestRedirect filter must not be used together with backendRefs + rule: '(has(self.backendRefs) && size(self.backendRefs) > 0) ? (!has(self.filters) || self.filters.all(f, !has(f.requestRedirect))): true' + - message: When using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.requestRedirect) && has(f.requestRedirect.path) && f.requestRedirect.path.type == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != ''PathPrefix'') ? false : true) : true' + - message: When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.urlRewrite) && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' && has(f.urlRewrite.path.replacePrefixMatch))) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != ''PathPrefix'') ? false : true) : true' + - message: Within backendRefs, when using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, (has(b.filters) && b.filters.exists_one(f, has(f.requestRedirect) && has(f.requestRedirect.path) && f.requestRedirect.path.type == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != ''PathPrefix'') ? false : true) : true' + - message: Within backendRefs, When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, (has(b.filters) && b.filters.exists_one(f, has(f.urlRewrite) && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' && has(f.urlRewrite.path.replacePrefixMatch))) )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != ''PathPrefix'') ? false : true) : true' + maxItems: 16 + type: array + type: object + status: + description: Status defines the current state of HTTPRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified. \n Note that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for. \n A maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway." + items: + description: RouteParentStatus describes the status of a route with respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with respect to the Gateway. Note that the route's availability is also subject to the Gateway's own status conditions and listener status. \n If the Route's ParentRef specifies an existing Gateway that supports Routes of this kind AND that Gateway's controller has sufficient access, then that Gateway's controller MUST set the \"Accepted\" condition on the Route, to indicate whether the route has been accepted or rejected by the Gateway, and why. \n A Route MUST be considered \"Accepted\" if at least one of the Route's rules is implemented by the Gateway. \n There are a number of cases where the \"Accepted\" condition may not be set due to lack of controller visibility, that includes when: \n * The Route refers to a non-existent parent. * The Route is of a type that the controller does not support. * The Route is in a namespace the controller does not have access to." + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates the name of the controller that wrote this status. This corresponds with the controllerName field on GatewayClass. \n Example: \"example.net/gateway-controller\". \n The format of this field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). \n Controllers MUST populate this field when writing status. Controllers should ensure that entries to status populated with their ControllerName are cleaned up when they are no longer necessary." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec that this RouteParentStatus struct describes the status of. + properties: group: - default: "" - description: Group is the group of the referent. For example, - "networking.k8s.io". When unspecified (empty string), - core API group is inferred. + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: - default: Service - description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". + default: Gateway + description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: - description: Name is the name of the referent. + description: "Name is the name of the referent. \n Support: Core" maxLength: 253 minLength: 1 type: string namespace: - description: "Namespace is the namespace of the backend. - When unspecified, the local namespace is inferred. \n - Note that when a namespace is specified, a ReferencePolicy - object is required in the referent namespace to allow - that namespace's owner to accept the reference. See - the ReferencePolicy documentation for details. \n Support: - Core" + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: - description: Port specifies the destination port number - to use for this resource. Port is required when the - referent is a Kubernetes Service. For other resources, - destination port might be derived from the referent - resource or this field. + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " format: int32 maximum: 65535 minimum: 1 type: integer - weight: - default: 1 - description: "Weight specifies the proportion of requests - forwarded to the referenced backend. This is computed - as weight/(sum of all weights in this BackendRefs list). - For non-zero values, there may be some epsilon from - the exact proportion defined here depending on the precision - an implementation supports. Weight is not a percentage - and the sum of weights does not need to equal 100. \n - If only one backend is specified and it has a weight - greater than 0, 100% of the traffic is forwarded to - that backend. If weight is set to 0, no traffic should - be forwarded for this entry. If unspecified, weight - defaults to 1. \n Support for this field varies based - on the context where used." - format: int32 - maximum: 1000000 - minimum: 0 - type: integer - required: - - name - type: object - maxItems: 16 - type: array - filters: - description: "Filters define the filters that are applied to - requests that match this rule. \n The effects of ordering - of multiple behaviors are currently unspecified. This can - change in the future based on feedback during the alpha stage. - \n Conformance-levels at this level are defined based on the - type of filter: \n - ALL core filters MUST be supported by - all implementations. - Implementers are encouraged to support - extended filters. - Implementation-specific custom filters - have no API guarantees across implementations. \n Specifying - a core filter multiple times has unspecified or custom conformance. - \n Support: Core" - items: - description: HTTPRouteFilter defines processing steps that - must be completed during the request or response lifecycle. - HTTPRouteFilters are meant as an extension point to express - processing that may be done in Gateway implementations. - Some examples include request or response modification, - implementing authentication strategies, rate-limiting, and - traffic shaping. API guarantee/conformance is defined based - on the type of the filter. - properties: - extensionRef: - description: "ExtensionRef is an optional, implementation-specific - extension to the \"filter\" behavior. For example, - resource \"myroutefilter\" in group \"networking.example.net\"). - ExtensionRef MUST NOT be used for core and extended - filters. \n Support: Implementation-specific" - properties: - group: - description: Group is the group of the referent. For - example, "networking.k8s.io". When unspecified (empty - string), core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - required: - - group - - kind - - name - type: object - requestHeaderModifier: - description: "RequestHeaderModifier defines a schema for - a filter that modifies request headers. \n Support: - Core" - properties: - add: - description: "Add adds the given header(s) (name, - value) to the request before the action. It appends - to any existing values associated with the header - name. \n Input: GET /foo HTTP/1.1 my-header: - foo \n Config: add: - name: \"my-header\" value: - \"bar\" \n Output: GET /foo HTTP/1.1 my-header: - foo my-header: bar" - items: - description: HTTPHeader represents an HTTP Header - name and value as defined by RFC 7230. - properties: - name: - description: "Name is the name of the HTTP Header - to be matched. Name matching MUST be case - insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - \n If multiple entries specify equivalent - header names, the first entry with an equivalent - name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST - be ignored. Due to the case-insensitivity - of header names, \"foo\" and \"Foo\" are considered - equivalent." - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - value: - description: Value is the value of HTTP Header - to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - remove: - description: "Remove the given header(s) from the - HTTP request before the action. The value of Remove - is a list of HTTP header names. Note that the header - names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - \n Input: GET /foo HTTP/1.1 my-header1: foo - \ my-header2: bar my-header3: baz \n Config: - \ remove: [\"my-header1\", \"my-header3\"] \n Output: - \ GET /foo HTTP/1.1 my-header2: bar" - items: - type: string - maxItems: 16 - type: array - set: - description: "Set overwrites the request with the - given header (name, value) before the action. \n - Input: GET /foo HTTP/1.1 my-header: foo \n Config: - \ set: - name: \"my-header\" value: \"bar\" - \n Output: GET /foo HTTP/1.1 my-header: bar" - items: - description: HTTPHeader represents an HTTP Header - name and value as defined by RFC 7230. - properties: - name: - description: "Name is the name of the HTTP Header - to be matched. Name matching MUST be case - insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - \n If multiple entries specify equivalent - header names, the first entry with an equivalent - name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST - be ignored. Due to the case-insensitivity - of header names, \"foo\" and \"Foo\" are considered - equivalent." - maxLength: 256 - minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ - type: string - value: - description: Value is the value of HTTP Header - to be matched. - maxLength: 4096 - minLength: 1 - type: string - required: - - name - - value - type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - requestMirror: - description: "RequestMirror defines a schema for a filter - that mirrors requests. Requests are sent to the specified - destination, but responses from that destination are - ignored. \n Support: Extended" - properties: - backendRef: - description: "BackendRef references a resource where - mirrored requests are sent. \n If the referent cannot - be found, this BackendRef is invalid and must be - dropped from the Gateway. The controller must ensure - the \"ResolvedRefs\" condition on the Route status - is set to `status: False` and not configure this - backend in the underlying implementation. \n If - there is a cross-namespace reference to an *existing* - object that is not allowed by a ReferencePolicy, - the controller must ensure the \"ResolvedRefs\" - \ condition on the Route is set to `status: False`, - with the \"RefNotPermitted\" reason and not configure - this backend in the underlying implementation. \n - In either error case, the Message of the `ResolvedRefs` - Condition should be used to provide more detail - about the problem. \n Support: Extended for Kubernetes - Service Support: Custom for any other resource" - properties: - group: - default: "" - description: Group is the group of the referent. - For example, "networking.k8s.io". When unspecified - (empty string), core API group is inferred. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Service - description: Kind is kind of the referent. For - example "HTTPRoute" or "Service". - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: "Namespace is the namespace of the - backend. When unspecified, the local namespace - is inferred. \n Note that when a namespace is - specified, a ReferencePolicy object is required - in the referent namespace to allow that namespace's - owner to accept the reference. See the ReferencePolicy - documentation for details. \n Support: Core" - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - port: - description: Port specifies the destination port - number to use for this resource. Port is required - when the referent is a Kubernetes Service. For - other resources, destination port might be derived - from the referent resource or this field. - format: int32 - maximum: 65535 - minimum: 1 - type: integer - required: - - name - type: object - required: - - backendRef - type: object - requestRedirect: - description: "RequestRedirect defines a schema for a filter - that responds to the request with an HTTP redirection. - \n Support: Core" - properties: - hostname: - description: "Hostname is the hostname to be used - in the value of the `Location` header in the response. - When empty, the hostname of the request is used. - \n Support: Core" - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - port: - description: "Port is the port to be used in the value - of the `Location` header in the response. When empty, - port (if specified) of the request is used. \n Support: - Extended" - format: int32 - maximum: 65535 - minimum: 1 - type: integer - scheme: - description: "Scheme is the scheme to be used in the - value of the `Location` header in the response. - When empty, the scheme of the request is used. \n - Support: Extended" - enum: - - http - - https - type: string - statusCode: - default: 302 - description: "StatusCode is the HTTP status code to - be used in response. \n Support: Core" - enum: - - 301 - - 302 - type: integer - type: object - type: - description: "Type identifies the type of filter to apply. - As with other API fields, types are classified into - three conformance levels: \n - Core: Filter types and - their corresponding configuration defined by \"Support: - Core\" in this package, e.g. \"RequestHeaderModifier\". - All implementations must support core filters. \n - - Extended: Filter types and their corresponding configuration - defined by \"Support: Extended\" in this package, - e.g. \"RequestMirror\". Implementers are encouraged - to support extended filters. \n - Custom: Filters that - are defined and supported by specific vendors. In - the future, filters showing convergence in behavior - across multiple implementations will be considered - for inclusion in extended or core conformance levels. - Filter-specific configuration for such filters is - specified using the ExtensionRef field. `Type` should - be set to \"ExtensionRef\" for custom filters. \n - Implementers are encouraged to define custom implementation - types to extend the core API with implementation-specific - behavior. \n If a reference to a custom filter type - cannot be resolved, the filter MUST NOT be skipped. - Instead, requests that would have been processed by - that filter MUST receive a HTTP error response." - enum: - - RequestHeaderModifier - - RequestMirror - - RequestRedirect - - ExtensionRef + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string required: - - type + - name type: object - maxItems: 16 - type: array - matches: - default: - - path: - type: PathPrefix - value: / - description: "Matches define conditions used for matching the - rule against incoming HTTP requests. Each match is independent, - i.e. this rule will be matched if **any** one of the matches - is satisfied. \n For example, take the following matches configuration: - \n ``` matches: - path: value: \"/foo\" headers: - - name: \"version\" value: \"v2\" - path: value: \"/v2/foo\" - ``` \n For a request to match against this rule, a request - must satisfy EITHER of the two conditions: \n - path prefixed - with `/foo` AND contains the header `version: v2` - path prefix - of `/v2/foo` \n See the documentation for HTTPRouteMatch on - how to specify multiple match conditions that should be ANDed - together. \n If no matches are specified, the default is a - prefix path match on \"/\", which has the effect of matching - every HTTP request. \n Proxy or Load Balancer routing configuration - generated from HTTPRoutes MUST prioritize rules based on the - following criteria, continuing on ties. Precedence must be - given to the the Rule with the largest number of: \n * Characters - in a matching non-wildcard hostname. * Characters in a matching - hostname. * Characters in a matching path. * Header matches. - * Query param matches. \n If ties still exist across multiple - Routes, matching precedence MUST be determined in order of - the following criteria, continuing on ties: \n * The oldest - Route based on creation timestamp. * The Route appearing first - in alphabetical order by \"/\". \n If ties - still exist within the Route that has been given precedence, - matching precedence MUST be granted to the first matching - rule meeting the above criteria." - items: - description: "HTTPRouteMatch defines the predicate used to - match requests to a given action. Multiple match types are - ANDed together, i.e. the match will evaluate to true only - if all conditions are satisfied. \n For example, the match - below will match a HTTP request only if its path starts - with `/foo` AND it contains the `version: v1` header: \n - ``` match: path: value: \"/foo\" headers: - name: - \"version\" value \"v1\" ```" - properties: - headers: - description: Headers specifies HTTP request header matchers. - Multiple match values are ANDed together, meaning, a - request must match all the specified headers to select - the route. - items: - description: HTTPHeaderMatch describes how to select - a HTTP route by matching HTTP request headers. + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.hostnames + name: Hostnames + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: HTTPRoute provides a way to route HTTP requests. This includes the capability to match requests by hostname, path, header, or query param. Filters can be used to specify additional processing steps. Backends specify where matching requests should be routed. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of HTTPRoute. + properties: + hostnames: + description: "Hostnames defines a set of hostnames that should match against the HTTP Host header to select a HTTPRoute used to process the request. Implementations MUST ignore any port value specified in the HTTP Host header while performing a match and (absent of any applicable header modification configuration) MUST forward this header unmodified to the backend. \n Valid values for Hostnames are determined by RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard label must appear by itself as the first label. \n If a hostname is specified by both the Listener and HTTPRoute, there must be at least one intersecting hostname for the HTTPRoute to be attached to the Listener. For example: \n * A Listener with `test.example.com` as the hostname matches HTTPRoutes that have either not specified any hostnames, or have specified at least one of `test.example.com` or `*.example.com`. * A Listener with `*.example.com` as the hostname matches HTTPRoutes that have either not specified any hostnames or have specified at least one hostname that matches the Listener hostname. For example, `*.example.com`, `test.example.com`, and `foo.test.example.com` would all match. On the other hand, `example.com` and `test.example.net` would not match. \n Hostnames that are prefixed with a wildcard label (`*.`) are interpreted as a suffix match. That means that a match for `*.example.com` would match both `test.example.com`, and `foo.test.example.com`, but not `example.com`. \n If both the Listener and HTTPRoute have specified hostnames, any HTTPRoute hostnames that do not match the Listener hostname MUST be ignored. For example, if a Listener specified `*.example.com`, and the HTTPRoute specified `test.example.com` and `test.example.net`, `test.example.net` must not be considered for a match. \n If both the Listener and HTTPRoute have specified hostnames, and none match with the criteria above, then the HTTPRoute is not accepted. The implementation must raise an 'Accepted' Condition with a status of `False` in the corresponding RouteParentStatus. \n In the event that multiple HTTPRoutes specify intersecting hostnames (e.g. overlapping wildcard matching and exact matching hostnames), precedence must be given to rules from the HTTPRoute with the largest number of: \n * Characters in a matching non-wildcard hostname. * Characters in a matching hostname. \n If ties exist across multiple Routes, the matching precedence rules for HTTPRouteMatches takes over. \n Support: Core" + items: + description: "Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard label must appear by itself as the first label. \n Hostname can be \"precise\" which is a domain name without the terminating dot of a network host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain name prefixed with a single wildcard label (e.g. `*.example.com`). \n Note that as per RFC1035 and RFC1123, a *label* must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character. No other punctuation is allowed." + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + description: "ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a \"producer\" route, or the mesh implementation must support and allow \"consumer\" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a \"producer\" route for a Service in a different namespace from the Route. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) This API may be extended in the future to support additional kinds of parent resources. \n ParentRefs must be _distinct_. This means either that: \n * They select different objects. If this is the case, then parentRef entries are distinct. In terms of fields, this means that the multi-part key defined by `group`, `kind`, `namespace`, and `name` must be unique across all parentRef entries in the Route. * They do not select different objects, but for each optional field used, each ParentRef that selects the same object must set the same set of optional fields to different values. If one ParentRef sets a combination of optional fields, all must set the same combination. \n Some examples: \n * If one ParentRef sets `sectionName`, all ParentRefs referencing the same object must also set `sectionName`. * If one ParentRef sets `port`, all ParentRefs referencing the same object must also set `port`. * If one ParentRef sets `sectionName` and `port`, all ParentRefs referencing the same object must also set `sectionName` and `port`. \n It is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged. \n Note that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n " + items: + description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n This API may be extended in the future to support additional kinds of parent resources. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + x-kubernetes-validations: + - message: sectionName or port must be specified when parentRefs includes 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__)) ? ((!has(p1.sectionName) || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) || p2.port == 0)): true))' + - message: sectionName or port must be unique when parentRefs includes 2 or more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName == '')) || ( has(p1.sectionName) && has(p2.sectionName) && p1.sectionName == p2.sectionName)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port == p2.port)))) + rules: + default: + - matches: + - path: + type: PathPrefix + value: / + description: Rules are a list of HTTP matchers, filters and actions. + items: + description: HTTPRouteRule defines semantics for matching an HTTP request based on conditions (matches), processing it (filters), and forwarding the request to an API object (backendRefs). + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching requests should be sent. \n Failure behavior here depends on how many BackendRefs are specified and how many are invalid. \n If *all* entries in BackendRefs are invalid, and there are also no filters specified in this route rule, *all* traffic which matches this rule MUST receive a 500 status code. \n See the HTTPBackendRef definition for the rules about what makes a single HTTPBackendRef invalid. \n When a HTTPBackendRef is invalid, 500 status codes MUST be returned for requests that would have otherwise been routed to an invalid backend. If multiple backends are specified, and some are invalid, the proportion of requests that would otherwise have been routed to an invalid backend MUST receive a 500 status code. \n For example, if two backends are specified with equal weights, and one is invalid, 50 percent of traffic must receive a 500. Implementations may choose how that 50 percent is determined. \n Support: Core for Kubernetes Service \n Support: Extended for Kubernetes ServiceImport \n Support: Implementation-specific for any other resource \n Support for weight: Core" + items: + description: "HTTPBackendRef defines how a HTTPRoute forwards a HTTP request. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n \n When the BackendRef points to a Kubernetes Service, implementations SHOULD honor the appProtocol field if it is set for the target Service Port. \n Implementations supporting appProtocol SHOULD recognize the Kubernetes Standard Application Protocols defined in KEP-3726. \n If a Service appProtocol isn't specified, an implementation MAY infer the backend protocol through its own means. Implementations MAY infer the protocol from the Route type referring to the backend Service. \n If a Route is not able to send traffic to the backend using the specified protocol then the backend is considered invalid. Implementations MUST set the \"ResolvedRefs\" condition to \"False\" with the \"UnsupportedProtocol\" reason. \n " + properties: + filters: + description: "Filters defined at this level should be executed if and only if the request is being forwarded to the backend defined here. \n Support: Implementation-specific (For broader support of filters, use the Filters field in HTTPRouteRule.)" + items: + description: HTTPRouteFilter defines processing steps that must be completed during the request or response lifecycle. HTTPRouteFilters are meant as an extension point to express processing that may be done in Gateway implementations. Some examples include request or response modification, implementing authentication strategies, rate-limiting, and traffic shaping. API guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: "ExtensionRef is an optional, implementation-specific extension to the \"filter\" behavior. For example, resource \"myroutefilter\" in group \"networking.example.net\"). ExtensionRef MUST NOT be used for core and extended filters. \n This filter can be used multiple times within the same rule. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema for a filter that modifies request headers. \n Support: Core" + properties: + add: + description: "Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: add: - name: \"my-header\" value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz \n Config: remove: [\"my-header1\", \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the given header (name, value) before the action. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: set: - name: \"my-header\" value: \"bar\" \n Output: GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: "RequestMirror defines a schema for a filter that mirrors requests. Requests are sent to the specified destination, but responses from that destination are ignored. \n This filter can be used multiple times within the same rule. Note that not all implementations will be able to support mirroring to multiple backends. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource where mirrored requests are sent. \n Mirrored requests must be sent only to a single destination endpoint within this BackendRef, irrespective of how many endpoints are present within this BackendRef. \n If the referent cannot be found, this BackendRef is invalid and must be dropped from the Gateway. The controller must ensure the \"ResolvedRefs\" condition on the Route status is set to `status: False` and not configure this backend in the underlying implementation. \n If there is a cross-namespace reference to an *existing* object that is not allowed by a ReferenceGrant, the controller must ensure the \"ResolvedRefs\" condition on the Route is set to `status: False`, with the \"RefNotPermitted\" reason and not configure this backend in the underlying implementation. \n In either error case, the Message of the `ResolvedRefs` Condition should be used to provide more detail about the problem. \n Support: Extended for Kubernetes Service \n Support: Implementation-specific for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource kind of the referent. For example \"Service\". \n Defaults to \"Service\" when not specified. \n ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. \n Support: Core (Services with a type other than ExternalName) \n Support: Implementation-specific (Services with type ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + required: + - backendRef + type: object + requestRedirect: + description: "RequestRedirect defines a schema for a filter that responds to the request with an HTTP redirection. \n Support: Core" + properties: + hostname: + description: "Hostname is the hostname to be used in the value of the `Location` header in the response. When empty, the hostname in the `Host` header of the request is used. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines parameters used to modify the path of the incoming request. The modified path is then used to construct the `Location` header. When empty, the request path is used as-is. \n Support: Extended" + properties: + replaceFullPath: + description: ReplaceFullPath specifies the value with which to replace the full path of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the value with which to replace the prefix match of a request during a rewrite or redirect. For example, a request to \"/foo/bar\" with a prefix match of \"/foo\" and a ReplacePrefixMatch of \"/xyz\" would be modified to \"/xyz/bar\". \n Note that this matches the behavior of the PathPrefix match type. This matches full path elements. A path element refers to the list of labels in the path split by the `/` separator. When specified, a trailing `/` is ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match the prefix `/abc`, but the path `/abcd` would not. \n ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in the implementation setting the Accepted Condition for the Route to `status: False`. \n Request Path | Prefix Match | Replace Prefix | Modified Path -------------|--------------|----------------|---------- /foo/bar | /foo | /xyz | /xyz/bar /foo/bar | /foo | /xyz/ | /xyz/bar /foo/bar | /foo/ | /xyz | /xyz/bar /foo/bar | /foo/ | /xyz/ | /xyz/bar /foo | /foo | /xyz | /xyz /foo/ | /foo | /xyz | /xyz/ /foo/bar | /foo | | /bar /foo/ | /foo | | / /foo | /foo | | / /foo/ | /foo | / | / /foo | /foo | / | /" + maxLength: 1024 + type: string + type: + description: "Type defines the type of path modifier. Additional types may be added in a future release of the API. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type == ''ReplacePrefixMatch'' : true' + port: + description: "Port is the port to be used in the value of the `Location` header in the response. \n If no port is specified, the redirect port MUST be derived using the following rules: \n * If redirect scheme is not-empty, the redirect port MUST be the well-known port associated with the redirect scheme. Specifically \"http\" to port 80 and \"https\" to port 443. If the redirect scheme does not have a well-known port, the listener port of the Gateway SHOULD be used. * If redirect scheme is empty, the redirect port MUST be the Gateway Listener port. \n Implementations SHOULD NOT add the port number in the 'Location' header in the following cases: \n * A Location header that will use HTTP (whether that is determined via the Listener protocol or the Scheme field) _and_ use port 80. * A Location header that will use HTTPS (whether that is determined via the Listener protocol or the Scheme field) _and_ use port 443. \n Support: Extended" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: "Scheme is the scheme to be used in the value of the `Location` header in the response. When empty, the scheme of the request is used. \n Scheme redirects can affect the port of the redirect, for more information, refer to the documentation for the port field of this filter. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. \n Support: Extended" + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status code to be used in response. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. \n Support: Core" + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: "ResponseHeaderModifier defines a schema for a filter that modifies response headers. \n Support: Extended" + properties: + add: + description: "Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: add: - name: \"my-header\" value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz \n Config: remove: [\"my-header1\", \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the given header (name, value) before the action. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: set: - name: \"my-header\" value: \"bar\" \n Output: GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: "Type identifies the type of filter to apply. As with other API fields, types are classified into three conformance levels: \n - Core: Filter types and their corresponding configuration defined by \"Support: Core\" in this package, e.g. \"RequestHeaderModifier\". All implementations must support core filters. \n - Extended: Filter types and their corresponding configuration defined by \"Support: Extended\" in this package, e.g. \"RequestMirror\". Implementers are encouraged to support extended filters. \n - Implementation-specific: Filters that are defined and supported by specific vendors. In the future, filters showing convergence in behavior across multiple implementations will be considered for inclusion in extended or core conformance levels. Filter-specific configuration for such filters is specified using the ExtensionRef field. `Type` should be set to \"ExtensionRef\" for custom filters. \n Implementers are encouraged to define custom implementation types to extend the core API with implementation-specific behavior. \n If a reference to a custom filter type cannot be resolved, the filter MUST NOT be skipped. Instead, requests that would have been processed by that filter MUST receive a HTTP error response. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: "URLRewrite defines a schema for a filter that modifies a request during forwarding. \n Support: Extended" + properties: + hostname: + description: "Hostname is the value to be used to replace the Host header value during forwarding. \n Support: Extended" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines a path rewrite. \n Support: Extended" + properties: + replaceFullPath: + description: ReplaceFullPath specifies the value with which to replace the full path of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the value with which to replace the prefix match of a request during a rewrite or redirect. For example, a request to \"/foo/bar\" with a prefix match of \"/foo\" and a ReplacePrefixMatch of \"/xyz\" would be modified to \"/xyz/bar\". \n Note that this matches the behavior of the PathPrefix match type. This matches full path elements. A path element refers to the list of labels in the path split by the `/` separator. When specified, a trailing `/` is ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match the prefix `/abc`, but the path `/abcd` would not. \n ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in the implementation setting the Accepted Condition for the Route to `status: False`. \n Request Path | Prefix Match | Replace Prefix | Modified Path -------------|--------------|----------------|---------- /foo/bar | /foo | /xyz | /xyz/bar /foo/bar | /foo | /xyz/ | /xyz/bar /foo/bar | /foo/ | /xyz | /xyz/bar /foo/bar | /foo/ | /xyz/ | /xyz/bar /foo | /foo | /xyz | /xyz /foo/ | /foo | /xyz | /xyz/ /foo/bar | /foo | | /bar /foo/ | /foo | | / /foo | /foo | | / /foo/ | /foo | / | / /foo | /foo | / | /" + maxLength: 1024 + type: string + type: + description: "Type defines the type of path modifier. Additional types may be added in a future release of the API. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the filter.type is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != ''RequestRedirect'')' + - message: filter.requestRedirect must be specified for RequestRedirect filter.type + rule: '!(!has(self.requestRedirect) && self.type == ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && self.exists(f, f.type == ''URLRewrite''))' + - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() <= 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 + group: + default: "" + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource kind of the referent. For example \"Service\". \n Defaults to \"Service\" when not specified. \n ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. \n Support: Core (Services with a type other than ExternalName) \n Support: Implementation-specific (Services with type ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests forwarded to the referenced backend. This is computed as weight/(sum of all weights in this BackendRefs list). For non-zero values, there may be some epsilon from the exact proportion defined here depending on the precision an implementation supports. Weight is not a percentage and the sum of weights does not need to equal 100. \n If only one backend is specified and it has a weight greater than 0, 100% of the traffic is forwarded to that backend. If weight is set to 0, no traffic should be forwarded for this entry. If unspecified, weight defaults to 1. \n Support for this field varies based on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + maxItems: 16 + type: array + filters: + description: "Filters define the filters that are applied to requests that match this rule. \n The effects of ordering of multiple behaviors are currently unspecified. This can change in the future based on feedback during the alpha stage. \n Conformance-levels at this level are defined based on the type of filter: \n - ALL core filters MUST be supported by all implementations. - Implementers are encouraged to support extended filters. - Implementation-specific custom filters have no API guarantees across implementations. \n Specifying the same filter multiple times is not supported unless explicitly indicated in the filter. \n All filters are expected to be compatible with each other except for the URLRewrite and RequestRedirect filters, which may not be combined. If an implementation can not support other combinations of filters, they must clearly document that limitation. In cases where incompatible or unsupported filters are specified and cause the `Accepted` condition to be set to status `False`, implementations may use the `IncompatibleFilters` reason to specify this configuration error. \n Support: Core" + items: + description: HTTPRouteFilter defines processing steps that must be completed during the request or response lifecycle. HTTPRouteFilters are meant as an extension point to express processing that may be done in Gateway implementations. Some examples include request or response modification, implementing authentication strategies, rate-limiting, and traffic shaping. API guarantee/conformance is defined based on the type of the filter. + properties: + extensionRef: + description: "ExtensionRef is an optional, implementation-specific extension to the \"filter\" behavior. For example, resource \"myroutefilter\" in group \"networking.example.net\"). ExtensionRef MUST NOT be used for core and extended filters. \n This filter can be used multiple times within the same rule. \n Support: Implementation-specific" properties: - name: - description: "Name is the name of the HTTP Header - to be matched. Name matching MUST be case insensitive. - (See https://tools.ietf.org/html/rfc7230#section-3.2). - \n If multiple entries specify equivalent header - names, only the first entry with an equivalent - name MUST be considered for a match. Subsequent - entries with an equivalent header name MUST be - ignored. Due to the case-insensitivity of header - names, \"foo\" and \"Foo\" are considered equivalent. - \n When a header is repeated in an HTTP request, - it is implementation-specific behavior as to how - this is represented. Generally, proxies should - follow the guidance from the RFC: https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 - regarding processing a repeated header, with special - handling for \"Set-Cookie\"." - maxLength: 256 + group: + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" or "Service". + maxLength: 63 minLength: 1 - pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string - type: - default: Exact - description: "Type specifies how to match against - the value of the header. \n Support: Core (Exact) - \n Support: Custom (RegularExpression) \n Since - RegularExpression HeaderMatchType has custom conformance, - implementations can support POSIX, PCRE or any - other dialects of regular expressions. Please - read the implementation's documentation to determine - the supported dialect." - enum: - - Exact - - RegularExpression - type: string - value: - description: Value is the value of HTTP Header to - be matched. - maxLength: 4096 + name: + description: Name is the name of the referent. + maxLength: 253 minLength: 1 type: string required: - - name - - value + - group + - kind + - name type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - method: - description: "Method specifies HTTP method matcher. When - specified, this route will be matched only if the request - has the specified method. \n Support: Extended" - enum: - - GET - - HEAD - - POST - - PUT - - DELETE - - CONNECT - - OPTIONS - - TRACE - - PATCH - type: string - path: - default: + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema for a filter that modifies request headers. \n Support: Core" + properties: + add: + description: "Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: add: - name: \"my-header\" value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz \n Config: remove: [\"my-header1\", \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the given header (name, value) before the action. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: set: - name: \"my-header\" value: \"bar\" \n Output: GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: "RequestMirror defines a schema for a filter that mirrors requests. Requests are sent to the specified destination, but responses from that destination are ignored. \n This filter can be used multiple times within the same rule. Note that not all implementations will be able to support mirroring to multiple backends. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource where mirrored requests are sent. \n Mirrored requests must be sent only to a single destination endpoint within this BackendRef, irrespective of how many endpoints are present within this BackendRef. \n If the referent cannot be found, this BackendRef is invalid and must be dropped from the Gateway. The controller must ensure the \"ResolvedRefs\" condition on the Route status is set to `status: False` and not configure this backend in the underlying implementation. \n If there is a cross-namespace reference to an *existing* object that is not allowed by a ReferenceGrant, the controller must ensure the \"ResolvedRefs\" condition on the Route is set to `status: False`, with the \"RefNotPermitted\" reason and not configure this backend in the underlying implementation. \n In either error case, the Message of the `ResolvedRefs` Condition should be used to provide more detail about the problem. \n Support: Extended for Kubernetes Service \n Support: Implementation-specific for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource kind of the referent. For example \"Service\". \n Defaults to \"Service\" when not specified. \n ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. \n Support: Core (Services with a type other than ExternalName) \n Support: Implementation-specific (Services with type ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + required: + - backendRef + type: object + requestRedirect: + description: "RequestRedirect defines a schema for a filter that responds to the request with an HTTP redirection. \n Support: Core" + properties: + hostname: + description: "Hostname is the hostname to be used in the value of the `Location` header in the response. When empty, the hostname in the `Host` header of the request is used. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines parameters used to modify the path of the incoming request. The modified path is then used to construct the `Location` header. When empty, the request path is used as-is. \n Support: Extended" + properties: + replaceFullPath: + description: ReplaceFullPath specifies the value with which to replace the full path of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the value with which to replace the prefix match of a request during a rewrite or redirect. For example, a request to \"/foo/bar\" with a prefix match of \"/foo\" and a ReplacePrefixMatch of \"/xyz\" would be modified to \"/xyz/bar\". \n Note that this matches the behavior of the PathPrefix match type. This matches full path elements. A path element refers to the list of labels in the path split by the `/` separator. When specified, a trailing `/` is ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match the prefix `/abc`, but the path `/abcd` would not. \n ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in the implementation setting the Accepted Condition for the Route to `status: False`. \n Request Path | Prefix Match | Replace Prefix | Modified Path -------------|--------------|----------------|---------- /foo/bar | /foo | /xyz | /xyz/bar /foo/bar | /foo | /xyz/ | /xyz/bar /foo/bar | /foo/ | /xyz | /xyz/bar /foo/bar | /foo/ | /xyz/ | /xyz/bar /foo | /foo | /xyz | /xyz /foo/ | /foo | /xyz | /xyz/ /foo/bar | /foo | | /bar /foo/ | /foo | | / /foo | /foo | | / /foo/ | /foo | / | / /foo | /foo | / | /" + maxLength: 1024 + type: string + type: + description: "Type defines the type of path modifier. Additional types may be added in a future release of the API. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type == ''ReplacePrefixMatch'' : true' + port: + description: "Port is the port to be used in the value of the `Location` header in the response. \n If no port is specified, the redirect port MUST be derived using the following rules: \n * If redirect scheme is not-empty, the redirect port MUST be the well-known port associated with the redirect scheme. Specifically \"http\" to port 80 and \"https\" to port 443. If the redirect scheme does not have a well-known port, the listener port of the Gateway SHOULD be used. * If redirect scheme is empty, the redirect port MUST be the Gateway Listener port. \n Implementations SHOULD NOT add the port number in the 'Location' header in the following cases: \n * A Location header that will use HTTP (whether that is determined via the Listener protocol or the Scheme field) _and_ use port 80. * A Location header that will use HTTPS (whether that is determined via the Listener protocol or the Scheme field) _and_ use port 443. \n Support: Extended" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: "Scheme is the scheme to be used in the value of the `Location` header in the response. When empty, the scheme of the request is used. \n Scheme redirects can affect the port of the redirect, for more information, refer to the documentation for the port field of this filter. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. \n Support: Extended" + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status code to be used in response. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`. \n Support: Core" + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: "ResponseHeaderModifier defines a schema for a filter that modifies response headers. \n Support: Extended" + properties: + add: + description: "Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header name. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: add: - name: \"my-header\" value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: bar my-header3: baz \n Config: remove: [\"my-header1\", \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the given header (name, value) before the action. \n Input: GET /foo HTTP/1.1 my-header: foo \n Config: set: - name: \"my-header\" value: \"bar\" \n Output: GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: "Type identifies the type of filter to apply. As with other API fields, types are classified into three conformance levels: \n - Core: Filter types and their corresponding configuration defined by \"Support: Core\" in this package, e.g. \"RequestHeaderModifier\". All implementations must support core filters. \n - Extended: Filter types and their corresponding configuration defined by \"Support: Extended\" in this package, e.g. \"RequestMirror\". Implementers are encouraged to support extended filters. \n - Implementation-specific: Filters that are defined and supported by specific vendors. In the future, filters showing convergence in behavior across multiple implementations will be considered for inclusion in extended or core conformance levels. Filter-specific configuration for such filters is specified using the ExtensionRef field. `Type` should be set to \"ExtensionRef\" for custom filters. \n Implementers are encouraged to define custom implementation types to extend the core API with implementation-specific behavior. \n If a reference to a custom filter type cannot be resolved, the filter MUST NOT be skipped. Instead, requests that would have been processed by that filter MUST receive a HTTP error response. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: "URLRewrite defines a schema for a filter that modifies a request during forwarding. \n Support: Extended" + properties: + hostname: + description: "Hostname is the value to be used to replace the Host header value during forwarding. \n Support: Extended" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines a path rewrite. \n Support: Extended" + properties: + replaceFullPath: + description: ReplaceFullPath specifies the value with which to replace the full path of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the value with which to replace the prefix match of a request during a rewrite or redirect. For example, a request to \"/foo/bar\" with a prefix match of \"/foo\" and a ReplacePrefixMatch of \"/xyz\" would be modified to \"/xyz/bar\". \n Note that this matches the behavior of the PathPrefix match type. This matches full path elements. A path element refers to the list of labels in the path split by the `/` separator. When specified, a trailing `/` is ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match the prefix `/abc`, but the path `/abcd` would not. \n ReplacePrefixMatch is only compatible with a `PathPrefix` HTTPRouteMatch. Using any other HTTPRouteMatch type on the same HTTPRouteRule will result in the implementation setting the Accepted Condition for the Route to `status: False`. \n Request Path | Prefix Match | Replace Prefix | Modified Path -------------|--------------|----------------|---------- /foo/bar | /foo | /xyz | /xyz/bar /foo/bar | /foo | /xyz/ | /xyz/bar /foo/bar | /foo/ | /xyz | /xyz/bar /foo/bar | /foo/ | /xyz/ | /xyz/bar /foo | /foo | /xyz | /xyz /foo/ | /foo | /xyz | /xyz/ /foo/bar | /foo | | /bar /foo/ | /foo | | / /foo | /foo | | / /foo/ | /foo | / | / /foo | /foo | / | /" + maxLength: 1024 + type: string + type: + description: "Type defines the type of path modifier. Additional types may be added in a future release of the API. \n Note that values may be added to this enum, implementations must ensure that unknown values will not cause a crash. \n Unknown values here must result in the implementation setting the Accepted Condition for the Route to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the filter.type is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != ''RequestRedirect'')' + - message: filter.requestRedirect must be specified for RequestRedirect filter.type + rule: '!(!has(self.requestRedirect) && self.type == ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() <= 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 + matches: + default: + - path: type: PathPrefix value: / - description: Path specifies a HTTP request path matcher. - If this field is not specified, a default prefix match - on the "/" path is provided. - properties: - type: - default: PathPrefix - description: "Type specifies how to match against - the path Value. \n Support: Core (Exact, PathPrefix) - \n Support: Custom (RegularExpression)" - enum: - - Exact - - PathPrefix - - RegularExpression - type: string - value: - default: / - description: Value of the HTTP path to match against. - maxLength: 1024 - type: string - type: object - queryParams: - description: QueryParams specifies HTTP query parameter - matchers. Multiple match values are ANDed together, - meaning, a request must match all the specified query - parameters to select the route. - items: - description: HTTPQueryParamMatch describes how to select - a HTTP route by matching HTTP query parameters. + description: "Matches define conditions used for matching the rule against incoming HTTP requests. Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied. \n For example, take the following matches configuration: \n ``` matches: - path: value: \"/foo\" headers: - name: \"version\" value: \"v2\" - path: value: \"/v2/foo\" ``` \n For a request to match against this rule, a request must satisfy EITHER of the two conditions: \n - path prefixed with `/foo` AND contains the header `version: v2` - path prefix of `/v2/foo` \n See the documentation for HTTPRouteMatch on how to specify multiple match conditions that should be ANDed together. \n If no matches are specified, the default is a prefix path match on \"/\", which has the effect of matching every HTTP request. \n Proxy or Load Balancer routing configuration generated from HTTPRoutes MUST prioritize matches based on the following criteria, continuing on ties. Across all rules specified on applicable Routes, precedence must be given to the match having: \n * \"Exact\" path match. * \"Prefix\" path match with largest number of characters. * Method match. * Largest number of header matches. * Largest number of query param matches. \n Note: The precedence of RegularExpression path matches are implementation-specific. \n If ties still exist across multiple Routes, matching precedence MUST be determined in order of the following criteria, continuing on ties: \n * The oldest Route based on creation timestamp. * The Route appearing first in alphabetical order by \"{namespace}/{name}\". \n If ties still exist within an HTTPRoute, matching precedence MUST be granted to the FIRST matching rule (in list order) with a match meeting the above criteria. \n When no rules matching a request have been successfully attached to the parent a request is coming from, a HTTP 404 status code MUST be returned." + items: + description: "HTTPRouteMatch defines the predicate used to match requests to a given action. Multiple match types are ANDed together, i.e. the match will evaluate to true only if all conditions are satisfied. \n For example, the match below will match a HTTP request only if its path starts with `/foo` AND it contains the `version: v1` header: \n ``` match: \n path: value: \"/foo\" headers: - name: \"version\" value \"v1\" \n ```" + properties: + headers: + description: Headers specifies HTTP request header matchers. Multiple match values are ANDed together, meaning, a request must match all the specified headers to select the route. + items: + description: HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request headers. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, only the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent. \n When a header is repeated in an HTTP request, it is implementation-specific behavior as to how this is represented. Generally, proxies should follow the guidance from the RFC: https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding processing a repeated header, with special handling for \"Set-Cookie\"." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: "Type specifies how to match against the value of the header. \n Support: Core (Exact) \n Support: Implementation-specific (RegularExpression) \n Since RegularExpression HeaderMatchType has implementation-specific conformance, implementations can support POSIX, PCRE or any other dialects of regular expressions. Please read the implementation's documentation to determine the supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + description: "Method specifies HTTP method matcher. When specified, this route will be matched only if the request has the specified method. \n Support: Extended" + enum: + - GET + - HEAD + - POST + - PUT + - DELETE + - CONNECT + - OPTIONS + - TRACE + - PATCH + type: string + path: + default: + type: PathPrefix + value: / + description: Path specifies a HTTP request path matcher. If this field is not specified, a default prefix match on the "/" path is provided. properties: - name: - description: Name is the name of the HTTP query - param to be matched. This must be an exact string - match. (See https://tools.ietf.org/html/rfc7230#section-2.7.3). - maxLength: 256 - minLength: 1 - type: string type: - default: Exact - description: "Type specifies how to match against - the value of the query parameter. \n Support: - Extended (Exact) \n Support: Custom (RegularExpression) - \n Since RegularExpression QueryParamMatchType - has custom conformance, implementations can support - POSIX, PCRE or any other dialects of regular expressions. - Please read the implementation's documentation - to determine the supported dialect." + default: PathPrefix + description: "Type specifies how to match against the path Value. \n Support: Core (Exact, PathPrefix) \n Support: Implementation-specific (RegularExpression)" enum: - - Exact - - RegularExpression + - Exact + - PathPrefix + - RegularExpression type: string value: - description: Value is the value of HTTP query param - to be matched. + default: / + description: Value of the HTTP path to match against. maxLength: 1024 - minLength: 1 type: string - required: - - name - - value type: object - maxItems: 16 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - type: object - maxItems: 8 - type: array - type: object - maxItems: 16 - type: array - type: object - status: - description: Status defines the current state of HTTPRoute. - properties: - parents: - description: "Parents is a list of parent resources (usually Gateways) - that are associated with the route, and the status of the route - with respect to each parent. When this route attaches to a parent, - the controller that manages the parent must add an entry to this - list when the controller first sees the route and should update - the entry as appropriate when the route or gateway is modified. - \n Note that parent references that cannot be resolved by an implementation - of this API will not be added to this list. Implementations of this - API can only populate Route status for the Gateways/parent resources - they are responsible for. \n A maximum of 32 Gateways will be represented - in this list. An empty list means the route has not been attached - to any Gateway." - items: - description: RouteParentStatus describes the status of a route with - respect to an associated Parent. - properties: - conditions: - description: "Conditions describes the status of the route with - respect to the Gateway. Note that the route's availability - is also subject to the Gateway's own status conditions and - listener status. \n If the Route's ParentRef specifies an - existing Gateway that supports Routes of this kind AND that - Gateway's controller has sufficient access, then that Gateway's - controller MUST set the \"Accepted\" condition on the Route, - to indicate whether the route has been accepted or rejected - by the Gateway, and why. \n A Route MUST be considered \"Accepted\" - if at least one of the Route's rules is implemented by the - Gateway. \n There are a number of cases where the \"Accepted\" - condition may not be set due to lack of controller visibility, - that includes when: \n * The Route refers to a non-existent - parent. * The Route is of a type that the controller does - not support. * The Route is in a namespace the the controller - does not have access to." - items: - description: "Condition contains details for one aspect of - the current state of this API Resource. --- This struct - is intended for direct use as an array at the field path - .status.conditions. For example, type FooStatus struct{ - \ // Represents the observations of a foo's current state. - \ // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // - +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" + x-kubernetes-validations: + - message: value must be an absolute path and start with '/' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.startsWith(''/'') : true' + - message: must not contain '//' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''//'') : true' + - message: must not contain '/./' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/./'') : true' + - message: must not contain '/../' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/../'') : true' + - message: must not contain '%2f' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2f'') : true' + - message: must not contain '%2F' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2F'') : true' + - message: must not contain '#' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''#'') : true' + - message: must not end with '/..' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/..'') : true' + - message: must not end with '/.' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/.'') : true' + - message: type must be one of ['Exact', 'PathPrefix', 'RegularExpression'] + rule: self.type in ['Exact','PathPrefix'] || self.type == 'RegularExpression' + - message: must only contain valid characters (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) for types ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") : true' + queryParams: + description: "QueryParams specifies HTTP query parameter matchers. Multiple match values are ANDed together, meaning, a request must match all the specified query parameters to select the route. \n Support: Extended" + items: + description: HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP query parameters. + properties: + name: + description: "Name is the name of the HTTP query param to be matched. This must be an exact string match. (See https://tools.ietf.org/html/rfc7230#section-2.7.3). \n If multiple entries specify equivalent query param names, only the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent query param name MUST be ignored. \n If a query param is repeated in an HTTP request, the behavior is purposely left undefined, since different data planes have different capabilities. However, it is *recommended* that implementations should match against the first value of the param if the data plane supports it, as this behavior is expected in other load balancing contexts outside of the Gateway API. \n Users SHOULD NOT route traffic based on repeated query params to guard themselves against potential differences in the implementations." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: "Type specifies how to match against the value of the query parameter. \n Support: Extended (Exact) \n Support: Implementation-specific (RegularExpression) \n Since RegularExpression QueryParamMatchType has Implementation-specific conformance, implementations can support POSIX, PCRE or any other dialects of regular expressions. Please read the implementation's documentation to determine the supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 8 + type: array + timeouts: + description: "Timeouts defines the timeouts that can be configured for an HTTP request. \n Support: Extended \n " properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should - be when the underlying condition changed. If that is - not known, then using the time when the API field changed - is acceptable. - format: date-time + backendRequest: + description: "BackendRequest specifies a timeout for an individual request from the gateway to a backend. This covers the time from when the request first starts being sent from the gateway to when the full response has been received from the backend. \n An entire client HTTP transaction with a gateway, covered by the Request timeout, may result in more than one call from the gateway to the destination backend, for example, if automatic retries are supported. \n Because the Request timeout encompasses the BackendRequest timeout, the value of BackendRequest must be <= the value of Request timeout. \n Support: Extended" + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 + request: + description: "Request specifies the maximum duration for a gateway to respond to an HTTP request. If the gateway has not been able to respond before this deadline is met, the gateway MUST return a timeout error. \n For example, setting the `rules.timeouts.request` field to the value `10s` in an `HTTPRoute` will cause a timeout if a client request is taking longer than 10 seconds to complete. \n This timeout is intended to cover as close to the whole request-response transaction as possible although an implementation MAY choose to start the timeout after the entire request stream has been received instead of immediately after the transaction is initiated by the client. \n When this field is unspecified, request timeout behavior is implementation-specific. \n Support: Extended" + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, - if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the - current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier - indicating the reason for the condition's last transition. - Producers of specific condition types may define expected - values and meanings for this field, and whether the - values are considered a guaranteed API. The value should - be a CamelCase string. This field may not be empty. - maxLength: 1024 + type: object + x-kubernetes-validations: + - message: backendRequest timeout cannot be longer than request timeout + rule: '!(has(self.request) && has(self.backendRequest) && duration(self.request) != duration(''0s'') && duration(self.backendRequest) > duration(self.request))' + type: object + x-kubernetes-validations: + - message: RequestRedirect filter must not be used together with backendRefs + rule: '(has(self.backendRefs) && size(self.backendRefs) > 0) ? (!has(self.filters) || self.filters.all(f, !has(f.requestRedirect))): true' + - message: When using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.requestRedirect) && has(f.requestRedirect.path) && f.requestRedirect.path.type == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != ''PathPrefix'') ? false : true) : true' + - message: When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.urlRewrite) && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' && has(f.urlRewrite.path.replacePrefixMatch))) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != ''PathPrefix'') ? false : true) : true' + - message: Within backendRefs, when using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, (has(b.filters) && b.filters.exists_one(f, has(f.requestRedirect) && has(f.requestRedirect.path) && f.requestRedirect.path.type == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != ''PathPrefix'') ? false : true) : true' + - message: Within backendRefs, When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, (has(b.filters) && b.filters.exists_one(f, has(f.urlRewrite) && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' && has(f.urlRewrite.path.replacePrefixMatch))) )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != ''PathPrefix'') ? false : true) : true' + maxItems: 16 + type: array + type: object + status: + description: Status defines the current state of HTTPRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified. \n Note that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for. \n A maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway." + items: + description: RouteParentStatus describes the status of a route with respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with respect to the Gateway. Note that the route's availability is also subject to the Gateway's own status conditions and listener status. \n If the Route's ParentRef specifies an existing Gateway that supports Routes of this kind AND that Gateway's controller has sufficient access, then that Gateway's controller MUST set the \"Accepted\" condition on the Route, to indicate whether the route has been accepted or rejected by the Gateway, and why. \n A Route MUST be considered \"Accepted\" if at least one of the Route's rules is implemented by the Gateway. \n There are a number of cases where the \"Accepted\" condition may not be set due to lack of controller visibility, that includes when: \n * The Route refers to a non-existent parent. * The Route is of a type that the controller does not support. * The Route is in a namespace the controller does not have access to." + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates the name of the controller that wrote this status. This corresponds with the controllerName field on GatewayClass. \n Example: \"example.net/gateway-controller\". \n The format of this field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). \n Controllers MUST populate this field when writing status. Controllers should ensure that entries to status populated with their ControllerName are cleaned up when they are no longer necessary." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec that this RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." + maxLength: 63 minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown + name: + description: "Name is the name of the referent. \n Support: Core" + maxLength: 253 + minLength: 1 type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across - resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability - to deconflict is important. The regex it matches is - (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + namespace: + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string required: - - lastTransitionTime - - message - - reason - - status - - type + - name type: object - maxItems: 8 - minItems: 1 - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - controllerName: - description: "ControllerName is a domain/path string that indicates - the name of the controller that wrote this status. This corresponds - with the controllerName field on GatewayClass. \n Example: - \"example.net/gateway-controller\". \n The format of this - field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid - Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ - type: string - parentRef: - description: ParentRef corresponds with a ParentRef in the spec - that this RouteParentStatus struct describes the status of. - properties: - group: - default: gateway.networking.k8s.io - description: "Group is the group of the referent. \n Support: - Core" - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Gateway - description: "Kind is kind of the referent. \n Support: - Core (Gateway) Support: Custom (Other Resources)" - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: "Name is the name of the referent. \n Support: - Core" - maxLength: 253 - minLength: 1 - type: string - namespace: - description: "Namespace is the namespace of the referent. - When unspecified (or empty string), this refers to the - local namespace of the Route. \n Support: Core" - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - sectionName: - description: "SectionName is the name of a section within - the target resource. In the following resources, SectionName - is interpreted as the following: \n * Gateway: Listener - Name \n Implementations MAY choose to support attaching - Routes to other resources. If that is the case, they MUST - clearly document how SectionName is interpreted. \n When - unspecified (empty string), this will reference the entire - resource. For the purpose of status, an attachment is - considered successful if at least one section in the parent - resource accepts it. For example, Gateway listeners can - restrict which Routes can attach to them by Route kind, - namespace, or hostname. If 1 of 2 Gateway listeners accept - attachment from the referencing Route, the Route MUST - be considered successfully attached. If no Gateway listeners - accept attachment from this Route, the Route MUST be considered - detached from the Gateway. \n Support: Core" - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - required: - - name - type: object - required: - - controllerName - - parentRef - type: object - maxItems: 32 - type: array - required: - - parents - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} status: acceptedNames: kind: "" plural: "" - conditions: [] - storedVersions: [] + conditions: null + storedVersions: null diff --git a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_referencegrants.yaml b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_referencegrants.yaml new file mode 100644 index 000000000..fb9a6dc1e --- /dev/null +++ b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_referencegrants.yaml @@ -0,0 +1,205 @@ +# +# config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml +# +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + name: referencegrants.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: ReferenceGrant + listKind: ReferenceGrantList + plural: referencegrants + shortNames: + - refgrant + singular: referencegrant + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: The v1alpha2 version of ReferenceGrant has been deprecated and will be removed in a future release of the API. Please upgrade to v1beta1. + name: v1alpha2 + schema: + openAPIV3Schema: + description: "ReferenceGrant identifies kinds of resources in other namespaces that are trusted to reference the specified kinds of resources in the same namespace as the policy. \n Each ReferenceGrant can be used to represent a unique trust relationship. Additional Reference Grants can be used to add to the set of trusted sources of inbound references for the namespace they are defined within. \n A ReferenceGrant is required for all cross-namespace references in Gateway API (with the exception of cross-namespace Route-Gateway attachment, which is governed by the AllowedRoutes configuration on the Gateway, and cross-namespace Service ParentRefs on a \"consumer\" mesh Route, which defines routing rules applicable only to workloads in the Route namespace). ReferenceGrants allowing a reference from a Route to a Service are only applicable to BackendRefs. \n ReferenceGrant is a form of runtime verification allowing users to assert which cross-namespace object references are permitted. Implementations that support ReferenceGrant MUST NOT permit cross-namespace references which have no grant, and MUST respond to the removal of a grant by revoking the access that the grant allowed." + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of ReferenceGrant. + properties: + from: + description: "From describes the trusted namespaces and kinds that can reference the resources described in \"To\". Each entry in this list MUST be considered to be an additional place that references can be valid from, or to put this another way, entries MUST be combined using OR. \n Support: Core" + items: + description: ReferenceGrantFrom describes trusted namespaces and kinds. + properties: + group: + description: "Group is the group of the referent. When empty, the Kubernetes core API group is inferred. \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: "Kind is the kind of the referent. Although implementations may support additional resources, the following types are part of the \"Core\" support level for this field. \n When used to permit a SecretObjectReference: \n * Gateway \n When used to permit a BackendObjectReference: \n * GRPCRoute * HTTPRoute * TCPRoute * TLSRoute * UDPRoute" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + namespace: + description: "Namespace is the namespace of the referent. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - namespace + type: object + maxItems: 16 + minItems: 1 + type: array + to: + description: "To describes the resources that may be referenced by the resources described in \"From\". Each entry in this list MUST be considered to be an additional place that references can be valid to, or to put this another way, entries MUST be combined using OR. \n Support: Core" + items: + description: ReferenceGrantTo describes what Kinds are allowed as targets of the references. + properties: + group: + description: "Group is the group of the referent. When empty, the Kubernetes core API group is inferred. \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: "Kind is the kind of the referent. Although implementations may support additional resources, the following types are part of the \"Core\" support level for this field: \n * Secret when used to permit a SecretObjectReference * Service when used to permit a BackendObjectReference" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. When unspecified, this policy refers to all resources of the specified Group and Kind in the local namespace. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - from + - to + type: object + type: object + served: true + storage: false + subresources: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: "ReferenceGrant identifies kinds of resources in other namespaces that are trusted to reference the specified kinds of resources in the same namespace as the policy. \n Each ReferenceGrant can be used to represent a unique trust relationship. Additional Reference Grants can be used to add to the set of trusted sources of inbound references for the namespace they are defined within. \n All cross-namespace references in Gateway API (with the exception of cross-namespace Gateway-route attachment) require a ReferenceGrant. \n ReferenceGrant is a form of runtime verification allowing users to assert which cross-namespace object references are permitted. Implementations that support ReferenceGrant MUST NOT permit cross-namespace references which have no grant, and MUST respond to the removal of a grant by revoking the access that the grant allowed." + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of ReferenceGrant. + properties: + from: + description: "From describes the trusted namespaces and kinds that can reference the resources described in \"To\". Each entry in this list MUST be considered to be an additional place that references can be valid from, or to put this another way, entries MUST be combined using OR. \n Support: Core" + items: + description: ReferenceGrantFrom describes trusted namespaces and kinds. + properties: + group: + description: "Group is the group of the referent. When empty, the Kubernetes core API group is inferred. \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: "Kind is the kind of the referent. Although implementations may support additional resources, the following types are part of the \"Core\" support level for this field. \n When used to permit a SecretObjectReference: \n * Gateway \n When used to permit a BackendObjectReference: \n * GRPCRoute * HTTPRoute * TCPRoute * TLSRoute * UDPRoute" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + namespace: + description: "Namespace is the namespace of the referent. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - namespace + type: object + maxItems: 16 + minItems: 1 + type: array + to: + description: "To describes the resources that may be referenced by the resources described in \"From\". Each entry in this list MUST be considered to be an additional place that references can be valid to, or to put this another way, entries MUST be combined using OR. \n Support: Core" + items: + description: ReferenceGrantTo describes what Kinds are allowed as targets of the references. + properties: + group: + description: "Group is the group of the referent. When empty, the Kubernetes core API group is inferred. \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: "Kind is the kind of the referent. Although implementations may support additional resources, the following types are part of the \"Core\" support level for this field: \n * Secret when used to permit a SecretObjectReference * Service when used to permit a BackendObjectReference" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. When unspecified, this policy refers to all resources of the specified Group and Kind in the local namespace. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - from + - to + type: object + type: object + served: true + storage: true + subresources: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_tcproutes.yaml b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_tcproutes.yaml index b7bf7ff16..b2284973c 100644 --- a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_tcproutes.yaml +++ b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_tcproutes.yaml @@ -1,431 +1,284 @@ - ---- +# +# config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml +# apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: tcproutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io names: categories: - - gateway-api + - gateway-api kind: TCPRoute listKind: TCPRouteList plural: tcproutes singular: tcproute scope: Namespaced versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha2 - schema: - openAPIV3Schema: - description: TCPRoute provides a way to route TCP requests. When combined - with a Gateway listener, it can be used to forward connections on the port - specified by the listener to a set of backends specified by the TCPRoute. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Spec defines the desired state of TCPRoute. - properties: - parentRefs: - description: "ParentRefs references the resources (usually Gateways) - that a Route wants to be attached to. Note that the referenced parent - resource needs to allow this for the attachment to be complete. - For Gateways, that means the Gateway needs to allow attachment from - Routes of this kind and namespace. \n The only kind of parent resource - with \"Core\" support is Gateway. This API may be extended in the - future to support additional kinds of parent resources such as one - of the route kinds. \n It is invalid to reference an identical parent - more than once. It is valid to reference multiple distinct sections - within the same parent resource, such as 2 Listeners within a Gateway. - \n It is possible to separately reference multiple distinct objects - that may be collapsed by an implementation. For example, some implementations - may choose to merge compatible Gateway Listeners together. If that - is the case, the list of routes attached to those resources should - also be merged." - items: - description: "ParentRef identifies an API object (usually a Gateway) - that can be considered a parent of this resource (usually a route). - The only kind of parent resource with \"Core\" support is Gateway. - This API may be extended in the future to support additional kinds - of parent resources, such as HTTPRoute. \n The API object must - be valid in the cluster; the Group and Kind must be registered - in the cluster for this reference to be valid. \n References to - objects with invalid Group and Kind are not valid, and must be - rejected by the implementation, with appropriate Conditions set - on the containing object." - properties: - group: - default: gateway.networking.k8s.io - description: "Group is the group of the referent. \n Support: - Core" - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Gateway - description: "Kind is kind of the referent. \n Support: Core - (Gateway) Support: Custom (Other Resources)" - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: "Name is the name of the referent. \n Support: - Core" - maxLength: 253 - minLength: 1 - type: string - namespace: - description: "Namespace is the namespace of the referent. When - unspecified (or empty string), this refers to the local namespace - of the Route. \n Support: Core" - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - sectionName: - description: "SectionName is the name of a section within the - target resource. In the following resources, SectionName is - interpreted as the following: \n * Gateway: Listener Name - \n Implementations MAY choose to support attaching Routes - to other resources. If that is the case, they MUST clearly - document how SectionName is interpreted. \n When unspecified - (empty string), this will reference the entire resource. For - the purpose of status, an attachment is considered successful - if at least one section in the parent resource accepts it. - For example, Gateway listeners can restrict which Routes can - attach to them by Route kind, namespace, or hostname. If 1 - of 2 Gateway listeners accept attachment from the referencing - Route, the Route MUST be considered successfully attached. - If no Gateway listeners accept attachment from this Route, - the Route MUST be considered detached from the Gateway. \n - Support: Core" - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - required: - - name - type: object - maxItems: 32 - type: array - rules: - description: Rules are a list of TCP matchers and actions. - items: - description: TCPRouteRule is the configuration for a given rule. - properties: - backendRefs: - description: "BackendRefs defines the backend(s) where matching - requests should be sent. If unspecified or invalid (refers - to a non-existent resource or a Service with no endpoints), - the underlying implementation MUST actively reject connection - attempts to this backend. Connection rejections must respect - weight; if an invalid backend is requested to have 80% of - connections, then 80% of connections must be rejected instead. - \n Support: Core for Kubernetes Service Support: Custom for - any other resource \n Support for weight: Extended" - items: - description: "BackendRef defines how a Route should forward - a request to a Kubernetes resource. \n Note that when a - namespace is specified, a ReferencePolicy object is required - in the referent namespace to allow that namespace's owner - to accept the reference. See the ReferencePolicy documentation - for details." + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: TCPRoute provides a way to route TCP requests. When combined with a Gateway listener, it can be used to forward connections on the port specified by the listener to a set of backends specified by the TCPRoute. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of TCPRoute. + properties: + parentRefs: + description: "ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a \"producer\" route, or the mesh implementation must support and allow \"consumer\" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a \"producer\" route for a Service in a different namespace from the Route. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) This API may be extended in the future to support additional kinds of parent resources. \n ParentRefs must be _distinct_. This means either that: \n * They select different objects. If this is the case, then parentRef entries are distinct. In terms of fields, this means that the multi-part key defined by `group`, `kind`, `namespace`, and `name` must be unique across all parentRef entries in the Route. * They do not select different objects, but for each optional field used, each ParentRef that selects the same object must set the same set of optional fields to different values. If one ParentRef sets a combination of optional fields, all must set the same combination. \n Some examples: \n * If one ParentRef sets `sectionName`, all ParentRefs referencing the same object must also set `sectionName`. * If one ParentRef sets `port`, all ParentRefs referencing the same object must also set `port`. * If one ParentRef sets `sectionName` and `port`, all ParentRefs referencing the same object must also set `sectionName` and `port`. \n It is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged. \n Note that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n " + items: + description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n This API may be extended in the future to support additional kinds of parent resources. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + x-kubernetes-validations: + - message: sectionName or port must be specified when parentRefs includes 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__)) ? ((!has(p1.sectionName) || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) || p2.port == 0)): true))' + - message: sectionName or port must be unique when parentRefs includes 2 or more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName == '')) || ( has(p1.sectionName) && has(p2.sectionName) && p1.sectionName == p2.sectionName)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port == p2.port)))) + rules: + description: Rules are a list of TCP matchers and actions. + items: + description: TCPRouteRule is the configuration for a given rule. + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching requests should be sent. If unspecified or invalid (refers to a non-existent resource or a Service with no endpoints), the underlying implementation MUST actively reject connection attempts to this backend. Connection rejections must respect weight; if an invalid backend is requested to have 80% of connections, then 80% of connections must be rejected instead. \n Support: Core for Kubernetes Service \n Support: Extended for Kubernetes ServiceImport \n Support: Implementation-specific for any other resource \n Support for weight: Extended" + items: + description: "BackendRef defines how a Route should forward a request to a Kubernetes resource. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n \n When the BackendRef points to a Kubernetes Service, implementations SHOULD honor the appProtocol field if it is set for the target Service Port. \n Implementations supporting appProtocol SHOULD recognize the Kubernetes Standard Application Protocols defined in KEP-3726. \n If a Service appProtocol isn't specified, an implementation MAY infer the backend protocol through its own means. Implementations MAY infer the protocol from the Route type referring to the backend Service. \n If a Route is not able to send traffic to the backend using the specified protocol then the backend is considered invalid. Implementations MUST set the \"ResolvedRefs\" condition to \"False\" with the \"UnsupportedProtocol\" reason. \n \n Note that when the BackendTLSPolicy object is enabled by the implementation, there are some extra rules about validity to consider here. See the fields where this struct is used for more information about the exact behavior." + properties: + group: + default: "" + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource kind of the referent. For example \"Service\". \n Defaults to \"Service\" when not specified. \n ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. \n Support: Core (Services with a type other than ExternalName) \n Support: Implementation-specific (Services with type ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests forwarded to the referenced backend. This is computed as weight/(sum of all weights in this BackendRefs list). For non-zero values, there may be some epsilon from the exact proportion defined here depending on the precision an implementation supports. Weight is not a percentage and the sum of weights does not need to equal 100. \n If only one backend is specified and it has a weight greater than 0, 100% of the traffic is forwarded to that backend. If weight is set to 0, no traffic should be forwarded for this entry. If unspecified, weight defaults to 1. \n Support for this field varies based on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + maxItems: 16 + minItems: 1 + type: array + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - rules + type: object + status: + description: Status defines the current state of TCPRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified. \n Note that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for. \n A maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway." + items: + description: RouteParentStatus describes the status of a route with respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with respect to the Gateway. Note that the route's availability is also subject to the Gateway's own status conditions and listener status. \n If the Route's ParentRef specifies an existing Gateway that supports Routes of this kind AND that Gateway's controller has sufficient access, then that Gateway's controller MUST set the \"Accepted\" condition on the Route, to indicate whether the route has been accepted or rejected by the Gateway, and why. \n A Route MUST be considered \"Accepted\" if at least one of the Route's rules is implemented by the Gateway. \n There are a number of cases where the \"Accepted\" condition may not be set due to lack of controller visibility, that includes when: \n * The Route refers to a non-existent parent. * The Route is of a type that the controller does not support. * The Route is in a namespace the controller does not have access to." + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates the name of the controller that wrote this status. This corresponds with the controllerName field on GatewayClass. \n Example: \"example.net/gateway-controller\". \n The format of this field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). \n Controllers MUST populate this field when writing status. Controllers should ensure that entries to status populated with their ControllerName are cleaned up when they are no longer necessary." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec that this RouteParentStatus struct describes the status of. properties: group: - default: "" - description: Group is the group of the referent. For example, - "networking.k8s.io". When unspecified (empty string), - core API group is inferred. + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: - default: Service - description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". + default: Gateway + description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: - description: Name is the name of the referent. + description: "Name is the name of the referent. \n Support: Core" maxLength: 253 minLength: 1 type: string namespace: - description: "Namespace is the namespace of the backend. - When unspecified, the local namespace is inferred. \n - Note that when a namespace is specified, a ReferencePolicy - object is required in the referent namespace to allow - that namespace's owner to accept the reference. See - the ReferencePolicy documentation for details. \n Support: - Core" + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: - description: Port specifies the destination port number - to use for this resource. Port is required when the - referent is a Kubernetes Service. For other resources, - destination port might be derived from the referent - resource or this field. + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " format: int32 maximum: 65535 minimum: 1 type: integer - weight: - default: 1 - description: "Weight specifies the proportion of requests - forwarded to the referenced backend. This is computed - as weight/(sum of all weights in this BackendRefs list). - For non-zero values, there may be some epsilon from - the exact proportion defined here depending on the precision - an implementation supports. Weight is not a percentage - and the sum of weights does not need to equal 100. \n - If only one backend is specified and it has a weight - greater than 0, 100% of the traffic is forwarded to - that backend. If weight is set to 0, no traffic should - be forwarded for this entry. If unspecified, weight - defaults to 1. \n Support for this field varies based - on the context where used." - format: int32 - maximum: 1000000 - minimum: 0 - type: integer - required: - - name - type: object - maxItems: 16 - minItems: 1 - type: array - type: object - maxItems: 16 - minItems: 1 - type: array - required: - - rules - type: object - status: - description: Status defines the current state of TCPRoute. - properties: - parents: - description: "Parents is a list of parent resources (usually Gateways) - that are associated with the route, and the status of the route - with respect to each parent. When this route attaches to a parent, - the controller that manages the parent must add an entry to this - list when the controller first sees the route and should update - the entry as appropriate when the route or gateway is modified. - \n Note that parent references that cannot be resolved by an implementation - of this API will not be added to this list. Implementations of this - API can only populate Route status for the Gateways/parent resources - they are responsible for. \n A maximum of 32 Gateways will be represented - in this list. An empty list means the route has not been attached - to any Gateway." - items: - description: RouteParentStatus describes the status of a route with - respect to an associated Parent. - properties: - conditions: - description: "Conditions describes the status of the route with - respect to the Gateway. Note that the route's availability - is also subject to the Gateway's own status conditions and - listener status. \n If the Route's ParentRef specifies an - existing Gateway that supports Routes of this kind AND that - Gateway's controller has sufficient access, then that Gateway's - controller MUST set the \"Accepted\" condition on the Route, - to indicate whether the route has been accepted or rejected - by the Gateway, and why. \n A Route MUST be considered \"Accepted\" - if at least one of the Route's rules is implemented by the - Gateway. \n There are a number of cases where the \"Accepted\" - condition may not be set due to lack of controller visibility, - that includes when: \n * The Route refers to a non-existent - parent. * The Route is of a type that the controller does - not support. * The Route is in a namespace the the controller - does not have access to." - items: - description: "Condition contains details for one aspect of - the current state of this API Resource. --- This struct - is intended for direct use as an array at the field path - .status.conditions. For example, type FooStatus struct{ - \ // Represents the observations of a foo's current state. - \ // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // - +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should - be when the underlying condition changed. If that is - not known, then using the time when the API field changed - is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, - if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the - current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier - indicating the reason for the condition's last transition. - Producers of specific condition types may define expected - values and meanings for this field, and whether the - values are considered a guaranteed API. The value should - be a CamelCase string. This field may not be empty. - maxLength: 1024 + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + maxLength: 253 minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across - resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability - to deconflict is important. The regex it matches is - (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string required: - - lastTransitionTime - - message - - reason - - status - - type + - name type: object - maxItems: 8 - minItems: 1 - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - controllerName: - description: "ControllerName is a domain/path string that indicates - the name of the controller that wrote this status. This corresponds - with the controllerName field on GatewayClass. \n Example: - \"example.net/gateway-controller\". \n The format of this - field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid - Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ - type: string - parentRef: - description: ParentRef corresponds with a ParentRef in the spec - that this RouteParentStatus struct describes the status of. - properties: - group: - default: gateway.networking.k8s.io - description: "Group is the group of the referent. \n Support: - Core" - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Gateway - description: "Kind is kind of the referent. \n Support: - Core (Gateway) Support: Custom (Other Resources)" - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: "Name is the name of the referent. \n Support: - Core" - maxLength: 253 - minLength: 1 - type: string - namespace: - description: "Namespace is the namespace of the referent. - When unspecified (or empty string), this refers to the - local namespace of the Route. \n Support: Core" - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - sectionName: - description: "SectionName is the name of a section within - the target resource. In the following resources, SectionName - is interpreted as the following: \n * Gateway: Listener - Name \n Implementations MAY choose to support attaching - Routes to other resources. If that is the case, they MUST - clearly document how SectionName is interpreted. \n When - unspecified (empty string), this will reference the entire - resource. For the purpose of status, an attachment is - considered successful if at least one section in the parent - resource accepts it. For example, Gateway listeners can - restrict which Routes can attach to them by Route kind, - namespace, or hostname. If 1 of 2 Gateway listeners accept - attachment from the referencing Route, the Route MUST - be considered successfully attached. If no Gateway listeners - accept attachment from this Route, the Route MUST be considered - detached from the Gateway. \n Support: Core" - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - required: - - name - type: object - required: - - controllerName - - parentRef - type: object - maxItems: 32 - type: array - required: - - parents - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} status: acceptedNames: kind: "" plural: "" - conditions: [] - storedVersions: [] + conditions: null + storedVersions: null diff --git a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_tlsroutes.yaml b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_tlsroutes.yaml index ab3b49990..fa097ea7f 100644 --- a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_tlsroutes.yaml +++ b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_tlsroutes.yaml @@ -1,480 +1,294 @@ - ---- +# +# config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml +# apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: tlsroutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io names: categories: - - gateway-api + - gateway-api kind: TLSRoute listKind: TLSRouteList plural: tlsroutes singular: tlsroute scope: Namespaced versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha2 - schema: - openAPIV3Schema: - description: "The TLSRoute resource is similar to TCPRoute, but can be configured - to match against TLS-specific metadata. This allows more flexibility in - matching streams for a given TLS listener. \n If you need to forward traffic - to a single target for a TLS listener, you could choose to use a TCPRoute - with a TLS listener." - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: Spec defines the desired state of TLSRoute. - properties: - hostnames: - description: "Hostnames defines a set of SNI names that should match - against the SNI attribute of TLS ClientHello message in TLS handshake. - This matches the RFC 1123 definition of a hostname with 2 notable - exceptions: \n 1. IPs are not allowed in SNI names per RFC 6066. - 2. A hostname may be prefixed with a wildcard label (`*.`). The - wildcard label must appear by itself as the first label. \n If - a hostname is specified by both the Listener and TLSRoute, there - must be at least one intersecting hostname for the TLSRoute to be - attached to the Listener. For example: \n * A Listener with `test.example.com` - as the hostname matches TLSRoutes that have either not specified - any hostnames, or have specified at least one of `test.example.com` - or `*.example.com`. * A Listener with `*.example.com` as the hostname - matches TLSRoutes that have either not specified any hostnames - or have specified at least one hostname that matches the Listener - hostname. For example, `test.example.com` and `*.example.com` - would both match. On the other hand, `example.com` and `test.example.net` - would not match. \n If both the Listener and TLSRoute have specified - hostnames, any TLSRoute hostnames that do not match the Listener - hostname MUST be ignored. For example, if a Listener specified `*.example.com`, - and the TLSRoute specified `test.example.com` and `test.example.net`, - `test.example.net` must not be considered for a match. \n If both - the Listener and TLSRoute have specified hostnames, and none match - with the criteria above, then the TLSRoute is not accepted. The - implementation must raise an 'Accepted' Condition with a status - of `False` in the corresponding RouteParentStatus. \n Support: Core" - items: - description: "Hostname is the fully qualified domain name of a network - host. This matches the RFC 1123 definition of a hostname with - 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname - may be prefixed with a wildcard label (`*.`). The wildcard label - must appear by itself as the first label. \n Hostname can be \"precise\" - which is a domain name without the terminating dot of a network - host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain - name prefixed with a single wildcard label (e.g. `*.example.com`). - \n Note that as per RFC1035 and RFC1123, a *label* must consist - of lower case alphanumeric characters or '-', and must start and - end with an alphanumeric character. No other punctuation is allowed." - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - maxItems: 16 - type: array - parentRefs: - description: "ParentRefs references the resources (usually Gateways) - that a Route wants to be attached to. Note that the referenced parent - resource needs to allow this for the attachment to be complete. - For Gateways, that means the Gateway needs to allow attachment from - Routes of this kind and namespace. \n The only kind of parent resource - with \"Core\" support is Gateway. This API may be extended in the - future to support additional kinds of parent resources such as one - of the route kinds. \n It is invalid to reference an identical parent - more than once. It is valid to reference multiple distinct sections - within the same parent resource, such as 2 Listeners within a Gateway. - \n It is possible to separately reference multiple distinct objects - that may be collapsed by an implementation. For example, some implementations - may choose to merge compatible Gateway Listeners together. If that - is the case, the list of routes attached to those resources should - also be merged." - items: - description: "ParentRef identifies an API object (usually a Gateway) - that can be considered a parent of this resource (usually a route). - The only kind of parent resource with \"Core\" support is Gateway. - This API may be extended in the future to support additional kinds - of parent resources, such as HTTPRoute. \n The API object must - be valid in the cluster; the Group and Kind must be registered - in the cluster for this reference to be valid. \n References to - objects with invalid Group and Kind are not valid, and must be - rejected by the implementation, with appropriate Conditions set - on the containing object." - properties: - group: - default: gateway.networking.k8s.io - description: "Group is the group of the referent. \n Support: - Core" - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Gateway - description: "Kind is kind of the referent. \n Support: Core - (Gateway) Support: Custom (Other Resources)" - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: "Name is the name of the referent. \n Support: - Core" - maxLength: 253 - minLength: 1 - type: string - namespace: - description: "Namespace is the namespace of the referent. When - unspecified (or empty string), this refers to the local namespace - of the Route. \n Support: Core" - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - sectionName: - description: "SectionName is the name of a section within the - target resource. In the following resources, SectionName is - interpreted as the following: \n * Gateway: Listener Name - \n Implementations MAY choose to support attaching Routes - to other resources. If that is the case, they MUST clearly - document how SectionName is interpreted. \n When unspecified - (empty string), this will reference the entire resource. For - the purpose of status, an attachment is considered successful - if at least one section in the parent resource accepts it. - For example, Gateway listeners can restrict which Routes can - attach to them by Route kind, namespace, or hostname. If 1 - of 2 Gateway listeners accept attachment from the referencing - Route, the Route MUST be considered successfully attached. - If no Gateway listeners accept attachment from this Route, - the Route MUST be considered detached from the Gateway. \n - Support: Core" - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - required: - - name - type: object - maxItems: 32 - type: array - rules: - description: Rules are a list of TLS matchers and actions. - items: - description: TLSRouteRule is the configuration for a given rule. - properties: - backendRefs: - description: "BackendRefs defines the backend(s) where matching - requests should be sent. If unspecified or invalid (refers - to a non-existent resource or a Service with no endpoints), - the rule performs no forwarding; if no filters are specified - that would result in a response being sent, the underlying - implementation must actively reject request attempts to this - backend, by rejecting the connection or returning a 503 status - code. Request rejections must respect weight; if an invalid - backend is requested to have 80% of requests, then 80% of - requests must be rejected instead. \n Support: Core for Kubernetes - Service Support: Custom for any other resource \n Support - for weight: Extended" - items: - description: "BackendRef defines how a Route should forward - a request to a Kubernetes resource. \n Note that when a - namespace is specified, a ReferencePolicy object is required - in the referent namespace to allow that namespace's owner - to accept the reference. See the ReferencePolicy documentation - for details." + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: "The TLSRoute resource is similar to TCPRoute, but can be configured to match against TLS-specific metadata. This allows more flexibility in matching streams for a given TLS listener. \n If you need to forward traffic to a single target for a TLS listener, you could choose to use a TCPRoute with a TLS listener." + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of TLSRoute. + properties: + hostnames: + description: "Hostnames defines a set of SNI names that should match against the SNI attribute of TLS ClientHello message in TLS handshake. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed in SNI names per RFC 6066. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard label must appear by itself as the first label. \n If a hostname is specified by both the Listener and TLSRoute, there must be at least one intersecting hostname for the TLSRoute to be attached to the Listener. For example: \n * A Listener with `test.example.com` as the hostname matches TLSRoutes that have either not specified any hostnames, or have specified at least one of `test.example.com` or `*.example.com`. * A Listener with `*.example.com` as the hostname matches TLSRoutes that have either not specified any hostnames or have specified at least one hostname that matches the Listener hostname. For example, `test.example.com` and `*.example.com` would both match. On the other hand, `example.com` and `test.example.net` would not match. \n If both the Listener and TLSRoute have specified hostnames, any TLSRoute hostnames that do not match the Listener hostname MUST be ignored. For example, if a Listener specified `*.example.com`, and the TLSRoute specified `test.example.com` and `test.example.net`, `test.example.net` must not be considered for a match. \n If both the Listener and TLSRoute have specified hostnames, and none match with the criteria above, then the TLSRoute is not accepted. The implementation must raise an 'Accepted' Condition with a status of `False` in the corresponding RouteParentStatus. \n Support: Core" + items: + description: "Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard label must appear by itself as the first label. \n Hostname can be \"precise\" which is a domain name without the terminating dot of a network host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain name prefixed with a single wildcard label (e.g. `*.example.com`). \n Note that as per RFC1035 and RFC1123, a *label* must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character. No other punctuation is allowed." + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + description: "ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a \"producer\" route, or the mesh implementation must support and allow \"consumer\" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a \"producer\" route for a Service in a different namespace from the Route. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) This API may be extended in the future to support additional kinds of parent resources. \n ParentRefs must be _distinct_. This means either that: \n * They select different objects. If this is the case, then parentRef entries are distinct. In terms of fields, this means that the multi-part key defined by `group`, `kind`, `namespace`, and `name` must be unique across all parentRef entries in the Route. * They do not select different objects, but for each optional field used, each ParentRef that selects the same object must set the same set of optional fields to different values. If one ParentRef sets a combination of optional fields, all must set the same combination. \n Some examples: \n * If one ParentRef sets `sectionName`, all ParentRefs referencing the same object must also set `sectionName`. * If one ParentRef sets `port`, all ParentRefs referencing the same object must also set `port`. * If one ParentRef sets `sectionName` and `port`, all ParentRefs referencing the same object must also set `sectionName` and `port`. \n It is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged. \n Note that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n " + items: + description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n This API may be extended in the future to support additional kinds of parent resources. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + x-kubernetes-validations: + - message: sectionName or port must be specified when parentRefs includes 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__)) ? ((!has(p1.sectionName) || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) || p2.port == 0)): true))' + - message: sectionName or port must be unique when parentRefs includes 2 or more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName == '')) || ( has(p1.sectionName) && has(p2.sectionName) && p1.sectionName == p2.sectionName)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port == p2.port)))) + rules: + description: Rules are a list of TLS matchers and actions. + items: + description: TLSRouteRule is the configuration for a given rule. + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching requests should be sent. If unspecified or invalid (refers to a non-existent resource or a Service with no endpoints), the rule performs no forwarding; if no filters are specified that would result in a response being sent, the underlying implementation must actively reject request attempts to this backend, by rejecting the connection or returning a 500 status code. Request rejections must respect weight; if an invalid backend is requested to have 80% of requests, then 80% of requests must be rejected instead. \n Support: Core for Kubernetes Service \n Support: Extended for Kubernetes ServiceImport \n Support: Implementation-specific for any other resource \n Support for weight: Extended" + items: + description: "BackendRef defines how a Route should forward a request to a Kubernetes resource. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n \n When the BackendRef points to a Kubernetes Service, implementations SHOULD honor the appProtocol field if it is set for the target Service Port. \n Implementations supporting appProtocol SHOULD recognize the Kubernetes Standard Application Protocols defined in KEP-3726. \n If a Service appProtocol isn't specified, an implementation MAY infer the backend protocol through its own means. Implementations MAY infer the protocol from the Route type referring to the backend Service. \n If a Route is not able to send traffic to the backend using the specified protocol then the backend is considered invalid. Implementations MUST set the \"ResolvedRefs\" condition to \"False\" with the \"UnsupportedProtocol\" reason. \n \n Note that when the BackendTLSPolicy object is enabled by the implementation, there are some extra rules about validity to consider here. See the fields where this struct is used for more information about the exact behavior." + properties: + group: + default: "" + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource kind of the referent. For example \"Service\". \n Defaults to \"Service\" when not specified. \n ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. \n Support: Core (Services with a type other than ExternalName) \n Support: Implementation-specific (Services with type ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests forwarded to the referenced backend. This is computed as weight/(sum of all weights in this BackendRefs list). For non-zero values, there may be some epsilon from the exact proportion defined here depending on the precision an implementation supports. Weight is not a percentage and the sum of weights does not need to equal 100. \n If only one backend is specified and it has a weight greater than 0, 100% of the traffic is forwarded to that backend. If weight is set to 0, no traffic should be forwarded for this entry. If unspecified, weight defaults to 1. \n Support for this field varies based on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + maxItems: 16 + minItems: 1 + type: array + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - rules + type: object + status: + description: Status defines the current state of TLSRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified. \n Note that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for. \n A maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway." + items: + description: RouteParentStatus describes the status of a route with respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with respect to the Gateway. Note that the route's availability is also subject to the Gateway's own status conditions and listener status. \n If the Route's ParentRef specifies an existing Gateway that supports Routes of this kind AND that Gateway's controller has sufficient access, then that Gateway's controller MUST set the \"Accepted\" condition on the Route, to indicate whether the route has been accepted or rejected by the Gateway, and why. \n A Route MUST be considered \"Accepted\" if at least one of the Route's rules is implemented by the Gateway. \n There are a number of cases where the \"Accepted\" condition may not be set due to lack of controller visibility, that includes when: \n * The Route refers to a non-existent parent. * The Route is of a type that the controller does not support. * The Route is in a namespace the controller does not have access to." + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates the name of the controller that wrote this status. This corresponds with the controllerName field on GatewayClass. \n Example: \"example.net/gateway-controller\". \n The format of this field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). \n Controllers MUST populate this field when writing status. Controllers should ensure that entries to status populated with their ControllerName are cleaned up when they are no longer necessary." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec that this RouteParentStatus struct describes the status of. properties: group: - default: "" - description: Group is the group of the referent. For example, - "networking.k8s.io". When unspecified (empty string), - core API group is inferred. + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: - default: Service - description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". + default: Gateway + description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ type: string name: - description: Name is the name of the referent. + description: "Name is the name of the referent. \n Support: Core" maxLength: 253 minLength: 1 type: string namespace: - description: "Namespace is the namespace of the backend. - When unspecified, the local namespace is inferred. \n - Note that when a namespace is specified, a ReferencePolicy - object is required in the referent namespace to allow - that namespace's owner to accept the reference. See - the ReferencePolicy documentation for details. \n Support: - Core" + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string port: - description: Port specifies the destination port number - to use for this resource. Port is required when the - referent is a Kubernetes Service. For other resources, - destination port might be derived from the referent - resource or this field. + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " format: int32 maximum: 65535 minimum: 1 type: integer - weight: - default: 1 - description: "Weight specifies the proportion of requests - forwarded to the referenced backend. This is computed - as weight/(sum of all weights in this BackendRefs list). - For non-zero values, there may be some epsilon from - the exact proportion defined here depending on the precision - an implementation supports. Weight is not a percentage - and the sum of weights does not need to equal 100. \n - If only one backend is specified and it has a weight - greater than 0, 100% of the traffic is forwarded to - that backend. If weight is set to 0, no traffic should - be forwarded for this entry. If unspecified, weight - defaults to 1. \n Support for this field varies based - on the context where used." - format: int32 - maximum: 1000000 - minimum: 0 - type: integer - required: - - name - type: object - maxItems: 16 - minItems: 1 - type: array - type: object - maxItems: 16 - minItems: 1 - type: array - required: - - rules - type: object - status: - description: Status defines the current state of TLSRoute. - properties: - parents: - description: "Parents is a list of parent resources (usually Gateways) - that are associated with the route, and the status of the route - with respect to each parent. When this route attaches to a parent, - the controller that manages the parent must add an entry to this - list when the controller first sees the route and should update - the entry as appropriate when the route or gateway is modified. - \n Note that parent references that cannot be resolved by an implementation - of this API will not be added to this list. Implementations of this - API can only populate Route status for the Gateways/parent resources - they are responsible for. \n A maximum of 32 Gateways will be represented - in this list. An empty list means the route has not been attached - to any Gateway." - items: - description: RouteParentStatus describes the status of a route with - respect to an associated Parent. - properties: - conditions: - description: "Conditions describes the status of the route with - respect to the Gateway. Note that the route's availability - is also subject to the Gateway's own status conditions and - listener status. \n If the Route's ParentRef specifies an - existing Gateway that supports Routes of this kind AND that - Gateway's controller has sufficient access, then that Gateway's - controller MUST set the \"Accepted\" condition on the Route, - to indicate whether the route has been accepted or rejected - by the Gateway, and why. \n A Route MUST be considered \"Accepted\" - if at least one of the Route's rules is implemented by the - Gateway. \n There are a number of cases where the \"Accepted\" - condition may not be set due to lack of controller visibility, - that includes when: \n * The Route refers to a non-existent - parent. * The Route is of a type that the controller does - not support. * The Route is in a namespace the the controller - does not have access to." - items: - description: "Condition contains details for one aspect of - the current state of this API Resource. --- This struct - is intended for direct use as an array at the field path - .status.conditions. For example, type FooStatus struct{ - \ // Represents the observations of a foo's current state. - \ // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // - +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should - be when the underlying condition changed. If that is - not known, then using the time when the API field changed - is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, - if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the - current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier - indicating the reason for the condition's last transition. - Producers of specific condition types may define expected - values and meanings for this field, and whether the - values are considered a guaranteed API. The value should - be a CamelCase string. This field may not be empty. - maxLength: 1024 + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + maxLength: 253 minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across - resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability - to deconflict is important. The regex it matches is - (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string required: - - lastTransitionTime - - message - - reason - - status - - type + - name type: object - maxItems: 8 - minItems: 1 - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - controllerName: - description: "ControllerName is a domain/path string that indicates - the name of the controller that wrote this status. This corresponds - with the controllerName field on GatewayClass. \n Example: - \"example.net/gateway-controller\". \n The format of this - field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid - Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ - type: string - parentRef: - description: ParentRef corresponds with a ParentRef in the spec - that this RouteParentStatus struct describes the status of. - properties: - group: - default: gateway.networking.k8s.io - description: "Group is the group of the referent. \n Support: - Core" - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - default: Gateway - description: "Kind is kind of the referent. \n Support: - Core (Gateway) Support: Custom (Other Resources)" - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: "Name is the name of the referent. \n Support: - Core" - maxLength: 253 - minLength: 1 - type: string - namespace: - description: "Namespace is the namespace of the referent. - When unspecified (or empty string), this refers to the - local namespace of the Route. \n Support: Core" - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - sectionName: - description: "SectionName is the name of a section within - the target resource. In the following resources, SectionName - is interpreted as the following: \n * Gateway: Listener - Name \n Implementations MAY choose to support attaching - Routes to other resources. If that is the case, they MUST - clearly document how SectionName is interpreted. \n When - unspecified (empty string), this will reference the entire - resource. For the purpose of status, an attachment is - considered successful if at least one section in the parent - resource accepts it. For example, Gateway listeners can - restrict which Routes can attach to them by Route kind, - namespace, or hostname. If 1 of 2 Gateway listeners accept - attachment from the referencing Route, the Route MUST - be considered successfully attached. If no Gateway listeners - accept attachment from this Route, the Route MUST be considered - detached from the Gateway. \n Support: Core" - maxLength: 253 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - required: - - name - type: object - required: - - controllerName - - parentRef - type: object - maxItems: 32 - type: array - required: - - parents - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} status: acceptedNames: kind: "" plural: "" - conditions: [] - storedVersions: [] + conditions: null + storedVersions: null diff --git a/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_udproutes.yaml b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_udproutes.yaml new file mode 100644 index 000000000..bb48563b9 --- /dev/null +++ b/docs/content/reference/dynamic-configuration/gateway.networking.k8s.io_udproutes.yaml @@ -0,0 +1,284 @@ +# +# config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml +# +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + name: udproutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: UDPRoute + listKind: UDPRouteList + plural: udproutes + singular: udproute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: UDPRoute provides a way to route UDP traffic. When combined with a Gateway listener, it can be used to forward traffic on the port specified by the listener to a set of backends specified by the UDPRoute. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of UDPRoute. + properties: + parentRefs: + description: "ParentRefs references the resources (usually Gateways) that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from Routes of this kind and namespace. For Services, that means the Service must either be in the same namespace for a \"producer\" route, or the mesh implementation must support and allow \"consumer\" routes for the referenced Service. ReferenceGrant is not applicable for governing ParentRefs to Services - it is not possible to create a \"producer\" route for a Service in a different namespace from the Route. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) This API may be extended in the future to support additional kinds of parent resources. \n ParentRefs must be _distinct_. This means either that: \n * They select different objects. If this is the case, then parentRef entries are distinct. In terms of fields, this means that the multi-part key defined by `group`, `kind`, `namespace`, and `name` must be unique across all parentRef entries in the Route. * They do not select different objects, but for each optional field used, each ParentRef that selects the same object must set the same set of optional fields to different values. If one ParentRef sets a combination of optional fields, all must set the same combination. \n Some examples: \n * If one ParentRef sets `sectionName`, all ParentRefs referencing the same object must also set `sectionName`. * If one ParentRef sets `port`, all ParentRefs referencing the same object must also set `port`. * If one ParentRef sets `sectionName` and `port`, all ParentRefs referencing the same object must also set `sectionName` and `port`. \n It is possible to separately reference multiple distinct objects that may be collapsed by an implementation. For example, some implementations may choose to merge compatible Gateway Listeners together. If that is the case, the list of routes attached to those resources should also be merged. \n Note that for ParentRefs that cross namespace boundaries, there are specific rules. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example, Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable other kinds of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n " + items: + description: "ParentReference identifies an API object (usually a Gateway) that can be considered a parent of this resource (usually a route). There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n This API may be extended in the future to support additional kinds of parent resources. \n The API object must be valid in the cluster; the Group and Kind must be registered in the cluster for this reference to be valid." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + x-kubernetes-validations: + - message: sectionName or port must be specified when parentRefs includes 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__)) ? ((!has(p1.sectionName) || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) || p2.port == 0)): true))' + - message: sectionName or port must be unique when parentRefs includes 2 or more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName == '')) || ( has(p1.sectionName) && has(p2.sectionName) && p1.sectionName == p2.sectionName)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port == p2.port)))) + rules: + description: Rules are a list of UDP matchers and actions. + items: + description: UDPRouteRule is the configuration for a given rule. + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching requests should be sent. If unspecified or invalid (refers to a non-existent resource or a Service with no endpoints), the underlying implementation MUST actively reject connection attempts to this backend. Packet drops must respect weight; if an invalid backend is requested to have 80% of the packets, then 80% of packets must be dropped instead. \n Support: Core for Kubernetes Service \n Support: Extended for Kubernetes ServiceImport \n Support: Implementation-specific for any other resource \n Support for weight: Extended" + items: + description: "BackendRef defines how a Route should forward a request to a Kubernetes resource. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n \n When the BackendRef points to a Kubernetes Service, implementations SHOULD honor the appProtocol field if it is set for the target Service Port. \n Implementations supporting appProtocol SHOULD recognize the Kubernetes Standard Application Protocols defined in KEP-3726. \n If a Service appProtocol isn't specified, an implementation MAY infer the backend protocol through its own means. Implementations MAY infer the protocol from the Route type referring to the backend Service. \n If a Route is not able to send traffic to the backend using the specified protocol then the backend is considered invalid. Implementations MUST set the \"ResolvedRefs\" condition to \"False\" with the \"UnsupportedProtocol\" reason. \n \n Note that when the BackendTLSPolicy object is enabled by the implementation, there are some extra rules about validity to consider here. See the fields where this struct is used for more information about the exact behavior." + properties: + group: + default: "" + description: Group is the group of the referent. For example, "gateway.networking.k8s.io". When unspecified or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource kind of the referent. For example \"Service\". \n Defaults to \"Service\" when not specified. \n ExternalName services can refer to CNAME DNS records that may live outside of the cluster and as such are difficult to reason about in terms of conformance. They also may not be safe to forward to (see CVE-2021-25740 for more information). Implementations SHOULD NOT support ExternalName Services. \n Support: Core (Services with a type other than ExternalName) \n Support: Implementation-specific (Services with type ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that when a namespace different than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number to use for this resource. Port is required when the referent is a Kubernetes Service. In this case, the port number is the service port number, not the target port. For other resources, destination port might be derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests forwarded to the referenced backend. This is computed as weight/(sum of all weights in this BackendRefs list). For non-zero values, there may be some epsilon from the exact proportion defined here depending on the precision an implementation supports. Weight is not a percentage and the sum of weights does not need to equal 100. \n If only one backend is specified and it has a weight greater than 0, 100% of the traffic is forwarded to that backend. If weight is set to 0, no traffic should be forwarded for this entry. If unspecified, weight defaults to 1. \n Support for this field varies based on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + maxItems: 16 + minItems: 1 + type: array + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - rules + type: object + status: + description: Status defines the current state of UDPRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) that are associated with the route, and the status of the route with respect to each parent. When this route attaches to a parent, the controller that manages the parent must add an entry to this list when the controller first sees the route and should update the entry as appropriate when the route or gateway is modified. \n Note that parent references that cannot be resolved by an implementation of this API will not be added to this list. Implementations of this API can only populate Route status for the Gateways/parent resources they are responsible for. \n A maximum of 32 Gateways will be represented in this list. An empty list means the route has not been attached to any Gateway." + items: + description: RouteParentStatus describes the status of a route with respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with respect to the Gateway. Note that the route's availability is also subject to the Gateway's own status conditions and listener status. \n If the Route's ParentRef specifies an existing Gateway that supports Routes of this kind AND that Gateway's controller has sufficient access, then that Gateway's controller MUST set the \"Accepted\" condition on the Route, to indicate whether the route has been accepted or rejected by the Gateway, and why. \n A Route MUST be considered \"Accepted\" if at least one of the Route's rules is implemented by the Gateway. \n There are a number of cases where the \"Accepted\" condition may not be set due to lack of controller visibility, that includes when: \n * The Route refers to a non-existent parent. * The Route is of a type that the controller does not support. * The Route is in a namespace the controller does not have access to." + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates the name of the controller that wrote this status. This corresponds with the controllerName field on GatewayClass. \n Example: \"example.net/gateway-controller\". \n The format of this field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). \n Controllers MUST populate this field when writing status. Controllers should ensure that entries to status populated with their ControllerName are cleaned up when they are no longer necessary." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec that this RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, \"gateway.networking.k8s.io\" is inferred. To set the core API group (such as for a \"Service\" kind referent), Group must be explicitly set to \"\" (empty string). \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are two kinds of parent resources with \"Core\" support: \n * Gateway (Gateway conformance profile) * Service (Mesh conformance profile, experimental, ClusterIP Services only) \n Support for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When unspecified, this refers to the local namespace of the Route. \n Note that there are specific rules for ParentRefs which cross namespace boundaries. Cross-namespace references are only valid if they are explicitly allowed by something in the namespace they are referring to. For example: Gateway has the AllowedRoutes field, and ReferenceGrant provides a generic way to enable any other kind of cross-namespace reference. \n ParentRefs from a Route to a Service in the same namespace are \"producer\" routes, which apply default routing rules to inbound connections from any namespace to the Service. \n ParentRefs from a Route to a Service in a different namespace are \"consumer\" routes, and these routing rules are only applied to outbound connections originating from the same namespace as the Route, for which the intended destination of the connections are a Service targeted as a ParentRef of the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. It can be interpreted differently based on the type of parent resource. \n When the parent resource is a Gateway, this targets all listeners listening on the specified port that also support this kind of Route(and select this Route). It's not recommended to set `Port` unless the networking behaviors specified in a Route must apply to a specific port as opposed to a listener(s) whose port(s) may be changed. When both Port and SectionName are specified, the name and port of the selected listener must match both specified values. \n When the parent resource is a Service, this targets a specific port in the Service spec. When both Port (experimental) and SectionName are specified, the name and port of the selected port must match both specified values. \n Implementations MAY choose to support other parent resources. Implementations supporting other types of parent resources MUST clearly document how/if Port is interpreted. \n For the purpose of status, an attachment is considered successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. * Service: Port Name. When both Port (experimental) and SectionName are specified, the name and port of the selected listener must match both specified values. Note that attaching Routes to Services as Parents is part of experimental Mesh support and is not supported for any other purpose. \n Implementations MAY choose to support attaching Routes to other resources. If that is the case, they MUST clearly document how SectionName is interpreted. \n When unspecified (empty string), this will reference the entire resource. For the purpose of status, an attachment is considered successful if at least one section in the parent resource accepts it. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/docs/content/reference/dynamic-configuration/kubernetes-gateway-resource.yml b/docs/content/reference/dynamic-configuration/kubernetes-gateway-resource.yml index a22858a69..d3b1bef20 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-gateway-resource.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-gateway-resource.yml @@ -1,5 +1,5 @@ --- -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: my-gateway-class @@ -7,7 +7,7 @@ spec: controllerName: traefik.io/gateway-controller --- -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: my-gateway @@ -44,7 +44,7 @@ spec: name: mysecret --- -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-app diff --git a/docs/content/reference/dynamic-configuration/kubernetes-gateway-simple-https.yml b/docs/content/reference/dynamic-configuration/kubernetes-gateway-simple-https.yml index c16a5dc2f..1f15ae429 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-gateway-simple-https.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-gateway-simple-https.yml @@ -1,5 +1,5 @@ --- -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: my-gateway-class @@ -8,7 +8,7 @@ spec: controllerName: traefik.io/gateway-controller --- -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: my-gateway @@ -25,7 +25,7 @@ spec: name: mysecret --- -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-app diff --git a/docs/content/reference/dynamic-configuration/kubernetes-gateway.md b/docs/content/reference/dynamic-configuration/kubernetes-gateway.md index 476dd2b47..1abbcf2b5 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-gateway.md +++ b/docs/content/reference/dynamic-configuration/kubernetes-gateway.md @@ -11,11 +11,15 @@ Dynamic configuration with Kubernetes Gateway provider. ## Definitions ```yaml +--8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_backendtlspolicies.yaml" --8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_gatewayclasses.yaml" --8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_gateways.yaml" +--8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_grpcroutes.yaml" --8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_httproutes.yaml" +--8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_referencegrants.yaml" --8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_tcproutes.yaml" --8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_tlsroutes.yaml" +--8<-- "content/reference/dynamic-configuration/gateway.networking.k8s.io_udproutes.yaml" ``` ## Resources diff --git a/docs/content/routing/providers/kubernetes-gateway.md b/docs/content/routing/providers/kubernetes-gateway.md index 04c4b621b..e8d11c426 100644 --- a/docs/content/routing/providers/kubernetes-gateway.md +++ b/docs/content/routing/providers/kubernetes-gateway.md @@ -39,19 +39,19 @@ The Kubernetes Gateway API, The Experimental Way. {: .subtitle } You can find an excerpt of the supported Kubernetes Gateway API resources in the table below: -| Kind | Purpose | Concept Behind | -|------------------------------------|---------------------------------------------------------------------------|---------------------------------------------------------------------------------| -| [GatewayClass](#kind-gatewayclass) | Defines a set of Gateways that share a common configuration and behaviour | [GatewayClass](https://gateway-api.sigs.k8s.io/v1alpha2/api-types/gatewayclass) | -| [Gateway](#kind-gateway) | Describes how traffic can be translated to Services within the cluster | [Gateway](https://gateway-api.sigs.k8s.io/v1alpha2/api-types/gateway) | -| [HTTPRoute](#kind-httproute) | HTTP rules for mapping requests from a Gateway to Kubernetes Services | [Route](https://gateway-api.sigs.k8s.io/v1alpha2/api-types/httproute) | -| [TCPRoute](#kind-tcproute) | Allows mapping TCP requests from a Gateway to Kubernetes Services | [Route](https://gateway-api.sigs.k8s.io/v1alpha2/guides/tcp/) | -| [TLSRoute](#kind-tlsroute) | Allows mapping TLS requests from a Gateway to Kubernetes Services | [Route](https://gateway-api.sigs.k8s.io/v1alpha2/guides/tls/) | +| Kind | Purpose | Concept Behind | +|------------------------------------|---------------------------------------------------------------------------|------------------------------------------------------------------------| +| [GatewayClass](#kind-gatewayclass) | Defines a set of Gateways that share a common configuration and behaviour | [GatewayClass](https://gateway-api.sigs.k8s.io/api-types/gatewayclass) | +| [Gateway](#kind-gateway) | Describes how traffic can be translated to Services within the cluster | [Gateway](https://gateway-api.sigs.k8s.io/api-types/gateway) | +| [HTTPRoute](#kind-httproute) | HTTP rules for mapping requests from a Gateway to Kubernetes Services | [Route](https://gateway-api.sigs.k8s.io/api-types/httproute) | +| [TCPRoute](#kind-tcproute) | Allows mapping TCP requests from a Gateway to Kubernetes Services | [Route](https://gateway-api.sigs.k8s.io/guides/tcp/) | +| [TLSRoute](#kind-tlsroute) | Allows mapping TLS requests from a Gateway to Kubernetes Services | [Route](https://gateway-api.sigs.k8s.io/guides/tls/) | ### Kind: `GatewayClass` `GatewayClass` is cluster-scoped resource defined by the infrastructure provider. This resource represents a class of Gateways that can be instantiated. More details on the -GatewayClass [official documentation](https://gateway-api.sigs.k8s.io/v1alpha2/api-types/gatewayclass/). +GatewayClass [official documentation](https://gateway-api.sigs.k8s.io/api-types/gatewayclass/). The `GatewayClass` should be declared by the infrastructure provider, otherwise please register the `GatewayClass` [definition](../../reference/dynamic-configuration/kubernetes-gateway.md#definitions) in the Kubernetes cluster before @@ -60,7 +60,7 @@ creating `GatewayClass` objects. !!! info "Declaring GatewayClass" ```yaml - apiVersion: gateway.networking.k8s.io/v1alpha2 + apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: my-gateway-class @@ -92,7 +92,7 @@ Depending on the Listener Protocol, different modes and Route types are supporte !!! info "Declaring Gateway" ```yaml tab="HTTP Listener" - apiVersion: gateway.networking.k8s.io/v1alpha2 + apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: my-http-gateway @@ -114,7 +114,7 @@ Depending on the Listener Protocol, different modes and Route types are supporte ``` ```yaml tab="HTTPS Listener" - apiVersion: gateway.networking.k8s.io/v1alpha2 + apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: my-https-gateway @@ -140,7 +140,7 @@ Depending on the Listener Protocol, different modes and Route types are supporte ``` ```yaml tab="TCP Listener" - apiVersion: gateway.networking.k8s.io/v1alpha2 + apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: my-tcp-gateway @@ -162,7 +162,7 @@ Depending on the Listener Protocol, different modes and Route types are supporte ``` ```yaml tab="TLS Listener" - apiVersion: gateway.networking.k8s.io/v1alpha2 + apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: my-tls-gateway @@ -213,7 +213,7 @@ Kubernetes cluster before creating `HTTPRoute` objects. !!! info "Declaring HTTPRoute" ```yaml - apiVersion: gateway.networking.k8s.io/v1alpha2 + apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-app @@ -274,7 +274,7 @@ Kubernetes cluster before creating `TCPRoute` objects. !!! info "Declaring TCPRoute" ```yaml - apiVersion: gateway.networking.k8s.io/v1alpha2 + apiVersion: gateway.networking.k8s.io/v1 kind: TCPRoute metadata: name: tcp-app @@ -318,7 +318,7 @@ Kubernetes cluster before creating `TLSRoute` objects. !!! info "Declaring TLSRoute" ```yaml - apiVersion: gateway.networking.k8s.io/v1alpha2 + apiVersion: gateway.networking.k8s.io/v1 kind: TLSRoute metadata: name: tls-app diff --git a/go.mod b/go.mod index 25d529a2d..51609de00 100644 --- a/go.mod +++ b/go.mod @@ -50,8 +50,8 @@ require ( github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pires/go-proxyproto v0.6.1 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 - github.com/prometheus/client_golang v1.14.0 - github.com/prometheus/client_model v0.3.0 + github.com/prometheus/client_golang v1.17.0 + github.com/prometheus/client_model v0.5.0 github.com/quic-go/quic-go v0.40.1 github.com/rs/zerolog v1.29.0 github.com/sirupsen/logrus v1.9.3 @@ -80,21 +80,21 @@ require ( go.opentelemetry.io/otel/sdk v1.21.0 go.opentelemetry.io/otel/sdk/metric v1.21.0 go.opentelemetry.io/otel/trace v1.21.0 - golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 - golang.org/x/mod v0.12.0 + golang.org/x/exp v0.0.0-20231006140011-7918f672742d + golang.org/x/mod v0.13.0 golang.org/x/net v0.17.0 golang.org/x/text v0.13.0 golang.org/x/time v0.3.0 - golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 + golang.org/x/tools v0.14.0 google.golang.org/grpc v1.59.0 gopkg.in/yaml.v3 v3.0.1 - k8s.io/api v0.26.3 - k8s.io/apiextensions-apiserver v0.26.3 - k8s.io/apimachinery v0.26.3 - k8s.io/client-go v0.26.3 - k8s.io/utils v0.0.0-20230313181309-38a27ef9d749 + k8s.io/api v0.28.3 + k8s.io/apiextensions-apiserver v0.28.3 + k8s.io/apimachinery v0.28.3 + k8s.io/client-go v0.28.3 + k8s.io/utils v0.0.0-20230726121419-3b25d923346b mvdan.cc/xurls/v2 v2.5.0 - sigs.k8s.io/gateway-api v0.4.0 + sigs.k8s.io/gateway-api v1.0.0 ) require ( @@ -157,8 +157,8 @@ require ( github.com/containerd/containerd v1.5.17 // indirect github.com/containerd/continuity v0.3.0 // indirect github.com/containerd/typeurl v1.0.2 // indirect - github.com/coreos/go-semver v0.3.0 // indirect - github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534 // indirect + github.com/coreos/go-semver v0.3.1 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cpu/goacmedns v0.1.1 // indirect github.com/deepmap/oapi-codegen v1.9.1 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect @@ -173,7 +173,7 @@ require ( github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.4.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/evanphx/json-patch v4.12.0+incompatible // indirect + github.com/evanphx/json-patch v5.7.0+incompatible // indirect github.com/exoscale/egoscale v0.100.1 // indirect github.com/fatih/color v1.15.0 // indirect github.com/fvbommel/sortorder v1.0.1 // indirect @@ -184,9 +184,9 @@ require ( github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect - 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-openapi/jsonpointer v0.20.0 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.4 // indirect github.com/go-resty/resty/v2 v2.7.0 // indirect github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect @@ -197,7 +197,7 @@ require ( github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect - github.com/google/gnostic v0.5.7-v3refs // indirect + github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect @@ -222,8 +222,8 @@ require ( github.com/hashicorp/serf v0.10.1 // indirect github.com/huandu/xstrings v1.4.0 // indirect github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect - github.com/imdario/mergo v0.3.12 // indirect - github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/imdario/mergo v0.3.16 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect github.com/jaguilar/vt100 v0.0.0-20150826170717-2703a27b14ea // indirect @@ -249,7 +249,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/miekg/pkcs11 v1.0.3 // indirect github.com/mimuret/golang-iij-dpf v0.9.1 // indirect @@ -287,8 +287,8 @@ require ( github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pquerna/otp v1.4.0 // indirect - github.com/prometheus/common v0.37.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-20 v0.4.1 // indirect github.com/redis/go-redis/v9 v9.2.1 // indirect @@ -305,7 +305,7 @@ require ( github.com/softlayer/softlayer-go v1.1.2 // indirect github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/cobra v1.6.0 // indirect + github.com/spf13/cobra v1.7.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.1 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 // indirect @@ -325,23 +325,23 @@ require ( github.com/yandex-cloud/go-genproto v0.0.0-20220805142335-27b56ddae16f // indirect github.com/yandex-cloud/go-sdk v0.0.0-20220805164847-cf028e604997 // indirect github.com/zeebo/errs v1.2.2 // indirect - go.etcd.io/etcd/api/v3 v3.5.5 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.5 // indirect - go.etcd.io/etcd/client/v3 v3.5.5 // indirect + go.etcd.io/etcd/api/v3 v3.5.9 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect + go.etcd.io/etcd/client/v3 v3.5.9 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/mock v0.3.0 // indirect - go.uber.org/multierr v1.8.0 // indirect + go.uber.org/multierr v1.11.0 // indirect go.uber.org/ratelimit v0.2.0 // indirect - go.uber.org/zap v1.21.0 // indirect + go.uber.org/zap v1.26.0 // indirect golang.org/x/crypto v0.14.0 // indirect - golang.org/x/oauth2 v0.11.0 // indirect - golang.org/x/sync v0.3.0 // indirect + golang.org/x/oauth2 v0.13.0 // indirect + golang.org/x/sync v0.4.0 // indirect golang.org/x/sys v0.14.0 // indirect golang.org/x/term v0.13.0 // indirect google.golang.org/api v0.128.0 // indirect - google.golang.org/appengine v1.6.7 // indirect + google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect @@ -352,12 +352,12 @@ require ( gopkg.in/ns1/ns1-go.v2 v2.7.6 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/klog/v2 v2.90.1 // indirect - k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect nhooyr.io/websocket v1.8.7 // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) // Containous forks diff --git a/go.sum b/go.sum index e51ba4439..1bf9ae159 100644 --- a/go.sum +++ b/go.sum @@ -79,14 +79,12 @@ github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSW github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A= github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg= github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= @@ -155,7 +153,6 @@ github.com/Microsoft/hcsshim v0.8.25/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01 github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= @@ -176,7 +173,6 @@ github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= -github.com/ahmetb/gen-crd-api-reference-docs v0.3.0/go.mod h1:TdjdkYhlOifCQWPs1UdTma97kQQMozf5h26hTuG70u8= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 h1:F1j7z+/DKEsYqZNoxC6wvfmaiDneLsQOFQmuq9NADSY= github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2/go.mod h1:QlXr/TrICfQ/ANa76sLeQyhAJyNR9sEcfNuZBkY9jgY= @@ -185,7 +181,6 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 h1:J45/QHgrzUdqe/Vco/Vxk0wRvdS2nKUxmf/zLgvfass= github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755/go.mod h1:RcDobYh8k5VP6TNybz9m++gL3ijVI5wueVr0EM10VsU= @@ -250,8 +245,6 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.19.3/go.mod h1:yVGZA1CPkmUhBdA039jXN github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/aws/smithy-go v1.14.2 h1:MJU9hqBGbvWZdApzpvoF2WAIJDbtjK2NDJSiJP7HblQ= github.com/aws/smithy-go v1.14.2/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -300,7 +293,6 @@ github.com/certifi/gocertifi v0.0.0-20180118203423-deb3ae2ef261/go.mod h1:GJKEex github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -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/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= @@ -467,8 +459,9 @@ github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmeka github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= @@ -477,8 +470,9 @@ github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7 github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534 h1:rtAn27wIbmOGUs7RIbVgPEjb31ehTVniDwPGXyMxm5U= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpu/goacmedns v0.1.1 h1:DM3H2NiN2oam7QljgGY5ygy4yDXhK5Z4JUnqaugs2C4= @@ -612,17 +606,14 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= -github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI= +github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exoscale/egoscale v0.100.1 h1:iXsV1Ei7daqe/6FYSCSDyrFs1iUG1l1X9qNh2uMw6z0= github.com/exoscale/egoscale v0.100.1/go.mod h1:BAb9p4rmyU+Wl400CJZO5270H2sXtdsZjLcm5xMKkz4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= @@ -631,7 +622,6 @@ github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= @@ -677,8 +667,6 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.1-0.20200915143503-439c4d2ed3ea h1:CnEQOUv4ilElSwFB9g/lVmz206oLE4aNZDYngIY1Gvg= github.com/go-kit/kit v0.10.1-0.20200915143503-439c4d2ed3ea/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= @@ -693,26 +681,26 @@ github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= +github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -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-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= @@ -745,7 +733,6 @@ github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b h1:/vQ+oYKu+JoyaMPDsv5FzwuL2wwWBgBbtj/YLCi4LuA= github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b/go.mod h1:Xo4aNUOrJnVruqWQJBtW6+bTBDTniY8yZum5rF3b5jw= -github.com/gobuffalo/flect v0.2.3/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= @@ -841,8 +828,8 @@ github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/certificate-transparency-go v1.0.21 h1:Yf1aXowfZ2nuboBsg7iYGLmwsOARdV86pfH3g95wXmE= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= -github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -857,6 +844,7 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.0.0-20191015185424-71da34e4d9b3/go.mod h1:ZXFeSndFcK4vB1NR4voH1Zm38K7ViUNiYtfIBDxrwf0= @@ -911,8 +899,6 @@ github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsC github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= -github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gophercloud/gophercloud v0.15.1-0.20210202035223-633d73521055/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4= github.com/gophercloud/gophercloud v1.0.0 h1:9nTGx0jizmHxDobe4mck89FyQHVyA3CaXLIUSGJjP9k= @@ -1015,7 +1001,6 @@ github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -1050,11 +1035,12 @@ github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb-client-go/v2 v2.7.0 h1:QgP5mlBE9sGnzplpnf96pr+p7uqlIlL4W2GAP3n+XZg= github.com/influxdata/influxdb-client-go/v2 v2.7.0/go.mod h1:Y/0W1+TZir7ypoQZYd2IrnVOKB3Tq6oegAQeSVN/+EU= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA= @@ -1092,7 +1078,6 @@ github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9q github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -1108,7 +1093,6 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 h1:qGQQKEcAR99REcMpsXCp3lJ03zYT1PkRd3kQGPn9GVg= github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw= @@ -1197,7 +1181,6 @@ github.com/liquidweb/liquidweb-cli v0.6.9 h1:acbIvdRauiwbxIsOCEMXGwF75aSJDbDiyAW github.com/liquidweb/liquidweb-cli v0.6.9/go.mod h1:cE1uvQ+x24NGUL75D0QagOFCG8Wdvmwu8aL9TLmA/eQ= github.com/liquidweb/liquidweb-go v1.6.3 h1:NVHvcnX3eb3BltiIoA+gLYn15nOpkYkdizOEYGSKrk4= github.com/liquidweb/liquidweb-go v1.6.3/go.mod h1:SuXXp+thr28LnjEw18AYtWwIbWMHSUiajPQs8T9c/Rc= -github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -1215,7 +1198,6 @@ github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN 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.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= @@ -1253,8 +1235,8 @@ github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsO github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/maxatome/go-testdeep v1.12.0 h1:Ql7Go8Tg0C1D/uMMX59LAoYK7LffeJQ6X2T04nTH68g= github.com/maxatome/go-testdeep v1.12.0/go.mod h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= @@ -1316,7 +1298,6 @@ github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdx github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= -github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -1389,7 +1370,6 @@ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= @@ -1406,7 +1386,6 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= @@ -1510,11 +1489,8 @@ github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQ github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -1522,8 +1498,8 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -1533,10 +1509,8 @@ github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= 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.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -1549,9 +1523,8 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/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.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/qri-io/jsonpointer v0.1.0/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64= github.com/qri-io/jsonschema v0.1.1/go.mod h1:QpzJ6gBQ0GYgGmh7mDQ1YsvvhSgE4rYj0k8t5MBOmUY= @@ -1654,8 +1627,8 @@ github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHN github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI= -github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -1675,7 +1648,6 @@ github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH github.com/spiffe/go-spiffe/v2 v2.1.1 h1:RT9kM8MZLZIsPTH+HKQEP5yaAk3yd/VBzlINaRjXs8k= github.com/spiffe/go-spiffe/v2 v2.1.1/go.mod h1:5qg6rpqlwIub0JAiF1UK9IMD6BpPTmvG6yfSgDBs5lg= github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -1835,14 +1807,14 @@ go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/api/v3 v3.5.5 h1:BX4JIbQ7hl7+jL+g+2j5UAr0o1bctCm6/Ct+ArBGkf0= -go.etcd.io/etcd/api/v3 v3.5.5/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8= +go.etcd.io/etcd/api/v3 v3.5.9 h1:4wSsluwyTbGGmyjJktOf3wFQoTBIURXHnq9n/G/JQHs= +go.etcd.io/etcd/api/v3 v3.5.9/go.mod h1:uyAal843mC8uUVSLWz6eHa/d971iDGnCRpmKd2Z+X8k= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/pkg/v3 v3.5.5 h1:9S0JUVvmrVl7wCF39iTQthdaaNIiAaQbmK75ogO6GU8= -go.etcd.io/etcd/client/pkg/v3 v3.5.5/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ= +go.etcd.io/etcd/client/pkg/v3 v3.5.9 h1:oidDC4+YEuSIQbsR94rY9gur91UPL6DnxDCIYd2IGsE= +go.etcd.io/etcd/client/pkg/v3 v3.5.9/go.mod h1:y+CzeSmkMpWN2Jyu1npecjB9BBnABxGM4pN8cGuJeL4= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v3 v3.5.5 h1:q++2WTJbUgpQu4B6hCuT7VkdwaTP7Qz6Daak3WzbrlI= -go.etcd.io/etcd/client/v3 v3.5.5/go.mod h1:aApjR4WGlSumpnJ2kloS75h6aHUmAyaPLjHMxpc7E7c= +go.etcd.io/etcd/client/v3 v3.5.9 h1:r5xghnU7CwbUxD/fbUtRyJGaYNfDun8sp/gTr1hew6E= +go.etcd.io/etcd/client/v3 v3.5.9/go.mod h1:i/Eo5LrZ5IKqpbtpPDuaUnDOUv471oDg8cjQaUr2MbA= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -1886,8 +1858,6 @@ go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= @@ -1896,17 +1866,16 @@ go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= -go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/ratelimit v0.2.0 h1:UQE2Bgi7p2B85uP5dC2bbRtig0C+OeNRnNEafLjsLPA= go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= -go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1961,8 +1930,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= -golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1986,13 +1955,12 @@ 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.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2051,13 +2019,10 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= @@ -2077,10 +2042,8 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= -golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= 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= @@ -2093,8 +2056,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2159,11 +2122,9 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2199,7 +2160,6 @@ 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-20210426230700-d19ff857e887/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-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2253,7 +2213,6 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -2284,7 +2243,6 @@ golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191014205221-18e3458ac98b/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -2306,7 +2264,6 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -2329,13 +2286,12 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= -golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= 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= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2 h1:CCXrcPKiGGotvnN6jfUsKk4rRqm7q09/YbKb5xCEvtM= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= @@ -2375,8 +2331,9 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -2416,7 +2373,6 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/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-20200904004341-0bd0a958aa1d/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-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -2541,7 +2497,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -2564,13 +2519,10 @@ k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU= -k8s.io/api v0.21.3/go.mod h1:hUgeYHUbBp23Ue4qdX9tR8/ANi/g3ehylAqDn9NWVOg= -k8s.io/api v0.22.1/go.mod h1:bh13rkTp3F1XEaLGykbyRD2QaTTzPm0e/BMd8ptFONY= -k8s.io/api v0.26.3 h1:emf74GIQMTik01Aum9dPP0gAypL8JTLl/lHa4V9RFSU= -k8s.io/api v0.26.3/go.mod h1:PXsqwPMXBSBcL1lJ9CYDKy7kIReUydukS5JiRlxC3qE= -k8s.io/apiextensions-apiserver v0.21.3/go.mod h1:kl6dap3Gd45+21Jnh6utCx8Z2xxLm8LGDkprcd+KbsE= -k8s.io/apiextensions-apiserver v0.26.3 h1:5PGMm3oEzdB1W/FTMgGIDmm100vn7IaUP5er36dB+YE= -k8s.io/apiextensions-apiserver v0.26.3/go.mod h1:jdA5MdjNWGP+njw1EKMZc64xAT5fIhN6VJrElV3sfpQ= +k8s.io/api v0.28.3 h1:Gj1HtbSdB4P08C8rs9AR94MfSGpRhJgsS+GF9V26xMM= +k8s.io/api v0.28.3/go.mod h1:MRCV/jr1dW87/qJnZ57U5Pak65LGmQVkKTzf3AtKFHc= +k8s.io/apiextensions-apiserver v0.28.3 h1:Od7DEnhXHnHPZG+W9I97/fSQkVpVPQx2diy+2EtmY08= +k8s.io/apiextensions-apiserver v0.28.3/go.mod h1:NE1XJZ4On0hS11aWWJUTNkmVB03j9LM7gJSisbRt8Lc= k8s.io/apimachinery v0.0.0-20180904193909-def12e63c512/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= k8s.io/apimachinery v0.0.0-20190806215851-162a2dabc72f/go.mod h1:+ntn62igV2hyNj7/0brOvXSMONE2KxcePkSxK7/9FFQ= k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ= @@ -2578,68 +2530,50 @@ k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRp k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= -k8s.io/apimachinery v0.21.3/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI= -k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= -k8s.io/apimachinery v0.26.3 h1:dQx6PNETJ7nODU3XPtrwkfuubs6w7sX0M8n61zHIV/k= -k8s.io/apimachinery v0.26.3/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= +k8s.io/apimachinery v0.28.3 h1:B1wYx8txOaCQG0HmYF6nbpU8dg6HvA06x5tEffvOe7A= +k8s.io/apimachinery v0.28.3/go.mod h1:uQTKmIqs+rAYaq+DFaoD2X7pcjLOqbQX2AOiO0nIpb8= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= -k8s.io/apiserver v0.21.3/go.mod h1:eDPWlZG6/cCCMj/JBcEpDoK+I+6i3r9GsChYBHSbAzU= k8s.io/client-go v0.0.0-20180910083459-2cefa64ff137/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= k8s.io/client-go v0.0.0-20191016111102-bec269661e48/go.mod h1:hrwktSwYGI4JK+TJA3dMaFyyvHVi/aLarVHpbs8bgCU= k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA= -k8s.io/client-go v0.21.3/go.mod h1:+VPhCgTsaFmGILxR/7E1N0S+ryO010QBeNCv5JwRGYU= -k8s.io/client-go v0.22.1/go.mod h1:BquC5A4UOo4qVDUtoc04/+Nxp1MeHcVc1HJm1KmG8kk= -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.21.3/go.mod h1:K3y0Bv9Cz2cOW2vXUrNZlFbflhuPvuadW6JdnN6gGKo= -k8s.io/code-generator v0.22.0/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o= +k8s.io/client-go v0.28.3 h1:2OqNb72ZuTZPKCl+4gTKvqao0AMOl9f3o2ijbAj3LI4= +k8s.io/client-go v0.28.3/go.mod h1:LTykbBp9gsA7SwqirlCXBWtK0guzfhpoW4qSm7i9dxo= k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= -k8s.io/component-base v0.21.3/go.mod h1:kkuhtfEHeZM6LkX0saqSK8PbdO7A0HigUngmhhrwfGQ= k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201203183100-97869a43a9d9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/klog/v2 v2.10.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= -k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4= k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= -k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -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/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= k8s.io/kubernetes v1.11.10/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210722164352-7f3ee0f31471/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210820185131-d34e5cb4466e/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20230313181309-38a27ef9d749 h1:xMMXJlJbsU8w3V5N2FLDQ8YgU8s1EoULdbQBcAeNJkY= -k8s.io/utils v0.0.0-20230313181309-38a27ef9d749/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8= mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE= nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= @@ -2650,23 +2584,19 @@ 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/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.19/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/controller-runtime v0.9.6/go.mod h1:q6PpkM5vqQubEKUKOM6qr06oXGzOBcCby1DA9FbyZeA= -sigs.k8s.io/controller-tools v0.6.2/go.mod h1:oaeGpjXn6+ZSEIQkUe/+3I40PNiDYp9aeawbt3xTgJ8= -sigs.k8s.io/gateway-api v0.4.0 h1:07IJkTt21NetZTHtPKJk2I4XIgDN4BAlTIq1wK7V11o= -sigs.k8s.io/gateway-api v0.4.0/go.mod h1:r3eiNP+0el+NTLwaTfOrCNXy8TukC+dIM3ggc+fbNWk= -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/gateway-api v1.0.0 h1:iPTStSv41+d9p0xFydll6d7f7MOBGuqXM6p2/zVYMAs= +sigs.k8s.io/gateway-api v1.0.0/go.mod h1:4cUgr0Lnp5FZ0Cdq8FdRwCvpiWws7LVhLHGIudLlf4c= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk= +sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= vbom.ml/util v0.0.0-20180919145318-efcd4e0f9787/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI= diff --git a/integration/fixtures/k8s/01-gateway-api-crd.yml b/integration/fixtures/k8s/01-gateway-api-crd.yml index cb10d17d5..f483bcb0a 100644 --- a/integration/fixtures/k8s/01-gateway-api-crd.yml +++ b/integration/fixtures/k8s/01-gateway-api-crd.yml @@ -1,10 +1,10 @@ - ---- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: gatewayclasses.gateway.networking.k8s.io spec: @@ -21,9 +21,12 @@ spec: scope: Cluster versions: - additionalPrinterColumns: - - jsonPath: .spec.controller + - jsonPath: .spec.controllerName name: Controller type: string + - jsonPath: .status.conditions[?(@.type=="Accepted")].status + name: Accepted + type: string - jsonPath: .metadata.creationTimestamp name: Age type: date @@ -31,7 +34,7 @@ spec: name: Description priority: 1 type: string - name: v1alpha2 + name: v1 schema: openAPIV3Schema: description: "GatewayClass describes a class of Gateways available to the @@ -43,7 +46,7 @@ spec: to GatewayClass or associated parameters. If implementations choose to propagate GatewayClass changes to existing Gateways, that MUST be clearly documented by the implementation. \n Whenever one or more Gateways are using a GatewayClass, - implementations MUST add the `gateway-exists-finalizer.gateway.networking.k8s.io` + implementations SHOULD add the `gateway-exists-finalizer.gateway.networking.k8s.io` finalizer on the associated GatewayClass. This ensures that a GatewayClass associated with a Gateway is not deleted while in use. \n GatewayClass is a Cluster level resource." @@ -72,6 +75,9 @@ spec: minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf description: description: Description helps describe a GatewayClass with more details. maxLength: 64 @@ -84,7 +90,7 @@ spec: resource, i.e. ConfigMap, or an implementation-specific custom resource. The resource can be cluster-scoped or namespace-scoped. \n If the referent cannot be found, the GatewayClass's \"InvalidParameters\" - status condition will be true. \n Support: Custom" + status condition will be true. \n Support: Implementation-specific" properties: group: description: Group is the group of the referent. @@ -126,13 +132,15 @@ spec: reason: Waiting status: Unknown type: Accepted - description: Status defines the current state of GatewayClass. + description: "Status defines the current state of GatewayClass. \n Implementations + MUST populate status on all GatewayClass resources which specify their + controller name." properties: conditions: default: - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller - reason: Waiting + reason: Pending status: Unknown type: Accepted description: "Conditions is the current status from the controller @@ -142,13 +150,12 @@ spec: description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, - type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: - \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // +listMapKey=type - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" properties: lastTransitionTime: description: lastTransitionTime is the last time the condition @@ -210,6 +217,269 @@ spec: x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map + supportedFeatures: + description: 'SupportedFeatures is the set of features the GatewayClass + support. It MUST be sorted in ascending alphabetical order. ' + items: + description: SupportedFeature is used to describe distinct features + that are covered by conformance tests. + enum: + - Gateway + - GatewayPort8080 + - GatewayStaticAddresses + - HTTPRoute + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + - Mesh + - ReferenceGrant + - TLSRoute + type: string + maxItems: 64 + type: array + x-kubernetes-list-type: set + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.controllerName + name: Controller + type: string + - jsonPath: .status.conditions[?(@.type=="Accepted")].status + name: Accepted + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.description + name: Description + priority: 1 + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: "GatewayClass describes a class of Gateways available to the + user for creating Gateway resources. \n It is recommended that this resource + be used as a template for Gateways. This means that a Gateway is based on + the state of the GatewayClass at the time it was created and changes to + the GatewayClass or associated parameters are not propagated down to existing + Gateways. This recommendation is intended to limit the blast radius of changes + to GatewayClass or associated parameters. If implementations choose to propagate + GatewayClass changes to existing Gateways, that MUST be clearly documented + by the implementation. \n Whenever one or more Gateways are using a GatewayClass, + implementations SHOULD add the `gateway-exists-finalizer.gateway.networking.k8s.io` + finalizer on the associated GatewayClass. This ensures that a GatewayClass + associated with a Gateway is not deleted while in use. \n GatewayClass is + a Cluster level resource." + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of GatewayClass. + properties: + controllerName: + description: "ControllerName is the name of the controller that is + managing Gateways of this class. The value of this field MUST be + a domain prefixed path. \n Example: \"example.net/gateway-controller\". + \n This field is not mutable and cannot be empty. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + description: + description: Description helps describe a GatewayClass with more details. + maxLength: 64 + type: string + parametersRef: + description: "ParametersRef is a reference to a resource that contains + the configuration parameters corresponding to the GatewayClass. + This is optional if the controller does not require any additional + configuration. \n ParametersRef can reference a standard Kubernetes + resource, i.e. ConfigMap, or an implementation-specific custom resource. + The resource can be cluster-scoped or namespace-scoped. \n If the + referent cannot be found, the GatewayClass's \"InvalidParameters\" + status condition will be true. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace is the namespace of the referent. This + field is required when referring to a Namespace-scoped resource + and MUST be unset when referring to a Cluster-scoped resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + required: + - controllerName + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Waiting + status: Unknown + type: Accepted + description: "Status defines the current state of GatewayClass. \n Implementations + MUST populate status on all GatewayClass resources which specify their + controller name." + properties: + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + description: "Conditions is the current status from the controller + for this GatewayClass. \n Controllers should prefer to publish conditions + using values of GatewayClassConditionType for the type of each Condition." + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + supportedFeatures: + description: 'SupportedFeatures is the set of features the GatewayClass + support. It MUST be sorted in ascending alphabetical order. ' + items: + description: SupportedFeature is used to describe distinct features + that are covered by conformance tests. + enum: + - Gateway + - GatewayPort8080 + - GatewayStaticAddresses + - HTTPRoute + - HTTPRouteDestinationPortMatching + - HTTPRouteHostRewrite + - HTTPRouteMethodMatching + - HTTPRoutePathRedirect + - HTTPRoutePathRewrite + - HTTPRoutePortRedirect + - HTTPRouteQueryParamMatching + - HTTPRouteRequestMirror + - HTTPRouteRequestMultipleMirrors + - HTTPRouteResponseHeaderModification + - HTTPRouteSchemeRedirect + - Mesh + - ReferenceGrant + - TLSRoute + type: string + maxItems: 64 + type: array + x-kubernetes-list-type: set type: object required: - spec @@ -222,15 +492,16 @@ status: acceptedNames: kind: "" plural: "" - conditions: [] - storedVersions: [] - + conditions: null + storedVersions: null --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: gateways.gateway.networking.k8s.io spec: @@ -253,13 +524,13 @@ spec: - jsonPath: .status.addresses[*].value name: Address type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready + - jsonPath: .status.conditions[?(@.type=="Programmed")].status + name: Programmed type: string - jsonPath: .metadata.creationTimestamp name: Age type: date - name: v1alpha2 + name: v1 schema: openAPIV3Schema: description: Gateway represents an instance of a service-traffic handling @@ -289,25 +560,36 @@ spec: for the address(es) on the \"outside of the Gateway\", that traffic bound for this Gateway will use. This could be the IP address or hostname of an external load balancer or other networking infrastructure, - or some other address that traffic will be sent to. \n The .listener.hostname - field is used to route traffic that has already arrived at the Gateway - to the correct in-cluster destination. \n If no Addresses are specified, - the implementation MAY schedule the Gateway in an implementation-specific - manner, assigning an appropriate set of Addresses. \n The implementation - MUST bind all Listeners to every GatewayAddress that it assigns - to the Gateway and add a corresponding entry in GatewayStatus.Addresses. - \n Support: Core" + or some other address that traffic will be sent to. \n If no Addresses + are specified, the implementation MAY schedule the Gateway in an + implementation-specific manner, assigning an appropriate set of + Addresses. \n The implementation MUST bind all Listeners to every + GatewayAddress that it assigns to the Gateway and add a corresponding + entry in GatewayStatus.Addresses. \n Support: Extended \n " items: description: GatewayAddress describes an address that can be bound to a Gateway. + oneOf: + - properties: + type: + enum: + - IPAddress + value: + anyOf: + - format: ipv4 + - format: ipv6 + - properties: + type: + not: + enum: + - IPAddress properties: type: default: IPAddress description: Type of the address. - enum: - - IPAddress - - Hostname - - NamedAddress + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ type: string value: description: "Value of the address. The validity of the values @@ -319,40 +601,154 @@ spec: required: - value type: object + x-kubernetes-validations: + - message: Hostname value must only contain valid characters (matching + ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): + true' maxItems: 16 type: array + x-kubernetes-validations: + - message: IPAddress values must be unique + rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2, + a2.type == a1.type && a2.value == a1.value) : true )' + - message: Hostname values must be unique + rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2, + a2.type == a1.type && a2.value == a1.value) : true )' gatewayClassName: description: GatewayClassName used for this Gateway. This is the name of a GatewayClass resource. maxLength: 253 minLength: 1 type: string + infrastructure: + description: "Infrastructure defines infrastructure level attributes + about this Gateway instance. \n Support: Core \n " + properties: + annotations: + additionalProperties: + description: AnnotationValue is the value of an annotation in + Gateway API. This is used for validation of maps such as TLS + options. This roughly matches Kubernetes annotation validation, + although the length validation in that case is based on the + entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: "Annotations that SHOULD be applied to any resources + created in response to this Gateway. \n For implementations + creating other Kubernetes objects, this should be the `metadata.annotations` + field on resources. For other implementations, this refers to + any relevant (implementation specific) \"annotations\" concepts. + \n An implementation may chose to add additional implementation-specific + annotations as they see fit. \n Support: Extended" + maxProperties: 8 + type: object + labels: + additionalProperties: + description: AnnotationValue is the value of an annotation in + Gateway API. This is used for validation of maps such as TLS + options. This roughly matches Kubernetes annotation validation, + although the length validation in that case is based on the + entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: "Labels that SHOULD be applied to any resources created + in response to this Gateway. \n For implementations creating + other Kubernetes objects, this should be the `metadata.labels` + field on resources. For other implementations, this refers to + any relevant (implementation specific) \"labels\" concepts. + \n An implementation may chose to add additional implementation-specific + labels as they see fit. \n Support: Extended" + maxProperties: 8 + type: object + type: object listeners: description: "Listeners associated with this Gateway. Listeners define logical endpoints that are bound on this Gateway's addresses. At - least one Listener MUST be specified. \n Each listener in a Gateway - must have a unique combination of Hostname, Port, and Protocol. - \n An implementation MAY group Listeners by Port and then collapse - each group of Listeners into a single Listener if the implementation - determines that the Listeners in the group are \"compatible\". An - implementation MAY also group together and collapse compatible Listeners - belonging to different Gateways. \n For example, an implementation - might consider Listeners to be compatible with each other if all - of the following conditions are met: \n 1. Either each Listener - within the group specifies the \"HTTP\" Protocol or each Listener - within the group specifies either the \"HTTPS\" or \"TLS\" Protocol. - \n 2. Each Listener within the group specifies a Hostname that is - unique within the group. \n 3. As a special case, one Listener - within a group may omit Hostname, in which case this Listener - matches when no other Listener matches. \n If the implementation - does collapse compatible Listeners, the hostname provided in the - incoming client request MUST be matched to a Listener to find the - correct set of Routes. The incoming hostname MUST be matched using - the Hostname field for each Listener in order of most to least specific. - That is, exact matches must be processed before wildcard matches. - \n If this field specifies multiple Listeners that have the same - Port value but are not compatible, the implementation must raise - a \"Conflicted\" condition in the Listener status. \n Support: Core" + least one Listener MUST be specified. \n Each Listener in a set + of Listeners (for example, in a single Gateway) MUST be _distinct_, + in that a traffic flow MUST be able to be assigned to exactly one + listener. (This section uses \"set of Listeners\" rather than \"Listeners + in a single Gateway\" because implementations MAY merge configuration + from multiple Gateways onto a single data plane, and these rules + _also_ apply in that case). \n Practically, this means that each + listener in a set MUST have a unique combination of Port, Protocol, + and, if supported by the protocol, Hostname. \n Some combinations + of port, protocol, and TLS settings are considered Core support + and MUST be supported by implementations based on their targeted + conformance profile: \n HTTP Profile \n 1. HTTPRoute, Port: 80, + Protocol: HTTP 2. HTTPRoute, Port: 443, Protocol: HTTPS, TLS Mode: + Terminate, TLS keypair provided \n TLS Profile \n 1. TLSRoute, Port: + 443, Protocol: TLS, TLS Mode: Passthrough \n \"Distinct\" Listeners + have the following property: \n The implementation can match inbound + requests to a single distinct Listener. When multiple Listeners + share values for fields (for example, two Listeners with the same + Port value), the implementation can match requests to only one of + the Listeners using other Listener fields. \n For example, the following + Listener scenarios are distinct: \n 1. Multiple Listeners with the + same Port that all use the \"HTTP\" Protocol that all have unique + Hostname values. 2. Multiple Listeners with the same Port that use + either the \"HTTPS\" or \"TLS\" Protocol that all have unique Hostname + values. 3. A mixture of \"TCP\" and \"UDP\" Protocol Listeners, + where no Listener with the same Protocol has the same Port value. + \n Some fields in the Listener struct have possible values that + affect whether the Listener is distinct. Hostname is particularly + relevant for HTTP or HTTPS protocols. \n When using the Hostname + value to select between same-Port, same-Protocol Listeners, the + Hostname value must be different on each Listener for the Listener + to be distinct. \n When the Listeners are distinct based on Hostname, + inbound request hostnames MUST match from the most specific to least + specific Hostname values to choose the correct Listener and its + associated set of Routes. \n Exact matches must be processed before + wildcard matches, and wildcard matches must be processed before + fallback (empty Hostname value) matches. For example, `\"foo.example.com\"` + takes precedence over `\"*.example.com\"`, and `\"*.example.com\"` + takes precedence over `\"\"`. \n Additionally, if there are multiple + wildcard entries, more specific wildcard entries must be processed + before less specific wildcard entries. For example, `\"*.foo.example.com\"` + takes precedence over `\"*.example.com\"`. The precise definition + here is that the higher the number of dots in the hostname to the + right of the wildcard character, the higher the precedence. \n The + wildcard character will match any number of characters _and dots_ + to the left, however, so `\"*.example.com\"` will match both `\"foo.bar.example.com\"` + _and_ `\"bar.example.com\"`. \n If a set of Listeners contains Listeners + that are not distinct, then those Listeners are Conflicted, and + the implementation MUST set the \"Conflicted\" condition in the + Listener Status to \"True\". \n Implementations MAY choose to accept + a Gateway with some Conflicted Listeners only if they only accept + the partial Listener set that contains no Conflicted Listeners. + To put this another way, implementations may accept a partial Listener + set only if they throw out *all* the conflicting Listeners. No picking + one of the conflicting listeners as the winner. This also means + that the Gateway must have at least one non-conflicting Listener + in this case, otherwise it violates the requirement that at least + one Listener must be present. \n The implementation MUST set a \"ListenersNotValid\" + condition on the Gateway Status when the Gateway contains Conflicted + Listeners whether or not they accept the Gateway. That Condition + SHOULD clearly indicate in the Message which Listeners are conflicted, + and which are Accepted. Additionally, the Listener status for those + listeners SHOULD indicate which Listeners are conflicted and not + Accepted. \n A Gateway's Listeners are considered \"compatible\" + if: \n 1. They are distinct. 2. The implementation can serve them + in compliance with the Addresses requirement that all Listeners + are available on all assigned addresses. \n Compatible combinations + in Extended support are expected to vary across implementations. + A combination that is compatible for one implementation may not + be compatible for another. \n For example, an implementation that + cannot serve both TCP and UDP listeners on the same address, or + cannot mix HTTPS and generic TLS listens on the same port would + not consider those cases compatible, even though they are distinct. + \n Note that requests SHOULD match at most one Listener. For example, + if Listeners are defined for \"foo.example.com\" and \"*.example.com\", + a request to \"foo.example.com\" SHOULD only be routed using routes + attached to the \"foo.example.com\" Listener (and not the \"*.example.com\" + Listener). This concept is known as \"Listener Isolation\". Implementations + that do not support Listener Isolation MUST clearly document this. + \n Implementations MAY merge separate Gateways onto a single set + of Addresses if all Listeners across all Gateways are compatible. + \n Support: Core" items: description: Listener embodies the concept of a logical endpoint where a Gateway accepts network connections. @@ -369,19 +765,18 @@ spec: determined in order of the following criteria: \n * The most specific match as defined by the Route type. * The oldest Route based on creation timestamp. For example, a Route with - \ a creation timestamp of \"2020-09-08 01:02:03\" is given - precedence over a Route with a creation timestamp of \"2020-09-08 - 01:02:04\". * If everything else is equivalent, the Route - appearing first in alphabetical order (namespace/name) should - be given precedence. For example, foo/bar is given precedence - over foo/baz. \n All valid rules within a Route attached to - this Listener should be implemented. Invalid Route rules can - be ignored (sometimes that will mean the full Route). If a - Route rule transitions from valid to invalid, support for - that Route rule should be dropped to ensure consistency. For - example, even if a filter specified by a Route rule is invalid, - the rest of the rules within that Route should still be supported. - \n Support: Core" + a creation timestamp of \"2020-09-08 01:02:03\" is given precedence + over a Route with a creation timestamp of \"2020-09-08 01:02:04\". + * If everything else is equivalent, the Route appearing first + in alphabetical order (namespace/name) should be given precedence. + For example, foo/bar is given precedence over foo/baz. \n + All valid rules within a Route attached to this Listener should + be implemented. Invalid Route rules can be ignored (sometimes + that will mean the full Route). If a Route rule transitions + from valid to invalid, support for that Route rule should + be dropped to ensure consistency. For example, even if a filter + specified by a Route rule is invalid, the rest of the rules + within that Route should still be supported. \n Support: Core" properties: kinds: description: "Kinds specifies the groups and kinds of Routes @@ -392,7 +787,7 @@ spec: with the application protocol specified in the Listener's Protocol field. If an implementation does not support or recognize this resource type, it MUST set the \"ResolvedRefs\" - condition to False for this Listener with the \"InvalidRoutesRef\" + condition to False for this Listener with the \"InvalidRouteKinds\" reason. \n Support: Core" items: description: RouteGroupKind indicates the group and kind @@ -426,12 +821,12 @@ spec: from: default: Same description: "From indicates where Routes will be selected - for this Gateway. Possible values are: * All: Routes + for this Gateway. Possible values are: \n * All: Routes in all namespaces may be used by this Gateway. * Selector: Routes in namespaces selected by the selector may - be used by this Gateway. * Same: Only Routes in - the same namespace may be used by this Gateway. \n - Support: Core" + be used by this Gateway. * Same: Only Routes in the + same namespace may be used by this Gateway. \n Support: + Core" enum: - All - Selector @@ -487,6 +882,7 @@ spec: requirements are ANDed. type: object type: object + x-kubernetes-map-type: atomic type: object type: object hostname: @@ -498,22 +894,25 @@ spec: following protocols: \n * TLS: The Listener Hostname MUST match the SNI. * HTTP: The Listener Hostname MUST match the Host header of the request. * HTTPS: The Listener Hostname - SHOULD match at both the TLS and HTTP protocol layers as - described above. If an implementation does not ensure that - both the SNI and Host header match the Listener hostname, - \ it MUST clearly document that. \n For HTTPRoute and TLSRoute - resources, there is an interaction with the `spec.hostnames` - array. When both listener and route specify hostnames, there - MUST be an intersection between the values for a Route to - be accepted. For more information, refer to the Route specific - Hostnames documentation. \n Support: Core" + SHOULD match at both the TLS and HTTP protocol layers as described + above. If an implementation does not ensure that both the + SNI and Host header match the Listener hostname, it MUST clearly + document that. \n For HTTPRoute and TLSRoute resources, there + is an interaction with the `spec.hostnames` array. When both + listener and route specify hostnames, there MUST be an intersection + between the values for a Route to be accepted. For more information, + refer to the Route specific Hostnames documentation. \n Hostnames + that are prefixed with a wildcard label (`*.`) are interpreted + as a suffix match. That means that a match for `*.example.com` + would match both `test.example.com`, and `foo.test.example.com`, + but not `example.com`. \n Support: Core" maxLength: 253 minLength: 1 pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string name: - description: "Name is the name of the Listener. \n Support: - Core" + description: "Name is the name of the Listener. This name MUST + be unique within a Gateway. \n Support: Core" maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -553,18 +952,19 @@ spec: MAY choose to support attaching multiple certificates to a Listener, but this behavior is implementation-specific. \n References to a resource in different namespace are - invalid UNLESS there is a ReferencePolicy in the target + invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. - If a ReferencePolicy does not allow this reference, the + If a ReferenceGrant does not allow this reference, the \"ResolvedRefs\" condition MUST be set to False for this - listener with the \"InvalidCertificateRef\" reason. \n - This field is required to have at least one element when - the mode is set to \"Terminate\" (default) and is optional + listener with the \"RefNotPermitted\" reason. \n This + field is required to have at least one element when the + mode is set to \"Terminate\" (default) and is optional otherwise. \n CertificateRefs can reference to standard Kubernetes resources, i.e. Secret, or implementation-specific custom resources. \n Support: Core - A single reference - to a Kubernetes Secret \n Support: Implementation-specific - (More than one reference or other resource types)" + to a Kubernetes Secret of type kubernetes.io/tls \n Support: + Implementation-specific (More than one reference or other + resource types)" items: description: "SecretObjectReference identifies an API object including its namespace, defaulting to Secret. @@ -578,15 +978,15 @@ spec: group: default: "" description: Group is the group of the referent. For - example, "networking.k8s.io". When unspecified (empty - string), core API group is inferred. + example, "gateway.networking.k8s.io". When unspecified + or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Secret description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". + "Secret". maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ @@ -597,12 +997,13 @@ spec: minLength: 1 type: string namespace: - description: "Namespace is the namespace of the backend. - When unspecified, the local namespace is inferred. - \n Note that when a namespace is specified, a ReferencePolicy + description: "Namespace is the namespace of the referenced + object. When unspecified, the local namespace is + inferred. \n Note that when a namespace different + than the local namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. - See the ReferencePolicy documentation for details. + See the ReferenceGrant documentation for details. \n Support: Core" maxLength: 63 minLength: 1 @@ -618,13 +1019,13 @@ spec: description: "Mode defines the TLS behavior for the TLS session initiated by the client. There are two possible modes: \n - Terminate: The TLS session between the downstream - client and the Gateway is terminated at the Gateway. - This mode requires certificateRefs to be set and contain - at least one element. - Passthrough: The TLS session is - NOT terminated by the Gateway. This implies that the - Gateway can't decipher the TLS stream except for the - ClientHello message of the TLS protocol. CertificateRefs - field is ignored in this mode. \n Support: Core" + client and the Gateway is terminated at the Gateway. This + mode requires certificateRefs to be set and contain at + least one element. - Passthrough: The TLS session is NOT + terminated by the Gateway. This implies that the Gateway + can't decipher the TLS stream except for the ClientHello + message of the TLS protocol. CertificateRefs field is + ignored in this mode. \n Support: Core" enum: - Terminate - Passthrough @@ -651,6 +1052,11 @@ spec: maxProperties: 16 type: object type: object + x-kubernetes-validations: + - message: certificateRefs must be specified when TLSModeType + is Terminate + rule: 'self.mode == ''Terminate'' ? size(self.certificateRefs) + > 0 : true' required: - name - port @@ -662,6 +1068,24 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map + x-kubernetes-validations: + - message: tls must be specified for protocols ['HTTPS', 'TLS'] + rule: 'self.all(l, l.protocol in [''HTTPS'', ''TLS''] ? has(l.tls) + : true)' + - message: tls must not be specified for protocols ['HTTP', 'TCP', + 'UDP'] + rule: 'self.all(l, l.protocol in [''HTTP'', ''TCP'', ''UDP''] ? + !has(l.tls) : true)' + - message: hostname must not be specified for protocols ['TCP', 'UDP'] + rule: 'self.all(l, l.protocol in [''TCP'', ''UDP''] ? (!has(l.hostname) + || l.hostname == '''') : true)' + - message: Listener name must be unique within the Gateway + rule: self.all(l1, self.exists_one(l2, l1.name == l2.name)) + - message: Combination of port, protocol and hostname must be unique + for each listener + rule: 'self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol + == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname + == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))' required: - gatewayClassName - listeners @@ -671,27 +1095,47 @@ spec: conditions: - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller - reason: NotReconciled + reason: Pending status: Unknown - type: Scheduled + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed description: Status defines the current state of Gateway. properties: addresses: - description: Addresses lists the IP addresses that have actually been - bound to the Gateway. These addresses may differ from the addresses - in the Spec, e.g. if the Gateway automatically assigns an address - from a reserved pool. + description: "Addresses lists the network addresses that have been + bound to the Gateway. \n This list may differ from the addresses + provided in the spec under some conditions: \n * no addresses are + specified, all addresses are dynamically assigned * a combination + of specified and dynamic addresses are assigned * a specified address + was unusable (e.g. already in use) \n " items: - description: GatewayAddress describes an address that can be bound - to a Gateway. + description: GatewayStatusAddress describes a network address that + is bound to a Gateway. + oneOf: + - properties: + type: + enum: + - IPAddress + value: + anyOf: + - format: ipv4 + - format: ipv6 + - properties: + type: + not: + enum: + - IPAddress properties: type: default: IPAddress description: Type of the address. - enum: - - IPAddress - - Hostname - - NamedAddress + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ type: string value: description: "Value of the address. The validity of the values @@ -703,32 +1147,41 @@ spec: required: - value type: object + x-kubernetes-validations: + - message: Hostname value must only contain valid characters (matching + ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): + true' maxItems: 16 type: array conditions: default: - lastTransitionTime: "1970-01-01T00:00:00Z" message: Waiting for controller - reason: NotReconciled + reason: Pending status: Unknown - type: Scheduled + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed description: "Conditions describe the current conditions of the Gateway. \n Implementations should prefer to express Gateway conditions using the `GatewayConditionType` and `GatewayConditionReason` constants so that operators and tools can converge on a common vocabulary - to describe Gateway state. \n Known condition types are: \n * \"Scheduled\" - * \"Ready\"" + to describe Gateway state. \n Known condition types are: \n * \"Accepted\" + * \"Programmed\" * \"Ready\"" items: description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, - type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: - \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // +listMapKey=type - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" properties: lastTransitionTime: description: lastTransitionTime is the last time the condition @@ -797,8 +1250,23 @@ spec: description: ListenerStatus is the status associated with a Listener. properties: attachedRoutes: - description: AttachedRoutes represents the total number of Routes - that have been successfully attached to this Listener. + description: "AttachedRoutes represents the total number of + Routes that have been successfully attached to this Listener. + \n Successful attachment of a Route to a Listener is based + solely on the combination of the AllowedRoutes field on the + corresponding Listener and the Route's ParentRefs field. A + Route is successfully attached to a Listener when it is selected + by the Listener's AllowedRoutes field AND the Route has a + valid ParentRef selecting the whole Gateway resource or a + specific Listener as a parent resource (more detail on attachment + semantics can be found in the documentation on the various + Route kinds ParentRefs fields). Listener or Route status does + not impact successful attachment, i.e. the AttachedRoutes + field count MUST be set for Listeners with condition Accepted: + false and MUST count successfully attached Routes that may + themselves have Accepted: false conditions. \n Uses for this + field include troubleshooting Route attachment and measuring + blast radius/impact of changes to a Listener." format: int32 type: integer conditions: @@ -808,14 +1276,902 @@ spec: description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path - .status.conditions. For example, type FooStatus struct{ - \ // Represents the observations of a foo's current state. - \ // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // - +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" + .status.conditions. For example, \n type FooStatus struct{ + // Represents the observations of a foo's current state. + // Known .status.conditions.type are: \"Available\", \"Progressing\", + and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields + }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + name: + description: Name is the name of the Listener that this status + corresponds to. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + supportedKinds: + description: "SupportedKinds is the list indicating the Kinds + supported by this listener. This MUST represent the kinds + an implementation supports for that Listener configuration. + \n If kinds are specified in Spec that are not supported, + they MUST NOT appear in this list and an implementation MUST + set the \"ResolvedRefs\" condition to \"False\" with the \"InvalidRouteKinds\" + reason. If both valid and invalid Route kinds are specified, + the implementation MUST reference the valid Route kinds that + have been specified." + items: + description: RouteGroupKind indicates the group and kind of + a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + required: + - attachedRoutes + - conditions + - name + - supportedKinds + type: object + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.gatewayClassName + name: Class + type: string + - jsonPath: .status.addresses[*].value + name: Address + type: string + - jsonPath: .status.conditions[?(@.type=="Programmed")].status + name: Programmed + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: Gateway represents an instance of a service-traffic handling + infrastructure by binding Listeners to a set of IP addresses. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of Gateway. + properties: + addresses: + description: "Addresses requested for this Gateway. This is optional + and behavior can depend on the implementation. If a value is set + in the spec and the requested address is invalid or unavailable, + the implementation MUST indicate this in the associated entry in + GatewayStatus.Addresses. \n The Addresses field represents a request + for the address(es) on the \"outside of the Gateway\", that traffic + bound for this Gateway will use. This could be the IP address or + hostname of an external load balancer or other networking infrastructure, + or some other address that traffic will be sent to. \n If no Addresses + are specified, the implementation MAY schedule the Gateway in an + implementation-specific manner, assigning an appropriate set of + Addresses. \n The implementation MUST bind all Listeners to every + GatewayAddress that it assigns to the Gateway and add a corresponding + entry in GatewayStatus.Addresses. \n Support: Extended \n " + items: + description: GatewayAddress describes an address that can be bound + to a Gateway. + oneOf: + - properties: + type: + enum: + - IPAddress + value: + anyOf: + - format: ipv4 + - format: ipv6 + - properties: + type: + not: + enum: + - IPAddress + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: "Value of the address. The validity of the values + will depend on the type and support by the controller. \n + Examples: `1.2.3.4`, `128::1`, `my-ip-address`." + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + x-kubernetes-validations: + - message: Hostname value must only contain valid characters (matching + ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): + true' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: IPAddress values must be unique + rule: 'self.all(a1, a1.type == ''IPAddress'' ? self.exists_one(a2, + a2.type == a1.type && a2.value == a1.value) : true )' + - message: Hostname values must be unique + rule: 'self.all(a1, a1.type == ''Hostname'' ? self.exists_one(a2, + a2.type == a1.type && a2.value == a1.value) : true )' + gatewayClassName: + description: GatewayClassName used for this Gateway. This is the name + of a GatewayClass resource. + maxLength: 253 + minLength: 1 + type: string + infrastructure: + description: "Infrastructure defines infrastructure level attributes + about this Gateway instance. \n Support: Core \n " + properties: + annotations: + additionalProperties: + description: AnnotationValue is the value of an annotation in + Gateway API. This is used for validation of maps such as TLS + options. This roughly matches Kubernetes annotation validation, + although the length validation in that case is based on the + entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: "Annotations that SHOULD be applied to any resources + created in response to this Gateway. \n For implementations + creating other Kubernetes objects, this should be the `metadata.annotations` + field on resources. For other implementations, this refers to + any relevant (implementation specific) \"annotations\" concepts. + \n An implementation may chose to add additional implementation-specific + annotations as they see fit. \n Support: Extended" + maxProperties: 8 + type: object + labels: + additionalProperties: + description: AnnotationValue is the value of an annotation in + Gateway API. This is used for validation of maps such as TLS + options. This roughly matches Kubernetes annotation validation, + although the length validation in that case is based on the + entire size of the annotations struct. + maxLength: 4096 + minLength: 0 + type: string + description: "Labels that SHOULD be applied to any resources created + in response to this Gateway. \n For implementations creating + other Kubernetes objects, this should be the `metadata.labels` + field on resources. For other implementations, this refers to + any relevant (implementation specific) \"labels\" concepts. + \n An implementation may chose to add additional implementation-specific + labels as they see fit. \n Support: Extended" + maxProperties: 8 + type: object + type: object + listeners: + description: "Listeners associated with this Gateway. Listeners define + logical endpoints that are bound on this Gateway's addresses. At + least one Listener MUST be specified. \n Each Listener in a set + of Listeners (for example, in a single Gateway) MUST be _distinct_, + in that a traffic flow MUST be able to be assigned to exactly one + listener. (This section uses \"set of Listeners\" rather than \"Listeners + in a single Gateway\" because implementations MAY merge configuration + from multiple Gateways onto a single data plane, and these rules + _also_ apply in that case). \n Practically, this means that each + listener in a set MUST have a unique combination of Port, Protocol, + and, if supported by the protocol, Hostname. \n Some combinations + of port, protocol, and TLS settings are considered Core support + and MUST be supported by implementations based on their targeted + conformance profile: \n HTTP Profile \n 1. HTTPRoute, Port: 80, + Protocol: HTTP 2. HTTPRoute, Port: 443, Protocol: HTTPS, TLS Mode: + Terminate, TLS keypair provided \n TLS Profile \n 1. TLSRoute, Port: + 443, Protocol: TLS, TLS Mode: Passthrough \n \"Distinct\" Listeners + have the following property: \n The implementation can match inbound + requests to a single distinct Listener. When multiple Listeners + share values for fields (for example, two Listeners with the same + Port value), the implementation can match requests to only one of + the Listeners using other Listener fields. \n For example, the following + Listener scenarios are distinct: \n 1. Multiple Listeners with the + same Port that all use the \"HTTP\" Protocol that all have unique + Hostname values. 2. Multiple Listeners with the same Port that use + either the \"HTTPS\" or \"TLS\" Protocol that all have unique Hostname + values. 3. A mixture of \"TCP\" and \"UDP\" Protocol Listeners, + where no Listener with the same Protocol has the same Port value. + \n Some fields in the Listener struct have possible values that + affect whether the Listener is distinct. Hostname is particularly + relevant for HTTP or HTTPS protocols. \n When using the Hostname + value to select between same-Port, same-Protocol Listeners, the + Hostname value must be different on each Listener for the Listener + to be distinct. \n When the Listeners are distinct based on Hostname, + inbound request hostnames MUST match from the most specific to least + specific Hostname values to choose the correct Listener and its + associated set of Routes. \n Exact matches must be processed before + wildcard matches, and wildcard matches must be processed before + fallback (empty Hostname value) matches. For example, `\"foo.example.com\"` + takes precedence over `\"*.example.com\"`, and `\"*.example.com\"` + takes precedence over `\"\"`. \n Additionally, if there are multiple + wildcard entries, more specific wildcard entries must be processed + before less specific wildcard entries. For example, `\"*.foo.example.com\"` + takes precedence over `\"*.example.com\"`. The precise definition + here is that the higher the number of dots in the hostname to the + right of the wildcard character, the higher the precedence. \n The + wildcard character will match any number of characters _and dots_ + to the left, however, so `\"*.example.com\"` will match both `\"foo.bar.example.com\"` + _and_ `\"bar.example.com\"`. \n If a set of Listeners contains Listeners + that are not distinct, then those Listeners are Conflicted, and + the implementation MUST set the \"Conflicted\" condition in the + Listener Status to \"True\". \n Implementations MAY choose to accept + a Gateway with some Conflicted Listeners only if they only accept + the partial Listener set that contains no Conflicted Listeners. + To put this another way, implementations may accept a partial Listener + set only if they throw out *all* the conflicting Listeners. No picking + one of the conflicting listeners as the winner. This also means + that the Gateway must have at least one non-conflicting Listener + in this case, otherwise it violates the requirement that at least + one Listener must be present. \n The implementation MUST set a \"ListenersNotValid\" + condition on the Gateway Status when the Gateway contains Conflicted + Listeners whether or not they accept the Gateway. That Condition + SHOULD clearly indicate in the Message which Listeners are conflicted, + and which are Accepted. Additionally, the Listener status for those + listeners SHOULD indicate which Listeners are conflicted and not + Accepted. \n A Gateway's Listeners are considered \"compatible\" + if: \n 1. They are distinct. 2. The implementation can serve them + in compliance with the Addresses requirement that all Listeners + are available on all assigned addresses. \n Compatible combinations + in Extended support are expected to vary across implementations. + A combination that is compatible for one implementation may not + be compatible for another. \n For example, an implementation that + cannot serve both TCP and UDP listeners on the same address, or + cannot mix HTTPS and generic TLS listens on the same port would + not consider those cases compatible, even though they are distinct. + \n Note that requests SHOULD match at most one Listener. For example, + if Listeners are defined for \"foo.example.com\" and \"*.example.com\", + a request to \"foo.example.com\" SHOULD only be routed using routes + attached to the \"foo.example.com\" Listener (and not the \"*.example.com\" + Listener). This concept is known as \"Listener Isolation\". Implementations + that do not support Listener Isolation MUST clearly document this. + \n Implementations MAY merge separate Gateways onto a single set + of Addresses if all Listeners across all Gateways are compatible. + \n Support: Core" + items: + description: Listener embodies the concept of a logical endpoint + where a Gateway accepts network connections. + properties: + allowedRoutes: + default: + namespaces: + from: Same + description: "AllowedRoutes defines the types of routes that + MAY be attached to a Listener and the trusted namespaces where + those Route resources MAY be present. \n Although a client + request may match multiple route rules, only one rule may + ultimately receive the request. Matching precedence MUST be + determined in order of the following criteria: \n * The most + specific match as defined by the Route type. * The oldest + Route based on creation timestamp. For example, a Route with + a creation timestamp of \"2020-09-08 01:02:03\" is given precedence + over a Route with a creation timestamp of \"2020-09-08 01:02:04\". + * If everything else is equivalent, the Route appearing first + in alphabetical order (namespace/name) should be given precedence. + For example, foo/bar is given precedence over foo/baz. \n + All valid rules within a Route attached to this Listener should + be implemented. Invalid Route rules can be ignored (sometimes + that will mean the full Route). If a Route rule transitions + from valid to invalid, support for that Route rule should + be dropped to ensure consistency. For example, even if a filter + specified by a Route rule is invalid, the rest of the rules + within that Route should still be supported. \n Support: Core" + properties: + kinds: + description: "Kinds specifies the groups and kinds of Routes + that are allowed to bind to this Gateway Listener. When + unspecified or empty, the kinds of Routes selected are + determined using the Listener protocol. \n A RouteGroupKind + MUST correspond to kinds of Routes that are compatible + with the application protocol specified in the Listener's + Protocol field. If an implementation does not support + or recognize this resource type, it MUST set the \"ResolvedRefs\" + condition to False for this Listener with the \"InvalidRouteKinds\" + reason. \n Support: Core" + items: + description: RouteGroupKind indicates the group and kind + of a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + namespaces: + default: + from: Same + description: "Namespaces indicates namespaces from which + Routes may be attached to this Listener. This is restricted + to the namespace of this Gateway by default. \n Support: + Core" + properties: + from: + default: Same + description: "From indicates where Routes will be selected + for this Gateway. Possible values are: \n * All: Routes + in all namespaces may be used by this Gateway. * Selector: + Routes in namespaces selected by the selector may + be used by this Gateway. * Same: Only Routes in the + same namespace may be used by this Gateway. \n Support: + Core" + enum: + - All + - Selector + - Same + type: string + selector: + description: "Selector must be specified when From is + set to \"Selector\". In that case, only Routes in + Namespaces matching this Selector will be selected + by this Gateway. This field is ignored for other values + of \"From\". \n Support: Core" + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + type: object + type: object + hostname: + description: "Hostname specifies the virtual hostname to match + for protocol types that define this concept. When unspecified, + all hostnames are matched. This field is ignored for protocols + that don't require hostname based matching. \n Implementations + MUST apply Hostname matching appropriately for each of the + following protocols: \n * TLS: The Listener Hostname MUST + match the SNI. * HTTP: The Listener Hostname MUST match the + Host header of the request. * HTTPS: The Listener Hostname + SHOULD match at both the TLS and HTTP protocol layers as described + above. If an implementation does not ensure that both the + SNI and Host header match the Listener hostname, it MUST clearly + document that. \n For HTTPRoute and TLSRoute resources, there + is an interaction with the `spec.hostnames` array. When both + listener and route specify hostnames, there MUST be an intersection + between the values for a Route to be accepted. For more information, + refer to the Route specific Hostnames documentation. \n Hostnames + that are prefixed with a wildcard label (`*.`) are interpreted + as a suffix match. That means that a match for `*.example.com` + would match both `test.example.com`, and `foo.test.example.com`, + but not `example.com`. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + name: + description: "Name is the name of the Listener. This name MUST + be unique within a Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + port: + description: "Port is the network port. Multiple listeners may + use the same port, subject to the Listener compatibility rules. + \n Support: Core" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + description: "Protocol specifies the network protocol this listener + expects to receive. \n Support: Core" + maxLength: 255 + minLength: 1 + pattern: ^[a-zA-Z0-9]([-a-zSA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$ + type: string + tls: + description: "TLS is the TLS configuration for the Listener. + This field is required if the Protocol field is \"HTTPS\" + or \"TLS\". It is invalid to set this field if the Protocol + field is \"HTTP\", \"TCP\", or \"UDP\". \n The association + of SNIs to Certificate defined in GatewayTLSConfig is defined + based on the Hostname field for this listener. \n The GatewayClass + MUST use the longest matching SNI out of all available certificates + for any TLS handshake. \n Support: Core" + properties: + certificateRefs: + description: "CertificateRefs contains a series of references + to Kubernetes objects that contains TLS certificates and + private keys. These certificates are used to establish + a TLS handshake for requests that match the hostname of + the associated listener. \n A single CertificateRef to + a Kubernetes Secret has \"Core\" support. Implementations + MAY choose to support attaching multiple certificates + to a Listener, but this behavior is implementation-specific. + \n References to a resource in different namespace are + invalid UNLESS there is a ReferenceGrant in the target + namespace that allows the certificate to be attached. + If a ReferenceGrant does not allow this reference, the + \"ResolvedRefs\" condition MUST be set to False for this + listener with the \"RefNotPermitted\" reason. \n This + field is required to have at least one element when the + mode is set to \"Terminate\" (default) and is optional + otherwise. \n CertificateRefs can reference to standard + Kubernetes resources, i.e. Secret, or implementation-specific + custom resources. \n Support: Core - A single reference + to a Kubernetes Secret of type kubernetes.io/tls \n Support: + Implementation-specific (More than one reference or other + resource types)" + items: + description: "SecretObjectReference identifies an API + object including its namespace, defaulting to Secret. + \n The API object must be valid in the cluster; the + Group and Kind must be registered in the cluster for + this reference to be valid. \n References to objects + with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate + Conditions set on the containing object." + properties: + group: + default: "" + description: Group is the group of the referent. For + example, "gateway.networking.k8s.io". When unspecified + or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Secret + description: Kind is kind of the referent. For example + "Secret". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referenced + object. When unspecified, the local namespace is + inferred. \n Note that when a namespace different + than the local namespace is specified, a ReferenceGrant + object is required in the referent namespace to + allow that namespace's owner to accept the reference. + See the ReferenceGrant documentation for details. + \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - name + type: object + maxItems: 64 + type: array + mode: + default: Terminate + description: "Mode defines the TLS behavior for the TLS + session initiated by the client. There are two possible + modes: \n - Terminate: The TLS session between the downstream + client and the Gateway is terminated at the Gateway. This + mode requires certificateRefs to be set and contain at + least one element. - Passthrough: The TLS session is NOT + terminated by the Gateway. This implies that the Gateway + can't decipher the TLS stream except for the ClientHello + message of the TLS protocol. CertificateRefs field is + ignored in this mode. \n Support: Core" + enum: + - Terminate + - Passthrough + type: string + options: + additionalProperties: + description: AnnotationValue is the value of an annotation + in Gateway API. This is used for validation of maps + such as TLS options. This roughly matches Kubernetes + annotation validation, although the length validation + in that case is based on the entire size of the annotations + struct. + maxLength: 4096 + minLength: 0 + type: string + description: "Options are a list of key/value pairs to enable + extended TLS configuration for each implementation. For + example, configuring the minimum TLS version or supported + cipher suites. \n A set of common keys MAY be defined + by the API in the future. To avoid any ambiguity, implementation-specific + definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`. + Un-prefixed names are reserved for key names defined by + Gateway API. \n Support: Implementation-specific" + maxProperties: 16 + type: object + type: object + x-kubernetes-validations: + - message: certificateRefs must be specified when TLSModeType + is Terminate + rule: 'self.mode == ''Terminate'' ? size(self.certificateRefs) + > 0 : true' + required: + - name + - port + - protocol + type: object + maxItems: 64 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + x-kubernetes-validations: + - message: tls must be specified for protocols ['HTTPS', 'TLS'] + rule: 'self.all(l, l.protocol in [''HTTPS'', ''TLS''] ? has(l.tls) + : true)' + - message: tls must not be specified for protocols ['HTTP', 'TCP', + 'UDP'] + rule: 'self.all(l, l.protocol in [''HTTP'', ''TCP'', ''UDP''] ? + !has(l.tls) : true)' + - message: hostname must not be specified for protocols ['TCP', 'UDP'] + rule: 'self.all(l, l.protocol in [''TCP'', ''UDP''] ? (!has(l.hostname) + || l.hostname == '''') : true)' + - message: Listener name must be unique within the Gateway + rule: self.all(l1, self.exists_one(l2, l1.name == l2.name)) + - message: Combination of port, protocol and hostname must be unique + for each listener + rule: 'self.all(l1, self.exists_one(l2, l1.port == l2.port && l1.protocol + == l2.protocol && (has(l1.hostname) && has(l2.hostname) ? l1.hostname + == l2.hostname : !has(l1.hostname) && !has(l2.hostname))))' + required: + - gatewayClassName + - listeners + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed + description: Status defines the current state of Gateway. + properties: + addresses: + description: "Addresses lists the network addresses that have been + bound to the Gateway. \n This list may differ from the addresses + provided in the spec under some conditions: \n * no addresses are + specified, all addresses are dynamically assigned * a combination + of specified and dynamic addresses are assigned * a specified address + was unusable (e.g. already in use) \n " + items: + description: GatewayStatusAddress describes a network address that + is bound to a Gateway. + oneOf: + - properties: + type: + enum: + - IPAddress + value: + anyOf: + - format: ipv4 + - format: ipv6 + - properties: + type: + not: + enum: + - IPAddress + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: "Value of the address. The validity of the values + will depend on the type and support by the controller. \n + Examples: `1.2.3.4`, `128::1`, `my-ip-address`." + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + x-kubernetes-validations: + - message: Hostname value must only contain valid characters (matching + ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$) + rule: 'self.type == ''Hostname'' ? self.value.matches(r"""^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"""): + true' + maxItems: 16 + type: array + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed + description: "Conditions describe the current conditions of the Gateway. + \n Implementations should prefer to express Gateway conditions using + the `GatewayConditionType` and `GatewayConditionReason` constants + so that operators and tools can converge on a common vocabulary + to describe Gateway state. \n Known condition types are: \n * \"Accepted\" + * \"Programmed\" * \"Ready\"" + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + listeners: + description: Listeners provide status for each unique listener port + defined in the Spec. + items: + description: ListenerStatus is the status associated with a Listener. + properties: + attachedRoutes: + description: "AttachedRoutes represents the total number of + Routes that have been successfully attached to this Listener. + \n Successful attachment of a Route to a Listener is based + solely on the combination of the AllowedRoutes field on the + corresponding Listener and the Route's ParentRefs field. A + Route is successfully attached to a Listener when it is selected + by the Listener's AllowedRoutes field AND the Route has a + valid ParentRef selecting the whole Gateway resource or a + specific Listener as a parent resource (more detail on attachment + semantics can be found in the documentation on the various + Route kinds ParentRefs fields). Listener or Route status does + not impact successful attachment, i.e. the AttachedRoutes + field count MUST be set for Listeners with condition Accepted: + false and MUST count successfully attached Routes that may + themselves have Accepted: false conditions. \n Uses for this + field include troubleshooting Route attachment and measuring + blast radius/impact of changes to a Listener." + format: int32 + type: integer + conditions: + description: Conditions describe the current condition of this + listener. + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, \n type FooStatus struct{ + // Represents the observations of a foo's current state. + // Known .status.conditions.type are: \"Available\", \"Progressing\", + and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields + }" properties: lastTransitionTime: description: lastTransitionTime is the last time the condition @@ -941,26 +2297,27 @@ status: acceptedNames: kind: "" plural: "" - conditions: [] - storedVersions: [] - + conditions: null + storedVersions: null --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental creationTimestamp: null - name: httproutes.gateway.networking.k8s.io + name: grpcroutes.gateway.networking.k8s.io spec: group: gateway.networking.k8s.io names: categories: - gateway-api - kind: HTTPRoute - listKind: HTTPRouteList - plural: httproutes - singular: httproute + kind: GRPCRoute + listKind: GRPCRouteList + plural: grpcroutes + singular: grpcroute scope: Namespaced versions: - additionalPrinterColumns: @@ -973,10 +2330,27 @@ spec: name: v1alpha2 schema: openAPIV3Schema: - description: HTTPRoute provides a way to route HTTP requests. This includes - the capability to match requests by hostname, path, header, or query param. - Filters can be used to specify additional processing steps. Backends specify - where matching requests should be routed. + description: "GRPCRoute provides a way to route gRPC requests. This includes + the capability to match requests by hostname, gRPC service, gRPC method, + or HTTP/2 header. Filters can be used to specify additional processing steps. + Backends specify where matching requests will be routed. \n GRPCRoute falls + under extended support within the Gateway API. Within the following specification, + the word \"MUST\" indicates that an implementation supporting GRPCRoute + must conform to the indicated requirement, but an implementation not supporting + this route type need not follow the requirement unless explicitly indicated. + \n Implementations supporting `GRPCRoute` with the `HTTPS` `ProtocolType` + MUST accept HTTP/2 connections without an initial upgrade from HTTP/1.1, + i.e. via ALPN. If the implementation does not support this, then it MUST + set the \"Accepted\" condition to \"False\" for the affected listener with + a reason of \"UnsupportedProtocol\". Implementations MAY also accept HTTP/2 + connections with an upgrade from HTTP/1. \n Implementations supporting `GRPCRoute` + with the `HTTP` `ProtocolType` MUST support HTTP/2 over cleartext TCP (h2c, + https://www.rfc-editor.org/rfc/rfc7540#section-3.1) without an initial upgrade + from HTTP/1.1, i.e. with prior knowledge (https://www.rfc-editor.org/rfc/rfc7540#section-3.4). + If the implementation does not support this, then it MUST set the \"Accepted\" + condition to \"False\" for the affected listener with a reason of \"UnsupportedProtocol\". + Implementations MAY also accept HTTP/2 connections with an upgrade from + HTTP/1, i.e. without prior knowledge." properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -991,39 +2365,52 @@ spec: metadata: type: object spec: - description: Spec defines the desired state of HTTPRoute. + description: Spec defines the desired state of GRPCRoute. properties: hostnames: - description: "Hostnames defines a set of hostname that should match - against the HTTP Host header to select a HTTPRoute to process the - request. This matches the RFC 1123 definition of a hostname with - 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname may - be prefixed with a wildcard label (`*.`). The wildcard label - must appear by itself as the first label. \n If a hostname is specified - by both the Listener and HTTPRoute, there must be at least one intersecting - hostname for the HTTPRoute to be attached to the Listener. For example: + description: "Hostnames defines a set of hostnames to match against + the GRPC Host header to select a GRPCRoute to process the request. + This matches the RFC 1123 definition of a hostname with 2 notable + exceptions: \n 1. IPs are not allowed. 2. A hostname may be prefixed + with a wildcard label (`*.`). The wildcard label MUST appear by + itself as the first label. \n If a hostname is specified by both + the Listener and GRPCRoute, there MUST be at least one intersecting + hostname for the GRPCRoute to be attached to the Listener. For example: \n * A Listener with `test.example.com` as the hostname matches - HTTPRoutes that have either not specified any hostnames, or have - specified at least one of `test.example.com` or `*.example.com`. - * A Listener with `*.example.com` as the hostname matches HTTPRoutes - \ that have either not specified any hostnames or have specified - at least one hostname that matches the Listener hostname. For - example, `test.example.com` and `*.example.com` would both match. - On the other hand, `example.com` and `test.example.net` would - not match. \n If both the Listener and HTTPRoute have specified - hostnames, any HTTPRoute hostnames that do not match the Listener - hostname MUST be ignored. For example, if a Listener specified `*.example.com`, - and the HTTPRoute specified `test.example.com` and `test.example.net`, - `test.example.net` must not be considered for a match. \n If both - the Listener and HTTPRoute have specified hostnames, and none match - with the criteria above, then the HTTPRoute is not accepted. The - implementation must raise an 'Accepted' Condition with a status - of `False` in the corresponding RouteParentStatus. \n Support: Core" + GRPCRoutes that have either not specified any hostnames, or have + specified at least one of `test.example.com` or `*.example.com`. + * A Listener with `*.example.com` as the hostname matches GRPCRoutes + that have either not specified any hostnames or have specified at + least one hostname that matches the Listener hostname. For example, + `test.example.com` and `*.example.com` would both match. On the + other hand, `example.com` and `test.example.net` would not match. + \n Hostnames that are prefixed with a wildcard label (`*.`) are + interpreted as a suffix match. That means that a match for `*.example.com` + would match both `test.example.com`, and `foo.test.example.com`, + but not `example.com`. \n If both the Listener and GRPCRoute have + specified hostnames, any GRPCRoute hostnames that do not match the + Listener hostname MUST be ignored. For example, if a Listener specified + `*.example.com`, and the GRPCRoute specified `test.example.com` + and `test.example.net`, `test.example.net` MUST NOT be considered + for a match. \n If both the Listener and GRPCRoute have specified + hostnames, and none match with the criteria above, then the GRPCRoute + MUST NOT be accepted by the implementation. The implementation MUST + raise an 'Accepted' Condition with a status of `False` in the corresponding + RouteParentStatus. \n If a Route (A) of type HTTPRoute or GRPCRoute + is attached to a Listener and that listener already has another + Route (B) of the other type attached and the intersection of the + hostnames of A and B is non-empty, then the implementation MUST + accept exactly one of these two routes, determined by the following + criteria, in order: \n * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by \"{namespace}/{name}\". + \n The rejected Route MUST raise an 'Accepted' condition with a + status of 'False' in the corresponding RouteParentStatus. \n Support: + Core" items: description: "Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname - may be prefixed with a wildcard label (`*.`). The wildcard label + may be prefixed with a wildcard label (`*.`). The wildcard label must appear by itself as the first label. \n Hostname can be \"precise\" which is a domain name without the terminating dot of a network host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain @@ -1042,40 +2429,76 @@ spec: that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from - Routes of this kind and namespace. \n The only kind of parent resource - with \"Core\" support is Gateway. This API may be extended in the - future to support additional kinds of parent resources such as one - of the route kinds. \n It is invalid to reference an identical parent - more than once. It is valid to reference multiple distinct sections - within the same parent resource, such as 2 Listeners within a Gateway. - \n It is possible to separately reference multiple distinct objects - that may be collapsed by an implementation. For example, some implementations - may choose to merge compatible Gateway Listeners together. If that - is the case, the list of routes attached to those resources should - also be merged." + Routes of this kind and namespace. For Services, that means the + Service must either be in the same namespace for a \"producer\" + route, or the mesh implementation must support and allow \"consumer\" + routes for the referenced Service. ReferenceGrant is not applicable + for governing ParentRefs to Services - it is not possible to create + a \"producer\" route for a Service in a different namespace from + the Route. \n There are two kinds of parent resources with \"Core\" + support: \n * Gateway (Gateway conformance profile) * Service (Mesh + conformance profile, experimental, ClusterIP Services only) This + API may be extended in the future to support additional kinds of + parent resources. \n ParentRefs must be _distinct_. This means either + that: \n * They select different objects. If this is the case, + then parentRef entries are distinct. In terms of fields, this means + that the multi-part key defined by `group`, `kind`, `namespace`, + and `name` must be unique across all parentRef entries in the Route. + * They do not select different objects, but for each optional field + used, each ParentRef that selects the same object must set the same + set of optional fields to different values. If one ParentRef sets + a combination of optional fields, all must set the same combination. + \n Some examples: \n * If one ParentRef sets `sectionName`, all + ParentRefs referencing the same object must also set `sectionName`. + * If one ParentRef sets `port`, all ParentRefs referencing the same + object must also set `port`. * If one ParentRef sets `sectionName` + and `port`, all ParentRefs referencing the same object must also + set `sectionName` and `port`. \n It is possible to separately reference + multiple distinct objects that may be collapsed by an implementation. + For example, some implementations may choose to merge compatible + Gateway Listeners together. If that is the case, the list of routes + attached to those resources should also be merged. \n Note that + for ParentRefs that cross namespace boundaries, there are specific + rules. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For + example, Gateway has the AllowedRoutes field, and ReferenceGrant + provides a generic way to enable other kinds of cross-namespace + reference. \n ParentRefs from a Route to a Service in the same + namespace are \"producer\" routes, which apply default routing rules + to inbound connections from any namespace to the Service. \n ParentRefs + from a Route to a Service in a different namespace are \"consumer\" + routes, and these routing rules are only applied to outbound connections + originating from the same namespace as the Route, for which the + intended destination of the connections are a Service targeted as + a ParentRef of the Route. \n " items: - description: "ParentRef identifies an API object (usually a Gateway) - that can be considered a parent of this resource (usually a route). - The only kind of parent resource with \"Core\" support is Gateway. - This API may be extended in the future to support additional kinds - of parent resources, such as HTTPRoute. \n The API object must - be valid in the cluster; the Group and Kind must be registered - in the cluster for this reference to be valid. \n References to - objects with invalid Group and Kind are not valid, and must be - rejected by the implementation, with appropriate Conditions set - on the containing object." + description: "ParentReference identifies an API object (usually + a Gateway) that can be considered a parent of this resource (usually + a route). There are two kinds of parent resources with \"Core\" + support: \n * Gateway (Gateway conformance profile) * Service + (Mesh conformance profile, experimental, ClusterIP Services only) + \n This API may be extended in the future to support additional + kinds of parent resources. \n The API object must be valid in + the cluster; the Group and Kind must be registered in the cluster + for this reference to be valid." properties: group: default: gateway.networking.k8s.io - description: "Group is the group of the referent. \n Support: + description: "Group is the group of the referent. When unspecified, + \"gateway.networking.k8s.io\" is inferred. To set the core + API group (such as for a \"Service\" kind referent), Group + must be explicitly set to \"\" (empty string). \n Support: Core" maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Gateway - description: "Kind is kind of the referent. \n Support: Core - (Gateway) Support: Custom (Other Resources)" + description: "Kind is kind of the referent. \n There are two + kinds of parent resources with \"Core\" support: \n * Gateway + (Gateway conformance profile) * Service (Mesh conformance + profile, experimental, ClusterIP Services only) \n Support + for other resources is Implementation-Specific." maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ @@ -1088,29 +2511,79 @@ spec: type: string namespace: description: "Namespace is the namespace of the referent. When - unspecified (or empty string), this refers to the local namespace - of the Route. \n Support: Core" + unspecified, this refers to the local namespace of the Route. + \n Note that there are specific rules for ParentRefs which + cross namespace boundaries. Cross-namespace references are + only valid if they are explicitly allowed by something in + the namespace they are referring to. For example: Gateway + has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + \n ParentRefs from a Route to a Service in the same namespace + are \"producer\" routes, which apply default routing rules + to inbound connections from any namespace to the Service. + \n ParentRefs from a Route to a Service in a different namespace + are \"consumer\" routes, and these routing rules are only + applied to outbound connections originating from the same + namespace as the Route, for which the intended destination + of the connections are a Service targeted as a ParentRef of + the Route. \n Support: Core" maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string - sectionName: - description: "SectionName is the name of a section within the - target resource. In the following resources, SectionName is - interpreted as the following: \n * Gateway: Listener Name - \n Implementations MAY choose to support attaching Routes - to other resources. If that is the case, they MUST clearly - document how SectionName is interpreted. \n When unspecified - (empty string), this will reference the entire resource. For - the purpose of status, an attachment is considered successful - if at least one section in the parent resource accepts it. + port: + description: "Port is the network port this Route targets. It + can be interpreted differently based on the type of parent + resource. \n When the parent resource is a Gateway, this targets + all listeners listening on the specified port that also support + this kind of Route(and select this Route). It's not recommended + to set `Port` unless the networking behaviors specified in + a Route must apply to a specific port as opposed to a listener(s) + whose port(s) may be changed. When both Port and SectionName + are specified, the name and port of the selected listener + must match both specified values. \n When the parent resource + is a Service, this targets a specific port in the Service + spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified + values. \n Implementations MAY choose to support other parent + resources. Implementations supporting other types of parent + resources MUST clearly document how/if Port is interpreted. + \n For the purpose of status, an attachment is considered + successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n - Support: Core" + Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match both + specified values. * Service: Port Name. When both Port (experimental) + and SectionName are specified, the name and port of the selected + listener must match both specified values. Note that attaching + Routes to Services as Parents is part of experimental Mesh + support and is not supported for any other purpose. \n Implementations + MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this will + reference the entire resource. For the purpose of status, + an attachment is considered successful if at least one section + in the parent resource accepts it. For example, Gateway listeners + can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept + attachment from the referencing Route, the Route MUST be considered + successfully attached. If no Gateway listeners accept attachment + from this Route, the Route MUST be considered detached from + the Gateway. \n Support: Core" maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -1120,42 +2593,87 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-validations: + - message: sectionName or port must be specified when parentRefs includes + 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ + == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__)) ? ((!has(p1.sectionName) + || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName + == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) + || p2.port == 0)): true))' + - message: sectionName or port must be unique when parentRefs includes + 2 or more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ + == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) + || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName + == '')) || ( has(p1.sectionName) && has(p2.sectionName) && p1.sectionName + == p2.sectionName)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) + || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port + == p2.port)))) rules: - default: - - matches: - - path: - type: PathPrefix - value: / - description: Rules are a list of HTTP matchers, filters and actions. + description: Rules are a list of GRPC matchers, filters and actions. items: - description: HTTPRouteRule defines semantics for matching an HTTP - request based on conditions (matches), processing it (filters), + description: GRPCRouteRule defines the semantics for matching a + gRPC request based on conditions (matches), processing it (filters), and forwarding the request to an API object (backendRefs). properties: backendRefs: - description: "If unspecified or invalid (refers to a non-existent - resource or a Service with no endpoints), the rule performs - no forwarding. If there are also no filters specified that - would result in a response being sent, a HTTP 503 status code - is returned. 503 responses must be sent so that the overall - weight is respected; if an invalid backend is requested to - have 80% of requests, then 80% of requests must get a 503 - instead. \n Support: Core for Kubernetes Service Support: - Custom for any other resource \n Support for weight: Core" + description: "BackendRefs defines the backend(s) where matching + requests should be sent. \n Failure behavior here depends + on how many BackendRefs are specified and how many are invalid. + \n If *all* entries in BackendRefs are invalid, and there + are also no filters specified in this route rule, *all* traffic + which matches this rule MUST receive an `UNAVAILABLE` status. + \n See the GRPCBackendRef definition for the rules about what + makes a single GRPCBackendRef invalid. \n When a GRPCBackendRef + is invalid, `UNAVAILABLE` statuses MUST be returned for requests + that would have otherwise been routed to an invalid backend. + If multiple backends are specified, and some are invalid, + the proportion of requests that would otherwise have been + routed to an invalid backend MUST receive an `UNAVAILABLE` + status. \n For example, if two backends are specified with + equal weights, and one is invalid, 50 percent of traffic MUST + receive an `UNAVAILABLE` status. Implementations may choose + how that 50 percent is determined. \n Support: Core for Kubernetes + Service \n Support: Implementation-specific for any other + resource \n Support for weight: Core" items: - description: HTTPBackendRef defines how a HTTPRoute should - forward an HTTP request. + description: "GRPCBackendRef defines how a GRPCRoute forwards + a gRPC request. \n Note that when a namespace different + than the local namespace is specified, a ReferenceGrant + object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. \n + \n When the BackendRef points to a Kubernetes Service, implementations + SHOULD honor the appProtocol field if it is set for the + target Service Port. \n Implementations supporting appProtocol + SHOULD recognize the Kubernetes Standard Application Protocols + defined in KEP-3726. \n If a Service appProtocol isn't specified, + an implementation MAY infer the backend protocol through + its own means. Implementations MAY infer the protocol from + the Route type referring to the backend Service. \n If a + Route is not able to send traffic to the backend using the + specified protocol then the backend is considered invalid. + Implementations MUST set the \"ResolvedRefs\" condition + to \"False\" with the \"UnsupportedProtocol\" reason. \n + " properties: filters: - description: "Filters defined at this level should be - executed if and only if the request is being forwarded - to the backend defined here. \n Support: Custom (For - broader support of filters, use the Filters field in - HTTPRouteRule.)" + description: "Filters defined at this level MUST be executed + if and only if the request is being forwarded to the + backend defined here. \n Support: Implementation-specific + (For broader support of filters, use the Filters field + in GRPCRouteRule.)" items: - description: HTTPRouteFilter defines processing steps + description: GRPCRouteFilter defines processing steps that must be completed during the request or response - lifecycle. HTTPRouteFilters are meant as an extension + lifecycle. GRPCRouteFilters are meant as an extension point to express processing that may be done in Gateway implementations. Some examples include request or response modification, implementing authentication @@ -1168,12 +2686,15 @@ spec: extension to the \"filter\" behavior. For example, resource \"myroutefilter\" in group \"networking.example.net\"). ExtensionRef MUST NOT be used for core and extended - filters. \n Support: Implementation-specific" + filters. \n Support: Implementation-specific \n + This filter can be used multiple times within + the same rule." properties: group: description: Group is the group of the referent. - For example, "networking.k8s.io". When unspecified - (empty string), core API group is inferred. + For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API + group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string @@ -1203,11 +2724,10 @@ spec: description: "Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated - with the header name. \n Input: GET /foo - HTTP/1.1 my-header: foo \n Config: add: - \ - name: \"my-header\" value: \"bar\" - \n Output: GET /foo HTTP/1.1 my-header: - foo my-header: bar" + with the header name. \n Input: GET /foo HTTP/1.1 + my-header: foo \n Config: add: - name: \"my-header\" + value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 + my-header: foo,bar,baz" items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC @@ -1250,22 +2770,22 @@ spec: of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - \n Input: GET /foo HTTP/1.1 my-header1: - foo my-header2: bar my-header3: baz \n - Config: remove: [\"my-header1\", \"my-header3\"] - \n Output: GET /foo HTTP/1.1 my-header2: - bar" + \n Input: GET /foo HTTP/1.1 my-header1: foo + my-header2: bar my-header3: baz \n Config: + remove: [\"my-header1\", \"my-header3\"] \n + Output: GET /foo HTTP/1.1 my-header2: bar" items: type: string maxItems: 16 type: array + x-kubernetes-list-type: set set: description: "Set overwrites the request with the given header (name, value) before the - action. \n Input: GET /foo HTTP/1.1 my-header: - foo \n Config: set: - name: \"my-header\" - \ value: \"bar\" \n Output: GET /foo - HTTP/1.1 my-header: bar" + action. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: set: - name: \"my-header\" + value: \"bar\" \n Output: GET /foo HTTP/1.1 + my-header: bar" items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC @@ -1307,42 +2827,61 @@ spec: description: "RequestMirror defines a schema for a filter that mirrors requests. Requests are sent to the specified destination, but responses from - that destination are ignored. \n Support: Extended" + that destination are ignored. \n This filter can + be used multiple times within the same rule. Note + that not all implementations will be able to support + mirroring to multiple backends. \n Support: Extended" properties: backendRef: description: "BackendRef references a resource - where mirrored requests are sent. \n If the - referent cannot be found, this BackendRef - is invalid and must be dropped from the Gateway. - The controller must ensure the \"ResolvedRefs\" - condition on the Route status is set to `status: - False` and not configure this backend in the - underlying implementation. \n If there is - a cross-namespace reference to an *existing* - object that is not allowed by a ReferencePolicy, - the controller must ensure the \"ResolvedRefs\" - \ condition on the Route is set to `status: - False`, with the \"RefNotPermitted\" reason - and not configure this backend in the underlying - implementation. \n In either error case, the - Message of the `ResolvedRefs` Condition should - be used to provide more detail about the problem. - \n Support: Extended for Kubernetes Service - Support: Custom for any other resource" + where mirrored requests are sent. \n Mirrored + requests must be sent only to a single destination + endpoint within this BackendRef, irrespective + of how many endpoints are present within this + BackendRef. \n If the referent cannot be found, + this BackendRef is invalid and must be dropped + from the Gateway. The controller must ensure + the \"ResolvedRefs\" condition on the Route + status is set to `status: False` and not configure + this backend in the underlying implementation. + \n If there is a cross-namespace reference + to an *existing* object that is not allowed + by a ReferenceGrant, the controller must ensure + the \"ResolvedRefs\" condition on the Route + is set to `status: False`, with the \"RefNotPermitted\" + reason and not configure this backend in the + underlying implementation. \n In either error + case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about + the problem. \n Support: Extended for Kubernetes + Service \n Support: Implementation-specific + for any other resource" properties: group: default: "" description: Group is the group of the referent. - For example, "networking.k8s.io". When - unspecified (empty string), core API group - is inferred. + For example, "gateway.networking.k8s.io". + When unspecified or empty string, core + API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service - description: Kind is kind of the referent. - For example "HTTPRoute" or "Service". + description: "Kind is the Kubernetes resource + kind of the referent. For example \"Service\". + \n Defaults to \"Service\" when not specified. + \n ExternalName services can refer to + CNAME DNS records that may live outside + of the cluster and as such are difficult + to reason about in terms of conformance. + They also may not be safe to forward to + (see CVE-2021-25740 for more information). + Implementations SHOULD NOT support ExternalName + Services. \n Support: Core (Services with + a type other than ExternalName) \n Support: + Implementation-specific (Services with + type ExternalName)" maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ @@ -1356,10 +2895,11 @@ spec: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n Note that - when a namespace is specified, a ReferencePolicy + when a namespace different than the local + namespace is specified, a ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept - the reference. See the ReferencePolicy + the reference. See the ReferenceGrant documentation for details. \n Support: Core" maxLength: 63 @@ -1370,7 +2910,9 @@ spec: description: Port specifies the destination port number to use for this resource. Port is required when the referent is - a Kubernetes Service. For other resources, + a Kubernetes Service. In this case, the + port number is the service port number, + not the target port. For other resources, destination port might be derived from the referent resource or this field. format: int32 @@ -1380,99 +2922,217 @@ spec: required: - name type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind + == ''Service'') ? has(self.port) : true' required: - backendRef type: object - requestRedirect: - description: "RequestRedirect defines a schema for - a filter that responds to the request with an - HTTP redirection. \n Support: Core" + responseHeaderModifier: + description: "ResponseHeaderModifier defines a schema + for a filter that modifies response headers. \n + Support: Extended" properties: - hostname: - description: "Hostname is the hostname to be - used in the value of the `Location` header - in the response. When empty, the hostname - of the request is used. \n Support: Core" - maxLength: 253 - minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - port: - description: "Port is the port to be used in - the value of the `Location` header in the - response. When empty, port (if specified) - of the request is used. \n Support: Extended" - format: int32 - maximum: 65535 - minimum: 1 - type: integer - scheme: - description: "Scheme is the scheme to be used - in the value of the `Location` header in the - response. When empty, the scheme of the request - is used. \n Support: Extended" - enum: - - http - - https - type: string - statusCode: - default: 302 - description: "StatusCode is the HTTP status - code to be used in response. \n Support: Core" - enum: - - 301 - - 302 - type: integer + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It + appends to any existing values associated + with the header name. \n Input: GET /foo HTTP/1.1 + my-header: foo \n Config: add: - name: \"my-header\" + value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 + my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: "Name is the name of the + HTTP Header to be matched. Name matching + MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an + equivalent name MUST be considered for + a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from + the HTTP request before the action. The value + of Remove is a list of HTTP header names. + Note that the header names are case-insensitive + (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: foo + my-header2: bar my-header3: baz \n Config: + remove: [\"my-header1\", \"my-header3\"] \n + Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with + the given header (name, value) before the + action. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: set: - name: \"my-header\" + value: \"bar\" \n Output: GET /foo HTTP/1.1 + my-header: bar" + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: "Name is the name of the + HTTP Header to be matched. Name matching + MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an + equivalent name MUST be considered for + a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map type: object type: description: "Type identifies the type of filter to apply. As with other API fields, types are classified into three conformance levels: \n - Core: Filter types and their corresponding configuration - defined by \"Support: Core\" in this package, - e.g. \"RequestHeaderModifier\". All implementations - must support core filters. \n - Extended: Filter - types and their corresponding configuration defined - by \"Support: Extended\" in this package, e.g. - \"RequestMirror\". Implementers are encouraged - to support extended filters. \n - Custom: Filters - that are defined and supported by specific vendors. - \ In the future, filters showing convergence - in behavior across multiple implementations - will be considered for inclusion in extended or - core conformance levels. Filter-specific configuration - for such filters is specified using the ExtensionRef - field. `Type` should be set to \"ExtensionRef\" - for custom filters. \n Implementers are encouraged - to define custom implementation types to extend - the core API with implementation-specific behavior. - \n If a reference to a custom filter type cannot - be resolved, the filter MUST NOT be skipped. Instead, - requests that would have been processed by that - filter MUST receive a HTTP error response." + defined by \"Support: Core\" in this package, + e.g. \"RequestHeaderModifier\". All implementations + supporting GRPCRoute MUST support core filters. + \n - Extended: Filter types and their corresponding + configuration defined by \"Support: Extended\" + in this package, e.g. \"RequestMirror\". Implementers + are encouraged to support extended filters. \n + - Implementation-specific: Filters that are defined + and supported by specific vendors. In the future, + filters showing convergence in behavior across + multiple implementations will be considered for + inclusion in extended or core conformance levels. + Filter-specific configuration for such filters + is specified using the ExtensionRef field. `Type` + MUST be set to \"ExtensionRef\" for custom filters. + \n Implementers are encouraged to define custom + implementation types to extend the core API with + implementation-specific behavior. \n If a reference + to a custom filter type cannot be resolved, the + filter MUST NOT be skipped. Instead, requests + that would have been processed by that filter + MUST receive a HTTP error response. \n " enum: + - ResponseHeaderModifier - RequestHeaderModifier - RequestMirror - - RequestRedirect - ExtensionRef type: string required: - type type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil + if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type + != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type + == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil + if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type + != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for + RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == + ''RequestMirror'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for + ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' maxItems: 16 type: array + x-kubernetes-validations: + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 group: default: "" description: Group is the group of the referent. For example, - "networking.k8s.io". When unspecified (empty string), - core API group is inferred. + "gateway.networking.k8s.io". When unspecified or empty + string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service - description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". + description: "Kind is the Kubernetes resource kind of + the referent. For example \"Service\". \n Defaults to + \"Service\" when not specified. \n ExternalName services + can refer to CNAME DNS records that may live outside + of the cluster and as such are difficult to reason about + in terms of conformance. They also may not be safe to + forward to (see CVE-2021-25740 for more information). + Implementations SHOULD NOT support ExternalName Services. + \n Support: Core (Services with a type other than ExternalName) + \n Support: Implementation-specific (Services with type + ExternalName)" maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ @@ -1485,11 +3145,11 @@ spec: namespace: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n - Note that when a namespace is specified, a ReferencePolicy - object is required in the referent namespace to allow - that namespace's owner to accept the reference. See - the ReferencePolicy documentation for details. \n Support: - Core" + Note that when a namespace different than the local + namespace is specified, a ReferenceGrant object is required + in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferenceGrant + documentation for details. \n Support: Core" maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ @@ -1497,9 +3157,10 @@ spec: port: description: Port specifies the destination port number to use for this resource. Port is required when the - referent is a Kubernetes Service. For other resources, - destination port might be derived from the referent - resource or this field. + referent is a Kubernetes Service. In this case, the + port number is the service port number, not the target + port. For other resources, destination port might be + derived from the referent resource or this field. format: int32 maximum: 65535 minimum: 1 @@ -1526,6 +3187,10 @@ spec: required: - name type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' maxItems: 16 type: array filters: @@ -1535,15 +3200,20 @@ spec: change in the future based on feedback during the alpha stage. \n Conformance-levels at this level are defined based on the type of filter: \n - ALL core filters MUST be supported by - all implementations. - Implementers are encouraged to support - extended filters. - Implementation-specific custom filters - have no API guarantees across implementations. \n Specifying - a core filter multiple times has unspecified or custom conformance. - \n Support: Core" + all implementations that support GRPCRoute. - Implementers + are encouraged to support extended filters. - Implementation-specific + custom filters have no API guarantees across implementations. + \n Specifying the same filter multiple times is not supported + unless explicitly indicated in the filter. \n If an implementation + can not support a combination of filters, it must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to + be set to status `False`, implementations may use the `IncompatibleFilters` + reason to specify this configuration error. \n Support: Core" items: - description: HTTPRouteFilter defines processing steps that + description: GRPCRouteFilter defines processing steps that must be completed during the request or response lifecycle. - HTTPRouteFilters are meant as an extension point to express + GRPCRouteFilters are meant as an extension point to express processing that may be done in Gateway implementations. Some examples include request or response modification, implementing authentication strategies, rate-limiting, and @@ -1555,12 +3225,13 @@ spec: extension to the \"filter\" behavior. For example, resource \"myroutefilter\" in group \"networking.example.net\"). ExtensionRef MUST NOT be used for core and extended - filters. \n Support: Implementation-specific" + filters. \n Support: Implementation-specific \n This + filter can be used multiple times within the same rule." properties: group: description: Group is the group of the referent. For - example, "networking.k8s.io". When unspecified (empty - string), core API group is inferred. + example, "gateway.networking.k8s.io". When unspecified + or empty string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string @@ -1590,10 +3261,9 @@ spec: description: "Add adds the given header(s) (name, value) to the request before the action. It appends to any existing values associated with the header - name. \n Input: GET /foo HTTP/1.1 my-header: - foo \n Config: add: - name: \"my-header\" value: - \"bar\" \n Output: GET /foo HTTP/1.1 my-header: - foo my-header: bar" + name. \n Input: GET /foo HTTP/1.1 my-header: foo + \n Config: add: - name: \"my-header\" value: \"bar,baz\" + \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. @@ -1633,20 +3303,21 @@ spec: HTTP request before the action. The value of Remove is a list of HTTP header names. Note that the header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). - \n Input: GET /foo HTTP/1.1 my-header1: foo - \ my-header2: bar my-header3: baz \n Config: - \ remove: [\"my-header1\", \"my-header3\"] \n Output: - \ GET /foo HTTP/1.1 my-header2: bar" + \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: + bar my-header3: baz \n Config: remove: [\"my-header1\", + \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: + bar" items: type: string maxItems: 16 type: array + x-kubernetes-list-type: set set: description: "Set overwrites the request with the given header (name, value) before the action. \n - Input: GET /foo HTTP/1.1 my-header: foo \n Config: - \ set: - name: \"my-header\" value: \"bar\" - \n Output: GET /foo HTTP/1.1 my-header: bar" + Input: GET /foo HTTP/1.1 my-header: foo \n Config: + set: - name: \"my-header\" value: \"bar\" \n Output: + GET /foo HTTP/1.1 my-header: bar" items: description: HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. @@ -1686,39 +3357,57 @@ spec: description: "RequestMirror defines a schema for a filter that mirrors requests. Requests are sent to the specified destination, but responses from that destination are - ignored. \n Support: Extended" + ignored. \n This filter can be used multiple times within + the same rule. Note that not all implementations will + be able to support mirroring to multiple backends. \n + Support: Extended" properties: backendRef: description: "BackendRef references a resource where - mirrored requests are sent. \n If the referent cannot - be found, this BackendRef is invalid and must be - dropped from the Gateway. The controller must ensure - the \"ResolvedRefs\" condition on the Route status - is set to `status: False` and not configure this - backend in the underlying implementation. \n If - there is a cross-namespace reference to an *existing* - object that is not allowed by a ReferencePolicy, - the controller must ensure the \"ResolvedRefs\" - \ condition on the Route is set to `status: False`, - with the \"RefNotPermitted\" reason and not configure - this backend in the underlying implementation. \n - In either error case, the Message of the `ResolvedRefs` - Condition should be used to provide more detail - about the problem. \n Support: Extended for Kubernetes - Service Support: Custom for any other resource" + mirrored requests are sent. \n Mirrored requests + must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many + endpoints are present within this BackendRef. \n + If the referent cannot be found, this BackendRef + is invalid and must be dropped from the Gateway. + The controller must ensure the \"ResolvedRefs\" + condition on the Route status is set to `status: + False` and not configure this backend in the underlying + implementation. \n If there is a cross-namespace + reference to an *existing* object that is not allowed + by a ReferenceGrant, the controller must ensure + the \"ResolvedRefs\" condition on the Route is + set to `status: False`, with the \"RefNotPermitted\" + reason and not configure this backend in the underlying + implementation. \n In either error case, the Message + of the `ResolvedRefs` Condition should be used to + provide more detail about the problem. \n Support: + Extended for Kubernetes Service \n Support: Implementation-specific + for any other resource" properties: group: default: "" description: Group is the group of the referent. - For example, "networking.k8s.io". When unspecified - (empty string), core API group is inferred. + For example, "gateway.networking.k8s.io". When + unspecified or empty string, core API group + is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service - description: Kind is kind of the referent. For - example "HTTPRoute" or "Service". + description: "Kind is the Kubernetes resource + kind of the referent. For example \"Service\". + \n Defaults to \"Service\" when not specified. + \n ExternalName services can refer to CNAME + DNS records that may live outside of the cluster + and as such are difficult to reason about in + terms of conformance. They also may not be safe + to forward to (see CVE-2021-25740 for more information). + Implementations SHOULD NOT support ExternalName + Services. \n Support: Core (Services with a + type other than ExternalName) \n Support: Implementation-specific + (Services with type ExternalName)" maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ @@ -1731,11 +3420,12 @@ spec: namespace: description: "Namespace is the namespace of the backend. When unspecified, the local namespace - is inferred. \n Note that when a namespace is - specified, a ReferencePolicy object is required - in the referent namespace to allow that namespace's - owner to accept the reference. See the ReferencePolicy - documentation for details. \n Support: Core" + is inferred. \n Note that when a namespace different + than the local namespace is specified, a ReferenceGrant + object is required in the referent namespace + to allow that namespace's owner to accept the + reference. See the ReferenceGrant documentation + for details. \n Support: Core" maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ @@ -1743,9 +3433,11 @@ spec: port: description: Port specifies the destination port number to use for this resource. Port is required - when the referent is a Kubernetes Service. For - other resources, destination port might be derived - from the referent resource or this field. + when the referent is a Kubernetes Service. In + this case, the port number is the service port + number, not the target port. For other resources, + destination port might be derived from the referent + resource or this field. format: int32 maximum: 65535 minimum: 1 @@ -1753,6 +3445,2024 @@ spec: required: - name type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + required: + - backendRef + type: object + responseHeaderModifier: + description: "ResponseHeaderModifier defines a schema + for a filter that modifies response headers. \n Support: + Extended" + properties: + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It appends + to any existing values associated with the header + name. \n Input: GET /foo HTTP/1.1 my-header: foo + \n Config: add: - name: \"my-header\" value: \"bar,baz\" + \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case + insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the + HTTP request before the action. The value of Remove + is a list of HTTP header names. Note that the header + names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: + bar my-header3: baz \n Config: remove: [\"my-header1\", + \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: + bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the + given header (name, value) before the action. \n + Input: GET /foo HTTP/1.1 my-header: foo \n Config: + set: - name: \"my-header\" value: \"bar\" \n Output: + GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case + insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: "Type identifies the type of filter to apply. + As with other API fields, types are classified into + three conformance levels: \n - Core: Filter types and + their corresponding configuration defined by \"Support: + Core\" in this package, e.g. \"RequestHeaderModifier\". + All implementations supporting GRPCRoute MUST support + core filters. \n - Extended: Filter types and their + corresponding configuration defined by \"Support: Extended\" + in this package, e.g. \"RequestMirror\". Implementers + are encouraged to support extended filters. \n - Implementation-specific: + Filters that are defined and supported by specific vendors. + In the future, filters showing convergence in behavior + across multiple implementations will be considered for + inclusion in extended or core conformance levels. Filter-specific + configuration for such filters is specified using the + ExtensionRef field. `Type` MUST be set to \"ExtensionRef\" + for custom filters. \n Implementers are encouraged to + define custom implementation types to extend the core + API with implementation-specific behavior. \n If a reference + to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have + been processed by that filter MUST receive a HTTP error + response. \n " + enum: + - ResponseHeaderModifier + - RequestHeaderModifier + - RequestMirror + - ExtensionRef + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the + filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != + ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == + ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the + filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != + ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror + filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef + filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + matches: + description: "Matches define conditions used for matching the + rule against incoming gRPC requests. Each match is independent, + i.e. this rule will be matched if **any** one of the matches + is satisfied. \n For example, take the following matches configuration: + \n ``` matches: - method: service: foo.bar headers: values: + version: 2 - method: service: foo.bar.v2 ``` \n For a request + to match against this rule, it MUST satisfy EITHER of the + two conditions: \n - service of foo.bar AND contains the header + `version: 2` - service of foo.bar.v2 \n See the documentation + for GRPCRouteMatch on how to specify multiple match conditions + to be ANDed together. \n If no matches are specified, the + implementation MUST match every gRPC request. \n Proxy or + Load Balancer routing configuration generated from GRPCRoutes + MUST prioritize rules based on the following criteria, continuing + on ties. Merging MUST not be done between GRPCRoutes and HTTPRoutes. + Precedence MUST be given to the rule with the largest number + of: \n * Characters in a matching non-wildcard hostname. * + Characters in a matching hostname. * Characters in a matching + service. * Characters in a matching method. * Header matches. + \n If ties still exist across multiple Routes, matching precedence + MUST be determined in order of the following criteria, continuing + on ties: \n * The oldest Route based on creation timestamp. + * The Route appearing first in alphabetical order by \"{namespace}/{name}\". + \n If ties still exist within the Route that has been given + precedence, matching precedence MUST be granted to the first + matching rule meeting the above criteria." + items: + description: "GRPCRouteMatch defines the predicate used to + match requests to a given action. Multiple match types are + ANDed together, i.e. the match will evaluate to true only + if all conditions are satisfied. \n For example, the match + below will match a gRPC request only if its service is `foo` + AND it contains the `version: v1` header: \n ``` matches: + - method: type: Exact service: \"foo\" headers: - name: + \"version\" value \"v1\" \n ```" + properties: + headers: + description: Headers specifies gRPC request header matchers. + Multiple match values are ANDed together, meaning, a + request MUST match all the specified headers to select + the route. + items: + description: GRPCHeaderMatch describes how to select + a gRPC route by matching gRPC request headers. + properties: + name: + description: "Name is the name of the gRPC Header + to be matched. \n If multiple entries specify + equivalent header names, only the first entry + with an equivalent name MUST be considered for + a match. Subsequent entries with an equivalent + header name MUST be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: Type specifies how to match against + the value of the header. + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of the gRPC Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + description: Method specifies a gRPC request service/method + matcher. If this field is not specified, all services + and methods will match. + properties: + method: + description: "Value of the method to match against. + If left empty or omitted, will match all services. + \n At least one of Service and Method MUST be a + non-empty string." + maxLength: 1024 + type: string + service: + description: "Value of the service to match against. + If left empty or omitted, will match any service. + \n At least one of Service and Method MUST be a + non-empty string." + maxLength: 1024 + type: string + type: + default: Exact + description: "Type specifies how to match against + the service and/or method. Support: Core (Exact + with service and method specified) \n Support: Implementation-specific + (Exact with method specified but no service specified) + \n Support: Implementation-specific (RegularExpression)" + enum: + - Exact + - RegularExpression + type: string + type: object + x-kubernetes-validations: + - message: One or both of 'service' or 'method' must be + specified + rule: 'has(self.type) ? has(self.service) || has(self.method) + : true' + - message: service must only contain valid characters + (matching ^(?i)\.?[a-z_][a-z_0-9]*(\.[a-z_][a-z_0-9]*)*$) + rule: '(!has(self.type) || self.type == ''Exact'') && + has(self.service) ? self.service.matches(r"""^(?i)\.?[a-z_][a-z_0-9]*(\.[a-z_][a-z_0-9]*)*$"""): + true' + - message: method must only contain valid characters (matching + ^[A-Za-z_][A-Za-z_0-9]*$) + rule: '(!has(self.type) || self.type == ''Exact'') && + has(self.method) ? self.method.matches(r"""^[A-Za-z_][A-Za-z_0-9]*$"""): + true' + type: object + maxItems: 8 + type: array + type: object + maxItems: 16 + type: array + type: object + status: + description: Status defines the current state of GRPCRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) + that are associated with the route, and the status of the route + with respect to each parent. When this route attaches to a parent, + the controller that manages the parent must add an entry to this + list when the controller first sees the route and should update + the entry as appropriate when the route or gateway is modified. + \n Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this + API can only populate Route status for the Gateways/parent resources + they are responsible for. \n A maximum of 32 Gateways will be represented + in this list. An empty list means the route has not been attached + to any Gateway." + items: + description: RouteParentStatus describes the status of a route with + respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with + respect to the Gateway. Note that the route's availability + is also subject to the Gateway's own status conditions and + listener status. \n If the Route's ParentRef specifies an + existing Gateway that supports Routes of this kind AND that + Gateway's controller has sufficient access, then that Gateway's + controller MUST set the \"Accepted\" condition on the Route, + to indicate whether the route has been accepted or rejected + by the Gateway, and why. \n A Route MUST be considered \"Accepted\" + if at least one of the Route's rules is implemented by the + Gateway. \n There are a number of cases where the \"Accepted\" + condition may not be set due to lack of controller visibility, + that includes when: \n * The Route refers to a non-existent + parent. * The Route is of a type that the controller does + not support. * The Route is in a namespace the controller + does not have access to." + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, \n type FooStatus struct{ + // Represents the observations of a foo's current state. + // Known .status.conditions.type are: \"Available\", \"Progressing\", + and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields + }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates + the name of the controller that wrote this status. This corresponds + with the controllerName field on GatewayClass. \n Example: + \"example.net/gateway-controller\". \n The format of this + field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + \n Controllers MUST populate this field when writing status. + Controllers should ensure that entries to status populated + with their ControllerName are cleaned up when they are no + longer necessary." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec + that this RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, + \"gateway.networking.k8s.io\" is inferred. To set the + core API group (such as for a \"Service\" kind referent), + Group must be explicitly set to \"\" (empty string). \n + Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are + two kinds of parent resources with \"Core\" support: \n + * Gateway (Gateway conformance profile) * Service (Mesh + conformance profile, experimental, ClusterIP Services + only) \n Support for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified, this refers to the local namespace of + the Route. \n Note that there are specific rules for ParentRefs + which cross namespace boundaries. Cross-namespace references + are only valid if they are explicitly allowed by something + in the namespace they are referring to. For example: Gateway + has the AllowedRoutes field, and ReferenceGrant provides + a generic way to enable any other kind of cross-namespace + reference. \n ParentRefs from a Route to a Service in + the same namespace are \"producer\" routes, which apply + default routing rules to inbound connections from any + namespace to the Service. \n ParentRefs from a Route to + a Service in a different namespace are \"consumer\" routes, + and these routing rules are only applied to outbound connections + originating from the same namespace as the Route, for + which the intended destination of the connections are + a Service targeted as a ParentRef of the Route. \n Support: + Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. + It can be interpreted differently based on the type of + parent resource. \n When the parent resource is a Gateway, + this targets all listeners listening on the specified + port that also support this kind of Route(and select this + Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to + a specific port as opposed to a listener(s) whose port(s) + may be changed. When both Port and SectionName are specified, + the name and port of the selected listener must match + both specified values. \n When the parent resource is + a Service, this targets a specific port in the Service + spec. When both Port (experimental) and SectionName are + specified, the name and port of the selected port must + match both specified values. \n Implementations MAY choose + to support other parent resources. Implementations supporting + other types of parent resources MUST clearly document + how/if Port is interpreted. \n For the purpose of status, + an attachment is considered successful as long as the + parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them + by Route kind, namespace, or hostname. If 1 of 2 Gateway + listeners accept attachment from the referencing Route, + the Route MUST be considered successfully attached. If + no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name. When both Port (experimental) and SectionName are + specified, the name and port of the selected listener + must match both specified values. * Service: Port Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match + both specified values. Note that attaching Routes to Services + as Parents is part of experimental Mesh support and is + not supported for any other purpose. \n Implementations + MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this + will reference the entire resource. For the purpose of + status, an attachment is considered successful if at least + one section in the parent resource accepts it. For example, + Gateway listeners can restrict which Routes can attach + to them by Route kind, namespace, or hostname. If 1 of + 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + name: httproutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: HTTPRoute + listKind: HTTPRouteList + plural: httproutes + singular: httproute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.hostnames + name: Hostnames + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: HTTPRoute provides a way to route HTTP requests. This includes + the capability to match requests by hostname, path, header, or query param. + Filters can be used to specify additional processing steps. Backends specify + where matching requests should be routed. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of HTTPRoute. + properties: + hostnames: + description: "Hostnames defines a set of hostnames that should match + against the HTTP Host header to select a HTTPRoute used to process + the request. Implementations MUST ignore any port value specified + in the HTTP Host header while performing a match and (absent of + any applicable header modification configuration) MUST forward this + header unmodified to the backend. \n Valid values for Hostnames + are determined by RFC 1123 definition of a hostname with 2 notable + exceptions: \n 1. IPs are not allowed. 2. A hostname may be prefixed + with a wildcard label (`*.`). The wildcard label must appear by + itself as the first label. \n If a hostname is specified by both + the Listener and HTTPRoute, there must be at least one intersecting + hostname for the HTTPRoute to be attached to the Listener. For example: + \n * A Listener with `test.example.com` as the hostname matches + HTTPRoutes that have either not specified any hostnames, or have + specified at least one of `test.example.com` or `*.example.com`. + * A Listener with `*.example.com` as the hostname matches HTTPRoutes + that have either not specified any hostnames or have specified at + least one hostname that matches the Listener hostname. For example, + `*.example.com`, `test.example.com`, and `foo.test.example.com` + would all match. On the other hand, `example.com` and `test.example.net` + would not match. \n Hostnames that are prefixed with a wildcard + label (`*.`) are interpreted as a suffix match. That means that + a match for `*.example.com` would match both `test.example.com`, + and `foo.test.example.com`, but not `example.com`. \n If both the + Listener and HTTPRoute have specified hostnames, any HTTPRoute hostnames + that do not match the Listener hostname MUST be ignored. For example, + if a Listener specified `*.example.com`, and the HTTPRoute specified + `test.example.com` and `test.example.net`, `test.example.net` must + not be considered for a match. \n If both the Listener and HTTPRoute + have specified hostnames, and none match with the criteria above, + then the HTTPRoute is not accepted. The implementation must raise + an 'Accepted' Condition with a status of `False` in the corresponding + RouteParentStatus. \n In the event that multiple HTTPRoutes specify + intersecting hostnames (e.g. overlapping wildcard matching and exact + matching hostnames), precedence must be given to rules from the + HTTPRoute with the largest number of: \n * Characters in a matching + non-wildcard hostname. * Characters in a matching hostname. \n If + ties exist across multiple Routes, the matching precedence rules + for HTTPRouteMatches takes over. \n Support: Core" + items: + description: "Hostname is the fully qualified domain name of a network + host. This matches the RFC 1123 definition of a hostname with + 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname + may be prefixed with a wildcard label (`*.`). The wildcard label + must appear by itself as the first label. \n Hostname can be \"precise\" + which is a domain name without the terminating dot of a network + host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain + name prefixed with a single wildcard label (e.g. `*.example.com`). + \n Note that as per RFC1035 and RFC1123, a *label* must consist + of lower case alphanumeric characters or '-', and must start and + end with an alphanumeric character. No other punctuation is allowed." + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + description: "ParentRefs references the resources (usually Gateways) + that a Route wants to be attached to. Note that the referenced parent + resource needs to allow this for the attachment to be complete. + For Gateways, that means the Gateway needs to allow attachment from + Routes of this kind and namespace. For Services, that means the + Service must either be in the same namespace for a \"producer\" + route, or the mesh implementation must support and allow \"consumer\" + routes for the referenced Service. ReferenceGrant is not applicable + for governing ParentRefs to Services - it is not possible to create + a \"producer\" route for a Service in a different namespace from + the Route. \n There are two kinds of parent resources with \"Core\" + support: \n * Gateway (Gateway conformance profile) * Service (Mesh + conformance profile, experimental, ClusterIP Services only) This + API may be extended in the future to support additional kinds of + parent resources. \n ParentRefs must be _distinct_. This means either + that: \n * They select different objects. If this is the case, + then parentRef entries are distinct. In terms of fields, this means + that the multi-part key defined by `group`, `kind`, `namespace`, + and `name` must be unique across all parentRef entries in the Route. + * They do not select different objects, but for each optional field + used, each ParentRef that selects the same object must set the same + set of optional fields to different values. If one ParentRef sets + a combination of optional fields, all must set the same combination. + \n Some examples: \n * If one ParentRef sets `sectionName`, all + ParentRefs referencing the same object must also set `sectionName`. + * If one ParentRef sets `port`, all ParentRefs referencing the same + object must also set `port`. * If one ParentRef sets `sectionName` + and `port`, all ParentRefs referencing the same object must also + set `sectionName` and `port`. \n It is possible to separately reference + multiple distinct objects that may be collapsed by an implementation. + For example, some implementations may choose to merge compatible + Gateway Listeners together. If that is the case, the list of routes + attached to those resources should also be merged. \n Note that + for ParentRefs that cross namespace boundaries, there are specific + rules. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For + example, Gateway has the AllowedRoutes field, and ReferenceGrant + provides a generic way to enable other kinds of cross-namespace + reference. \n ParentRefs from a Route to a Service in the same + namespace are \"producer\" routes, which apply default routing rules + to inbound connections from any namespace to the Service. \n ParentRefs + from a Route to a Service in a different namespace are \"consumer\" + routes, and these routing rules are only applied to outbound connections + originating from the same namespace as the Route, for which the + intended destination of the connections are a Service targeted as + a ParentRef of the Route. \n " + items: + description: "ParentReference identifies an API object (usually + a Gateway) that can be considered a parent of this resource (usually + a route). There are two kinds of parent resources with \"Core\" + support: \n * Gateway (Gateway conformance profile) * Service + (Mesh conformance profile, experimental, ClusterIP Services only) + \n This API may be extended in the future to support additional + kinds of parent resources. \n The API object must be valid in + the cluster; the Group and Kind must be registered in the cluster + for this reference to be valid." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, + \"gateway.networking.k8s.io\" is inferred. To set the core + API group (such as for a \"Service\" kind referent), Group + must be explicitly set to \"\" (empty string). \n Support: + Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are two + kinds of parent resources with \"Core\" support: \n * Gateway + (Gateway conformance profile) * Service (Mesh conformance + profile, experimental, ClusterIP Services only) \n Support + for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When + unspecified, this refers to the local namespace of the Route. + \n Note that there are specific rules for ParentRefs which + cross namespace boundaries. Cross-namespace references are + only valid if they are explicitly allowed by something in + the namespace they are referring to. For example: Gateway + has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + \n ParentRefs from a Route to a Service in the same namespace + are \"producer\" routes, which apply default routing rules + to inbound connections from any namespace to the Service. + \n ParentRefs from a Route to a Service in a different namespace + are \"consumer\" routes, and these routing rules are only + applied to outbound connections originating from the same + namespace as the Route, for which the intended destination + of the connections are a Service targeted as a ParentRef of + the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. It + can be interpreted differently based on the type of parent + resource. \n When the parent resource is a Gateway, this targets + all listeners listening on the specified port that also support + this kind of Route(and select this Route). It's not recommended + to set `Port` unless the networking behaviors specified in + a Route must apply to a specific port as opposed to a listener(s) + whose port(s) may be changed. When both Port and SectionName + are specified, the name and port of the selected listener + must match both specified values. \n When the parent resource + is a Service, this targets a specific port in the Service + spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified + values. \n Implementations MAY choose to support other parent + resources. Implementations supporting other types of parent + resources MUST clearly document how/if Port is interpreted. + \n For the purpose of status, an attachment is considered + successful as long as the parent resource accepts it partially. + For example, Gateway listeners can restrict which Routes can + attach to them by Route kind, namespace, or hostname. If 1 + of 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. \n + Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match both + specified values. * Service: Port Name. When both Port (experimental) + and SectionName are specified, the name and port of the selected + listener must match both specified values. Note that attaching + Routes to Services as Parents is part of experimental Mesh + support and is not supported for any other purpose. \n Implementations + MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this will + reference the entire resource. For the purpose of status, + an attachment is considered successful if at least one section + in the parent resource accepts it. For example, Gateway listeners + can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept + attachment from the referencing Route, the Route MUST be considered + successfully attached. If no Gateway listeners accept attachment + from this Route, the Route MUST be considered detached from + the Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + x-kubernetes-validations: + - message: sectionName or port must be specified when parentRefs includes + 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ + == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__)) ? ((!has(p1.sectionName) + || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName + == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) + || p2.port == 0)): true))' + - message: sectionName or port must be unique when parentRefs includes + 2 or more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ + == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) + || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName + == '')) || ( has(p1.sectionName) && has(p2.sectionName) && p1.sectionName + == p2.sectionName)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) + || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port + == p2.port)))) + rules: + default: + - matches: + - path: + type: PathPrefix + value: / + description: Rules are a list of HTTP matchers, filters and actions. + items: + description: HTTPRouteRule defines semantics for matching an HTTP + request based on conditions (matches), processing it (filters), + and forwarding the request to an API object (backendRefs). + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching + requests should be sent. \n Failure behavior here depends + on how many BackendRefs are specified and how many are invalid. + \n If *all* entries in BackendRefs are invalid, and there + are also no filters specified in this route rule, *all* traffic + which matches this rule MUST receive a 500 status code. \n + See the HTTPBackendRef definition for the rules about what + makes a single HTTPBackendRef invalid. \n When a HTTPBackendRef + is invalid, 500 status codes MUST be returned for requests + that would have otherwise been routed to an invalid backend. + If multiple backends are specified, and some are invalid, + the proportion of requests that would otherwise have been + routed to an invalid backend MUST receive a 500 status code. + \n For example, if two backends are specified with equal weights, + and one is invalid, 50 percent of traffic must receive a 500. + Implementations may choose how that 50 percent is determined. + \n Support: Core for Kubernetes Service \n Support: Extended + for Kubernetes ServiceImport \n Support: Implementation-specific + for any other resource \n Support for weight: Core" + items: + description: "HTTPBackendRef defines how a HTTPRoute forwards + a HTTP request. \n Note that when a namespace different + than the local namespace is specified, a ReferenceGrant + object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. \n + \n When the BackendRef points to a Kubernetes Service, implementations + SHOULD honor the appProtocol field if it is set for the + target Service Port. \n Implementations supporting appProtocol + SHOULD recognize the Kubernetes Standard Application Protocols + defined in KEP-3726. \n If a Service appProtocol isn't specified, + an implementation MAY infer the backend protocol through + its own means. Implementations MAY infer the protocol from + the Route type referring to the backend Service. \n If a + Route is not able to send traffic to the backend using the + specified protocol then the backend is considered invalid. + Implementations MUST set the \"ResolvedRefs\" condition + to \"False\" with the \"UnsupportedProtocol\" reason. \n + " + properties: + filters: + description: "Filters defined at this level should be + executed if and only if the request is being forwarded + to the backend defined here. \n Support: Implementation-specific + (For broader support of filters, use the Filters field + in HTTPRouteRule.)" + items: + description: HTTPRouteFilter defines processing steps + that must be completed during the request or response + lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway + implementations. Some examples include request or + response modification, implementing authentication + strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type + of the filter. + properties: + extensionRef: + description: "ExtensionRef is an optional, implementation-specific + extension to the \"filter\" behavior. For example, + resource \"myroutefilter\" in group \"networking.example.net\"). + ExtensionRef MUST NOT be used for core and extended + filters. \n This filter can be used multiple times + within the same rule. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. + For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API + group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For + example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema + for a filter that modifies request headers. \n + Support: Core" + properties: + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It + appends to any existing values associated + with the header name. \n Input: GET /foo HTTP/1.1 + my-header: foo \n Config: add: - name: \"my-header\" + value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 + my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: "Name is the name of the + HTTP Header to be matched. Name matching + MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an + equivalent name MUST be considered for + a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from + the HTTP request before the action. The value + of Remove is a list of HTTP header names. + Note that the header names are case-insensitive + (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: foo + my-header2: bar my-header3: baz \n Config: + remove: [\"my-header1\", \"my-header3\"] \n + Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with + the given header (name, value) before the + action. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: set: - name: \"my-header\" + value: \"bar\" \n Output: GET /foo HTTP/1.1 + my-header: bar" + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: "Name is the name of the + HTTP Header to be matched. Name matching + MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an + equivalent name MUST be considered for + a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: "RequestMirror defines a schema for + a filter that mirrors requests. Requests are sent + to the specified destination, but responses from + that destination are ignored. \n This filter can + be used multiple times within the same rule. Note + that not all implementations will be able to support + mirroring to multiple backends. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource + where mirrored requests are sent. \n Mirrored + requests must be sent only to a single destination + endpoint within this BackendRef, irrespective + of how many endpoints are present within this + BackendRef. \n If the referent cannot be found, + this BackendRef is invalid and must be dropped + from the Gateway. The controller must ensure + the \"ResolvedRefs\" condition on the Route + status is set to `status: False` and not configure + this backend in the underlying implementation. + \n If there is a cross-namespace reference + to an *existing* object that is not allowed + by a ReferenceGrant, the controller must ensure + the \"ResolvedRefs\" condition on the Route + is set to `status: False`, with the \"RefNotPermitted\" + reason and not configure this backend in the + underlying implementation. \n In either error + case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about + the problem. \n Support: Extended for Kubernetes + Service \n Support: Implementation-specific + for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. + For example, "gateway.networking.k8s.io". + When unspecified or empty string, core + API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource + kind of the referent. For example \"Service\". + \n Defaults to \"Service\" when not specified. + \n ExternalName services can refer to + CNAME DNS records that may live outside + of the cluster and as such are difficult + to reason about in terms of conformance. + They also may not be safe to forward to + (see CVE-2021-25740 for more information). + Implementations SHOULD NOT support ExternalName + Services. \n Support: Core (Services with + a type other than ExternalName) \n Support: + Implementation-specific (Services with + type ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace + of the backend. When unspecified, the + local namespace is inferred. \n Note that + when a namespace different than the local + namespace is specified, a ReferenceGrant + object is required in the referent namespace + to allow that namespace's owner to accept + the reference. See the ReferenceGrant + documentation for details. \n Support: + Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination + port number to use for this resource. + Port is required when the referent is + a Kubernetes Service. In this case, the + port number is the service port number, + not the target port. For other resources, + destination port might be derived from + the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind + == ''Service'') ? has(self.port) : true' + required: + - backendRef + type: object + requestRedirect: + description: "RequestRedirect defines a schema for + a filter that responds to the request with an + HTTP redirection. \n Support: Core" + properties: + hostname: + description: "Hostname is the hostname to be + used in the value of the `Location` header + in the response. When empty, the hostname + in the `Host` header of the request is used. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines parameters used to + modify the path of the incoming request. The + modified path is then used to construct the + `Location` header. When empty, the request + path is used as-is. \n Support: Extended" + properties: + replaceFullPath: + description: ReplaceFullPath specifies the + value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies + the value with which to replace the prefix + match of a request during a rewrite or + redirect. For example, a request to \"/foo/bar\" + with a prefix match of \"/foo\" and a + ReplacePrefixMatch of \"/xyz\" would be + modified to \"/xyz/bar\". \n Note that + this matches the behavior of the PathPrefix + match type. This matches full path elements. + A path element refers to the list of labels + in the path split by the `/` separator. + When specified, a trailing `/` is ignored. + For example, the paths `/abc`, `/abc/`, + and `/abc/def` would all match the prefix + `/abc`, but the path `/abcd` would not. + \n ReplacePrefixMatch is only compatible + with a `PathPrefix` HTTPRouteMatch. Using + any other HTTPRouteMatch type on the same + HTTPRouteRule will result in the implementation + setting the Accepted Condition for the + Route to `status: False`. \n Request Path + | Prefix Match | Replace Prefix | Modified + Path -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | + /xyz/bar /foo/bar | /foo | + /xyz/ | /xyz/bar /foo/bar | + /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | + /xyz/bar /foo | /foo | + /xyz | /xyz /foo/ | /foo + \ | /xyz | /xyz/ /foo/bar + \ | /foo | | + /bar /foo/ | /foo | | / /foo | /foo | + | / /foo/ | /foo + \ | / | / /foo | + /foo | / | /" + maxLength: 1024 + type: string + type: + description: "Type defines the type of path + modifier. Additional types may be added + in a future release of the API. \n Note + that values may be added to this enum, + implementations must ensure that unknown + values will not cause a crash. \n Unknown + values here must result in the implementation + setting the Accepted Condition for the + Route to `status: False`, with a Reason + of `UnsupportedValue`." + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified + when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? + has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when + replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type + == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified + when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' + ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' + when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + port: + description: "Port is the port to be used in + the value of the `Location` header in the + response. \n If no port is specified, the + redirect port MUST be derived using the following + rules: \n * If redirect scheme is not-empty, + the redirect port MUST be the well-known port + associated with the redirect scheme. Specifically + \"http\" to port 80 and \"https\" to port + 443. If the redirect scheme does not have + a well-known port, the listener port of the + Gateway SHOULD be used. * If redirect scheme + is empty, the redirect port MUST be the Gateway + Listener port. \n Implementations SHOULD NOT + add the port number in the 'Location' header + in the following cases: \n * A Location header + that will use HTTP (whether that is determined + via the Listener protocol or the Scheme field) + _and_ use port 80. * A Location header that + will use HTTPS (whether that is determined + via the Listener protocol or the Scheme field) + _and_ use port 443. \n Support: Extended" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: "Scheme is the scheme to be used + in the value of the `Location` header in the + response. When empty, the scheme of the request + is used. \n Scheme redirects can affect the + port of the redirect, for more information, + refer to the documentation for the port field + of this filter. \n Note that values may be + added to this enum, implementations must ensure + that unknown values will not cause a crash. + \n Unknown values here must result in the + implementation setting the Accepted Condition + for the Route to `status: False`, with a Reason + of `UnsupportedValue`. \n Support: Extended" + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status + code to be used in response. \n Note that + values may be added to this enum, implementations + must ensure that unknown values will not cause + a crash. \n Unknown values here must result + in the implementation setting the Accepted + Condition for the Route to `status: False`, + with a Reason of `UnsupportedValue`. \n Support: + Core" + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: "ResponseHeaderModifier defines a schema + for a filter that modifies response headers. \n + Support: Extended" + properties: + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It + appends to any existing values associated + with the header name. \n Input: GET /foo HTTP/1.1 + my-header: foo \n Config: add: - name: \"my-header\" + value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 + my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: "Name is the name of the + HTTP Header to be matched. Name matching + MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an + equivalent name MUST be considered for + a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from + the HTTP request before the action. The value + of Remove is a list of HTTP header names. + Note that the header names are case-insensitive + (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: foo + my-header2: bar my-header3: baz \n Config: + remove: [\"my-header1\", \"my-header3\"] \n + Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with + the given header (name, value) before the + action. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: set: - name: \"my-header\" + value: \"bar\" \n Output: GET /foo HTTP/1.1 + my-header: bar" + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: "Name is the name of the + HTTP Header to be matched. Name matching + MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an + equivalent name MUST be considered for + a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: "Type identifies the type of filter + to apply. As with other API fields, types are + classified into three conformance levels: \n - + Core: Filter types and their corresponding configuration + defined by \"Support: Core\" in this package, + e.g. \"RequestHeaderModifier\". All implementations + must support core filters. \n - Extended: Filter + types and their corresponding configuration defined + by \"Support: Extended\" in this package, e.g. + \"RequestMirror\". Implementers are encouraged + to support extended filters. \n - Implementation-specific: + Filters that are defined and supported by specific + vendors. In the future, filters showing convergence + in behavior across multiple implementations will + be considered for inclusion in extended or core + conformance levels. Filter-specific configuration + for such filters is specified using the ExtensionRef + field. `Type` should be set to \"ExtensionRef\" + for custom filters. \n Implementers are encouraged + to define custom implementation types to extend + the core API with implementation-specific behavior. + \n If a reference to a custom filter type cannot + be resolved, the filter MUST NOT be skipped. Instead, + requests that would have been processed by that + filter MUST receive a HTTP error response. \n + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause + a crash. \n Unknown values here must result in + the implementation setting the Accepted Condition + for the Route to `status: False`, with a Reason + of `UnsupportedValue`." + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: "URLRewrite defines a schema for a + filter that modifies a request during forwarding. + \n Support: Extended" + properties: + hostname: + description: "Hostname is the value to be used + to replace the Host header value during forwarding. + \n Support: Extended" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines a path rewrite. \n + Support: Extended" + properties: + replaceFullPath: + description: ReplaceFullPath specifies the + value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies + the value with which to replace the prefix + match of a request during a rewrite or + redirect. For example, a request to \"/foo/bar\" + with a prefix match of \"/foo\" and a + ReplacePrefixMatch of \"/xyz\" would be + modified to \"/xyz/bar\". \n Note that + this matches the behavior of the PathPrefix + match type. This matches full path elements. + A path element refers to the list of labels + in the path split by the `/` separator. + When specified, a trailing `/` is ignored. + For example, the paths `/abc`, `/abc/`, + and `/abc/def` would all match the prefix + `/abc`, but the path `/abcd` would not. + \n ReplacePrefixMatch is only compatible + with a `PathPrefix` HTTPRouteMatch. Using + any other HTTPRouteMatch type on the same + HTTPRouteRule will result in the implementation + setting the Accepted Condition for the + Route to `status: False`. \n Request Path + | Prefix Match | Replace Prefix | Modified + Path -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | + /xyz/bar /foo/bar | /foo | + /xyz/ | /xyz/bar /foo/bar | + /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | + /xyz/bar /foo | /foo | + /xyz | /xyz /foo/ | /foo + \ | /xyz | /xyz/ /foo/bar + \ | /foo | | + /bar /foo/ | /foo | | / /foo | /foo | + | / /foo/ | /foo + \ | / | / /foo | + /foo | / | /" + maxLength: 1024 + type: string + type: + description: "Type defines the type of path + modifier. Additional types may be added + in a future release of the API. \n Note + that values may be added to this enum, + implementations must ensure that unknown + values will not cause a crash. \n Unknown + values here must result in the implementation + setting the Accepted Condition for the + Route to `status: False`, with a Reason + of `UnsupportedValue`." + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified + when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? + has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when + replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type + == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified + when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' + ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' + when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil + if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type + != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type + == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil + if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type + != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for + RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == + ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the + filter.type is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != + ''RequestRedirect'')' + - message: filter.requestRedirect must be specified + for RequestRedirect filter.type + rule: '!(!has(self.requestRedirect) && self.type == + ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type + is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite + filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for + ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') + && self.exists(f, f.type == ''URLRewrite''))' + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') + && self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() + <= 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() + <= 1 + group: + default: "" + description: Group is the group of the referent. For example, + "gateway.networking.k8s.io". When unspecified or empty + string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource kind of + the referent. For example \"Service\". \n Defaults to + \"Service\" when not specified. \n ExternalName services + can refer to CNAME DNS records that may live outside + of the cluster and as such are difficult to reason about + in terms of conformance. They also may not be safe to + forward to (see CVE-2021-25740 for more information). + Implementations SHOULD NOT support ExternalName Services. + \n Support: Core (Services with a type other than ExternalName) + \n Support: Implementation-specific (Services with type + ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a namespace different than the local + namespace is specified, a ReferenceGrant object is required + in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferenceGrant + documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number + to use for this resource. Port is required when the + referent is a Kubernetes Service. In this case, the + port number is the service port number, not the target + port. For other resources, destination port might be + derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests + forwarded to the referenced backend. This is computed + as weight/(sum of all weights in this BackendRefs list). + For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision + an implementation supports. Weight is not a percentage + and the sum of weights does not need to equal 100. \n + If only one backend is specified and it has a weight + greater than 0, 100% of the traffic is forwarded to + that backend. If weight is set to 0, no traffic should + be forwarded for this entry. If unspecified, weight + defaults to 1. \n Support for this field varies based + on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + maxItems: 16 + type: array + filters: + description: "Filters define the filters that are applied to + requests that match this rule. \n The effects of ordering + of multiple behaviors are currently unspecified. This can + change in the future based on feedback during the alpha stage. + \n Conformance-levels at this level are defined based on the + type of filter: \n - ALL core filters MUST be supported by + all implementations. - Implementers are encouraged to support + extended filters. - Implementation-specific custom filters + have no API guarantees across implementations. \n Specifying + the same filter multiple times is not supported unless explicitly + indicated in the filter. \n All filters are expected to be + compatible with each other except for the URLRewrite and RequestRedirect + filters, which may not be combined. If an implementation can + not support other combinations of filters, they must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to + be set to status `False`, implementations may use the `IncompatibleFilters` + reason to specify this configuration error. \n Support: Core" + items: + description: HTTPRouteFilter defines processing steps that + must be completed during the request or response lifecycle. + HTTPRouteFilters are meant as an extension point to express + processing that may be done in Gateway implementations. + Some examples include request or response modification, + implementing authentication strategies, rate-limiting, and + traffic shaping. API guarantee/conformance is defined based + on the type of the filter. + properties: + extensionRef: + description: "ExtensionRef is an optional, implementation-specific + extension to the \"filter\" behavior. For example, + resource \"myroutefilter\" in group \"networking.example.net\"). + ExtensionRef MUST NOT be used for core and extended + filters. \n This filter can be used multiple times within + the same rule. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. For + example, "gateway.networking.k8s.io". When unspecified + or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example + "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema for + a filter that modifies request headers. \n Support: + Core" + properties: + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It appends + to any existing values associated with the header + name. \n Input: GET /foo HTTP/1.1 my-header: foo + \n Config: add: - name: \"my-header\" value: \"bar,baz\" + \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case + insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the + HTTP request before the action. The value of Remove + is a list of HTTP header names. Note that the header + names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: + bar my-header3: baz \n Config: remove: [\"my-header1\", + \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: + bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the + given header (name, value) before the action. \n + Input: GET /foo HTTP/1.1 my-header: foo \n Config: + set: - name: \"my-header\" value: \"bar\" \n Output: + GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case + insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: "RequestMirror defines a schema for a filter + that mirrors requests. Requests are sent to the specified + destination, but responses from that destination are + ignored. \n This filter can be used multiple times within + the same rule. Note that not all implementations will + be able to support mirroring to multiple backends. \n + Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource where + mirrored requests are sent. \n Mirrored requests + must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many + endpoints are present within this BackendRef. \n + If the referent cannot be found, this BackendRef + is invalid and must be dropped from the Gateway. + The controller must ensure the \"ResolvedRefs\" + condition on the Route status is set to `status: + False` and not configure this backend in the underlying + implementation. \n If there is a cross-namespace + reference to an *existing* object that is not allowed + by a ReferenceGrant, the controller must ensure + the \"ResolvedRefs\" condition on the Route is + set to `status: False`, with the \"RefNotPermitted\" + reason and not configure this backend in the underlying + implementation. \n In either error case, the Message + of the `ResolvedRefs` Condition should be used to + provide more detail about the problem. \n Support: + Extended for Kubernetes Service \n Support: Implementation-specific + for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. + For example, "gateway.networking.k8s.io". When + unspecified or empty string, core API group + is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource + kind of the referent. For example \"Service\". + \n Defaults to \"Service\" when not specified. + \n ExternalName services can refer to CNAME + DNS records that may live outside of the cluster + and as such are difficult to reason about in + terms of conformance. They also may not be safe + to forward to (see CVE-2021-25740 for more information). + Implementations SHOULD NOT support ExternalName + Services. \n Support: Core (Services with a + type other than ExternalName) \n Support: Implementation-specific + (Services with type ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the + backend. When unspecified, the local namespace + is inferred. \n Note that when a namespace different + than the local namespace is specified, a ReferenceGrant + object is required in the referent namespace + to allow that namespace's owner to accept the + reference. See the ReferenceGrant documentation + for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port + number to use for this resource. Port is required + when the referent is a Kubernetes Service. In + this case, the port number is the service port + number, not the target port. For other resources, + destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' required: - backendRef type: object @@ -1764,17 +5474,114 @@ spec: hostname: description: "Hostname is the hostname to be used in the value of the `Location` header in the response. - When empty, the hostname of the request is used. - \n Support: Core" + When empty, the hostname in the `Host` header of + the request is used. \n Support: Core" maxLength: 253 minLength: 1 - pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string + path: + description: "Path defines parameters used to modify + the path of the incoming request. The modified path + is then used to construct the `Location` header. + When empty, the request path is used as-is. \n Support: + Extended" + properties: + replaceFullPath: + description: ReplaceFullPath specifies the value + with which to replace the full path of a request + during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the + value with which to replace the prefix match + of a request during a rewrite or redirect. For + example, a request to \"/foo/bar\" with a prefix + match of \"/foo\" and a ReplacePrefixMatch of + \"/xyz\" would be modified to \"/xyz/bar\". + \n Note that this matches the behavior of the + PathPrefix match type. This matches full path + elements. A path element refers to the list + of labels in the path split by the `/` separator. + When specified, a trailing `/` is ignored. For + example, the paths `/abc`, `/abc/`, and `/abc/def` + would all match the prefix `/abc`, but the path + `/abcd` would not. \n ReplacePrefixMatch is + only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same + HTTPRouteRule will result in the implementation + setting the Accepted Condition for the Route + to `status: False`. \n Request Path | Prefix + Match | Replace Prefix | Modified Path -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | + /xyz/bar /foo/bar | /foo | /xyz/ + \ | /xyz/bar /foo/bar | /foo/ | + /xyz | /xyz/bar /foo/bar | /foo/ + \ | /xyz/ | /xyz/bar /foo | + /foo | /xyz | /xyz /foo/ | + /foo | /xyz | /xyz/ /foo/bar + \ | /foo | | /bar + /foo/ | /foo | + | / /foo | /foo | + | / /foo/ | /foo | / | + / /foo | /foo | / | + /" + maxLength: 1024 + type: string + type: + description: "Type defines the type of path modifier. + Additional types may be added in a future release + of the API. \n Note that values may be added + to this enum, implementations must ensure that + unknown values will not cause a crash. \n Unknown + values here must result in the implementation + setting the Accepted Condition for the Route + to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when + type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) + : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath + is set + rule: 'has(self.replaceFullPath) ? self.type == + ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when + type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) + : true' + - message: type must be 'ReplacePrefixMatch' when + replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' port: description: "Port is the port to be used in the value - of the `Location` header in the response. When empty, - port (if specified) of the request is used. \n Support: - Extended" + of the `Location` header in the response. \n If + no port is specified, the redirect port MUST be + derived using the following rules: \n * If redirect + scheme is not-empty, the redirect port MUST be the + well-known port associated with the redirect scheme. + Specifically \"http\" to port 80 and \"https\" to + port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway + SHOULD be used. * If redirect scheme is empty, the + redirect port MUST be the Gateway Listener port. + \n Implementations SHOULD NOT add the port number + in the 'Location' header in the following cases: + \n * A Location header that will use HTTP (whether + that is determined via the Listener protocol or + the Scheme field) _and_ use port 80. * A Location + header that will use HTTPS (whether that is determined + via the Listener protocol or the Scheme field) _and_ + use port 443. \n Support: Extended" format: int32 maximum: 65535 minimum: 1 @@ -1783,7 +5590,15 @@ spec: description: "Scheme is the scheme to be used in the value of the `Location` header in the response. When empty, the scheme of the request is used. \n - Support: Extended" + Scheme redirects can affect the port of the redirect, + for more information, refer to the documentation + for the port field of this filter. \n Note that + values may be added to this enum, implementations + must ensure that unknown values will not cause a + crash. \n Unknown values here must result in the + implementation setting the Accepted Condition for + the Route to `status: False`, with a Reason of `UnsupportedValue`. + \n Support: Extended" enum: - http - https @@ -1791,47 +5606,310 @@ spec: statusCode: default: 302 description: "StatusCode is the HTTP status code to - be used in response. \n Support: Core" + be used in response. \n Note that values may be + added to this enum, implementations must ensure + that unknown values will not cause a crash. \n Unknown + values here must result in the implementation setting + the Accepted Condition for the Route to `status: + False`, with a Reason of `UnsupportedValue`. \n + Support: Core" enum: - 301 - 302 type: integer type: object + responseHeaderModifier: + description: "ResponseHeaderModifier defines a schema + for a filter that modifies response headers. \n Support: + Extended" + properties: + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It appends + to any existing values associated with the header + name. \n Input: GET /foo HTTP/1.1 my-header: foo + \n Config: add: - name: \"my-header\" value: \"bar,baz\" + \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case + insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the + HTTP request before the action. The value of Remove + is a list of HTTP header names. Note that the header + names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: + bar my-header3: baz \n Config: remove: [\"my-header1\", + \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: + bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the + given header (name, value) before the action. \n + Input: GET /foo HTTP/1.1 my-header: foo \n Config: + set: - name: \"my-header\" value: \"bar\" \n Output: + GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case + insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object type: description: "Type identifies the type of filter to apply. As with other API fields, types are classified into three conformance levels: \n - Core: Filter types and - their corresponding configuration defined by \"Support: + their corresponding configuration defined by \"Support: Core\" in this package, e.g. \"RequestHeaderModifier\". - All implementations must support core filters. \n - - Extended: Filter types and their corresponding configuration - defined by \"Support: Extended\" in this package, - e.g. \"RequestMirror\". Implementers are encouraged - to support extended filters. \n - Custom: Filters that - are defined and supported by specific vendors. In - the future, filters showing convergence in behavior - across multiple implementations will be considered - for inclusion in extended or core conformance levels. - Filter-specific configuration for such filters is - specified using the ExtensionRef field. `Type` should - be set to \"ExtensionRef\" for custom filters. \n - Implementers are encouraged to define custom implementation - types to extend the core API with implementation-specific - behavior. \n If a reference to a custom filter type - cannot be resolved, the filter MUST NOT be skipped. - Instead, requests that would have been processed by - that filter MUST receive a HTTP error response." + All implementations must support core filters. \n - + Extended: Filter types and their corresponding configuration + defined by \"Support: Extended\" in this package, e.g. + \"RequestMirror\". Implementers are encouraged to support + extended filters. \n - Implementation-specific: Filters + that are defined and supported by specific vendors. + In the future, filters showing convergence in behavior + across multiple implementations will be considered for + inclusion in extended or core conformance levels. Filter-specific + configuration for such filters is specified using the + ExtensionRef field. `Type` should be set to \"ExtensionRef\" + for custom filters. \n Implementers are encouraged to + define custom implementation types to extend the core + API with implementation-specific behavior. \n If a reference + to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have + been processed by that filter MUST receive a HTTP error + response. \n Note that values may be added to this enum, + implementations must ensure that unknown values will + not cause a crash. \n Unknown values here must result + in the implementation setting the Accepted Condition + for the Route to `status: False`, with a Reason of `UnsupportedValue`." enum: - RequestHeaderModifier + - ResponseHeaderModifier - RequestMirror - RequestRedirect + - URLRewrite - ExtensionRef type: string + urlRewrite: + description: "URLRewrite defines a schema for a filter + that modifies a request during forwarding. \n Support: + Extended" + properties: + hostname: + description: "Hostname is the value to be used to + replace the Host header value during forwarding. + \n Support: Extended" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines a path rewrite. \n Support: + Extended" + properties: + replaceFullPath: + description: ReplaceFullPath specifies the value + with which to replace the full path of a request + during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the + value with which to replace the prefix match + of a request during a rewrite or redirect. For + example, a request to \"/foo/bar\" with a prefix + match of \"/foo\" and a ReplacePrefixMatch of + \"/xyz\" would be modified to \"/xyz/bar\". + \n Note that this matches the behavior of the + PathPrefix match type. This matches full path + elements. A path element refers to the list + of labels in the path split by the `/` separator. + When specified, a trailing `/` is ignored. For + example, the paths `/abc`, `/abc/`, and `/abc/def` + would all match the prefix `/abc`, but the path + `/abcd` would not. \n ReplacePrefixMatch is + only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same + HTTPRouteRule will result in the implementation + setting the Accepted Condition for the Route + to `status: False`. \n Request Path | Prefix + Match | Replace Prefix | Modified Path -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | + /xyz/bar /foo/bar | /foo | /xyz/ + \ | /xyz/bar /foo/bar | /foo/ | + /xyz | /xyz/bar /foo/bar | /foo/ + \ | /xyz/ | /xyz/bar /foo | + /foo | /xyz | /xyz /foo/ | + /foo | /xyz | /xyz/ /foo/bar + \ | /foo | | /bar + /foo/ | /foo | + | / /foo | /foo | + | / /foo/ | /foo | / | + / /foo | /foo | / | + /" + maxLength: 1024 + type: string + type: + description: "Type defines the type of path modifier. + Additional types may be added in a future release + of the API. \n Note that values may be added + to this enum, implementations must ensure that + unknown values will not cause a crash. \n Unknown + values here must result in the implementation + setting the Accepted Condition for the Route + to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when + type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) + : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath + is set + rule: 'has(self.replaceFullPath) ? self.type == + ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when + type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) + : true' + - message: type must be 'ReplacePrefixMatch' when + replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + type: object required: - type type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the + filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != + ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == + ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the + filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != + ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror + filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the filter.type + is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != ''RequestRedirect'')' + - message: filter.requestRedirect must be specified for RequestRedirect + filter.type + rule: '!(!has(self.requestRedirect) && self.type == ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type + is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite + filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef + filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' maxItems: 16 type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && + self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() <= + 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 matches: default: - path: @@ -1841,29 +5919,33 @@ spec: rule against incoming HTTP requests. Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied. \n For example, take the following matches configuration: - \n ``` matches: - path: value: \"/foo\" headers: - - name: \"version\" value: \"v2\" - path: value: \"/v2/foo\" - ``` \n For a request to match against this rule, a request - must satisfy EITHER of the two conditions: \n - path prefixed - with `/foo` AND contains the header `version: v2` - path prefix - of `/v2/foo` \n See the documentation for HTTPRouteMatch on - how to specify multiple match conditions that should be ANDed - together. \n If no matches are specified, the default is a - prefix path match on \"/\", which has the effect of matching - every HTTP request. \n Proxy or Load Balancer routing configuration - generated from HTTPRoutes MUST prioritize rules based on the - following criteria, continuing on ties. Precedence must be - given to the the Rule with the largest number of: \n * Characters - in a matching non-wildcard hostname. * Characters in a matching - hostname. * Characters in a matching path. * Header matches. - * Query param matches. \n If ties still exist across multiple + \n ``` matches: - path: value: \"/foo\" headers: - name: \"version\" + value: \"v2\" - path: value: \"/v2/foo\" ``` \n For a request + to match against this rule, a request must satisfy EITHER + of the two conditions: \n - path prefixed with `/foo` AND + contains the header `version: v2` - path prefix of `/v2/foo` + \n See the documentation for HTTPRouteMatch on how to specify + multiple match conditions that should be ANDed together. \n + If no matches are specified, the default is a prefix path + match on \"/\", which has the effect of matching every HTTP + request. \n Proxy or Load Balancer routing configuration generated + from HTTPRoutes MUST prioritize matches based on the following + criteria, continuing on ties. Across all rules specified on + applicable Routes, precedence must be given to the match having: + \n * \"Exact\" path match. * \"Prefix\" path match with largest + number of characters. * Method match. * Largest number of + header matches. * Largest number of query param matches. \n + Note: The precedence of RegularExpression path matches are + implementation-specific. \n If ties still exist across multiple Routes, matching precedence MUST be determined in order of the following criteria, continuing on ties: \n * The oldest Route based on creation timestamp. * The Route appearing first - in alphabetical order by \"/\". \n If ties - still exist within the Route that has been given precedence, - matching precedence MUST be granted to the first matching - rule meeting the above criteria." + in alphabetical order by \"{namespace}/{name}\". \n If ties + still exist within an HTTPRoute, matching precedence MUST + be granted to the FIRST matching rule (in list order) with + a match meeting the above criteria. \n When no rules matching + a request have been successfully attached to the parent a + request is coming from, a HTTP 404 status code MUST be returned." items: description: "HTTPRouteMatch defines the predicate used to match requests to a given action. Multiple match types are @@ -1871,8 +5953,8 @@ spec: if all conditions are satisfied. \n For example, the match below will match a HTTP request only if its path starts with `/foo` AND it contains the `version: v1` header: \n - ``` match: path: value: \"/foo\" headers: - name: - \"version\" value \"v1\" ```" + ``` match: \n path: value: \"/foo\" headers: - name: \"version\" + value \"v1\" \n ```" properties: headers: description: Headers specifies HTTP request header matchers. @@ -1907,12 +5989,12 @@ spec: default: Exact description: "Type specifies how to match against the value of the header. \n Support: Core (Exact) - \n Support: Custom (RegularExpression) \n Since - RegularExpression HeaderMatchType has custom conformance, - implementations can support POSIX, PCRE or any - other dialects of regular expressions. Please - read the implementation's documentation to determine - the supported dialect." + \n Support: Implementation-specific (RegularExpression) + \n Since RegularExpression HeaderMatchType has + implementation-specific conformance, implementations + can support POSIX, PCRE or any other dialects + of regular expressions. Please read the implementation's + documentation to determine the supported dialect." enum: - Exact - RegularExpression @@ -1959,7 +6041,7 @@ spec: default: PathPrefix description: "Type specifies how to match against the path Value. \n Support: Core (Exact, PathPrefix) - \n Support: Custom (RegularExpression)" + \n Support: Implementation-specific (RegularExpression)" enum: - Exact - PathPrefix @@ -1971,30 +6053,93 @@ spec: maxLength: 1024 type: string type: object + x-kubernetes-validations: + - message: value must be an absolute path and start with + '/' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.startsWith(''/'') + : true' + - message: must not contain '//' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''//'') + : true' + - message: must not contain '/./' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/./'') + : true' + - message: must not contain '/../' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/../'') + : true' + - message: must not contain '%2f' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2f'') + : true' + - message: must not contain '%2F' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2F'') + : true' + - message: must not contain '#' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''#'') + : true' + - message: must not end with '/..' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/..'') + : true' + - message: must not end with '/.' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/.'') + : true' + - message: type must be one of ['Exact', 'PathPrefix', + 'RegularExpression'] + rule: self.type in ['Exact','PathPrefix'] || self.type + == 'RegularExpression' + - message: must only contain valid characters (matching + ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) + for types ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") + : true' queryParams: - description: QueryParams specifies HTTP query parameter + description: "QueryParams specifies HTTP query parameter matchers. Multiple match values are ANDed together, meaning, a request must match all the specified query - parameters to select the route. + parameters to select the route. \n Support: Extended" items: description: HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP query parameters. properties: name: - description: Name is the name of the HTTP query + description: "Name is the name of the HTTP query param to be matched. This must be an exact string match. (See https://tools.ietf.org/html/rfc7230#section-2.7.3). + \n If multiple entries specify equivalent query + param names, only the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent query param name MUST + be ignored. \n If a query param is repeated in + an HTTP request, the behavior is purposely left + undefined, since different data planes have different + capabilities. However, it is *recommended* that + implementations should match against the first + value of the param if the data plane supports + it, as this behavior is expected in other load + balancing contexts outside of the Gateway API. + \n Users SHOULD NOT route traffic based on repeated + query params to guard themselves against potential + differences in the implementations." maxLength: 256 minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ type: string type: default: Exact description: "Type specifies how to match against the value of the query parameter. \n Support: - Extended (Exact) \n Support: Custom (RegularExpression) - \n Since RegularExpression QueryParamMatchType - has custom conformance, implementations can support - POSIX, PCRE or any other dialects of regular expressions. + Extended (Exact) \n Support: Implementation-specific + (RegularExpression) \n Since RegularExpression + QueryParamMatchType has Implementation-specific + conformance, implementations can support POSIX, + PCRE or any other dialects of regular expressions. Please read the implementation's documentation to determine the supported dialect." enum: @@ -2019,7 +6164,89 @@ spec: type: object maxItems: 8 type: array + timeouts: + description: "Timeouts defines the timeouts that can be configured + for an HTTP request. \n Support: Extended \n " + properties: + backendRequest: + description: "BackendRequest specifies a timeout for an + individual request from the gateway to a backend. This + covers the time from when the request first starts being + sent from the gateway to when the full response has been + received from the backend. \n An entire client HTTP transaction + with a gateway, covered by the Request timeout, may result + in more than one call from the gateway to the destination + backend, for example, if automatic retries are supported. + \n Because the Request timeout encompasses the BackendRequest + timeout, the value of BackendRequest must be <= the value + of Request timeout. \n Support: Extended" + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + request: + description: "Request specifies the maximum duration for + a gateway to respond to an HTTP request. If the gateway + has not been able to respond before this deadline is met, + the gateway MUST return a timeout error. \n For example, + setting the `rules.timeouts.request` field to the value + `10s` in an `HTTPRoute` will cause a timeout if a client + request is taking longer than 10 seconds to complete. + \n This timeout is intended to cover as close to the whole + request-response transaction as possible although an implementation + MAY choose to start the timeout after the entire request + stream has been received instead of immediately after + the transaction is initiated by the client. \n When this + field is unspecified, request timeout behavior is implementation-specific. + \n Support: Extended" + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + type: object + x-kubernetes-validations: + - message: backendRequest timeout cannot be longer than request + timeout + rule: '!(has(self.request) && has(self.backendRequest) && + duration(self.request) != duration(''0s'') && duration(self.backendRequest) + > duration(self.request))' type: object + x-kubernetes-validations: + - message: RequestRedirect filter must not be used together with + backendRefs + rule: '(has(self.backendRefs) && size(self.backendRefs) > 0) ? + (!has(self.filters) || self.filters.all(f, !has(f.requestRedirect))): + true' + - message: When using RequestRedirect filter with path.replacePrefixMatch, + exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.requestRedirect) + && has(f.requestRedirect.path) && f.requestRedirect.path.type + == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) + ? ((size(self.matches) != 1 || !has(self.matches[0].path) || + self.matches[0].path.type != ''PathPrefix'') ? false : true) + : true' + - message: When using URLRewrite filter with path.replacePrefixMatch, + exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.urlRewrite) + && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' + && has(f.urlRewrite.path.replacePrefixMatch))) ? ((size(self.matches) + != 1 || !has(self.matches[0].path) || self.matches[0].path.type + != ''PathPrefix'') ? false : true) : true' + - message: Within backendRefs, when using RequestRedirect filter + with path.replacePrefixMatch, exactly one PathPrefix match must + be specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, + (has(b.filters) && b.filters.exists_one(f, has(f.requestRedirect) + && has(f.requestRedirect.path) && f.requestRedirect.path.type + == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) + )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) + || self.matches[0].path.type != ''PathPrefix'') ? false : true) + : true' + - message: Within backendRefs, When using URLRewrite filter with + path.replacePrefixMatch, exactly one PathPrefix match must be + specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, + (has(b.filters) && b.filters.exists_one(f, has(f.urlRewrite) + && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' + && has(f.urlRewrite.path.replacePrefixMatch))) )) ? ((size(self.matches) + != 1 || !has(self.matches[0].path) || self.matches[0].path.type + != ''PathPrefix'') ? false : true) : true' maxItems: 16 type: array type: object @@ -2058,20 +6285,20 @@ spec: condition may not be set due to lack of controller visibility, that includes when: \n * The Route refers to a non-existent parent. * The Route is of a type that the controller does - not support. * The Route is in a namespace the the controller + not support. * The Route is in a namespace the controller does not have access to." items: description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path - .status.conditions. For example, type FooStatus struct{ - \ // Represents the observations of a foo's current state. - \ // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // - +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" + .status.conditions. For example, \n type FooStatus struct{ + // Represents the observations of a foo's current state. + // Known .status.conditions.type are: \"Available\", \"Progressing\", + and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields + }" properties: lastTransitionTime: description: lastTransitionTime is the last time the condition @@ -2143,7 +6370,11 @@ spec: with the controllerName field on GatewayClass. \n Example: \"example.net/gateway-controller\". \n The format of this field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid - Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + \n Controllers MUST populate this field when writing status. + Controllers should ensure that entries to status populated + with their ControllerName are cleaned up when they are no + longer necessary." maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ @@ -2154,15 +6385,21 @@ spec: properties: group: default: gateway.networking.k8s.io - description: "Group is the group of the referent. \n Support: - Core" + description: "Group is the group of the referent. When unspecified, + \"gateway.networking.k8s.io\" is inferred. To set the + core API group (such as for a \"Service\" kind referent), + Group must be explicitly set to \"\" (empty string). \n + Support: Core" maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Gateway - description: "Kind is kind of the referent. \n Support: - Core (Gateway) Support: Custom (Other Resources)" + description: "Kind is kind of the referent. \n There are + two kinds of parent resources with \"Core\" support: \n + * Gateway (Gateway conformance profile) * Service (Mesh + conformance profile, experimental, ClusterIP Services + only) \n Support for other resources is Implementation-Specific." maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ @@ -2175,29 +6412,2550 @@ spec: type: string namespace: description: "Namespace is the namespace of the referent. - When unspecified (or empty string), this refers to the - local namespace of the Route. \n Support: Core" + When unspecified, this refers to the local namespace of + the Route. \n Note that there are specific rules for ParentRefs + which cross namespace boundaries. Cross-namespace references + are only valid if they are explicitly allowed by something + in the namespace they are referring to. For example: Gateway + has the AllowedRoutes field, and ReferenceGrant provides + a generic way to enable any other kind of cross-namespace + reference. \n ParentRefs from a Route to a Service in + the same namespace are \"producer\" routes, which apply + default routing rules to inbound connections from any + namespace to the Service. \n ParentRefs from a Route to + a Service in a different namespace are \"consumer\" routes, + and these routing rules are only applied to outbound connections + originating from the same namespace as the Route, for + which the intended destination of the connections are + a Service targeted as a ParentRef of the Route. \n Support: + Core" maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string + port: + description: "Port is the network port this Route targets. + It can be interpreted differently based on the type of + parent resource. \n When the parent resource is a Gateway, + this targets all listeners listening on the specified + port that also support this kind of Route(and select this + Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to + a specific port as opposed to a listener(s) whose port(s) + may be changed. When both Port and SectionName are specified, + the name and port of the selected listener must match + both specified values. \n When the parent resource is + a Service, this targets a specific port in the Service + spec. When both Port (experimental) and SectionName are + specified, the name and port of the selected port must + match both specified values. \n Implementations MAY choose + to support other parent resources. Implementations supporting + other types of parent resources MUST clearly document + how/if Port is interpreted. \n For the purpose of status, + an attachment is considered successful as long as the + parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them + by Route kind, namespace, or hostname. If 1 of 2 Gateway + listeners accept attachment from the referencing Route, + the Route MUST be considered successfully attached. If + no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer sectionName: description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener - Name \n Implementations MAY choose to support attaching - Routes to other resources. If that is the case, they MUST - clearly document how SectionName is interpreted. \n When - unspecified (empty string), this will reference the entire - resource. For the purpose of status, an attachment is - considered successful if at least one section in the parent - resource accepts it. For example, Gateway listeners can - restrict which Routes can attach to them by Route kind, - namespace, or hostname. If 1 of 2 Gateway listeners accept - attachment from the referencing Route, the Route MUST - be considered successfully attached. If no Gateway listeners - accept attachment from this Route, the Route MUST be considered - detached from the Gateway. \n Support: Core" + Name. When both Port (experimental) and SectionName are + specified, the name and port of the selected listener + must match both specified values. * Service: Port Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match + both specified values. Note that attaching Routes to Services + as Parents is part of experimental Mesh support and is + not supported for any other purpose. \n Implementations + MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this + will reference the entire resource. For the purpose of + status, an attachment is considered successful if at least + one section in the parent resource accepts it. For example, + Gateway listeners can restrict which Routes can attach + to them by Route kind, namespace, or hostname. If 1 of + 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.hostnames + name: Hostnames + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: HTTPRoute provides a way to route HTTP requests. This includes + the capability to match requests by hostname, path, header, or query param. + Filters can be used to specify additional processing steps. Backends specify + where matching requests should be routed. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of HTTPRoute. + properties: + hostnames: + description: "Hostnames defines a set of hostnames that should match + against the HTTP Host header to select a HTTPRoute used to process + the request. Implementations MUST ignore any port value specified + in the HTTP Host header while performing a match and (absent of + any applicable header modification configuration) MUST forward this + header unmodified to the backend. \n Valid values for Hostnames + are determined by RFC 1123 definition of a hostname with 2 notable + exceptions: \n 1. IPs are not allowed. 2. A hostname may be prefixed + with a wildcard label (`*.`). The wildcard label must appear by + itself as the first label. \n If a hostname is specified by both + the Listener and HTTPRoute, there must be at least one intersecting + hostname for the HTTPRoute to be attached to the Listener. For example: + \n * A Listener with `test.example.com` as the hostname matches + HTTPRoutes that have either not specified any hostnames, or have + specified at least one of `test.example.com` or `*.example.com`. + * A Listener with `*.example.com` as the hostname matches HTTPRoutes + that have either not specified any hostnames or have specified at + least one hostname that matches the Listener hostname. For example, + `*.example.com`, `test.example.com`, and `foo.test.example.com` + would all match. On the other hand, `example.com` and `test.example.net` + would not match. \n Hostnames that are prefixed with a wildcard + label (`*.`) are interpreted as a suffix match. That means that + a match for `*.example.com` would match both `test.example.com`, + and `foo.test.example.com`, but not `example.com`. \n If both the + Listener and HTTPRoute have specified hostnames, any HTTPRoute hostnames + that do not match the Listener hostname MUST be ignored. For example, + if a Listener specified `*.example.com`, and the HTTPRoute specified + `test.example.com` and `test.example.net`, `test.example.net` must + not be considered for a match. \n If both the Listener and HTTPRoute + have specified hostnames, and none match with the criteria above, + then the HTTPRoute is not accepted. The implementation must raise + an 'Accepted' Condition with a status of `False` in the corresponding + RouteParentStatus. \n In the event that multiple HTTPRoutes specify + intersecting hostnames (e.g. overlapping wildcard matching and exact + matching hostnames), precedence must be given to rules from the + HTTPRoute with the largest number of: \n * Characters in a matching + non-wildcard hostname. * Characters in a matching hostname. \n If + ties exist across multiple Routes, the matching precedence rules + for HTTPRouteMatches takes over. \n Support: Core" + items: + description: "Hostname is the fully qualified domain name of a network + host. This matches the RFC 1123 definition of a hostname with + 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname + may be prefixed with a wildcard label (`*.`). The wildcard label + must appear by itself as the first label. \n Hostname can be \"precise\" + which is a domain name without the terminating dot of a network + host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain + name prefixed with a single wildcard label (e.g. `*.example.com`). + \n Note that as per RFC1035 and RFC1123, a *label* must consist + of lower case alphanumeric characters or '-', and must start and + end with an alphanumeric character. No other punctuation is allowed." + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + description: "ParentRefs references the resources (usually Gateways) + that a Route wants to be attached to. Note that the referenced parent + resource needs to allow this for the attachment to be complete. + For Gateways, that means the Gateway needs to allow attachment from + Routes of this kind and namespace. For Services, that means the + Service must either be in the same namespace for a \"producer\" + route, or the mesh implementation must support and allow \"consumer\" + routes for the referenced Service. ReferenceGrant is not applicable + for governing ParentRefs to Services - it is not possible to create + a \"producer\" route for a Service in a different namespace from + the Route. \n There are two kinds of parent resources with \"Core\" + support: \n * Gateway (Gateway conformance profile) * Service (Mesh + conformance profile, experimental, ClusterIP Services only) This + API may be extended in the future to support additional kinds of + parent resources. \n ParentRefs must be _distinct_. This means either + that: \n * They select different objects. If this is the case, + then parentRef entries are distinct. In terms of fields, this means + that the multi-part key defined by `group`, `kind`, `namespace`, + and `name` must be unique across all parentRef entries in the Route. + * They do not select different objects, but for each optional field + used, each ParentRef that selects the same object must set the same + set of optional fields to different values. If one ParentRef sets + a combination of optional fields, all must set the same combination. + \n Some examples: \n * If one ParentRef sets `sectionName`, all + ParentRefs referencing the same object must also set `sectionName`. + * If one ParentRef sets `port`, all ParentRefs referencing the same + object must also set `port`. * If one ParentRef sets `sectionName` + and `port`, all ParentRefs referencing the same object must also + set `sectionName` and `port`. \n It is possible to separately reference + multiple distinct objects that may be collapsed by an implementation. + For example, some implementations may choose to merge compatible + Gateway Listeners together. If that is the case, the list of routes + attached to those resources should also be merged. \n Note that + for ParentRefs that cross namespace boundaries, there are specific + rules. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For + example, Gateway has the AllowedRoutes field, and ReferenceGrant + provides a generic way to enable other kinds of cross-namespace + reference. \n ParentRefs from a Route to a Service in the same + namespace are \"producer\" routes, which apply default routing rules + to inbound connections from any namespace to the Service. \n ParentRefs + from a Route to a Service in a different namespace are \"consumer\" + routes, and these routing rules are only applied to outbound connections + originating from the same namespace as the Route, for which the + intended destination of the connections are a Service targeted as + a ParentRef of the Route. \n " + items: + description: "ParentReference identifies an API object (usually + a Gateway) that can be considered a parent of this resource (usually + a route). There are two kinds of parent resources with \"Core\" + support: \n * Gateway (Gateway conformance profile) * Service + (Mesh conformance profile, experimental, ClusterIP Services only) + \n This API may be extended in the future to support additional + kinds of parent resources. \n The API object must be valid in + the cluster; the Group and Kind must be registered in the cluster + for this reference to be valid." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, + \"gateway.networking.k8s.io\" is inferred. To set the core + API group (such as for a \"Service\" kind referent), Group + must be explicitly set to \"\" (empty string). \n Support: + Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are two + kinds of parent resources with \"Core\" support: \n * Gateway + (Gateway conformance profile) * Service (Mesh conformance + profile, experimental, ClusterIP Services only) \n Support + for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When + unspecified, this refers to the local namespace of the Route. + \n Note that there are specific rules for ParentRefs which + cross namespace boundaries. Cross-namespace references are + only valid if they are explicitly allowed by something in + the namespace they are referring to. For example: Gateway + has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + \n ParentRefs from a Route to a Service in the same namespace + are \"producer\" routes, which apply default routing rules + to inbound connections from any namespace to the Service. + \n ParentRefs from a Route to a Service in a different namespace + are \"consumer\" routes, and these routing rules are only + applied to outbound connections originating from the same + namespace as the Route, for which the intended destination + of the connections are a Service targeted as a ParentRef of + the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. It + can be interpreted differently based on the type of parent + resource. \n When the parent resource is a Gateway, this targets + all listeners listening on the specified port that also support + this kind of Route(and select this Route). It's not recommended + to set `Port` unless the networking behaviors specified in + a Route must apply to a specific port as opposed to a listener(s) + whose port(s) may be changed. When both Port and SectionName + are specified, the name and port of the selected listener + must match both specified values. \n When the parent resource + is a Service, this targets a specific port in the Service + spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified + values. \n Implementations MAY choose to support other parent + resources. Implementations supporting other types of parent + resources MUST clearly document how/if Port is interpreted. + \n For the purpose of status, an attachment is considered + successful as long as the parent resource accepts it partially. + For example, Gateway listeners can restrict which Routes can + attach to them by Route kind, namespace, or hostname. If 1 + of 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. \n + Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match both + specified values. * Service: Port Name. When both Port (experimental) + and SectionName are specified, the name and port of the selected + listener must match both specified values. Note that attaching + Routes to Services as Parents is part of experimental Mesh + support and is not supported for any other purpose. \n Implementations + MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this will + reference the entire resource. For the purpose of status, + an attachment is considered successful if at least one section + in the parent resource accepts it. For example, Gateway listeners + can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept + attachment from the referencing Route, the Route MUST be considered + successfully attached. If no Gateway listeners accept attachment + from this Route, the Route MUST be considered detached from + the Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + x-kubernetes-validations: + - message: sectionName or port must be specified when parentRefs includes + 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ + == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__)) ? ((!has(p1.sectionName) + || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName + == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) + || p2.port == 0)): true))' + - message: sectionName or port must be unique when parentRefs includes + 2 or more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ + == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) + || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName + == '')) || ( has(p1.sectionName) && has(p2.sectionName) && p1.sectionName + == p2.sectionName)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) + || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port + == p2.port)))) + rules: + default: + - matches: + - path: + type: PathPrefix + value: / + description: Rules are a list of HTTP matchers, filters and actions. + items: + description: HTTPRouteRule defines semantics for matching an HTTP + request based on conditions (matches), processing it (filters), + and forwarding the request to an API object (backendRefs). + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching + requests should be sent. \n Failure behavior here depends + on how many BackendRefs are specified and how many are invalid. + \n If *all* entries in BackendRefs are invalid, and there + are also no filters specified in this route rule, *all* traffic + which matches this rule MUST receive a 500 status code. \n + See the HTTPBackendRef definition for the rules about what + makes a single HTTPBackendRef invalid. \n When a HTTPBackendRef + is invalid, 500 status codes MUST be returned for requests + that would have otherwise been routed to an invalid backend. + If multiple backends are specified, and some are invalid, + the proportion of requests that would otherwise have been + routed to an invalid backend MUST receive a 500 status code. + \n For example, if two backends are specified with equal weights, + and one is invalid, 50 percent of traffic must receive a 500. + Implementations may choose how that 50 percent is determined. + \n Support: Core for Kubernetes Service \n Support: Extended + for Kubernetes ServiceImport \n Support: Implementation-specific + for any other resource \n Support for weight: Core" + items: + description: "HTTPBackendRef defines how a HTTPRoute forwards + a HTTP request. \n Note that when a namespace different + than the local namespace is specified, a ReferenceGrant + object is required in the referent namespace to allow that + namespace's owner to accept the reference. See the ReferenceGrant + documentation for details. \n + \n When the BackendRef points to a Kubernetes Service, implementations + SHOULD honor the appProtocol field if it is set for the + target Service Port. \n Implementations supporting appProtocol + SHOULD recognize the Kubernetes Standard Application Protocols + defined in KEP-3726. \n If a Service appProtocol isn't specified, + an implementation MAY infer the backend protocol through + its own means. Implementations MAY infer the protocol from + the Route type referring to the backend Service. \n If a + Route is not able to send traffic to the backend using the + specified protocol then the backend is considered invalid. + Implementations MUST set the \"ResolvedRefs\" condition + to \"False\" with the \"UnsupportedProtocol\" reason. \n + " + properties: + filters: + description: "Filters defined at this level should be + executed if and only if the request is being forwarded + to the backend defined here. \n Support: Implementation-specific + (For broader support of filters, use the Filters field + in HTTPRouteRule.)" + items: + description: HTTPRouteFilter defines processing steps + that must be completed during the request or response + lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway + implementations. Some examples include request or + response modification, implementing authentication + strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type + of the filter. + properties: + extensionRef: + description: "ExtensionRef is an optional, implementation-specific + extension to the \"filter\" behavior. For example, + resource \"myroutefilter\" in group \"networking.example.net\"). + ExtensionRef MUST NOT be used for core and extended + filters. \n This filter can be used multiple times + within the same rule. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. + For example, "gateway.networking.k8s.io". + When unspecified or empty string, core API + group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For + example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema + for a filter that modifies request headers. \n + Support: Core" + properties: + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It + appends to any existing values associated + with the header name. \n Input: GET /foo HTTP/1.1 + my-header: foo \n Config: add: - name: \"my-header\" + value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 + my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: "Name is the name of the + HTTP Header to be matched. Name matching + MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an + equivalent name MUST be considered for + a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from + the HTTP request before the action. The value + of Remove is a list of HTTP header names. + Note that the header names are case-insensitive + (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: foo + my-header2: bar my-header3: baz \n Config: + remove: [\"my-header1\", \"my-header3\"] \n + Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with + the given header (name, value) before the + action. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: set: - name: \"my-header\" + value: \"bar\" \n Output: GET /foo HTTP/1.1 + my-header: bar" + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: "Name is the name of the + HTTP Header to be matched. Name matching + MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an + equivalent name MUST be considered for + a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: "RequestMirror defines a schema for + a filter that mirrors requests. Requests are sent + to the specified destination, but responses from + that destination are ignored. \n This filter can + be used multiple times within the same rule. Note + that not all implementations will be able to support + mirroring to multiple backends. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource + where mirrored requests are sent. \n Mirrored + requests must be sent only to a single destination + endpoint within this BackendRef, irrespective + of how many endpoints are present within this + BackendRef. \n If the referent cannot be found, + this BackendRef is invalid and must be dropped + from the Gateway. The controller must ensure + the \"ResolvedRefs\" condition on the Route + status is set to `status: False` and not configure + this backend in the underlying implementation. + \n If there is a cross-namespace reference + to an *existing* object that is not allowed + by a ReferenceGrant, the controller must ensure + the \"ResolvedRefs\" condition on the Route + is set to `status: False`, with the \"RefNotPermitted\" + reason and not configure this backend in the + underlying implementation. \n In either error + case, the Message of the `ResolvedRefs` Condition + should be used to provide more detail about + the problem. \n Support: Extended for Kubernetes + Service \n Support: Implementation-specific + for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. + For example, "gateway.networking.k8s.io". + When unspecified or empty string, core + API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource + kind of the referent. For example \"Service\". + \n Defaults to \"Service\" when not specified. + \n ExternalName services can refer to + CNAME DNS records that may live outside + of the cluster and as such are difficult + to reason about in terms of conformance. + They also may not be safe to forward to + (see CVE-2021-25740 for more information). + Implementations SHOULD NOT support ExternalName + Services. \n Support: Core (Services with + a type other than ExternalName) \n Support: + Implementation-specific (Services with + type ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace + of the backend. When unspecified, the + local namespace is inferred. \n Note that + when a namespace different than the local + namespace is specified, a ReferenceGrant + object is required in the referent namespace + to allow that namespace's owner to accept + the reference. See the ReferenceGrant + documentation for details. \n Support: + Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination + port number to use for this resource. + Port is required when the referent is + a Kubernetes Service. In this case, the + port number is the service port number, + not the target port. For other resources, + destination port might be derived from + the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind + == ''Service'') ? has(self.port) : true' + required: + - backendRef + type: object + requestRedirect: + description: "RequestRedirect defines a schema for + a filter that responds to the request with an + HTTP redirection. \n Support: Core" + properties: + hostname: + description: "Hostname is the hostname to be + used in the value of the `Location` header + in the response. When empty, the hostname + in the `Host` header of the request is used. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines parameters used to + modify the path of the incoming request. The + modified path is then used to construct the + `Location` header. When empty, the request + path is used as-is. \n Support: Extended" + properties: + replaceFullPath: + description: ReplaceFullPath specifies the + value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies + the value with which to replace the prefix + match of a request during a rewrite or + redirect. For example, a request to \"/foo/bar\" + with a prefix match of \"/foo\" and a + ReplacePrefixMatch of \"/xyz\" would be + modified to \"/xyz/bar\". \n Note that + this matches the behavior of the PathPrefix + match type. This matches full path elements. + A path element refers to the list of labels + in the path split by the `/` separator. + When specified, a trailing `/` is ignored. + For example, the paths `/abc`, `/abc/`, + and `/abc/def` would all match the prefix + `/abc`, but the path `/abcd` would not. + \n ReplacePrefixMatch is only compatible + with a `PathPrefix` HTTPRouteMatch. Using + any other HTTPRouteMatch type on the same + HTTPRouteRule will result in the implementation + setting the Accepted Condition for the + Route to `status: False`. \n Request Path + | Prefix Match | Replace Prefix | Modified + Path -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | + /xyz/bar /foo/bar | /foo | + /xyz/ | /xyz/bar /foo/bar | + /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | + /xyz/bar /foo | /foo | + /xyz | /xyz /foo/ | /foo + \ | /xyz | /xyz/ /foo/bar + \ | /foo | | + /bar /foo/ | /foo | | / /foo | /foo | + | / /foo/ | /foo + \ | / | / /foo | + /foo | / | /" + maxLength: 1024 + type: string + type: + description: "Type defines the type of path + modifier. Additional types may be added + in a future release of the API. \n Note + that values may be added to this enum, + implementations must ensure that unknown + values will not cause a crash. \n Unknown + values here must result in the implementation + setting the Accepted Condition for the + Route to `status: False`, with a Reason + of `UnsupportedValue`." + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified + when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? + has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when + replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type + == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified + when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' + ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' + when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + port: + description: "Port is the port to be used in + the value of the `Location` header in the + response. \n If no port is specified, the + redirect port MUST be derived using the following + rules: \n * If redirect scheme is not-empty, + the redirect port MUST be the well-known port + associated with the redirect scheme. Specifically + \"http\" to port 80 and \"https\" to port + 443. If the redirect scheme does not have + a well-known port, the listener port of the + Gateway SHOULD be used. * If redirect scheme + is empty, the redirect port MUST be the Gateway + Listener port. \n Implementations SHOULD NOT + add the port number in the 'Location' header + in the following cases: \n * A Location header + that will use HTTP (whether that is determined + via the Listener protocol or the Scheme field) + _and_ use port 80. * A Location header that + will use HTTPS (whether that is determined + via the Listener protocol or the Scheme field) + _and_ use port 443. \n Support: Extended" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: "Scheme is the scheme to be used + in the value of the `Location` header in the + response. When empty, the scheme of the request + is used. \n Scheme redirects can affect the + port of the redirect, for more information, + refer to the documentation for the port field + of this filter. \n Note that values may be + added to this enum, implementations must ensure + that unknown values will not cause a crash. + \n Unknown values here must result in the + implementation setting the Accepted Condition + for the Route to `status: False`, with a Reason + of `UnsupportedValue`. \n Support: Extended" + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status + code to be used in response. \n Note that + values may be added to this enum, implementations + must ensure that unknown values will not cause + a crash. \n Unknown values here must result + in the implementation setting the Accepted + Condition for the Route to `status: False`, + with a Reason of `UnsupportedValue`. \n Support: + Core" + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: "ResponseHeaderModifier defines a schema + for a filter that modifies response headers. \n + Support: Extended" + properties: + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It + appends to any existing values associated + with the header name. \n Input: GET /foo HTTP/1.1 + my-header: foo \n Config: add: - name: \"my-header\" + value: \"bar,baz\" \n Output: GET /foo HTTP/1.1 + my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: "Name is the name of the + HTTP Header to be matched. Name matching + MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an + equivalent name MUST be considered for + a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from + the HTTP request before the action. The value + of Remove is a list of HTTP header names. + Note that the header names are case-insensitive + (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: foo + my-header2: bar my-header3: baz \n Config: + remove: [\"my-header1\", \"my-header3\"] \n + Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with + the given header (name, value) before the + action. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: set: - name: \"my-header\" + value: \"bar\" \n Output: GET /foo HTTP/1.1 + my-header: bar" + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: "Name is the name of the + HTTP Header to be matched. Name matching + MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an + equivalent name MUST be considered for + a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: "Type identifies the type of filter + to apply. As with other API fields, types are + classified into three conformance levels: \n - + Core: Filter types and their corresponding configuration + defined by \"Support: Core\" in this package, + e.g. \"RequestHeaderModifier\". All implementations + must support core filters. \n - Extended: Filter + types and their corresponding configuration defined + by \"Support: Extended\" in this package, e.g. + \"RequestMirror\". Implementers are encouraged + to support extended filters. \n - Implementation-specific: + Filters that are defined and supported by specific + vendors. In the future, filters showing convergence + in behavior across multiple implementations will + be considered for inclusion in extended or core + conformance levels. Filter-specific configuration + for such filters is specified using the ExtensionRef + field. `Type` should be set to \"ExtensionRef\" + for custom filters. \n Implementers are encouraged + to define custom implementation types to extend + the core API with implementation-specific behavior. + \n If a reference to a custom filter type cannot + be resolved, the filter MUST NOT be skipped. Instead, + requests that would have been processed by that + filter MUST receive a HTTP error response. \n + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause + a crash. \n Unknown values here must result in + the implementation setting the Accepted Condition + for the Route to `status: False`, with a Reason + of `UnsupportedValue`." + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: "URLRewrite defines a schema for a + filter that modifies a request during forwarding. + \n Support: Extended" + properties: + hostname: + description: "Hostname is the value to be used + to replace the Host header value during forwarding. + \n Support: Extended" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines a path rewrite. \n + Support: Extended" + properties: + replaceFullPath: + description: ReplaceFullPath specifies the + value with which to replace the full path + of a request during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies + the value with which to replace the prefix + match of a request during a rewrite or + redirect. For example, a request to \"/foo/bar\" + with a prefix match of \"/foo\" and a + ReplacePrefixMatch of \"/xyz\" would be + modified to \"/xyz/bar\". \n Note that + this matches the behavior of the PathPrefix + match type. This matches full path elements. + A path element refers to the list of labels + in the path split by the `/` separator. + When specified, a trailing `/` is ignored. + For example, the paths `/abc`, `/abc/`, + and `/abc/def` would all match the prefix + `/abc`, but the path `/abcd` would not. + \n ReplacePrefixMatch is only compatible + with a `PathPrefix` HTTPRouteMatch. Using + any other HTTPRouteMatch type on the same + HTTPRouteRule will result in the implementation + setting the Accepted Condition for the + Route to `status: False`. \n Request Path + | Prefix Match | Replace Prefix | Modified + Path -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | + /xyz/bar /foo/bar | /foo | + /xyz/ | /xyz/bar /foo/bar | + /foo/ | /xyz | /xyz/bar + /foo/bar | /foo/ | /xyz/ | + /xyz/bar /foo | /foo | + /xyz | /xyz /foo/ | /foo + \ | /xyz | /xyz/ /foo/bar + \ | /foo | | + /bar /foo/ | /foo | | / /foo | /foo | + | / /foo/ | /foo + \ | / | / /foo | + /foo | / | /" + maxLength: 1024 + type: string + type: + description: "Type defines the type of path + modifier. Additional types may be added + in a future release of the API. \n Note + that values may be added to this enum, + implementations must ensure that unknown + values will not cause a crash. \n Unknown + values here must result in the implementation + setting the Accepted Condition for the + Route to `status: False`, with a Reason + of `UnsupportedValue`." + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified + when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? + has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when + replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type + == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified + when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' + ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' + when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil + if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type + != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type + == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil + if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type + != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for + RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == + ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the + filter.type is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != + ''RequestRedirect'')' + - message: filter.requestRedirect must be specified + for RequestRedirect filter.type + rule: '!(!has(self.requestRedirect) && self.type == + ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type + is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite + filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for + ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') + && self.exists(f, f.type == ''URLRewrite''))' + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') + && self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() + <= 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() + <= 1 + group: + default: "" + description: Group is the group of the referent. For example, + "gateway.networking.k8s.io". When unspecified or empty + string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource kind of + the referent. For example \"Service\". \n Defaults to + \"Service\" when not specified. \n ExternalName services + can refer to CNAME DNS records that may live outside + of the cluster and as such are difficult to reason about + in terms of conformance. They also may not be safe to + forward to (see CVE-2021-25740 for more information). + Implementations SHOULD NOT support ExternalName Services. + \n Support: Core (Services with a type other than ExternalName) + \n Support: Implementation-specific (Services with type + ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a namespace different than the local + namespace is specified, a ReferenceGrant object is required + in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferenceGrant + documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number + to use for this resource. Port is required when the + referent is a Kubernetes Service. In this case, the + port number is the service port number, not the target + port. For other resources, destination port might be + derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests + forwarded to the referenced backend. This is computed + as weight/(sum of all weights in this BackendRefs list). + For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision + an implementation supports. Weight is not a percentage + and the sum of weights does not need to equal 100. \n + If only one backend is specified and it has a weight + greater than 0, 100% of the traffic is forwarded to + that backend. If weight is set to 0, no traffic should + be forwarded for this entry. If unspecified, weight + defaults to 1. \n Support for this field varies based + on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + maxItems: 16 + type: array + filters: + description: "Filters define the filters that are applied to + requests that match this rule. \n The effects of ordering + of multiple behaviors are currently unspecified. This can + change in the future based on feedback during the alpha stage. + \n Conformance-levels at this level are defined based on the + type of filter: \n - ALL core filters MUST be supported by + all implementations. - Implementers are encouraged to support + extended filters. - Implementation-specific custom filters + have no API guarantees across implementations. \n Specifying + the same filter multiple times is not supported unless explicitly + indicated in the filter. \n All filters are expected to be + compatible with each other except for the URLRewrite and RequestRedirect + filters, which may not be combined. If an implementation can + not support other combinations of filters, they must clearly + document that limitation. In cases where incompatible or unsupported + filters are specified and cause the `Accepted` condition to + be set to status `False`, implementations may use the `IncompatibleFilters` + reason to specify this configuration error. \n Support: Core" + items: + description: HTTPRouteFilter defines processing steps that + must be completed during the request or response lifecycle. + HTTPRouteFilters are meant as an extension point to express + processing that may be done in Gateway implementations. + Some examples include request or response modification, + implementing authentication strategies, rate-limiting, and + traffic shaping. API guarantee/conformance is defined based + on the type of the filter. + properties: + extensionRef: + description: "ExtensionRef is an optional, implementation-specific + extension to the \"filter\" behavior. For example, + resource \"myroutefilter\" in group \"networking.example.net\"). + ExtensionRef MUST NOT be used for core and extended + filters. \n This filter can be used multiple times within + the same rule. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. For + example, "gateway.networking.k8s.io". When unspecified + or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example + "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema for + a filter that modifies request headers. \n Support: + Core" + properties: + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It appends + to any existing values associated with the header + name. \n Input: GET /foo HTTP/1.1 my-header: foo + \n Config: add: - name: \"my-header\" value: \"bar,baz\" + \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case + insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the + HTTP request before the action. The value of Remove + is a list of HTTP header names. Note that the header + names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: + bar my-header3: baz \n Config: remove: [\"my-header1\", + \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: + bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the + given header (name, value) before the action. \n + Input: GET /foo HTTP/1.1 my-header: foo \n Config: + set: - name: \"my-header\" value: \"bar\" \n Output: + GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case + insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: "RequestMirror defines a schema for a filter + that mirrors requests. Requests are sent to the specified + destination, but responses from that destination are + ignored. \n This filter can be used multiple times within + the same rule. Note that not all implementations will + be able to support mirroring to multiple backends. \n + Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource where + mirrored requests are sent. \n Mirrored requests + must be sent only to a single destination endpoint + within this BackendRef, irrespective of how many + endpoints are present within this BackendRef. \n + If the referent cannot be found, this BackendRef + is invalid and must be dropped from the Gateway. + The controller must ensure the \"ResolvedRefs\" + condition on the Route status is set to `status: + False` and not configure this backend in the underlying + implementation. \n If there is a cross-namespace + reference to an *existing* object that is not allowed + by a ReferenceGrant, the controller must ensure + the \"ResolvedRefs\" condition on the Route is + set to `status: False`, with the \"RefNotPermitted\" + reason and not configure this backend in the underlying + implementation. \n In either error case, the Message + of the `ResolvedRefs` Condition should be used to + provide more detail about the problem. \n Support: + Extended for Kubernetes Service \n Support: Implementation-specific + for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. + For example, "gateway.networking.k8s.io". When + unspecified or empty string, core API group + is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource + kind of the referent. For example \"Service\". + \n Defaults to \"Service\" when not specified. + \n ExternalName services can refer to CNAME + DNS records that may live outside of the cluster + and as such are difficult to reason about in + terms of conformance. They also may not be safe + to forward to (see CVE-2021-25740 for more information). + Implementations SHOULD NOT support ExternalName + Services. \n Support: Core (Services with a + type other than ExternalName) \n Support: Implementation-specific + (Services with type ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the + backend. When unspecified, the local namespace + is inferred. \n Note that when a namespace different + than the local namespace is specified, a ReferenceGrant + object is required in the referent namespace + to allow that namespace's owner to accept the + reference. See the ReferenceGrant documentation + for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port + number to use for this resource. Port is required + when the referent is a Kubernetes Service. In + this case, the port number is the service port + number, not the target port. For other resources, + destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + required: + - backendRef + type: object + requestRedirect: + description: "RequestRedirect defines a schema for a filter + that responds to the request with an HTTP redirection. + \n Support: Core" + properties: + hostname: + description: "Hostname is the hostname to be used + in the value of the `Location` header in the response. + When empty, the hostname in the `Host` header of + the request is used. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines parameters used to modify + the path of the incoming request. The modified path + is then used to construct the `Location` header. + When empty, the request path is used as-is. \n Support: + Extended" + properties: + replaceFullPath: + description: ReplaceFullPath specifies the value + with which to replace the full path of a request + during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the + value with which to replace the prefix match + of a request during a rewrite or redirect. For + example, a request to \"/foo/bar\" with a prefix + match of \"/foo\" and a ReplacePrefixMatch of + \"/xyz\" would be modified to \"/xyz/bar\". + \n Note that this matches the behavior of the + PathPrefix match type. This matches full path + elements. A path element refers to the list + of labels in the path split by the `/` separator. + When specified, a trailing `/` is ignored. For + example, the paths `/abc`, `/abc/`, and `/abc/def` + would all match the prefix `/abc`, but the path + `/abcd` would not. \n ReplacePrefixMatch is + only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same + HTTPRouteRule will result in the implementation + setting the Accepted Condition for the Route + to `status: False`. \n Request Path | Prefix + Match | Replace Prefix | Modified Path -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | + /xyz/bar /foo/bar | /foo | /xyz/ + \ | /xyz/bar /foo/bar | /foo/ | + /xyz | /xyz/bar /foo/bar | /foo/ + \ | /xyz/ | /xyz/bar /foo | + /foo | /xyz | /xyz /foo/ | + /foo | /xyz | /xyz/ /foo/bar + \ | /foo | | /bar + /foo/ | /foo | + | / /foo | /foo | + | / /foo/ | /foo | / | + / /foo | /foo | / | + /" + maxLength: 1024 + type: string + type: + description: "Type defines the type of path modifier. + Additional types may be added in a future release + of the API. \n Note that values may be added + to this enum, implementations must ensure that + unknown values will not cause a crash. \n Unknown + values here must result in the implementation + setting the Accepted Condition for the Route + to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when + type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) + : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath + is set + rule: 'has(self.replaceFullPath) ? self.type == + ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when + type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) + : true' + - message: type must be 'ReplacePrefixMatch' when + replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + port: + description: "Port is the port to be used in the value + of the `Location` header in the response. \n If + no port is specified, the redirect port MUST be + derived using the following rules: \n * If redirect + scheme is not-empty, the redirect port MUST be the + well-known port associated with the redirect scheme. + Specifically \"http\" to port 80 and \"https\" to + port 443. If the redirect scheme does not have a + well-known port, the listener port of the Gateway + SHOULD be used. * If redirect scheme is empty, the + redirect port MUST be the Gateway Listener port. + \n Implementations SHOULD NOT add the port number + in the 'Location' header in the following cases: + \n * A Location header that will use HTTP (whether + that is determined via the Listener protocol or + the Scheme field) _and_ use port 80. * A Location + header that will use HTTPS (whether that is determined + via the Listener protocol or the Scheme field) _and_ + use port 443. \n Support: Extended" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: "Scheme is the scheme to be used in the + value of the `Location` header in the response. + When empty, the scheme of the request is used. \n + Scheme redirects can affect the port of the redirect, + for more information, refer to the documentation + for the port field of this filter. \n Note that + values may be added to this enum, implementations + must ensure that unknown values will not cause a + crash. \n Unknown values here must result in the + implementation setting the Accepted Condition for + the Route to `status: False`, with a Reason of `UnsupportedValue`. + \n Support: Extended" + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status code to + be used in response. \n Note that values may be + added to this enum, implementations must ensure + that unknown values will not cause a crash. \n Unknown + values here must result in the implementation setting + the Accepted Condition for the Route to `status: + False`, with a Reason of `UnsupportedValue`. \n + Support: Core" + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + description: "ResponseHeaderModifier defines a schema + for a filter that modifies response headers. \n Support: + Extended" + properties: + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It appends + to any existing values associated with the header + name. \n Input: GET /foo HTTP/1.1 my-header: foo + \n Config: add: - name: \"my-header\" value: \"bar,baz\" + \n Output: GET /foo HTTP/1.1 my-header: foo,bar,baz" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case + insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the + HTTP request before the action. The value of Remove + is a list of HTTP header names. Note that the header + names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: + bar my-header3: baz \n Config: remove: [\"my-header1\", + \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: + bar" + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: "Set overwrites the request with the + given header (name, value) before the action. \n + Input: GET /foo HTTP/1.1 my-header: foo \n Config: + set: - name: \"my-header\" value: \"bar\" \n Output: + GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case + insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + description: "Type identifies the type of filter to apply. + As with other API fields, types are classified into + three conformance levels: \n - Core: Filter types and + their corresponding configuration defined by \"Support: + Core\" in this package, e.g. \"RequestHeaderModifier\". + All implementations must support core filters. \n - + Extended: Filter types and their corresponding configuration + defined by \"Support: Extended\" in this package, e.g. + \"RequestMirror\". Implementers are encouraged to support + extended filters. \n - Implementation-specific: Filters + that are defined and supported by specific vendors. + In the future, filters showing convergence in behavior + across multiple implementations will be considered for + inclusion in extended or core conformance levels. Filter-specific + configuration for such filters is specified using the + ExtensionRef field. `Type` should be set to \"ExtensionRef\" + for custom filters. \n Implementers are encouraged to + define custom implementation types to extend the core + API with implementation-specific behavior. \n If a reference + to a custom filter type cannot be resolved, the filter + MUST NOT be skipped. Instead, requests that would have + been processed by that filter MUST receive a HTTP error + response. \n Note that values may be added to this enum, + implementations must ensure that unknown values will + not cause a crash. \n Unknown values here must result + in the implementation setting the Accepted Condition + for the Route to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: "URLRewrite defines a schema for a filter + that modifies a request during forwarding. \n Support: + Extended" + properties: + hostname: + description: "Hostname is the value to be used to + replace the Host header value during forwarding. + \n Support: Extended" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines a path rewrite. \n Support: + Extended" + properties: + replaceFullPath: + description: ReplaceFullPath specifies the value + with which to replace the full path of a request + during a rewrite or redirect. + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the + value with which to replace the prefix match + of a request during a rewrite or redirect. For + example, a request to \"/foo/bar\" with a prefix + match of \"/foo\" and a ReplacePrefixMatch of + \"/xyz\" would be modified to \"/xyz/bar\". + \n Note that this matches the behavior of the + PathPrefix match type. This matches full path + elements. A path element refers to the list + of labels in the path split by the `/` separator. + When specified, a trailing `/` is ignored. For + example, the paths `/abc`, `/abc/`, and `/abc/def` + would all match the prefix `/abc`, but the path + `/abcd` would not. \n ReplacePrefixMatch is + only compatible with a `PathPrefix` HTTPRouteMatch. + Using any other HTTPRouteMatch type on the same + HTTPRouteRule will result in the implementation + setting the Accepted Condition for the Route + to `status: False`. \n Request Path | Prefix + Match | Replace Prefix | Modified Path -------------|--------------|----------------|---------- + /foo/bar | /foo | /xyz | + /xyz/bar /foo/bar | /foo | /xyz/ + \ | /xyz/bar /foo/bar | /foo/ | + /xyz | /xyz/bar /foo/bar | /foo/ + \ | /xyz/ | /xyz/bar /foo | + /foo | /xyz | /xyz /foo/ | + /foo | /xyz | /xyz/ /foo/bar + \ | /foo | | /bar + /foo/ | /foo | + | / /foo | /foo | + | / /foo/ | /foo | / | + / /foo | /foo | / | + /" + maxLength: 1024 + type: string + type: + description: "Type defines the type of path modifier. + Additional types may be added in a future release + of the API. \n Note that values may be added + to this enum, implementations must ensure that + unknown values will not cause a crash. \n Unknown + values here must result in the implementation + setting the Accepted Condition for the Route + to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when + type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) + : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath + is set + rule: 'has(self.replaceFullPath) ? self.type == + ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when + type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) + : true' + - message: type must be 'ReplacePrefixMatch' when + replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type + == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the + filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != + ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified + for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == + ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the + filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != + ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified + for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type + == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type + is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror + filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the filter.type + is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != ''RequestRedirect'')' + - message: filter.requestRedirect must be specified for RequestRedirect + filter.type + rule: '!(!has(self.requestRedirect) && self.type == ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type + is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite + filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type + is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef + filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect + or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && + self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() + <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() + <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() <= + 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 + matches: + default: + - path: + type: PathPrefix + value: / + description: "Matches define conditions used for matching the + rule against incoming HTTP requests. Each match is independent, + i.e. this rule will be matched if **any** one of the matches + is satisfied. \n For example, take the following matches configuration: + \n ``` matches: - path: value: \"/foo\" headers: - name: \"version\" + value: \"v2\" - path: value: \"/v2/foo\" ``` \n For a request + to match against this rule, a request must satisfy EITHER + of the two conditions: \n - path prefixed with `/foo` AND + contains the header `version: v2` - path prefix of `/v2/foo` + \n See the documentation for HTTPRouteMatch on how to specify + multiple match conditions that should be ANDed together. \n + If no matches are specified, the default is a prefix path + match on \"/\", which has the effect of matching every HTTP + request. \n Proxy or Load Balancer routing configuration generated + from HTTPRoutes MUST prioritize matches based on the following + criteria, continuing on ties. Across all rules specified on + applicable Routes, precedence must be given to the match having: + \n * \"Exact\" path match. * \"Prefix\" path match with largest + number of characters. * Method match. * Largest number of + header matches. * Largest number of query param matches. \n + Note: The precedence of RegularExpression path matches are + implementation-specific. \n If ties still exist across multiple + Routes, matching precedence MUST be determined in order of + the following criteria, continuing on ties: \n * The oldest + Route based on creation timestamp. * The Route appearing first + in alphabetical order by \"{namespace}/{name}\". \n If ties + still exist within an HTTPRoute, matching precedence MUST + be granted to the FIRST matching rule (in list order) with + a match meeting the above criteria. \n When no rules matching + a request have been successfully attached to the parent a + request is coming from, a HTTP 404 status code MUST be returned." + items: + description: "HTTPRouteMatch defines the predicate used to + match requests to a given action. Multiple match types are + ANDed together, i.e. the match will evaluate to true only + if all conditions are satisfied. \n For example, the match + below will match a HTTP request only if its path starts + with `/foo` AND it contains the `version: v1` header: \n + ``` match: \n path: value: \"/foo\" headers: - name: \"version\" + value \"v1\" \n ```" + properties: + headers: + description: Headers specifies HTTP request header matchers. + Multiple match values are ANDed together, meaning, a + request must match all the specified headers to select + the route. + items: + description: HTTPHeaderMatch describes how to select + a HTTP route by matching HTTP request headers. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case insensitive. + (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent header + names, only the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be + ignored. Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered equivalent. + \n When a header is repeated in an HTTP request, + it is implementation-specific behavior as to how + this is represented. Generally, proxies should + follow the guidance from the RFC: https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 + regarding processing a repeated header, with special + handling for \"Set-Cookie\"." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: "Type specifies how to match against + the value of the header. \n Support: Core (Exact) + \n Support: Implementation-specific (RegularExpression) + \n Since RegularExpression HeaderMatchType has + implementation-specific conformance, implementations + can support POSIX, PCRE or any other dialects + of regular expressions. Please read the implementation's + documentation to determine the supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to + be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + description: "Method specifies HTTP method matcher. When + specified, this route will be matched only if the request + has the specified method. \n Support: Extended" + enum: + - GET + - HEAD + - POST + - PUT + - DELETE + - CONNECT + - OPTIONS + - TRACE + - PATCH + type: string + path: + default: + type: PathPrefix + value: / + description: Path specifies a HTTP request path matcher. + If this field is not specified, a default prefix match + on the "/" path is provided. + properties: + type: + default: PathPrefix + description: "Type specifies how to match against + the path Value. \n Support: Core (Exact, PathPrefix) + \n Support: Implementation-specific (RegularExpression)" + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + x-kubernetes-validations: + - message: value must be an absolute path and start with + '/' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.startsWith(''/'') + : true' + - message: must not contain '//' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''//'') + : true' + - message: must not contain '/./' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/./'') + : true' + - message: must not contain '/../' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/../'') + : true' + - message: must not contain '%2f' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2f'') + : true' + - message: must not contain '%2F' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2F'') + : true' + - message: must not contain '#' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''#'') + : true' + - message: must not end with '/..' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/..'') + : true' + - message: must not end with '/.' when type one of ['Exact', + 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/.'') + : true' + - message: type must be one of ['Exact', 'PathPrefix', + 'RegularExpression'] + rule: self.type in ['Exact','PathPrefix'] || self.type + == 'RegularExpression' + - message: must only contain valid characters (matching + ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) + for types ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") + : true' + queryParams: + description: "QueryParams specifies HTTP query parameter + matchers. Multiple match values are ANDed together, + meaning, a request must match all the specified query + parameters to select the route. \n Support: Extended" + items: + description: HTTPQueryParamMatch describes how to select + a HTTP route by matching HTTP query parameters. + properties: + name: + description: "Name is the name of the HTTP query + param to be matched. This must be an exact string + match. (See https://tools.ietf.org/html/rfc7230#section-2.7.3). + \n If multiple entries specify equivalent query + param names, only the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent query param name MUST + be ignored. \n If a query param is repeated in + an HTTP request, the behavior is purposely left + undefined, since different data planes have different + capabilities. However, it is *recommended* that + implementations should match against the first + value of the param if the data plane supports + it, as this behavior is expected in other load + balancing contexts outside of the Gateway API. + \n Users SHOULD NOT route traffic based on repeated + query params to guard themselves against potential + differences in the implementations." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: "Type specifies how to match against + the value of the query parameter. \n Support: + Extended (Exact) \n Support: Implementation-specific + (RegularExpression) \n Since RegularExpression + QueryParamMatchType has Implementation-specific + conformance, implementations can support POSIX, + PCRE or any other dialects of regular expressions. + Please read the implementation's documentation + to determine the supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param + to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 8 + type: array + timeouts: + description: "Timeouts defines the timeouts that can be configured + for an HTTP request. \n Support: Extended \n " + properties: + backendRequest: + description: "BackendRequest specifies a timeout for an + individual request from the gateway to a backend. This + covers the time from when the request first starts being + sent from the gateway to when the full response has been + received from the backend. \n An entire client HTTP transaction + with a gateway, covered by the Request timeout, may result + in more than one call from the gateway to the destination + backend, for example, if automatic retries are supported. + \n Because the Request timeout encompasses the BackendRequest + timeout, the value of BackendRequest must be <= the value + of Request timeout. \n Support: Extended" + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + request: + description: "Request specifies the maximum duration for + a gateway to respond to an HTTP request. If the gateway + has not been able to respond before this deadline is met, + the gateway MUST return a timeout error. \n For example, + setting the `rules.timeouts.request` field to the value + `10s` in an `HTTPRoute` will cause a timeout if a client + request is taking longer than 10 seconds to complete. + \n This timeout is intended to cover as close to the whole + request-response transaction as possible although an implementation + MAY choose to start the timeout after the entire request + stream has been received instead of immediately after + the transaction is initiated by the client. \n When this + field is unspecified, request timeout behavior is implementation-specific. + \n Support: Extended" + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + type: object + x-kubernetes-validations: + - message: backendRequest timeout cannot be longer than request + timeout + rule: '!(has(self.request) && has(self.backendRequest) && + duration(self.request) != duration(''0s'') && duration(self.backendRequest) + > duration(self.request))' + type: object + x-kubernetes-validations: + - message: RequestRedirect filter must not be used together with + backendRefs + rule: '(has(self.backendRefs) && size(self.backendRefs) > 0) ? + (!has(self.filters) || self.filters.all(f, !has(f.requestRedirect))): + true' + - message: When using RequestRedirect filter with path.replacePrefixMatch, + exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.requestRedirect) + && has(f.requestRedirect.path) && f.requestRedirect.path.type + == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) + ? ((size(self.matches) != 1 || !has(self.matches[0].path) || + self.matches[0].path.type != ''PathPrefix'') ? false : true) + : true' + - message: When using URLRewrite filter with path.replacePrefixMatch, + exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.urlRewrite) + && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' + && has(f.urlRewrite.path.replacePrefixMatch))) ? ((size(self.matches) + != 1 || !has(self.matches[0].path) || self.matches[0].path.type + != ''PathPrefix'') ? false : true) : true' + - message: Within backendRefs, when using RequestRedirect filter + with path.replacePrefixMatch, exactly one PathPrefix match must + be specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, + (has(b.filters) && b.filters.exists_one(f, has(f.requestRedirect) + && has(f.requestRedirect.path) && f.requestRedirect.path.type + == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) + )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) + || self.matches[0].path.type != ''PathPrefix'') ? false : true) + : true' + - message: Within backendRefs, When using URLRewrite filter with + path.replacePrefixMatch, exactly one PathPrefix match must be + specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, + (has(b.filters) && b.filters.exists_one(f, has(f.urlRewrite) + && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' + && has(f.urlRewrite.path.replacePrefixMatch))) )) ? ((size(self.matches) + != 1 || !has(self.matches[0].path) || self.matches[0].path.type + != ''PathPrefix'') ? false : true) : true' + maxItems: 16 + type: array + type: object + status: + description: Status defines the current state of HTTPRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) + that are associated with the route, and the status of the route + with respect to each parent. When this route attaches to a parent, + the controller that manages the parent must add an entry to this + list when the controller first sees the route and should update + the entry as appropriate when the route or gateway is modified. + \n Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this + API can only populate Route status for the Gateways/parent resources + they are responsible for. \n A maximum of 32 Gateways will be represented + in this list. An empty list means the route has not been attached + to any Gateway." + items: + description: RouteParentStatus describes the status of a route with + respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with + respect to the Gateway. Note that the route's availability + is also subject to the Gateway's own status conditions and + listener status. \n If the Route's ParentRef specifies an + existing Gateway that supports Routes of this kind AND that + Gateway's controller has sufficient access, then that Gateway's + controller MUST set the \"Accepted\" condition on the Route, + to indicate whether the route has been accepted or rejected + by the Gateway, and why. \n A Route MUST be considered \"Accepted\" + if at least one of the Route's rules is implemented by the + Gateway. \n There are a number of cases where the \"Accepted\" + condition may not be set due to lack of controller visibility, + that includes when: \n * The Route refers to a non-existent + parent. * The Route is of a type that the controller does + not support. * The Route is in a namespace the controller + does not have access to." + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, \n type FooStatus struct{ + // Represents the observations of a foo's current state. + // Known .status.conditions.type are: \"Available\", \"Progressing\", + and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields + }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates + the name of the controller that wrote this status. This corresponds + with the controllerName field on GatewayClass. \n Example: + \"example.net/gateway-controller\". \n The format of this + field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + \n Controllers MUST populate this field when writing status. + Controllers should ensure that entries to status populated + with their ControllerName are cleaned up when they are no + longer necessary." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec + that this RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, + \"gateway.networking.k8s.io\" is inferred. To set the + core API group (such as for a \"Service\" kind referent), + Group must be explicitly set to \"\" (empty string). \n + Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are + two kinds of parent resources with \"Core\" support: \n + * Gateway (Gateway conformance profile) * Service (Mesh + conformance profile, experimental, ClusterIP Services + only) \n Support for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified, this refers to the local namespace of + the Route. \n Note that there are specific rules for ParentRefs + which cross namespace boundaries. Cross-namespace references + are only valid if they are explicitly allowed by something + in the namespace they are referring to. For example: Gateway + has the AllowedRoutes field, and ReferenceGrant provides + a generic way to enable any other kind of cross-namespace + reference. \n ParentRefs from a Route to a Service in + the same namespace are \"producer\" routes, which apply + default routing rules to inbound connections from any + namespace to the Service. \n ParentRefs from a Route to + a Service in a different namespace are \"consumer\" routes, + and these routing rules are only applied to outbound connections + originating from the same namespace as the Route, for + which the intended destination of the connections are + a Service targeted as a ParentRef of the Route. \n Support: + Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. + It can be interpreted differently based on the type of + parent resource. \n When the parent resource is a Gateway, + this targets all listeners listening on the specified + port that also support this kind of Route(and select this + Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to + a specific port as opposed to a listener(s) whose port(s) + may be changed. When both Port and SectionName are specified, + the name and port of the selected listener must match + both specified values. \n When the parent resource is + a Service, this targets a specific port in the Service + spec. When both Port (experimental) and SectionName are + specified, the name and port of the selected port must + match both specified values. \n Implementations MAY choose + to support other parent resources. Implementations supporting + other types of parent resources MUST clearly document + how/if Port is interpreted. \n For the purpose of status, + an attachment is considered successful as long as the + parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them + by Route kind, namespace, or hostname. If 1 of 2 Gateway + listeners accept attachment from the referencing Route, + the Route MUST be considered successfully attached. If + no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name. When both Port (experimental) and SectionName are + specified, the name and port of the selected listener + must match both specified values. * Service: Port Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match + both specified values. Note that attaching Routes to Services + as Parents is part of experimental Mesh support and is + not supported for any other purpose. \n Implementations + MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this + will reference the entire resource. For the purpose of + status, an attachment is considered successful if at least + one section in the parent resource accepts it. For example, + Gateway listeners can restrict which Routes can attach + to them by Route kind, namespace, or hostname. If 1 of + 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Core" maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -2225,15 +8983,302 @@ status: acceptedNames: kind: "" plural: "" - conditions: [] - storedVersions: [] - + conditions: null + storedVersions: null --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + name: referencegrants.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: ReferenceGrant + listKind: ReferenceGrantList + plural: referencegrants + shortNames: + - refgrant + singular: referencegrant + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: The v1alpha2 version of ReferenceGrant has been deprecated + and will be removed in a future release of the API. Please upgrade to v1beta1. + name: v1alpha2 + schema: + openAPIV3Schema: + description: "ReferenceGrant identifies kinds of resources in other namespaces + that are trusted to reference the specified kinds of resources in the same + namespace as the policy. \n Each ReferenceGrant can be used to represent + a unique trust relationship. Additional Reference Grants can be used to + add to the set of trusted sources of inbound references for the namespace + they are defined within. \n A ReferenceGrant is required for all cross-namespace + references in Gateway API (with the exception of cross-namespace Route-Gateway + attachment, which is governed by the AllowedRoutes configuration on the + Gateway, and cross-namespace Service ParentRefs on a \"consumer\" mesh Route, + which defines routing rules applicable only to workloads in the Route namespace). + ReferenceGrants allowing a reference from a Route to a Service are only + applicable to BackendRefs. \n ReferenceGrant is a form of runtime verification + allowing users to assert which cross-namespace object references are permitted. + Implementations that support ReferenceGrant MUST NOT permit cross-namespace + references which have no grant, and MUST respond to the removal of a grant + by revoking the access that the grant allowed." + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of ReferenceGrant. + properties: + from: + description: "From describes the trusted namespaces and kinds that + can reference the resources described in \"To\". Each entry in this + list MUST be considered to be an additional place that references + can be valid from, or to put this another way, entries MUST be combined + using OR. \n Support: Core" + items: + description: ReferenceGrantFrom describes trusted namespaces and + kinds. + properties: + group: + description: "Group is the group of the referent. When empty, + the Kubernetes core API group is inferred. \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: "Kind is the kind of the referent. Although implementations + may support additional resources, the following types are + part of the \"Core\" support level for this field. \n When + used to permit a SecretObjectReference: \n * Gateway \n When + used to permit a BackendObjectReference: \n * GRPCRoute * + HTTPRoute * TCPRoute * TLSRoute * UDPRoute" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + namespace: + description: "Namespace is the namespace of the referent. \n + Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - namespace + type: object + maxItems: 16 + minItems: 1 + type: array + to: + description: "To describes the resources that may be referenced by + the resources described in \"From\". Each entry in this list MUST + be considered to be an additional place that references can be valid + to, or to put this another way, entries MUST be combined using OR. + \n Support: Core" + items: + description: ReferenceGrantTo describes what Kinds are allowed as + targets of the references. + properties: + group: + description: "Group is the group of the referent. When empty, + the Kubernetes core API group is inferred. \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: "Kind is the kind of the referent. Although implementations + may support additional resources, the following types are + part of the \"Core\" support level for this field: \n * Secret + when used to permit a SecretObjectReference * Service when + used to permit a BackendObjectReference" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. When unspecified, + this policy refers to all resources of the specified Group + and Kind in the local namespace. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - from + - to + type: object + type: object + served: true + storage: false + subresources: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: "ReferenceGrant identifies kinds of resources in other namespaces + that are trusted to reference the specified kinds of resources in the same + namespace as the policy. \n Each ReferenceGrant can be used to represent + a unique trust relationship. Additional Reference Grants can be used to + add to the set of trusted sources of inbound references for the namespace + they are defined within. \n All cross-namespace references in Gateway API + (with the exception of cross-namespace Gateway-route attachment) require + a ReferenceGrant. \n ReferenceGrant is a form of runtime verification allowing + users to assert which cross-namespace object references are permitted. Implementations + that support ReferenceGrant MUST NOT permit cross-namespace references which + have no grant, and MUST respond to the removal of a grant by revoking the + access that the grant allowed." + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of ReferenceGrant. + properties: + from: + description: "From describes the trusted namespaces and kinds that + can reference the resources described in \"To\". Each entry in this + list MUST be considered to be an additional place that references + can be valid from, or to put this another way, entries MUST be combined + using OR. \n Support: Core" + items: + description: ReferenceGrantFrom describes trusted namespaces and + kinds. + properties: + group: + description: "Group is the group of the referent. When empty, + the Kubernetes core API group is inferred. \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: "Kind is the kind of the referent. Although implementations + may support additional resources, the following types are + part of the \"Core\" support level for this field. \n When + used to permit a SecretObjectReference: \n * Gateway \n When + used to permit a BackendObjectReference: \n * GRPCRoute * + HTTPRoute * TCPRoute * TLSRoute * UDPRoute" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + namespace: + description: "Namespace is the namespace of the referent. \n + Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - namespace + type: object + maxItems: 16 + minItems: 1 + type: array + to: + description: "To describes the resources that may be referenced by + the resources described in \"From\". Each entry in this list MUST + be considered to be an additional place that references can be valid + to, or to put this another way, entries MUST be combined using OR. + \n Support: Core" + items: + description: ReferenceGrantTo describes what Kinds are allowed as + targets of the references. + properties: + group: + description: "Group is the group of the referent. When empty, + the Kubernetes core API group is inferred. \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: "Kind is the kind of the referent. Although implementations + may support additional resources, the following types are + part of the \"Core\" support level for this field: \n * Secret + when used to permit a SecretObjectReference * Service when + used to permit a BackendObjectReference" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. When unspecified, + this policy refers to all resources of the specified Group + and Kind in the local namespace. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - from + - to + type: object + type: object + served: true + storage: true + subresources: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: tcproutes.gateway.networking.k8s.io spec: @@ -2278,40 +9323,76 @@ spec: that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from - Routes of this kind and namespace. \n The only kind of parent resource - with \"Core\" support is Gateway. This API may be extended in the - future to support additional kinds of parent resources such as one - of the route kinds. \n It is invalid to reference an identical parent - more than once. It is valid to reference multiple distinct sections - within the same parent resource, such as 2 Listeners within a Gateway. - \n It is possible to separately reference multiple distinct objects - that may be collapsed by an implementation. For example, some implementations - may choose to merge compatible Gateway Listeners together. If that - is the case, the list of routes attached to those resources should - also be merged." + Routes of this kind and namespace. For Services, that means the + Service must either be in the same namespace for a \"producer\" + route, or the mesh implementation must support and allow \"consumer\" + routes for the referenced Service. ReferenceGrant is not applicable + for governing ParentRefs to Services - it is not possible to create + a \"producer\" route for a Service in a different namespace from + the Route. \n There are two kinds of parent resources with \"Core\" + support: \n * Gateway (Gateway conformance profile) * Service (Mesh + conformance profile, experimental, ClusterIP Services only) This + API may be extended in the future to support additional kinds of + parent resources. \n ParentRefs must be _distinct_. This means either + that: \n * They select different objects. If this is the case, + then parentRef entries are distinct. In terms of fields, this means + that the multi-part key defined by `group`, `kind`, `namespace`, + and `name` must be unique across all parentRef entries in the Route. + * They do not select different objects, but for each optional field + used, each ParentRef that selects the same object must set the same + set of optional fields to different values. If one ParentRef sets + a combination of optional fields, all must set the same combination. + \n Some examples: \n * If one ParentRef sets `sectionName`, all + ParentRefs referencing the same object must also set `sectionName`. + * If one ParentRef sets `port`, all ParentRefs referencing the same + object must also set `port`. * If one ParentRef sets `sectionName` + and `port`, all ParentRefs referencing the same object must also + set `sectionName` and `port`. \n It is possible to separately reference + multiple distinct objects that may be collapsed by an implementation. + For example, some implementations may choose to merge compatible + Gateway Listeners together. If that is the case, the list of routes + attached to those resources should also be merged. \n Note that + for ParentRefs that cross namespace boundaries, there are specific + rules. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For + example, Gateway has the AllowedRoutes field, and ReferenceGrant + provides a generic way to enable other kinds of cross-namespace + reference. \n ParentRefs from a Route to a Service in the same + namespace are \"producer\" routes, which apply default routing rules + to inbound connections from any namespace to the Service. \n ParentRefs + from a Route to a Service in a different namespace are \"consumer\" + routes, and these routing rules are only applied to outbound connections + originating from the same namespace as the Route, for which the + intended destination of the connections are a Service targeted as + a ParentRef of the Route. \n " items: - description: "ParentRef identifies an API object (usually a Gateway) - that can be considered a parent of this resource (usually a route). - The only kind of parent resource with \"Core\" support is Gateway. - This API may be extended in the future to support additional kinds - of parent resources, such as HTTPRoute. \n The API object must - be valid in the cluster; the Group and Kind must be registered - in the cluster for this reference to be valid. \n References to - objects with invalid Group and Kind are not valid, and must be - rejected by the implementation, with appropriate Conditions set - on the containing object." + description: "ParentReference identifies an API object (usually + a Gateway) that can be considered a parent of this resource (usually + a route). There are two kinds of parent resources with \"Core\" + support: \n * Gateway (Gateway conformance profile) * Service + (Mesh conformance profile, experimental, ClusterIP Services only) + \n This API may be extended in the future to support additional + kinds of parent resources. \n The API object must be valid in + the cluster; the Group and Kind must be registered in the cluster + for this reference to be valid." properties: group: default: gateway.networking.k8s.io - description: "Group is the group of the referent. \n Support: + description: "Group is the group of the referent. When unspecified, + \"gateway.networking.k8s.io\" is inferred. To set the core + API group (such as for a \"Service\" kind referent), Group + must be explicitly set to \"\" (empty string). \n Support: Core" maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Gateway - description: "Kind is kind of the referent. \n Support: Core - (Gateway) Support: Custom (Other Resources)" + description: "Kind is kind of the referent. \n There are two + kinds of parent resources with \"Core\" support: \n * Gateway + (Gateway conformance profile) * Service (Mesh conformance + profile, experimental, ClusterIP Services only) \n Support + for other resources is Implementation-Specific." maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ @@ -2324,29 +9405,79 @@ spec: type: string namespace: description: "Namespace is the namespace of the referent. When - unspecified (or empty string), this refers to the local namespace - of the Route. \n Support: Core" + unspecified, this refers to the local namespace of the Route. + \n Note that there are specific rules for ParentRefs which + cross namespace boundaries. Cross-namespace references are + only valid if they are explicitly allowed by something in + the namespace they are referring to. For example: Gateway + has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + \n ParentRefs from a Route to a Service in the same namespace + are \"producer\" routes, which apply default routing rules + to inbound connections from any namespace to the Service. + \n ParentRefs from a Route to a Service in a different namespace + are \"consumer\" routes, and these routing rules are only + applied to outbound connections originating from the same + namespace as the Route, for which the intended destination + of the connections are a Service targeted as a ParentRef of + the Route. \n Support: Core" maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string - sectionName: - description: "SectionName is the name of a section within the - target resource. In the following resources, SectionName is - interpreted as the following: \n * Gateway: Listener Name - \n Implementations MAY choose to support attaching Routes - to other resources. If that is the case, they MUST clearly - document how SectionName is interpreted. \n When unspecified - (empty string), this will reference the entire resource. For - the purpose of status, an attachment is considered successful - if at least one section in the parent resource accepts it. + port: + description: "Port is the network port this Route targets. It + can be interpreted differently based on the type of parent + resource. \n When the parent resource is a Gateway, this targets + all listeners listening on the specified port that also support + this kind of Route(and select this Route). It's not recommended + to set `Port` unless the networking behaviors specified in + a Route must apply to a specific port as opposed to a listener(s) + whose port(s) may be changed. When both Port and SectionName + are specified, the name and port of the selected listener + must match both specified values. \n When the parent resource + is a Service, this targets a specific port in the Service + spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified + values. \n Implementations MAY choose to support other parent + resources. Implementations supporting other types of parent + resources MUST clearly document how/if Port is interpreted. + \n For the purpose of status, an attachment is considered + successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n - Support: Core" + Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match both + specified values. * Service: Port Name. When both Port (experimental) + and SectionName are specified, the name and port of the selected + listener must match both specified values. Note that attaching + Routes to Services as Parents is part of experimental Mesh + support and is not supported for any other purpose. \n Implementations + MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this will + reference the entire resource. For the purpose of status, + an attachment is considered successful if at least one section + in the parent resource accepts it. For example, Gateway listeners + can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept + attachment from the referencing Route, the Route MUST be considered + successfully attached. If no Gateway listeners accept attachment + from this Route, the Route MUST be considered detached from + the Gateway. \n Support: Core" maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -2356,6 +9487,29 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-validations: + - message: sectionName or port must be specified when parentRefs includes + 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ + == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__)) ? ((!has(p1.sectionName) + || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName + == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) + || p2.port == 0)): true))' + - message: sectionName or port must be unique when parentRefs includes + 2 or more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ + == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) + || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName + == '')) || ( has(p1.sectionName) && has(p2.sectionName) && p1.sectionName + == p2.sectionName)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) + || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port + == p2.port)))) rules: description: Rules are a list of TCP matchers and actions. items: @@ -2369,28 +9523,55 @@ spec: attempts to this backend. Connection rejections must respect weight; if an invalid backend is requested to have 80% of connections, then 80% of connections must be rejected instead. - \n Support: Core for Kubernetes Service Support: Custom for - any other resource \n Support for weight: Extended" + \n Support: Core for Kubernetes Service \n Support: Extended + for Kubernetes ServiceImport \n Support: Implementation-specific + for any other resource \n Support for weight: Extended" items: description: "BackendRef defines how a Route should forward a request to a Kubernetes resource. \n Note that when a - namespace is specified, a ReferencePolicy object is required - in the referent namespace to allow that namespace's owner - to accept the reference. See the ReferencePolicy documentation - for details." + namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace + to allow that namespace's owner to accept the reference. + See the ReferenceGrant documentation for details. \n + \n When the BackendRef points to a Kubernetes Service, implementations + SHOULD honor the appProtocol field if it is set for the + target Service Port. \n Implementations supporting appProtocol + SHOULD recognize the Kubernetes Standard Application Protocols + defined in KEP-3726. \n If a Service appProtocol isn't specified, + an implementation MAY infer the backend protocol through + its own means. Implementations MAY infer the protocol from + the Route type referring to the backend Service. \n If a + Route is not able to send traffic to the backend using the + specified protocol then the backend is considered invalid. + Implementations MUST set the \"ResolvedRefs\" condition + to \"False\" with the \"UnsupportedProtocol\" reason. \n + \n Note that when the + BackendTLSPolicy object is enabled by the implementation, + there are some extra rules about validity to consider here. + See the fields where this struct is used for more information + about the exact behavior." properties: group: default: "" description: Group is the group of the referent. For example, - "networking.k8s.io". When unspecified (empty string), - core API group is inferred. + "gateway.networking.k8s.io". When unspecified or empty + string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service - description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". + description: "Kind is the Kubernetes resource kind of + the referent. For example \"Service\". \n Defaults to + \"Service\" when not specified. \n ExternalName services + can refer to CNAME DNS records that may live outside + of the cluster and as such are difficult to reason about + in terms of conformance. They also may not be safe to + forward to (see CVE-2021-25740 for more information). + Implementations SHOULD NOT support ExternalName Services. + \n Support: Core (Services with a type other than ExternalName) + \n Support: Implementation-specific (Services with type + ExternalName)" maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ @@ -2403,11 +9584,11 @@ spec: namespace: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n - Note that when a namespace is specified, a ReferencePolicy - object is required in the referent namespace to allow - that namespace's owner to accept the reference. See - the ReferencePolicy documentation for details. \n Support: - Core" + Note that when a namespace different than the local + namespace is specified, a ReferenceGrant object is required + in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferenceGrant + documentation for details. \n Support: Core" maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ @@ -2415,9 +9596,10 @@ spec: port: description: Port specifies the destination port number to use for this resource. Port is required when the - referent is a Kubernetes Service. For other resources, - destination port might be derived from the referent - resource or this field. + referent is a Kubernetes Service. In this case, the + port number is the service port number, not the target + port. For other resources, destination port might be + derived from the referent resource or this field. format: int32 maximum: 65535 minimum: 1 @@ -2444,6 +9626,10 @@ spec: required: - name type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' maxItems: 16 minItems: 1 type: array @@ -2489,20 +9675,20 @@ spec: condition may not be set due to lack of controller visibility, that includes when: \n * The Route refers to a non-existent parent. * The Route is of a type that the controller does - not support. * The Route is in a namespace the the controller + not support. * The Route is in a namespace the controller does not have access to." items: description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path - .status.conditions. For example, type FooStatus struct{ - \ // Represents the observations of a foo's current state. - \ // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // - +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" + .status.conditions. For example, \n type FooStatus struct{ + // Represents the observations of a foo's current state. + // Known .status.conditions.type are: \"Available\", \"Progressing\", + and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields + }" properties: lastTransitionTime: description: lastTransitionTime is the last time the condition @@ -2574,7 +9760,11 @@ spec: with the controllerName field on GatewayClass. \n Example: \"example.net/gateway-controller\". \n The format of this field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid - Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + \n Controllers MUST populate this field when writing status. + Controllers should ensure that entries to status populated + with their ControllerName are cleaned up when they are no + longer necessary." maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ @@ -2585,15 +9775,21 @@ spec: properties: group: default: gateway.networking.k8s.io - description: "Group is the group of the referent. \n Support: - Core" + description: "Group is the group of the referent. When unspecified, + \"gateway.networking.k8s.io\" is inferred. To set the + core API group (such as for a \"Service\" kind referent), + Group must be explicitly set to \"\" (empty string). \n + Support: Core" maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Gateway - description: "Kind is kind of the referent. \n Support: - Core (Gateway) Support: Custom (Other Resources)" + description: "Kind is kind of the referent. \n There are + two kinds of parent resources with \"Core\" support: \n + * Gateway (Gateway conformance profile) * Service (Mesh + conformance profile, experimental, ClusterIP Services + only) \n Support for other resources is Implementation-Specific." maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ @@ -2606,29 +9802,84 @@ spec: type: string namespace: description: "Namespace is the namespace of the referent. - When unspecified (or empty string), this refers to the - local namespace of the Route. \n Support: Core" + When unspecified, this refers to the local namespace of + the Route. \n Note that there are specific rules for ParentRefs + which cross namespace boundaries. Cross-namespace references + are only valid if they are explicitly allowed by something + in the namespace they are referring to. For example: Gateway + has the AllowedRoutes field, and ReferenceGrant provides + a generic way to enable any other kind of cross-namespace + reference. \n ParentRefs from a Route to a Service in + the same namespace are \"producer\" routes, which apply + default routing rules to inbound connections from any + namespace to the Service. \n ParentRefs from a Route to + a Service in a different namespace are \"consumer\" routes, + and these routing rules are only applied to outbound connections + originating from the same namespace as the Route, for + which the intended destination of the connections are + a Service targeted as a ParentRef of the Route. \n Support: + Core" maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string + port: + description: "Port is the network port this Route targets. + It can be interpreted differently based on the type of + parent resource. \n When the parent resource is a Gateway, + this targets all listeners listening on the specified + port that also support this kind of Route(and select this + Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to + a specific port as opposed to a listener(s) whose port(s) + may be changed. When both Port and SectionName are specified, + the name and port of the selected listener must match + both specified values. \n When the parent resource is + a Service, this targets a specific port in the Service + spec. When both Port (experimental) and SectionName are + specified, the name and port of the selected port must + match both specified values. \n Implementations MAY choose + to support other parent resources. Implementations supporting + other types of parent resources MUST clearly document + how/if Port is interpreted. \n For the purpose of status, + an attachment is considered successful as long as the + parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them + by Route kind, namespace, or hostname. If 1 of 2 Gateway + listeners accept attachment from the referencing Route, + the Route MUST be considered successfully attached. If + no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer sectionName: description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener - Name \n Implementations MAY choose to support attaching - Routes to other resources. If that is the case, they MUST - clearly document how SectionName is interpreted. \n When - unspecified (empty string), this will reference the entire - resource. For the purpose of status, an attachment is - considered successful if at least one section in the parent - resource accepts it. For example, Gateway listeners can - restrict which Routes can attach to them by Route kind, - namespace, or hostname. If 1 of 2 Gateway listeners accept - attachment from the referencing Route, the Route MUST - be considered successfully attached. If no Gateway listeners - accept attachment from this Route, the Route MUST be considered - detached from the Gateway. \n Support: Core" + Name. When both Port (experimental) and SectionName are + specified, the name and port of the selected listener + must match both specified values. * Service: Port Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match + both specified values. Note that attaching Routes to Services + as Parents is part of experimental Mesh support and is + not supported for any other purpose. \n Implementations + MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this + will reference the entire resource. For the purpose of + status, an attachment is considered successful if at least + one section in the parent resource accepts it. For example, + Gateway listeners can restrict which Routes can attach + to them by Route kind, namespace, or hostname. If 1 of + 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Core" maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -2656,15 +9907,16 @@ status: acceptedNames: kind: "" plural: "" - conditions: [] - storedVersions: [] - + conditions: null + storedVersions: null --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/891 + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental creationTimestamp: null name: tlsroutes.gateway.networking.k8s.io spec: @@ -2712,20 +9964,20 @@ spec: This matches the RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed in SNI names per RFC 6066. 2. A hostname may be prefixed with a wildcard label (`*.`). The - wildcard label must appear by itself as the first label. \n If - a hostname is specified by both the Listener and TLSRoute, there - must be at least one intersecting hostname for the TLSRoute to be - attached to the Listener. For example: \n * A Listener with `test.example.com` - as the hostname matches TLSRoutes that have either not specified - any hostnames, or have specified at least one of `test.example.com` + wildcard label must appear by itself as the first label. \n If a + hostname is specified by both the Listener and TLSRoute, there must + be at least one intersecting hostname for the TLSRoute to be attached + to the Listener. For example: \n * A Listener with `test.example.com` + as the hostname matches TLSRoutes that have either not specified + any hostnames, or have specified at least one of `test.example.com` or `*.example.com`. * A Listener with `*.example.com` as the hostname - matches TLSRoutes that have either not specified any hostnames - or have specified at least one hostname that matches the Listener - hostname. For example, `test.example.com` and `*.example.com` - would both match. On the other hand, `example.com` and `test.example.net` - would not match. \n If both the Listener and TLSRoute have specified - hostnames, any TLSRoute hostnames that do not match the Listener - hostname MUST be ignored. For example, if a Listener specified `*.example.com`, + matches TLSRoutes that have either not specified any hostnames or + have specified at least one hostname that matches the Listener hostname. + For example, `test.example.com` and `*.example.com` would both match. + On the other hand, `example.com` and `test.example.net` would not + match. \n If both the Listener and TLSRoute have specified hostnames, + any TLSRoute hostnames that do not match the Listener hostname MUST + be ignored. For example, if a Listener specified `*.example.com`, and the TLSRoute specified `test.example.com` and `test.example.net`, `test.example.net` must not be considered for a match. \n If both the Listener and TLSRoute have specified hostnames, and none match @@ -2736,7 +9988,7 @@ spec: description: "Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname - may be prefixed with a wildcard label (`*.`). The wildcard label + may be prefixed with a wildcard label (`*.`). The wildcard label must appear by itself as the first label. \n Hostname can be \"precise\" which is a domain name without the terminating dot of a network host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain @@ -2755,40 +10007,76 @@ spec: that a Route wants to be attached to. Note that the referenced parent resource needs to allow this for the attachment to be complete. For Gateways, that means the Gateway needs to allow attachment from - Routes of this kind and namespace. \n The only kind of parent resource - with \"Core\" support is Gateway. This API may be extended in the - future to support additional kinds of parent resources such as one - of the route kinds. \n It is invalid to reference an identical parent - more than once. It is valid to reference multiple distinct sections - within the same parent resource, such as 2 Listeners within a Gateway. - \n It is possible to separately reference multiple distinct objects - that may be collapsed by an implementation. For example, some implementations - may choose to merge compatible Gateway Listeners together. If that - is the case, the list of routes attached to those resources should - also be merged." + Routes of this kind and namespace. For Services, that means the + Service must either be in the same namespace for a \"producer\" + route, or the mesh implementation must support and allow \"consumer\" + routes for the referenced Service. ReferenceGrant is not applicable + for governing ParentRefs to Services - it is not possible to create + a \"producer\" route for a Service in a different namespace from + the Route. \n There are two kinds of parent resources with \"Core\" + support: \n * Gateway (Gateway conformance profile) * Service (Mesh + conformance profile, experimental, ClusterIP Services only) This + API may be extended in the future to support additional kinds of + parent resources. \n ParentRefs must be _distinct_. This means either + that: \n * They select different objects. If this is the case, + then parentRef entries are distinct. In terms of fields, this means + that the multi-part key defined by `group`, `kind`, `namespace`, + and `name` must be unique across all parentRef entries in the Route. + * They do not select different objects, but for each optional field + used, each ParentRef that selects the same object must set the same + set of optional fields to different values. If one ParentRef sets + a combination of optional fields, all must set the same combination. + \n Some examples: \n * If one ParentRef sets `sectionName`, all + ParentRefs referencing the same object must also set `sectionName`. + * If one ParentRef sets `port`, all ParentRefs referencing the same + object must also set `port`. * If one ParentRef sets `sectionName` + and `port`, all ParentRefs referencing the same object must also + set `sectionName` and `port`. \n It is possible to separately reference + multiple distinct objects that may be collapsed by an implementation. + For example, some implementations may choose to merge compatible + Gateway Listeners together. If that is the case, the list of routes + attached to those resources should also be merged. \n Note that + for ParentRefs that cross namespace boundaries, there are specific + rules. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For + example, Gateway has the AllowedRoutes field, and ReferenceGrant + provides a generic way to enable other kinds of cross-namespace + reference. \n ParentRefs from a Route to a Service in the same + namespace are \"producer\" routes, which apply default routing rules + to inbound connections from any namespace to the Service. \n ParentRefs + from a Route to a Service in a different namespace are \"consumer\" + routes, and these routing rules are only applied to outbound connections + originating from the same namespace as the Route, for which the + intended destination of the connections are a Service targeted as + a ParentRef of the Route. \n " items: - description: "ParentRef identifies an API object (usually a Gateway) - that can be considered a parent of this resource (usually a route). - The only kind of parent resource with \"Core\" support is Gateway. - This API may be extended in the future to support additional kinds - of parent resources, such as HTTPRoute. \n The API object must - be valid in the cluster; the Group and Kind must be registered - in the cluster for this reference to be valid. \n References to - objects with invalid Group and Kind are not valid, and must be - rejected by the implementation, with appropriate Conditions set - on the containing object." + description: "ParentReference identifies an API object (usually + a Gateway) that can be considered a parent of this resource (usually + a route). There are two kinds of parent resources with \"Core\" + support: \n * Gateway (Gateway conformance profile) * Service + (Mesh conformance profile, experimental, ClusterIP Services only) + \n This API may be extended in the future to support additional + kinds of parent resources. \n The API object must be valid in + the cluster; the Group and Kind must be registered in the cluster + for this reference to be valid." properties: group: default: gateway.networking.k8s.io - description: "Group is the group of the referent. \n Support: + description: "Group is the group of the referent. When unspecified, + \"gateway.networking.k8s.io\" is inferred. To set the core + API group (such as for a \"Service\" kind referent), Group + must be explicitly set to \"\" (empty string). \n Support: Core" maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Gateway - description: "Kind is kind of the referent. \n Support: Core - (Gateway) Support: Custom (Other Resources)" + description: "Kind is kind of the referent. \n There are two + kinds of parent resources with \"Core\" support: \n * Gateway + (Gateway conformance profile) * Service (Mesh conformance + profile, experimental, ClusterIP Services only) \n Support + for other resources is Implementation-Specific." maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ @@ -2801,29 +10089,79 @@ spec: type: string namespace: description: "Namespace is the namespace of the referent. When - unspecified (or empty string), this refers to the local namespace - of the Route. \n Support: Core" + unspecified, this refers to the local namespace of the Route. + \n Note that there are specific rules for ParentRefs which + cross namespace boundaries. Cross-namespace references are + only valid if they are explicitly allowed by something in + the namespace they are referring to. For example: Gateway + has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + \n ParentRefs from a Route to a Service in the same namespace + are \"producer\" routes, which apply default routing rules + to inbound connections from any namespace to the Service. + \n ParentRefs from a Route to a Service in a different namespace + are \"consumer\" routes, and these routing rules are only + applied to outbound connections originating from the same + namespace as the Route, for which the intended destination + of the connections are a Service targeted as a ParentRef of + the Route. \n Support: Core" maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string - sectionName: - description: "SectionName is the name of a section within the - target resource. In the following resources, SectionName is - interpreted as the following: \n * Gateway: Listener Name - \n Implementations MAY choose to support attaching Routes - to other resources. If that is the case, they MUST clearly - document how SectionName is interpreted. \n When unspecified - (empty string), this will reference the entire resource. For - the purpose of status, an attachment is considered successful - if at least one section in the parent resource accepts it. + port: + description: "Port is the network port this Route targets. It + can be interpreted differently based on the type of parent + resource. \n When the parent resource is a Gateway, this targets + all listeners listening on the specified port that also support + this kind of Route(and select this Route). It's not recommended + to set `Port` unless the networking behaviors specified in + a Route must apply to a specific port as opposed to a listener(s) + whose port(s) may be changed. When both Port and SectionName + are specified, the name and port of the selected listener + must match both specified values. \n When the parent resource + is a Service, this targets a specific port in the Service + spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified + values. \n Implementations MAY choose to support other parent + resources. Implementations supporting other types of parent + resources MUST clearly document how/if Port is interpreted. + \n For the purpose of status, an attachment is considered + successful as long as the parent resource accepts it partially. For example, Gateway listeners can restrict which Routes can attach to them by Route kind, namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from the referencing Route, the Route MUST be considered successfully attached. If no Gateway listeners accept attachment from this Route, the Route MUST be considered detached from the Gateway. \n - Support: Core" + Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match both + specified values. * Service: Port Name. When both Port (experimental) + and SectionName are specified, the name and port of the selected + listener must match both specified values. Note that attaching + Routes to Services as Parents is part of experimental Mesh + support and is not supported for any other purpose. \n Implementations + MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this will + reference the entire resource. For the purpose of status, + an attachment is considered successful if at least one section + in the parent resource accepts it. For example, Gateway listeners + can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept + attachment from the referencing Route, the Route MUST be considered + successfully attached. If no Gateway listeners accept attachment + from this Route, the Route MUST be considered detached from + the Gateway. \n Support: Core" maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -2833,6 +10171,29 @@ spec: type: object maxItems: 32 type: array + x-kubernetes-validations: + - message: sectionName or port must be specified when parentRefs includes + 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ + == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__)) ? ((!has(p1.sectionName) + || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName + == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) + || p2.port == 0)): true))' + - message: sectionName or port must be unique when parentRefs includes + 2 or more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ + == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) + || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName + == '')) || ( has(p1.sectionName) && has(p2.sectionName) && p1.sectionName + == p2.sectionName)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) + || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port + == p2.port)))) rules: description: Rules are a list of TLS matchers and actions. items: @@ -2845,32 +10206,59 @@ spec: the rule performs no forwarding; if no filters are specified that would result in a response being sent, the underlying implementation must actively reject request attempts to this - backend, by rejecting the connection or returning a 503 status + backend, by rejecting the connection or returning a 500 status code. Request rejections must respect weight; if an invalid backend is requested to have 80% of requests, then 80% of requests must be rejected instead. \n Support: Core for Kubernetes - Service Support: Custom for any other resource \n Support - for weight: Extended" + Service \n Support: Extended for Kubernetes ServiceImport + \n Support: Implementation-specific for any other resource + \n Support for weight: Extended" items: description: "BackendRef defines how a Route should forward a request to a Kubernetes resource. \n Note that when a - namespace is specified, a ReferencePolicy object is required - in the referent namespace to allow that namespace's owner - to accept the reference. See the ReferencePolicy documentation - for details." + namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace + to allow that namespace's owner to accept the reference. + See the ReferenceGrant documentation for details. \n + \n When the BackendRef points to a Kubernetes Service, implementations + SHOULD honor the appProtocol field if it is set for the + target Service Port. \n Implementations supporting appProtocol + SHOULD recognize the Kubernetes Standard Application Protocols + defined in KEP-3726. \n If a Service appProtocol isn't specified, + an implementation MAY infer the backend protocol through + its own means. Implementations MAY infer the protocol from + the Route type referring to the backend Service. \n If a + Route is not able to send traffic to the backend using the + specified protocol then the backend is considered invalid. + Implementations MUST set the \"ResolvedRefs\" condition + to \"False\" with the \"UnsupportedProtocol\" reason. \n + \n Note that when the + BackendTLSPolicy object is enabled by the implementation, + there are some extra rules about validity to consider here. + See the fields where this struct is used for more information + about the exact behavior." properties: group: default: "" description: Group is the group of the referent. For example, - "networking.k8s.io". When unspecified (empty string), - core API group is inferred. + "gateway.networking.k8s.io". When unspecified or empty + string, core API group is inferred. maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Service - description: Kind is kind of the referent. For example - "HTTPRoute" or "Service". + description: "Kind is the Kubernetes resource kind of + the referent. For example \"Service\". \n Defaults to + \"Service\" when not specified. \n ExternalName services + can refer to CNAME DNS records that may live outside + of the cluster and as such are difficult to reason about + in terms of conformance. They also may not be safe to + forward to (see CVE-2021-25740 for more information). + Implementations SHOULD NOT support ExternalName Services. + \n Support: Core (Services with a type other than ExternalName) + \n Support: Implementation-specific (Services with type + ExternalName)" maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ @@ -2883,11 +10271,11 @@ spec: namespace: description: "Namespace is the namespace of the backend. When unspecified, the local namespace is inferred. \n - Note that when a namespace is specified, a ReferencePolicy - object is required in the referent namespace to allow - that namespace's owner to accept the reference. See - the ReferencePolicy documentation for details. \n Support: - Core" + Note that when a namespace different than the local + namespace is specified, a ReferenceGrant object is required + in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferenceGrant + documentation for details. \n Support: Core" maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ @@ -2895,9 +10283,10 @@ spec: port: description: Port specifies the destination port number to use for this resource. Port is required when the - referent is a Kubernetes Service. For other resources, - destination port might be derived from the referent - resource or this field. + referent is a Kubernetes Service. In this case, the + port number is the service port number, not the target + port. For other resources, destination port might be + derived from the referent resource or this field. format: int32 maximum: 65535 minimum: 1 @@ -2924,6 +10313,10 @@ spec: required: - name type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' maxItems: 16 minItems: 1 type: array @@ -2969,20 +10362,20 @@ spec: condition may not be set due to lack of controller visibility, that includes when: \n * The Route refers to a non-existent parent. * The Route is of a type that the controller does - not support. * The Route is in a namespace the the controller + not support. * The Route is in a namespace the controller does not have access to." items: description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path - .status.conditions. For example, type FooStatus struct{ - \ // Represents the observations of a foo's current state. - \ // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // - +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" + .status.conditions. For example, \n type FooStatus struct{ + // Represents the observations of a foo's current state. + // Known .status.conditions.type are: \"Available\", \"Progressing\", + and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields + }" properties: lastTransitionTime: description: lastTransitionTime is the last time the condition @@ -3054,7 +10447,11 @@ spec: with the controllerName field on GatewayClass. \n Example: \"example.net/gateway-controller\". \n The format of this field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid - Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names)." + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + \n Controllers MUST populate this field when writing status. + Controllers should ensure that entries to status populated + with their ControllerName are cleaned up when they are no + longer necessary." maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ @@ -3065,15 +10462,21 @@ spec: properties: group: default: gateway.networking.k8s.io - description: "Group is the group of the referent. \n Support: - Core" + description: "Group is the group of the referent. When unspecified, + \"gateway.networking.k8s.io\" is inferred. To set the + core API group (such as for a \"Service\" kind referent), + Group must be explicitly set to \"\" (empty string). \n + Support: Core" maxLength: 253 pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string kind: default: Gateway - description: "Kind is kind of the referent. \n Support: - Core (Gateway) Support: Custom (Other Resources)" + description: "Kind is kind of the referent. \n There are + two kinds of parent resources with \"Core\" support: \n + * Gateway (Gateway conformance profile) * Service (Mesh + conformance profile, experimental, ClusterIP Services + only) \n Support for other resources is Implementation-Specific." maxLength: 63 minLength: 1 pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ @@ -3086,29 +10489,84 @@ spec: type: string namespace: description: "Namespace is the namespace of the referent. - When unspecified (or empty string), this refers to the - local namespace of the Route. \n Support: Core" + When unspecified, this refers to the local namespace of + the Route. \n Note that there are specific rules for ParentRefs + which cross namespace boundaries. Cross-namespace references + are only valid if they are explicitly allowed by something + in the namespace they are referring to. For example: Gateway + has the AllowedRoutes field, and ReferenceGrant provides + a generic way to enable any other kind of cross-namespace + reference. \n ParentRefs from a Route to a Service in + the same namespace are \"producer\" routes, which apply + default routing rules to inbound connections from any + namespace to the Service. \n ParentRefs from a Route to + a Service in a different namespace are \"consumer\" routes, + and these routing rules are only applied to outbound connections + originating from the same namespace as the Route, for + which the intended destination of the connections are + a Service targeted as a ParentRef of the Route. \n Support: + Core" maxLength: 63 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ type: string + port: + description: "Port is the network port this Route targets. + It can be interpreted differently based on the type of + parent resource. \n When the parent resource is a Gateway, + this targets all listeners listening on the specified + port that also support this kind of Route(and select this + Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to + a specific port as opposed to a listener(s) whose port(s) + may be changed. When both Port and SectionName are specified, + the name and port of the selected listener must match + both specified values. \n When the parent resource is + a Service, this targets a specific port in the Service + spec. When both Port (experimental) and SectionName are + specified, the name and port of the selected port must + match both specified values. \n Implementations MAY choose + to support other parent resources. Implementations supporting + other types of parent resources MUST clearly document + how/if Port is interpreted. \n For the purpose of status, + an attachment is considered successful as long as the + parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them + by Route kind, namespace, or hostname. If 1 of 2 Gateway + listeners accept attachment from the referencing Route, + the Route MUST be considered successfully attached. If + no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer sectionName: description: "SectionName is the name of a section within the target resource. In the following resources, SectionName is interpreted as the following: \n * Gateway: Listener - Name \n Implementations MAY choose to support attaching - Routes to other resources. If that is the case, they MUST - clearly document how SectionName is interpreted. \n When - unspecified (empty string), this will reference the entire - resource. For the purpose of status, an attachment is - considered successful if at least one section in the parent - resource accepts it. For example, Gateway listeners can - restrict which Routes can attach to them by Route kind, - namespace, or hostname. If 1 of 2 Gateway listeners accept - attachment from the referencing Route, the Route MUST - be considered successfully attached. If no Gateway listeners - accept attachment from this Route, the Route MUST be considered - detached from the Gateway. \n Support: Core" + Name. When both Port (experimental) and SectionName are + specified, the name and port of the selected listener + must match both specified values. * Service: Port Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match + both specified values. Note that attaching Routes to Services + as Parents is part of experimental Mesh support and is + not supported for any other purpose. \n Implementations + MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this + will reference the entire resource. For the purpose of + status, an attachment is considered successful if at least + one section in the parent resource accepts it. For example, + Gateway listeners can restrict which Routes can attach + to them by Route kind, namespace, or hostname. If 1 of + 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Core" maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -3136,5 +10594,643 @@ status: acceptedNames: kind: "" plural: "" - conditions: [] - storedVersions: [] + conditions: null + storedVersions: null +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v1.0.0 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + name: udproutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: UDPRoute + listKind: UDPRouteList + plural: udproutes + singular: udproute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: UDPRoute provides a way to route UDP traffic. When combined with + a Gateway listener, it can be used to forward traffic on the port specified + by the listener to a set of backends specified by the UDPRoute. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of UDPRoute. + properties: + parentRefs: + description: "ParentRefs references the resources (usually Gateways) + that a Route wants to be attached to. Note that the referenced parent + resource needs to allow this for the attachment to be complete. + For Gateways, that means the Gateway needs to allow attachment from + Routes of this kind and namespace. For Services, that means the + Service must either be in the same namespace for a \"producer\" + route, or the mesh implementation must support and allow \"consumer\" + routes for the referenced Service. ReferenceGrant is not applicable + for governing ParentRefs to Services - it is not possible to create + a \"producer\" route for a Service in a different namespace from + the Route. \n There are two kinds of parent resources with \"Core\" + support: \n * Gateway (Gateway conformance profile) * Service (Mesh + conformance profile, experimental, ClusterIP Services only) This + API may be extended in the future to support additional kinds of + parent resources. \n ParentRefs must be _distinct_. This means either + that: \n * They select different objects. If this is the case, + then parentRef entries are distinct. In terms of fields, this means + that the multi-part key defined by `group`, `kind`, `namespace`, + and `name` must be unique across all parentRef entries in the Route. + * They do not select different objects, but for each optional field + used, each ParentRef that selects the same object must set the same + set of optional fields to different values. If one ParentRef sets + a combination of optional fields, all must set the same combination. + \n Some examples: \n * If one ParentRef sets `sectionName`, all + ParentRefs referencing the same object must also set `sectionName`. + * If one ParentRef sets `port`, all ParentRefs referencing the same + object must also set `port`. * If one ParentRef sets `sectionName` + and `port`, all ParentRefs referencing the same object must also + set `sectionName` and `port`. \n It is possible to separately reference + multiple distinct objects that may be collapsed by an implementation. + For example, some implementations may choose to merge compatible + Gateway Listeners together. If that is the case, the list of routes + attached to those resources should also be merged. \n Note that + for ParentRefs that cross namespace boundaries, there are specific + rules. Cross-namespace references are only valid if they are explicitly + allowed by something in the namespace they are referring to. For + example, Gateway has the AllowedRoutes field, and ReferenceGrant + provides a generic way to enable other kinds of cross-namespace + reference. \n ParentRefs from a Route to a Service in the same + namespace are \"producer\" routes, which apply default routing rules + to inbound connections from any namespace to the Service. \n ParentRefs + from a Route to a Service in a different namespace are \"consumer\" + routes, and these routing rules are only applied to outbound connections + originating from the same namespace as the Route, for which the + intended destination of the connections are a Service targeted as + a ParentRef of the Route. \n " + items: + description: "ParentReference identifies an API object (usually + a Gateway) that can be considered a parent of this resource (usually + a route). There are two kinds of parent resources with \"Core\" + support: \n * Gateway (Gateway conformance profile) * Service + (Mesh conformance profile, experimental, ClusterIP Services only) + \n This API may be extended in the future to support additional + kinds of parent resources. \n The API object must be valid in + the cluster; the Group and Kind must be registered in the cluster + for this reference to be valid." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, + \"gateway.networking.k8s.io\" is inferred. To set the core + API group (such as for a \"Service\" kind referent), Group + must be explicitly set to \"\" (empty string). \n Support: + Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are two + kinds of parent resources with \"Core\" support: \n * Gateway + (Gateway conformance profile) * Service (Mesh conformance + profile, experimental, ClusterIP Services only) \n Support + for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When + unspecified, this refers to the local namespace of the Route. + \n Note that there are specific rules for ParentRefs which + cross namespace boundaries. Cross-namespace references are + only valid if they are explicitly allowed by something in + the namespace they are referring to. For example: Gateway + has the AllowedRoutes field, and ReferenceGrant provides a + generic way to enable any other kind of cross-namespace reference. + \n ParentRefs from a Route to a Service in the same namespace + are \"producer\" routes, which apply default routing rules + to inbound connections from any namespace to the Service. + \n ParentRefs from a Route to a Service in a different namespace + are \"consumer\" routes, and these routing rules are only + applied to outbound connections originating from the same + namespace as the Route, for which the intended destination + of the connections are a Service targeted as a ParentRef of + the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. It + can be interpreted differently based on the type of parent + resource. \n When the parent resource is a Gateway, this targets + all listeners listening on the specified port that also support + this kind of Route(and select this Route). It's not recommended + to set `Port` unless the networking behaviors specified in + a Route must apply to a specific port as opposed to a listener(s) + whose port(s) may be changed. When both Port and SectionName + are specified, the name and port of the selected listener + must match both specified values. \n When the parent resource + is a Service, this targets a specific port in the Service + spec. When both Port (experimental) and SectionName are specified, + the name and port of the selected port must match both specified + values. \n Implementations MAY choose to support other parent + resources. Implementations supporting other types of parent + resources MUST clearly document how/if Port is interpreted. + \n For the purpose of status, an attachment is considered + successful as long as the parent resource accepts it partially. + For example, Gateway listeners can restrict which Routes can + attach to them by Route kind, namespace, or hostname. If 1 + of 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. \n + Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match both + specified values. * Service: Port Name. When both Port (experimental) + and SectionName are specified, the name and port of the selected + listener must match both specified values. Note that attaching + Routes to Services as Parents is part of experimental Mesh + support and is not supported for any other purpose. \n Implementations + MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this will + reference the entire resource. For the purpose of status, + an attachment is considered successful if at least one section + in the parent resource accepts it. For example, Gateway listeners + can restrict which Routes can attach to them by Route kind, + namespace, or hostname. If 1 of 2 Gateway listeners accept + attachment from the referencing Route, the Route MUST be considered + successfully attached. If no Gateway listeners accept attachment + from this Route, the Route MUST be considered detached from + the Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + x-kubernetes-validations: + - message: sectionName or port must be specified when parentRefs includes + 2 or more references to the same parent + rule: 'self.all(p1, self.all(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '''') && (!has(p2.__namespace__) || p2.__namespace__ + == '''')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__)) ? ((!has(p1.sectionName) + || p1.sectionName == '''') == (!has(p2.sectionName) || p2.sectionName + == '''') && (!has(p1.port) || p1.port == 0) == (!has(p2.port) + || p2.port == 0)): true))' + - message: sectionName or port must be unique when parentRefs includes + 2 or more references to the same parent + rule: self.all(p1, self.exists_one(p2, p1.group == p2.group && p1.kind + == p2.kind && p1.name == p2.name && (((!has(p1.__namespace__) + || p1.__namespace__ == '') && (!has(p2.__namespace__) || p2.__namespace__ + == '')) || (has(p1.__namespace__) && has(p2.__namespace__) && + p1.__namespace__ == p2.__namespace__ )) && (((!has(p1.sectionName) + || p1.sectionName == '') && (!has(p2.sectionName) || p2.sectionName + == '')) || ( has(p1.sectionName) && has(p2.sectionName) && p1.sectionName + == p2.sectionName)) && (((!has(p1.port) || p1.port == 0) && (!has(p2.port) + || p2.port == 0)) || (has(p1.port) && has(p2.port) && p1.port + == p2.port)))) + rules: + description: Rules are a list of UDP matchers and actions. + items: + description: UDPRouteRule is the configuration for a given rule. + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching + requests should be sent. If unspecified or invalid (refers + to a non-existent resource or a Service with no endpoints), + the underlying implementation MUST actively reject connection + attempts to this backend. Packet drops must respect weight; + if an invalid backend is requested to have 80% of the packets, + then 80% of packets must be dropped instead. \n Support: Core + for Kubernetes Service \n Support: Extended for Kubernetes + ServiceImport \n Support: Implementation-specific for any + other resource \n Support for weight: Extended" + items: + description: "BackendRef defines how a Route should forward + a request to a Kubernetes resource. \n Note that when a + namespace different than the local namespace is specified, + a ReferenceGrant object is required in the referent namespace + to allow that namespace's owner to accept the reference. + See the ReferenceGrant documentation for details. \n + \n When the BackendRef points to a Kubernetes Service, implementations + SHOULD honor the appProtocol field if it is set for the + target Service Port. \n Implementations supporting appProtocol + SHOULD recognize the Kubernetes Standard Application Protocols + defined in KEP-3726. \n If a Service appProtocol isn't specified, + an implementation MAY infer the backend protocol through + its own means. Implementations MAY infer the protocol from + the Route type referring to the backend Service. \n If a + Route is not able to send traffic to the backend using the + specified protocol then the backend is considered invalid. + Implementations MUST set the \"ResolvedRefs\" condition + to \"False\" with the \"UnsupportedProtocol\" reason. \n + \n Note that when the + BackendTLSPolicy object is enabled by the implementation, + there are some extra rules about validity to consider here. + See the fields where this struct is used for more information + about the exact behavior." + properties: + group: + default: "" + description: Group is the group of the referent. For example, + "gateway.networking.k8s.io". When unspecified or empty + string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource kind of + the referent. For example \"Service\". \n Defaults to + \"Service\" when not specified. \n ExternalName services + can refer to CNAME DNS records that may live outside + of the cluster and as such are difficult to reason about + in terms of conformance. They also may not be safe to + forward to (see CVE-2021-25740 for more information). + Implementations SHOULD NOT support ExternalName Services. + \n Support: Core (Services with a type other than ExternalName) + \n Support: Implementation-specific (Services with type + ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a namespace different than the local + namespace is specified, a ReferenceGrant object is required + in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferenceGrant + documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number + to use for this resource. Port is required when the + referent is a Kubernetes Service. In this case, the + port number is the service port number, not the target + port. For other resources, destination port might be + derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests + forwarded to the referenced backend. This is computed + as weight/(sum of all weights in this BackendRefs list). + For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision + an implementation supports. Weight is not a percentage + and the sum of weights does not need to equal 100. \n + If only one backend is specified and it has a weight + greater than 0, 100% of the traffic is forwarded to + that backend. If weight is set to 0, no traffic should + be forwarded for this entry. If unspecified, weight + defaults to 1. \n Support for this field varies based + on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + maxItems: 16 + minItems: 1 + type: array + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - rules + type: object + status: + description: Status defines the current state of UDPRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) + that are associated with the route, and the status of the route + with respect to each parent. When this route attaches to a parent, + the controller that manages the parent must add an entry to this + list when the controller first sees the route and should update + the entry as appropriate when the route or gateway is modified. + \n Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this + API can only populate Route status for the Gateways/parent resources + they are responsible for. \n A maximum of 32 Gateways will be represented + in this list. An empty list means the route has not been attached + to any Gateway." + items: + description: RouteParentStatus describes the status of a route with + respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with + respect to the Gateway. Note that the route's availability + is also subject to the Gateway's own status conditions and + listener status. \n If the Route's ParentRef specifies an + existing Gateway that supports Routes of this kind AND that + Gateway's controller has sufficient access, then that Gateway's + controller MUST set the \"Accepted\" condition on the Route, + to indicate whether the route has been accepted or rejected + by the Gateway, and why. \n A Route MUST be considered \"Accepted\" + if at least one of the Route's rules is implemented by the + Gateway. \n There are a number of cases where the \"Accepted\" + condition may not be set due to lack of controller visibility, + that includes when: \n * The Route refers to a non-existent + parent. * The Route is of a type that the controller does + not support. * The Route is in a namespace the controller + does not have access to." + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, \n type FooStatus struct{ + // Represents the observations of a foo's current state. + // Known .status.conditions.type are: \"Available\", \"Progressing\", + and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields + }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates + the name of the controller that wrote this status. This corresponds + with the controllerName field on GatewayClass. \n Example: + \"example.net/gateway-controller\". \n The format of this + field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + \n Controllers MUST populate this field when writing status. + Controllers should ensure that entries to status populated + with their ControllerName are cleaned up when they are no + longer necessary." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec + that this RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, + \"gateway.networking.k8s.io\" is inferred. To set the + core API group (such as for a \"Service\" kind referent), + Group must be explicitly set to \"\" (empty string). \n + Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are + two kinds of parent resources with \"Core\" support: \n + * Gateway (Gateway conformance profile) * Service (Mesh + conformance profile, experimental, ClusterIP Services + only) \n Support for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified, this refers to the local namespace of + the Route. \n Note that there are specific rules for ParentRefs + which cross namespace boundaries. Cross-namespace references + are only valid if they are explicitly allowed by something + in the namespace they are referring to. For example: Gateway + has the AllowedRoutes field, and ReferenceGrant provides + a generic way to enable any other kind of cross-namespace + reference. \n ParentRefs from a Route to a Service in + the same namespace are \"producer\" routes, which apply + default routing rules to inbound connections from any + namespace to the Service. \n ParentRefs from a Route to + a Service in a different namespace are \"consumer\" routes, + and these routing rules are only applied to outbound connections + originating from the same namespace as the Route, for + which the intended destination of the connections are + a Service targeted as a ParentRef of the Route. \n Support: + Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. + It can be interpreted differently based on the type of + parent resource. \n When the parent resource is a Gateway, + this targets all listeners listening on the specified + port that also support this kind of Route(and select this + Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to + a specific port as opposed to a listener(s) whose port(s) + may be changed. When both Port and SectionName are specified, + the name and port of the selected listener must match + both specified values. \n When the parent resource is + a Service, this targets a specific port in the Service + spec. When both Port (experimental) and SectionName are + specified, the name and port of the selected port must + match both specified values. \n Implementations MAY choose + to support other parent resources. Implementations supporting + other types of parent resources MUST clearly document + how/if Port is interpreted. \n For the purpose of status, + an attachment is considered successful as long as the + parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them + by Route kind, namespace, or hostname. If 1 of 2 Gateway + listeners accept attachment from the referencing Route, + the Route MUST be considered successfully attached. If + no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name. When both Port (experimental) and SectionName are + specified, the name and port of the selected listener + must match both specified values. * Service: Port Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match + both specified values. Note that attaching Routes to Services + as Parents is part of experimental Mesh support and is + not supported for any other purpose. \n Implementations + MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this + will reference the entire resource. For the purpose of + status, an attachment is considered successful if at least + one section in the parent resource accepts it. For example, + Gateway listeners can restrict which Routes can attach + to them by Route kind, namespace, or hostname. If 1 of + 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/integration/fixtures/k8s/03-gateway.yml b/integration/fixtures/k8s/03-gateway.yml index c52f7c166..d985b00c1 100644 --- a/integration/fixtures/k8s/03-gateway.yml +++ b/integration/fixtures/k8s/03-gateway.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-tcp-gateway namespace: default @@ -51,7 +51,7 @@ data: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-tls-gateway namespace: default @@ -83,7 +83,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-https-gateway namespace: default @@ -104,7 +104,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/client.go b/pkg/provider/kubernetes/gateway/client.go index 22a93dcda..ce4e02588 100644 --- a/pkg/provider/kubernetes/gateway/client.go +++ b/pkg/provider/kubernetes/gateway/client.go @@ -16,9 +16,10 @@ import ( kclientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" + gatev1 "sigs.k8s.io/gateway-api/apis/v1" gatev1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - gateclientset "sigs.k8s.io/gateway-api/pkg/client/clientset/gateway/versioned" - gateinformers "sigs.k8s.io/gateway-api/pkg/client/informers/gateway/externalversions" + gateclientset "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned" + gateinformers "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions" ) const resyncPeriod = 10 * time.Minute @@ -27,13 +28,13 @@ type resourceEventHandler struct { ev chan<- interface{} } -func (reh *resourceEventHandler) OnAdd(obj interface{}) { +func (reh *resourceEventHandler) OnAdd(obj interface{}, isInInitialList bool) { eventHandlerFunc(reh.ev, obj) } func (reh *resourceEventHandler) OnUpdate(oldObj, newObj interface{}) { switch oldObj.(type) { - case *gatev1alpha2.GatewayClass: + case *gatev1.GatewayClass: // Skip update for gateway classes. We only manage addition or deletion for this cluster-wide resource. return default: @@ -50,11 +51,11 @@ func (reh *resourceEventHandler) OnDelete(obj interface{}) { // The stores can then be accessed via the Get* functions. type Client interface { WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error) - GetGatewayClasses() ([]*gatev1alpha2.GatewayClass, error) - UpdateGatewayStatus(gateway *gatev1alpha2.Gateway, gatewayStatus gatev1alpha2.GatewayStatus) error - UpdateGatewayClassStatus(gatewayClass *gatev1alpha2.GatewayClass, condition metav1.Condition) error - GetGateways() []*gatev1alpha2.Gateway - GetHTTPRoutes(namespaces []string) ([]*gatev1alpha2.HTTPRoute, error) + GetGatewayClasses() ([]*gatev1.GatewayClass, error) + UpdateGatewayStatus(gateway *gatev1.Gateway, gatewayStatus gatev1.GatewayStatus) error + UpdateGatewayClassStatus(gatewayClass *gatev1.GatewayClass, condition metav1.Condition) error + GetGateways() []*gatev1.Gateway + GetHTTPRoutes(namespaces []string) ([]*gatev1.HTTPRoute, error) GetTCPRoutes(namespaces []string) ([]*gatev1alpha2.TCPRoute, error) GetTLSRoutes(namespaces []string) ([]*gatev1alpha2.TLSRoute, error) GetService(namespace, name string) (*corev1.Service, bool, error) @@ -177,7 +178,7 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (< } c.factoryGatewayClass = gateinformers.NewSharedInformerFactoryWithOptions(c.csGateway, resyncPeriod, gateinformers.WithTweakListOptions(labelSelectorOptions)) - _, err = c.factoryGatewayClass.Gateway().V1alpha2().GatewayClasses().Informer().AddEventHandler(eventHandler) + _, err = c.factoryGatewayClass.Gateway().V1().GatewayClasses().Informer().AddEventHandler(eventHandler) if err != nil { return nil, err } @@ -187,11 +188,11 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (< for _, ns := range namespaces { factoryGateway := gateinformers.NewSharedInformerFactoryWithOptions(c.csGateway, resyncPeriod, gateinformers.WithNamespace(ns)) - _, err = factoryGateway.Gateway().V1alpha2().Gateways().Informer().AddEventHandler(eventHandler) + _, err = factoryGateway.Gateway().V1().Gateways().Informer().AddEventHandler(eventHandler) if err != nil { return nil, err } - _, err = factoryGateway.Gateway().V1alpha2().HTTPRoutes().Informer().AddEventHandler(eventHandler) + _, err = factoryGateway.Gateway().V1().HTTPRoutes().Informer().AddEventHandler(eventHandler) if err != nil { return nil, err } @@ -286,15 +287,15 @@ func (c *clientWrapper) GetNamespaces(selector labels.Selector) ([]string, error return namespaces, nil } -func (c *clientWrapper) GetHTTPRoutes(namespaces []string) ([]*gatev1alpha2.HTTPRoute, error) { - var httpRoutes []*gatev1alpha2.HTTPRoute +func (c *clientWrapper) GetHTTPRoutes(namespaces []string) ([]*gatev1.HTTPRoute, error) { + var httpRoutes []*gatev1.HTTPRoute for _, namespace := range namespaces { if !c.isWatchedNamespace(namespace) { log.Warn().Msgf("Failed to get HTTPRoutes: %q is not within watched namespaces", namespace) continue } - routes, err := c.factoriesGateway[c.lookupNamespace(namespace)].Gateway().V1alpha2().HTTPRoutes().Lister().HTTPRoutes(namespace).List(labels.Everything()) + routes, err := c.factoriesGateway[c.lookupNamespace(namespace)].Gateway().V1().HTTPRoutes().Lister().HTTPRoutes(namespace).List(labels.Everything()) if err != nil { return nil, err } @@ -356,11 +357,11 @@ func (c *clientWrapper) GetTLSRoutes(namespaces []string) ([]*gatev1alpha2.TLSRo return tlsRoutes, nil } -func (c *clientWrapper) GetGateways() []*gatev1alpha2.Gateway { - var result []*gatev1alpha2.Gateway +func (c *clientWrapper) GetGateways() []*gatev1.Gateway { + var result []*gatev1.Gateway for ns, factory := range c.factoriesGateway { - gateways, err := factory.Gateway().V1alpha2().Gateways().Lister().List(labels.Everything()) + gateways, err := factory.Gateway().V1().Gateways().Lister().List(labels.Everything()) if err != nil { log.Error().Err(err).Msgf("Failed to list Gateways in namespace %s", ns) continue @@ -371,11 +372,11 @@ func (c *clientWrapper) GetGateways() []*gatev1alpha2.Gateway { return result } -func (c *clientWrapper) GetGatewayClasses() ([]*gatev1alpha2.GatewayClass, error) { - return c.factoryGatewayClass.Gateway().V1alpha2().GatewayClasses().Lister().List(labels.Everything()) +func (c *clientWrapper) GetGatewayClasses() ([]*gatev1.GatewayClass, error) { + return c.factoryGatewayClass.Gateway().V1().GatewayClasses().Lister().List(labels.Everything()) } -func (c *clientWrapper) UpdateGatewayClassStatus(gatewayClass *gatev1alpha2.GatewayClass, condition metav1.Condition) error { +func (c *clientWrapper) UpdateGatewayClassStatus(gatewayClass *gatev1.GatewayClass, condition metav1.Condition) error { gc := gatewayClass.DeepCopy() var newConditions []metav1.Condition @@ -398,7 +399,7 @@ func (c *clientWrapper) UpdateGatewayClassStatus(gatewayClass *gatev1alpha2.Gate ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - _, err := c.csGateway.GatewayV1alpha2().GatewayClasses().UpdateStatus(ctx, gc, metav1.UpdateOptions{}) + _, err := c.csGateway.GatewayV1().GatewayClasses().UpdateStatus(ctx, gc, metav1.UpdateOptions{}) if err != nil { return fmt.Errorf("failed to update GatewayClass %q status: %w", gatewayClass.Name, err) } @@ -406,7 +407,7 @@ func (c *clientWrapper) UpdateGatewayClassStatus(gatewayClass *gatev1alpha2.Gate return nil } -func (c *clientWrapper) UpdateGatewayStatus(gateway *gatev1alpha2.Gateway, gatewayStatus gatev1alpha2.GatewayStatus) error { +func (c *clientWrapper) UpdateGatewayStatus(gateway *gatev1.Gateway, gatewayStatus gatev1.GatewayStatus) error { if !c.isWatchedNamespace(gateway.Namespace) { return fmt.Errorf("cannot update Gateway status %s/%s: namespace is not within watched namespaces", gateway.Namespace, gateway.Name) } @@ -421,7 +422,7 @@ func (c *clientWrapper) UpdateGatewayStatus(gateway *gatev1alpha2.Gateway, gatew ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - _, err := c.csGateway.GatewayV1alpha2().Gateways(gateway.Namespace).UpdateStatus(ctx, g, metav1.UpdateOptions{}) + _, err := c.csGateway.GatewayV1().Gateways(gateway.Namespace).UpdateStatus(ctx, g, metav1.UpdateOptions{}) if err != nil { return fmt.Errorf("failed to update Gateway %q status: %w", gateway.Name, err) } @@ -429,7 +430,7 @@ func (c *clientWrapper) UpdateGatewayStatus(gateway *gatev1alpha2.Gateway, gatew return nil } -func statusEquals(oldStatus, newStatus gatev1alpha2.GatewayStatus) bool { +func statusEquals(oldStatus, newStatus gatev1.GatewayStatus) bool { if len(oldStatus.Listeners) != len(newStatus.Listeners) { return false } diff --git a/pkg/provider/kubernetes/gateway/client_mock_test.go b/pkg/provider/kubernetes/gateway/client_mock_test.go index 10c78801c..01611de40 100644 --- a/pkg/provider/kubernetes/gateway/client_mock_test.go +++ b/pkg/provider/kubernetes/gateway/client_mock_test.go @@ -10,6 +10,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" kscheme "k8s.io/client-go/kubernetes/scheme" + gatev1 "sigs.k8s.io/gateway-api/apis/v1" gatev1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" ) @@ -21,6 +22,11 @@ func init() { if err != nil { panic(err) } + + err = gatev1.AddToScheme(kscheme.Scheme) + if err != nil { + panic(err) + } } type clientMock struct { @@ -33,9 +39,9 @@ type clientMock struct { apiSecretError error apiEndpointsError error - gatewayClasses []*gatev1alpha2.GatewayClass - gateways []*gatev1alpha2.Gateway - httpRoutes []*gatev1alpha2.HTTPRoute + gatewayClasses []*gatev1.GatewayClass + gateways []*gatev1.Gateway + httpRoutes []*gatev1.HTTPRoute tcpRoutes []*gatev1alpha2.TCPRoute tlsRoutes []*gatev1alpha2.TLSRoute @@ -62,11 +68,11 @@ func newClientMock(paths ...string) clientMock { c.namespaces = append(c.namespaces, o) case *corev1.Endpoints: c.endpoints = append(c.endpoints, o) - case *gatev1alpha2.GatewayClass: + case *gatev1.GatewayClass: c.gatewayClasses = append(c.gatewayClasses, o) - case *gatev1alpha2.Gateway: + case *gatev1.Gateway: c.gateways = append(c.gateways, o) - case *gatev1alpha2.HTTPRoute: + case *gatev1.HTTPRoute: c.httpRoutes = append(c.httpRoutes, o) case *gatev1alpha2.TCPRoute: c.tcpRoutes = append(c.tcpRoutes, o) @@ -81,7 +87,7 @@ func newClientMock(paths ...string) clientMock { return c } -func (c clientMock) UpdateGatewayStatus(gateway *gatev1alpha2.Gateway, gatewayStatus gatev1alpha2.GatewayStatus) error { +func (c clientMock) UpdateGatewayStatus(gateway *gatev1.Gateway, gatewayStatus gatev1.GatewayStatus) error { for _, g := range c.gateways { if g.Name == gateway.Name { if !statusEquals(g.Status, gatewayStatus) { @@ -94,7 +100,7 @@ func (c clientMock) UpdateGatewayStatus(gateway *gatev1alpha2.Gateway, gatewaySt return nil } -func (c clientMock) UpdateGatewayClassStatus(gatewayClass *gatev1alpha2.GatewayClass, condition metav1.Condition) error { +func (c clientMock) UpdateGatewayClassStatus(gatewayClass *gatev1.GatewayClass, condition metav1.Condition) error { for _, gc := range c.gatewayClasses { if gc.Name == gatewayClass.Name { for _, c := range gc.Status.Conditions { @@ -110,7 +116,7 @@ func (c clientMock) UpdateGatewayClassStatus(gatewayClass *gatev1alpha2.GatewayC return nil } -func (c clientMock) UpdateGatewayStatusConditions(gateway *gatev1alpha2.Gateway, condition metav1.Condition) error { +func (c clientMock) UpdateGatewayStatusConditions(gateway *gatev1.Gateway, condition metav1.Condition) error { for _, g := range c.gatewayClasses { if g.Name == gateway.Name { for _, c := range g.Status.Conditions { @@ -126,11 +132,11 @@ func (c clientMock) UpdateGatewayStatusConditions(gateway *gatev1alpha2.Gateway, return nil } -func (c clientMock) GetGatewayClasses() ([]*gatev1alpha2.GatewayClass, error) { +func (c clientMock) GetGatewayClasses() ([]*gatev1.GatewayClass, error) { return c.gatewayClasses, nil } -func (c clientMock) GetGateways() []*gatev1alpha2.Gateway { +func (c clientMock) GetGateways() []*gatev1.Gateway { return c.gateways } @@ -148,8 +154,8 @@ func (c clientMock) GetNamespaces(selector labels.Selector) ([]string, error) { return ns, nil } -func (c clientMock) GetHTTPRoutes(namespaces []string) ([]*gatev1alpha2.HTTPRoute, error) { - var httpRoutes []*gatev1alpha2.HTTPRoute +func (c clientMock) GetHTTPRoutes(namespaces []string) ([]*gatev1.HTTPRoute, error) { + var httpRoutes []*gatev1.HTTPRoute for _, namespace := range namespaces { for _, httpRoute := range c.httpRoutes { if inNamespace(httpRoute.ObjectMeta, namespace) { diff --git a/pkg/provider/kubernetes/gateway/client_test.go b/pkg/provider/kubernetes/gateway/client_test.go index 794f7d6a8..e6e751959 100644 --- a/pkg/provider/kubernetes/gateway/client_test.go +++ b/pkg/provider/kubernetes/gateway/client_test.go @@ -5,32 +5,32 @@ import ( "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - gatev1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + gatev1 "sigs.k8s.io/gateway-api/apis/v1" ) func TestStatusEquals(t *testing.T) { testCases := []struct { desc string - statusA gatev1alpha2.GatewayStatus - statusB gatev1alpha2.GatewayStatus + statusA gatev1.GatewayStatus + statusB gatev1.GatewayStatus expected bool }{ { desc: "Empty", - statusA: gatev1alpha2.GatewayStatus{}, - statusB: gatev1alpha2.GatewayStatus{}, + statusA: gatev1.GatewayStatus{}, + statusB: gatev1.GatewayStatus{}, expected: true, }, { desc: "Same status", - statusA: gatev1alpha2.GatewayStatus{ + statusA: gatev1.GatewayStatus{ Conditions: []metav1.Condition{ { Type: "foobar", Reason: "foobar", }, }, - Listeners: []gatev1alpha2.ListenerStatus{ + Listeners: []gatev1.ListenerStatus{ { Name: "foo", Conditions: []metav1.Condition{ @@ -42,14 +42,14 @@ func TestStatusEquals(t *testing.T) { }, }, }, - statusB: gatev1alpha2.GatewayStatus{ + statusB: gatev1.GatewayStatus{ Conditions: []metav1.Condition{ { Type: "foobar", Reason: "foobar", }, }, - Listeners: []gatev1alpha2.ListenerStatus{ + Listeners: []gatev1.ListenerStatus{ { Name: "foo", Conditions: []metav1.Condition{ @@ -65,11 +65,11 @@ func TestStatusEquals(t *testing.T) { }, { desc: "Listeners length not equal", - statusA: gatev1alpha2.GatewayStatus{ - Listeners: []gatev1alpha2.ListenerStatus{}, + statusA: gatev1.GatewayStatus{ + Listeners: []gatev1.ListenerStatus{}, }, - statusB: gatev1alpha2.GatewayStatus{ - Listeners: []gatev1alpha2.ListenerStatus{ + statusB: gatev1.GatewayStatus{ + Listeners: []gatev1.ListenerStatus{ {}, }, }, @@ -77,10 +77,10 @@ func TestStatusEquals(t *testing.T) { }, { desc: "Gateway conditions length not equal", - statusA: gatev1alpha2.GatewayStatus{ + statusA: gatev1.GatewayStatus{ Conditions: []metav1.Condition{}, }, - statusB: gatev1alpha2.GatewayStatus{ + statusB: gatev1.GatewayStatus{ Conditions: []metav1.Condition{ {}, }, @@ -89,14 +89,14 @@ func TestStatusEquals(t *testing.T) { }, { desc: "Gateway conditions different types", - statusA: gatev1alpha2.GatewayStatus{ + statusA: gatev1.GatewayStatus{ Conditions: []metav1.Condition{ { Type: "foobar", }, }, }, - statusB: gatev1alpha2.GatewayStatus{ + statusB: gatev1.GatewayStatus{ Conditions: []metav1.Condition{ { Type: "foobir", @@ -107,14 +107,14 @@ func TestStatusEquals(t *testing.T) { }, { desc: "Gateway conditions same types but different reason", - statusA: gatev1alpha2.GatewayStatus{ + statusA: gatev1.GatewayStatus{ Conditions: []metav1.Condition{ { Type: "foobar", }, }, }, - statusB: gatev1alpha2.GatewayStatus{ + statusB: gatev1.GatewayStatus{ Conditions: []metav1.Condition{ { Type: "foobar", @@ -126,16 +126,16 @@ func TestStatusEquals(t *testing.T) { }, { desc: "Gateway listeners conditions length", - statusA: gatev1alpha2.GatewayStatus{ - Listeners: []gatev1alpha2.ListenerStatus{ + statusA: gatev1.GatewayStatus{ + Listeners: []gatev1.ListenerStatus{ { Name: "foo", Conditions: []metav1.Condition{}, }, }, }, - statusB: gatev1alpha2.GatewayStatus{ - Listeners: []gatev1alpha2.ListenerStatus{ + statusB: gatev1.GatewayStatus{ + Listeners: []gatev1.ListenerStatus{ { Name: "foo", Conditions: []metav1.Condition{ @@ -148,8 +148,8 @@ func TestStatusEquals(t *testing.T) { }, { desc: "Gateway listeners conditions same types but different status", - statusA: gatev1alpha2.GatewayStatus{ - Listeners: []gatev1alpha2.ListenerStatus{ + statusA: gatev1.GatewayStatus{ + Listeners: []gatev1.ListenerStatus{ { Conditions: []metav1.Condition{ { @@ -159,8 +159,8 @@ func TestStatusEquals(t *testing.T) { }, }, }, - statusB: gatev1alpha2.GatewayStatus{ - Listeners: []gatev1alpha2.ListenerStatus{ + statusB: gatev1.GatewayStatus{ + Listeners: []gatev1.ListenerStatus{ { Conditions: []metav1.Condition{ { @@ -175,8 +175,8 @@ func TestStatusEquals(t *testing.T) { }, { desc: "Gateway listeners conditions same types but different message", - statusA: gatev1alpha2.GatewayStatus{ - Listeners: []gatev1alpha2.ListenerStatus{ + statusA: gatev1.GatewayStatus{ + Listeners: []gatev1.ListenerStatus{ { Conditions: []metav1.Condition{ { @@ -186,8 +186,8 @@ func TestStatusEquals(t *testing.T) { }, }, }, - statusB: gatev1alpha2.GatewayStatus{ - Listeners: []gatev1alpha2.ListenerStatus{ + statusB: gatev1.GatewayStatus{ + Listeners: []gatev1.ListenerStatus{ { Conditions: []metav1.Condition{ { @@ -202,8 +202,8 @@ func TestStatusEquals(t *testing.T) { }, { desc: "Gateway listeners conditions same types/reason but different names", - statusA: gatev1alpha2.GatewayStatus{ - Listeners: []gatev1alpha2.ListenerStatus{ + statusA: gatev1.GatewayStatus{ + Listeners: []gatev1.ListenerStatus{ { Name: "foo", Conditions: []metav1.Condition{ @@ -215,8 +215,8 @@ func TestStatusEquals(t *testing.T) { }, }, }, - statusB: gatev1alpha2.GatewayStatus{ - Listeners: []gatev1alpha2.ListenerStatus{ + statusB: gatev1.GatewayStatus{ + Listeners: []gatev1.ListenerStatus{ { Name: "bar", Conditions: []metav1.Condition{ diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https.yml index 5b8d1607d..de4cdf9ec 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -27,7 +27,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https_with_hostname_and_port.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https_with_hostname_and_port.yml index 79e875be1..f1aba4c62 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https_with_hostname_and_port.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https_with_hostname_and_port.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -27,7 +27,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/gatewayclass_with_unknown_controller.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/gatewayclass_with_unknown_controller.yml index f4962f2b3..c618fa851 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/gatewayclass_with_unknown_controller.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/gatewayclass_with_unknown_controller.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/one_rule_two_targets.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/one_rule_two_targets.yml index bd181b220..3c466202f 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/one_rule_two_targets.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/one_rule_two_targets.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple.yml index f48efddf2..d4a79574a 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -27,7 +27,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_cross_provider.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_cross_provider.yml index ff90c82d0..d44b97236 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_cross_provider.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_cross_provider.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_to_api_internal.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_to_api_internal.yml index 6426736f6..b78cc0a56 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_to_api_internal.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_to_api_internal.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_with_bad_rule.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_with_bad_rule.yml index 0ce0690e3..0ff70ee1a 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_with_bad_rule.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_with_bad_rule.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_with_tls_entrypoint.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_with_tls_entrypoint.yml index ca1f133c3..115dfb982 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_with_tls_entrypoint.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/simple_with_tls_entrypoint.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/two_rules.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/two_rules.yml index cc4ee179f..e1a08baba 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/two_rules.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/two_rules.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_host.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_host.yml index 34e676f55..1f35bc7bc 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_host.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_host.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_all.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_all.yml index d40ab73ca..5db1069ca 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_all.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_all.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-default namespace: default @@ -49,7 +49,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-bar namespace: bar diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_same.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_same.yml index aa793a556..486c16764 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_same.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_same.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-default namespace: default @@ -49,7 +49,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-bar namespace: bar diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_selector.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_selector.yml index a5bffb47a..cb7da2f50 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_selector.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_namespace_selector.yml @@ -8,7 +8,7 @@ metadata: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -16,7 +16,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -35,7 +35,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-default namespace: default @@ -60,7 +60,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-bar namespace: bar diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https.yml index 9512aae07..cd4abdec1 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -40,7 +40,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https_with_tls_passthrough.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https_with_tls_passthrough.yml index e104514e0..9804bc80d 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https_with_tls_passthrough.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https_with_tls_passthrough.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -40,7 +40,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https_without_tls.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https_without_tls.yml index 09c74b40d..c43d4684c 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https_without_tls.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_https_without_tls.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_tcp.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_tcp.yml index 02ca3936d..a4cbed65e 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_tcp.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_tcp.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_tls.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_tls.yml index 9733a895c..bace669a0 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_tls.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_protocol_tls.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -40,7 +40,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_several_rules.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_several_rules.yml index aeea3c26b..3dc9b9ecf 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_several_rules.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_several_rules.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_tls_configuration.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_tls_configuration.yml index 81362d6d6..0218677df 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_tls_configuration.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_tls_configuration.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_two_gateways_one_httproute.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_two_gateways_one_httproute.yml index ceb9f2061..934b67f82 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_two_gateways_one_httproute.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_two_gateways_one_httproute.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-https namespace: default @@ -40,7 +40,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-http namespace: default @@ -56,7 +56,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_two_listeners_one_httproute.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_two_listeners_one_httproute.yml index 7bd9fd05e..ca1c1a90e 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_two_listeners_one_httproute.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_two_listeners_one_httproute.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -47,7 +47,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_wrong_service_port.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_wrong_service_port.yml index e5959a809..48813cf21 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_wrong_service_port.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_wrong_service_port.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/without_gatewayclass.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/without_gatewayclass.yml index be795970a..bbf20fcd8 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/without_gatewayclass.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/without_gatewayclass.yml @@ -1,6 +1,6 @@ --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -16,7 +16,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/without_httproute.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/without_httproute.yml index 228525d55..ec10f8fda 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/without_httproute.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/without_httproute.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/simple.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/simple.yml index 60f77deb4..ac15a9934 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/simple.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/simple.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -92,7 +92,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_protocol.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_protocol.yml index f6519d8ea..3c11ca130 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_protocol.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_protocol.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -27,7 +27,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_route_kind.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_route_kind.yml index 3df51b8a4..1e54ea49c 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_route_kind.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_route_kind.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -27,7 +27,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_core_group.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_core_group.yml index 88047e8e1..d9a0c0a00 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_core_group.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_core_group.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -79,7 +79,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-default namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_incompatible_protocol_and_route_kind.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_incompatible_protocol_and_route_kind.yml index c4a146881..6f983f1ec 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_incompatible_protocol_and_route_kind.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_incompatible_protocol_and_route_kind.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -27,7 +27,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_multiple_listeners_using_same_hostname_port_protocol.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_multiple_listeners_using_same_hostname_port_protocol.yml index dd3d32238..b57edc456 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_multiple_listeners_using_same_hostname_port_protocol.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_multiple_listeners_using_same_hostname_port_protocol.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-http namespace: default @@ -49,7 +49,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-tcp namespace: default @@ -77,7 +77,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-tls namespace: default @@ -113,7 +113,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default @@ -128,7 +128,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-2 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_all.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_all.yml index f12dad908..a05cf0c73 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_all.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_all.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -92,7 +92,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-default namespace: default @@ -160,7 +160,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-bar namespace: bar diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_same.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_same.yml index 4dbf7118c..78ce26173 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_same.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_same.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -92,7 +92,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-default namespace: default @@ -160,7 +160,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-bar namespace: bar diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_selector.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_selector.yml index e2c982eaa..eb16d4727 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_selector.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_selector.yml @@ -30,7 +30,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -38,7 +38,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -126,7 +126,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-default namespace: default @@ -194,7 +194,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-bar namespace: bar diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_wrong_routes_selector.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_wrong_routes_selector.yml index 4562ecfe4..9d915f3e6 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_wrong_routes_selector.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_wrong_routes_selector.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class namespace: default @@ -9,7 +9,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-mixed-gateway namespace: default @@ -74,7 +74,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/gatewayclass_with_unknown_controller.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/gatewayclass_with_unknown_controller.yml index 5dafcdfd3..5c6769c1c 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/gatewayclass_with_unknown_controller.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/gatewayclass_with_unknown_controller.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple.yml index 49e6fb1d4..707cc79c0 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class namespace: default @@ -9,7 +9,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-tcp-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple_cross_provider.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple_cross_provider.yml index be491cf79..01b314182 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple_cross_provider.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/simple_cross_provider.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_multiple_routes.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_multiple_routes.yml index d4da7c2fc..f6e64920b 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_multiple_routes.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_multiple_routes.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class namespace: default @@ -9,7 +9,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-tcp-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_multiple_rules.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_multiple_rules.yml index 57496b0d6..ab6118021 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_multiple_rules.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_multiple_rules.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class namespace: default @@ -9,7 +9,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-tcp-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_all.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_all.yml index 27c9abce6..1386c859d 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_all.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_all.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class namespace: default @@ -9,7 +9,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-tcp-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_same.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_same.yml index 43e251edd..20b2d0b87 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_same.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_same.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class namespace: default @@ -9,7 +9,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-tcp-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_selector.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_selector.yml index 94c7770c9..23d0c9540 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_selector.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_namespace_selector.yml @@ -8,7 +8,7 @@ metadata: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class namespace: default @@ -17,7 +17,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-tcp-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_http.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_http.yml index 724103c4a..2a9068ffa 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_http.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_http.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_https.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_https.yml index b207e758c..ceb2f0bb0 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_https.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_https.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_tls.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_tls.yml index 6d4228279..05e3fc5ae 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_tls.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_protocol_tls.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_tls_configuration.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_tls_configuration.yml index d31ddeb04..4c859717d 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_tls_configuration.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_tls_configuration.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_wrong_service_port.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_wrong_service_port.yml index 7c442a179..6de20a14a 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_wrong_service_port.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/with_wrong_service_port.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_gatewayclass.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_gatewayclass.yml index 231e6e55d..6b21d91c0 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_gatewayclass.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_gatewayclass.yml @@ -1,6 +1,6 @@ --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_tcproute.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_tcproute.yml index 64eb3c73b..1dc7bd058 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_tcproute.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_tcproute.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_tcproute_tls_protocol.yml b/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_tcproute_tls_protocol.yml index d6c6fa309..67e8f584d 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_tcproute_tls_protocol.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tcproute/without_tcproute_tls_protocol.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/gatewayclass_with_unknown_controller.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/gatewayclass_with_unknown_controller.yml index 6b19420b0..0e9c8f448 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/gatewayclass_with_unknown_controller.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/gatewayclass_with_unknown_controller.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute.yml index 25c935451..4a2dc107f 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class namespace: default @@ -20,7 +20,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-tls-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute_passthrough.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute_passthrough.yml index 525d6dbf2..664ad837a 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute_passthrough.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TCPRoute_passthrough.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class namespace: default @@ -9,7 +9,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-tls-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TLSRoute.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TLSRoute.yml index de79b72a0..e41a60aa7 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TLSRoute.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_TLS_to_TLSRoute.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class namespace: default @@ -20,7 +20,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-tls-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_cross_provider.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_cross_provider.yml index 4d687b5de..46c588590 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_cross_provider.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/simple_cross_provider.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_SNI_matching.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_SNI_matching.yml index f4f09af5f..fa61b383f 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_SNI_matching.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_SNI_matching.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_invalid_SNI_matching.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_invalid_SNI_matching.yml index 512e39770..f1485032d 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_invalid_SNI_matching.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_invalid_SNI_matching.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_SNI_matching.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_SNI_matching.yml index ae03dc627..a99ac3ac5 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_SNI_matching.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_SNI_matching.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_routes_kind.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_routes_kind.yml index 2f62394e4..c88672329 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_routes_kind.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_routes_kind.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class namespace: default @@ -20,7 +20,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-tls-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_rules.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_rules.yml index f6313193c..44cd37953 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_rules.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_multiple_rules.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class namespace: default @@ -9,7 +9,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_all.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_all.yml index e9a942afa..763ce9006 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_all.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_all.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_same.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_same.yml index ef81e534c..473e7618b 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_same.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_same.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_selector.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_selector.yml index c51ed45a2..25cd31c65 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_selector.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_namespace_selector.yml @@ -8,7 +8,7 @@ metadata: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -16,7 +16,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_passthrough.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_passthrough.yml index 2c3369aca..149b4af98 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_passthrough.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_passthrough.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_passthrough_tls.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_passthrough_tls.yml index da5d22d84..e04d4e362 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_passthrough_tls.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_passthrough_tls.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_http.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_http.yml index 25411db69..072f74477 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_http.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_http.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_https.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_https.yml index 782f344aa..c5d904baa 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_https.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_https.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_tcp.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_tcp.yml index b27e1fe7e..916506a4a 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_tcp.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_protocol_tcp.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_wrong_service_port.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_wrong_service_port.yml index 1aafeb234..c0c472a55 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_wrong_service_port.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/with_wrong_service_port.yml @@ -11,7 +11,7 @@ data: --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -19,7 +19,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/without_gatewayclass.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/without_gatewayclass.yml index c053f92e1..c4970535c 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/without_gatewayclass.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/without_gatewayclass.yml @@ -1,6 +1,6 @@ --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/without_tlsroute.yml b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/without_tlsroute.yml index 9eb8cc5e0..b134a16d7 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/tlsroute/without_tlsroute.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/tlsroute/without_tlsroute.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_one_wildcard.yml b/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_one_wildcard.yml index 5e20fd9bf..33b2cad7e 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_one_wildcard.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_one_wildcard.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_wildcard.yml b/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_wildcard.yml index c368d7fbc..f069e9b3b 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_wildcard.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_wildcard.yml @@ -1,6 +1,6 @@ --- kind: GatewayClass -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway-class spec: @@ -8,7 +8,7 @@ spec: --- kind: Gateway -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: my-gateway namespace: default @@ -24,7 +24,7 @@ spec: --- kind: HTTPRoute -apiVersion: gateway.networking.k8s.io/v1alpha2 +apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-app-1 namespace: default diff --git a/pkg/provider/kubernetes/gateway/kubernetes.go b/pkg/provider/kubernetes/gateway/kubernetes.go index bbdf63fc7..2379b2cfa 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes.go +++ b/pkg/provider/kubernetes/gateway/kubernetes.go @@ -30,9 +30,9 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" "k8s.io/utils/strings/slices" - gatev1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + gatev1 "sigs.k8s.io/gateway-api/apis/v1" ) const ( @@ -64,7 +64,7 @@ func (p *Provider) SetRouterTransform(routerTransform k8s.RouterTransform) { p.routerTransform = routerTransform } -func (p *Provider) applyRouterTransform(ctx context.Context, rt *dynamic.Router, route *gatev1alpha2.HTTPRoute) { +func (p *Provider) applyRouterTransform(ctx context.Context, rt *dynamic.Router, route *gatev1.HTTPRoute) { if p.routerTransform == nil { return } @@ -227,14 +227,14 @@ func (p *Provider) loadConfigurationFromGateway(ctx context.Context, client Clie gatewayClassNames[gatewayClass.Name] = struct{}{} err := client.UpdateGatewayClassStatus(gatewayClass, metav1.Condition{ - Type: string(gatev1alpha2.GatewayClassConditionStatusAccepted), + Type: string(gatev1.GatewayClassConditionStatusAccepted), Status: metav1.ConditionTrue, Reason: "Handled", Message: "Handled by Traefik controller", LastTransitionTime: metav1.Now(), }) if err != nil { - logger.Error().Err(err).Msgf("Failed to update %s condition", gatev1alpha2.GatewayClassConditionStatusAccepted) + logger.Error().Err(err).Msgf("Failed to update %s condition", gatev1.GatewayClassConditionStatusAccepted) } } } @@ -290,7 +290,7 @@ func (p *Provider) loadConfigurationFromGateway(ctx context.Context, client Clie return conf } -func (p *Provider) createGatewayConf(ctx context.Context, client Client, gateway *gatev1alpha2.Gateway) (*dynamic.Configuration, error) { +func (p *Provider) createGatewayConf(ctx context.Context, client Client, gateway *gatev1.Gateway) (*dynamic.Configuration, error) { conf := &dynamic.Configuration{ HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -318,7 +318,7 @@ func (p *Provider) createGatewayConf(ctx context.Context, client Client, gateway // and cannot be configured on the Gateway. listenerStatuses := p.fillGatewayConf(ctx, client, gateway, conf, tlsConfigs) - gatewayStatus, errG := p.makeGatewayStatus(listenerStatuses) + gatewayStatus, errG := p.makeGatewayStatus(gateway, listenerStatuses) err := client.UpdateGatewayStatus(gateway, gatewayStatus) if err != nil { @@ -336,15 +336,15 @@ func (p *Provider) createGatewayConf(ctx context.Context, client Client, gateway return conf, nil } -func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *gatev1alpha2.Gateway, conf *dynamic.Configuration, tlsConfigs map[string]*tls.CertAndStores) []gatev1alpha2.ListenerStatus { +func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *gatev1.Gateway, conf *dynamic.Configuration, tlsConfigs map[string]*tls.CertAndStores) []gatev1.ListenerStatus { logger := log.Ctx(ctx) - listenerStatuses := make([]gatev1alpha2.ListenerStatus, len(gateway.Spec.Listeners)) + listenerStatuses := make([]gatev1.ListenerStatus, len(gateway.Spec.Listeners)) allocatedListeners := make(map[string]struct{}) for i, listener := range gateway.Spec.Listeners { - listenerStatuses[i] = gatev1alpha2.ListenerStatus{ + listenerStatuses[i] = gatev1.ListenerStatus{ Name: listener.Name, - SupportedKinds: []gatev1alpha2.RouteGroupKind{}, + SupportedKinds: []gatev1.RouteGroupKind{}, Conditions: []metav1.Condition{}, } @@ -356,7 +356,7 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway * listenerStatuses[i].SupportedKinds = supportedKinds - routeKinds, conditions := getAllowedRouteKinds(listener, supportedKinds) + routeKinds, conditions := getAllowedRouteKinds(gateway, listener, supportedKinds) if len(conditions) > 0 { listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, conditions...) continue @@ -366,8 +366,9 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway * if _, ok := allocatedListeners[listenerKey]; ok { listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionConflicted), + Type: string(gatev1.ListenerConditionConflicted), Status: metav1.ConditionTrue, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "DuplicateListener", Message: "A listener with same protocol, port and hostname already exists", @@ -382,20 +383,22 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway * if err != nil { // update "Detached" status with "PortUnavailable" reason listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionDetached), - Status: metav1.ConditionTrue, + Type: string(gatev1.ListenerConditionAccepted), + Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), - Reason: string(gatev1alpha2.ListenerReasonPortUnavailable), + Reason: string(gatev1.ListenerReasonPortUnavailable), Message: fmt.Sprintf("Cannot find entryPoint for Gateway: %v", err), }) continue } - if (listener.Protocol == gatev1alpha2.HTTPProtocolType || listener.Protocol == gatev1alpha2.TCPProtocolType) && listener.TLS != nil { + if (listener.Protocol == gatev1.HTTPProtocolType || listener.Protocol == gatev1.TCPProtocolType) && listener.TLS != nil { listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionDetached), - Status: metav1.ConditionTrue, + Type: string(gatev1.ListenerConditionAccepted), + Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "InvalidTLSConfiguration", // TODO check the spec if a proper reason is introduced at some point Message: "TLS configuration must no be defined when using HTTP or TCP protocol", @@ -405,12 +408,13 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway * } // TLS - if listener.Protocol == gatev1alpha2.HTTPSProtocolType || listener.Protocol == gatev1alpha2.TLSProtocolType { - if listener.TLS == nil || (len(listener.TLS.CertificateRefs) == 0 && listener.TLS.Mode != nil && *listener.TLS.Mode != gatev1alpha2.TLSModePassthrough) { + if listener.Protocol == gatev1.HTTPSProtocolType || listener.Protocol == gatev1.TLSProtocolType { + if listener.TLS == nil || (len(listener.TLS.CertificateRefs) == 0 && listener.TLS.Mode != nil && *listener.TLS.Mode != gatev1.TLSModePassthrough) { // update "Detached" status with "UnsupportedProtocol" reason listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionDetached), - Status: metav1.ConditionTrue, + Type: string(gatev1.ListenerConditionAccepted), + Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "InvalidTLSConfiguration", // TODO check the spec if a proper reason is introduced at some point Message: fmt.Sprintf("No TLS configuration for Gateway Listener %s:%d and protocol %q", @@ -420,12 +424,12 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway * continue } - var tlsModeType gatev1alpha2.TLSModeType + var tlsModeType gatev1.TLSModeType if listener.TLS.Mode != nil { tlsModeType = *listener.TLS.Mode } - isTLSPassthrough := tlsModeType == gatev1alpha2.TLSModePassthrough + isTLSPassthrough := tlsModeType == gatev1.TLSModePassthrough if isTLSPassthrough && len(listener.TLS.CertificateRefs) > 0 { // https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.GatewayTLSConfig @@ -436,12 +440,13 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway * // Protocol TLS -> Passthrough -> TLSRoute/TCPRoute // Protocol TLS -> Terminate -> TLSRoute/TCPRoute // Protocol HTTPS -> Terminate -> HTTPRoute - if listener.Protocol == gatev1alpha2.HTTPSProtocolType && isTLSPassthrough { + if listener.Protocol == gatev1.HTTPSProtocolType && isTLSPassthrough { listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionDetached), - Status: metav1.ConditionTrue, + Type: string(gatev1.ListenerConditionAccepted), + Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), - Reason: string(gatev1alpha2.ListenerReasonUnsupportedProtocol), + Reason: string(gatev1.ListenerReasonUnsupportedProtocol), Message: "HTTPS protocol is not supported with TLS mode Passthrough", }) @@ -452,10 +457,11 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway * if len(listener.TLS.CertificateRefs) == 0 { // update "ResolvedRefs" status true with "InvalidCertificateRef" reason listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), - Reason: string(gatev1alpha2.ListenerReasonInvalidCertificateRef), + Reason: string(gatev1.ListenerReasonInvalidCertificateRef), Message: "One TLS CertificateRef is required in Terminate mode", }) @@ -469,10 +475,11 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway * certificateRef.Group == nil || (*certificateRef.Group != "" && *certificateRef.Group != "core") { // update "ResolvedRefs" status true with "InvalidCertificateRef" reason listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), - Reason: string(gatev1alpha2.ListenerReasonInvalidCertificateRef), + Reason: string(gatev1.ListenerReasonInvalidCertificateRef), Message: fmt.Sprintf("Unsupported TLS CertificateRef group/kind: %v/%v", certificateRef.Group, certificateRef.Kind), }) @@ -482,10 +489,11 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway * // TODO Support ReferencePolicy to support cross namespace references. if certificateRef.Namespace != nil && string(*certificateRef.Namespace) != gateway.Namespace { listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), - Reason: string(gatev1alpha2.ListenerReasonInvalidCertificateRef), + Reason: string(gatev1.ListenerReasonInvalidCertificateRef), Message: "Cross namespace secrets are not supported", }) @@ -498,10 +506,11 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway * if err != nil { // update "ResolvedRefs" status true with "InvalidCertificateRef" reason listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), - Reason: string(gatev1alpha2.ListenerReasonInvalidCertificateRef), + Reason: string(gatev1.ListenerReasonInvalidCertificateRef), Message: fmt.Sprintf("Error while retrieving certificate: %v", err), }) @@ -528,10 +537,10 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway * return listenerStatuses } -func (p *Provider) makeGatewayStatus(listenerStatuses []gatev1alpha2.ListenerStatus) (gatev1alpha2.GatewayStatus, error) { +func (p *Provider) makeGatewayStatus(gateway *gatev1.Gateway, listenerStatuses []gatev1.ListenerStatus) (gatev1.GatewayStatus, error) { // As Status.Addresses are not implemented yet, we initialize an empty array to follow the API expectations. - gatewayStatus := gatev1alpha2.GatewayStatus{ - Addresses: []gatev1alpha2.GatewayAddress{}, + gatewayStatus := gatev1.GatewayStatus{ + Addresses: []gatev1.GatewayStatusAddress{}, } var result error @@ -539,8 +548,9 @@ func (p *Provider) makeGatewayStatus(listenerStatuses []gatev1alpha2.ListenerSta if len(listener.Conditions) == 0 { // GatewayConditionReady "Ready", GatewayConditionReason "ListenerReady" listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionReady), + Type: string(gatev1.ListenerReasonAccepted), Status: metav1.ConditionTrue, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "ListenerReady", Message: "No error found", @@ -557,10 +567,11 @@ func (p *Provider) makeGatewayStatus(listenerStatuses []gatev1alpha2.ListenerSta if result != nil { // GatewayConditionReady "Ready", GatewayConditionReason "ListenersNotValid" gatewayStatus.Conditions = append(gatewayStatus.Conditions, metav1.Condition{ - Type: string(gatev1alpha2.GatewayConditionReady), + Type: string(gatev1.GatewayConditionAccepted), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), - Reason: string(gatev1alpha2.GatewayReasonListenersNotValid), + Reason: string(gatev1.GatewayReasonListenersNotValid), Message: "All Listeners must be valid", }) @@ -570,20 +581,13 @@ func (p *Provider) makeGatewayStatus(listenerStatuses []gatev1alpha2.ListenerSta gatewayStatus.Listeners = listenerStatuses gatewayStatus.Conditions = append(gatewayStatus.Conditions, - // update "Scheduled" status with "ResourcesAvailable" reason + // update "Accepted" status with "Accepted" reason metav1.Condition{ - Type: string(gatev1alpha2.GatewayConditionScheduled), + Type: string(gatev1.GatewayConditionAccepted), Status: metav1.ConditionTrue, - Reason: "ResourcesAvailable", - Message: "Resources available", - LastTransitionTime: metav1.Now(), - }, - // update "Ready" status with "ListenersValid" reason - metav1.Condition{ - Type: string(gatev1alpha2.GatewayConditionReady), - Status: metav1.ConditionTrue, - Reason: "ListenersValid", - Message: "Listeners valid", + ObservedGeneration: gateway.Generation, + Reason: string(gatev1.GatewayConditionAccepted), + Message: "Gateway successfully scheduled", LastTransitionTime: metav1.Now(), }, ) @@ -591,14 +595,14 @@ func (p *Provider) makeGatewayStatus(listenerStatuses []gatev1alpha2.ListenerSta return gatewayStatus, nil } -func (p *Provider) entryPointName(port gatev1alpha2.PortNumber, protocol gatev1alpha2.ProtocolType) (string, error) { +func (p *Provider) entryPointName(port gatev1.PortNumber, protocol gatev1.ProtocolType) (string, error) { portStr := strconv.FormatInt(int64(port), 10) for name, entryPoint := range p.EntryPoints { if strings.HasSuffix(entryPoint.Address, ":"+portStr) { // If the protocol is HTTP the entryPoint must have no TLS conf - // Not relevant for gatev1alpha2.TLSProtocolType && gatev1alpha2.TCPProtocolType - if protocol == gatev1alpha2.HTTPProtocolType && entryPoint.HasHTTPTLSConf { + // Not relevant for gatev1.TLSProtocolType && gatev1.TCPProtocolType + if protocol == gatev1.HTTPProtocolType && entryPoint.HasHTTPTLSConf { continue } @@ -609,43 +613,43 @@ func (p *Provider) entryPointName(port gatev1alpha2.PortNumber, protocol gatev1a return "", fmt.Errorf("no matching entryPoint for port %d and protocol %q", port, protocol) } -func supportedRouteKinds(protocol gatev1alpha2.ProtocolType) ([]gatev1alpha2.RouteGroupKind, []metav1.Condition) { - group := gatev1alpha2.Group(gatev1alpha2.GroupName) +func supportedRouteKinds(protocol gatev1.ProtocolType) ([]gatev1.RouteGroupKind, []metav1.Condition) { + group := gatev1.Group(gatev1.GroupName) switch protocol { - case gatev1alpha2.TCPProtocolType: - return []gatev1alpha2.RouteGroupKind{{Kind: kindTCPRoute, Group: &group}}, nil + case gatev1.TCPProtocolType: + return []gatev1.RouteGroupKind{{Kind: kindTCPRoute, Group: &group}}, nil - case gatev1alpha2.HTTPProtocolType, gatev1alpha2.HTTPSProtocolType: - return []gatev1alpha2.RouteGroupKind{{Kind: kindHTTPRoute, Group: &group}}, nil + case gatev1.HTTPProtocolType, gatev1.HTTPSProtocolType: + return []gatev1.RouteGroupKind{{Kind: kindHTTPRoute, Group: &group}}, nil - case gatev1alpha2.TLSProtocolType: - return []gatev1alpha2.RouteGroupKind{ + case gatev1.TLSProtocolType: + return []gatev1.RouteGroupKind{ {Kind: kindTCPRoute, Group: &group}, {Kind: kindTLSRoute, Group: &group}, }, nil } return nil, []metav1.Condition{{ - Type: string(gatev1alpha2.ListenerConditionDetached), - Status: metav1.ConditionTrue, + Type: string(gatev1.ListenerConditionAccepted), + Status: metav1.ConditionFalse, LastTransitionTime: metav1.Now(), - Reason: string(gatev1alpha2.ListenerReasonUnsupportedProtocol), + Reason: string(gatev1.ListenerReasonUnsupportedProtocol), Message: fmt.Sprintf("Unsupported listener protocol %q", protocol), }} } -func getAllowedRouteKinds(listener gatev1alpha2.Listener, supportedKinds []gatev1alpha2.RouteGroupKind) ([]gatev1alpha2.RouteGroupKind, []metav1.Condition) { +func getAllowedRouteKinds(gateway *gatev1.Gateway, listener gatev1.Listener, supportedKinds []gatev1.RouteGroupKind) ([]gatev1.RouteGroupKind, []metav1.Condition) { if listener.AllowedRoutes == nil || len(listener.AllowedRoutes.Kinds) == 0 { return supportedKinds, nil } var ( - routeKinds []gatev1alpha2.RouteGroupKind + routeKinds []gatev1.RouteGroupKind conditions []metav1.Condition ) - uniqRouteKinds := map[gatev1alpha2.Kind]struct{}{} + uniqRouteKinds := map[gatev1.Kind]struct{}{} for _, routeKind := range listener.AllowedRoutes.Kinds { var isSupported bool for _, kind := range supportedKinds { @@ -657,10 +661,11 @@ func getAllowedRouteKinds(listener gatev1alpha2.Listener, supportedKinds []gatev if !isSupported { conditions = append(conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionDetached), + Type: string(gatev1.ListenerConditionAccepted), Status: metav1.ConditionTrue, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), - Reason: string(gatev1alpha2.ListenerReasonInvalidRouteKinds), + Reason: string(gatev1.ListenerReasonInvalidRouteKinds), Message: fmt.Sprintf("Listener protocol %q does not support RouteGroupKind %v/%s", listener.Protocol, routeKind.Group, routeKind.Kind), }) continue @@ -675,7 +680,7 @@ func getAllowedRouteKinds(listener gatev1alpha2.Listener, supportedKinds []gatev return routeKinds, conditions } -func (p *Provider) gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener gatev1alpha2.Listener, gateway *gatev1alpha2.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { +func (p *Provider) gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, listener gatev1.Listener, gateway *gatev1.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { if listener.AllowedRoutes == nil { // Should not happen due to validation. return nil @@ -685,8 +690,9 @@ func (p *Provider) gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, li if err != nil { // update "ResolvedRefs" status true with "InvalidRoutesRef" reason return []metav1.Condition{{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "InvalidRouteNamespacesSelector", // Should never happen as the selector is validated by kubernetes Message: fmt.Sprintf("Invalid route namespaces selector: %v", err), @@ -697,10 +703,11 @@ func (p *Provider) gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, li if err != nil { // update "ResolvedRefs" status true with "InvalidRoutesRef" reason return []metav1.Condition{{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), - Reason: string(gatev1alpha2.ListenerReasonRefNotPermitted), + Reason: string(gatev1.ListenerReasonRefNotPermitted), Message: fmt.Sprintf("Cannot fetch HTTPRoutes: %v", err), }} } @@ -726,8 +733,9 @@ func (p *Provider) gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, li hostRule, err := hostRule(hostnames) if err != nil { conditions = append(conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "InvalidRouteHostname", // TODO check the spec if a proper reason is introduced at some point Message: fmt.Sprintf("Skipping HTTPRoute %s: invalid hostname: %v", route.Name, err), @@ -740,8 +748,9 @@ func (p *Provider) gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, li if err != nil { // update "ResolvedRefs" status true with "DroppedRoutes" reason conditions = append(conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "UnsupportedPathOrHeaderType", // TODO check the spec if a proper reason is introduced at some point Message: fmt.Sprintf("Skipping HTTPRoute %s: cannot generate rule: %v", route.Name, err), @@ -753,7 +762,7 @@ func (p *Provider) gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, li EntryPoints: []string{ep}, } - if listener.Protocol == gatev1alpha2.HTTPSProtocolType && listener.TLS != nil { + if listener.Protocol == gatev1.HTTPSProtocolType && listener.TLS != nil { // TODO support let's encrypt router.TLS = &dynamic.RouterTLSConfig{} } @@ -764,8 +773,9 @@ func (p *Provider) gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, li if err != nil { // update "ResolvedRefs" status true with "DroppedRoutes" reason conditions = append(conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "InvalidRouterKey", // Should never happen Message: fmt.Sprintf("Skipping HTTPRoute %s: cannot make router's key with rule %s: %v", route.Name, router.Rule, err), @@ -779,8 +789,9 @@ func (p *Provider) gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, li if err != nil { // update "ResolvedRefs" status true with "InvalidFilters" reason conditions = append(conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "InvalidFilters", // TODO check the spec if a proper reason is introduced at some point Message: fmt.Sprintf("Cannot load HTTPRoute filter %s/%s: %v", route.Namespace, route.Name, err), @@ -807,8 +818,9 @@ func (p *Provider) gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, li if err != nil { // update "ResolvedRefs" status true with "DroppedRoutes" reason conditions = append(conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "InvalidBackendRefs", // TODO check the spec if a proper reason is introduced at some point Message: fmt.Sprintf("Cannot load HTTPRoute service %s/%s: %v", route.Namespace, route.Name, err), @@ -839,7 +851,7 @@ func (p *Provider) gatewayHTTPRouteToHTTPConf(ctx context.Context, ep string, li return conditions } -func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener gatev1alpha2.Listener, gateway *gatev1alpha2.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { +func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener gatev1.Listener, gateway *gatev1.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { if listener.AllowedRoutes == nil { // Should not happen due to validation. return nil @@ -849,8 +861,9 @@ func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener gatev1alp if err != nil { // update "ResolvedRefs" status true with "InvalidRoutesRef" reason return []metav1.Condition{{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "InvalidRouteNamespacesSelector", // TODO should never happen as the selector is validated by Kubernetes Message: fmt.Sprintf("Invalid route namespaces selector: %v", err), @@ -861,10 +874,11 @@ func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener gatev1alp if err != nil { // update "ResolvedRefs" status true with "InvalidRoutesRef" reason return []metav1.Condition{{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), - Reason: string(gatev1alpha2.ListenerReasonRefNotPermitted), + Reason: string(gatev1.ListenerReasonRefNotPermitted), Message: fmt.Sprintf("Cannot fetch TCPRoutes: %v", err), }} } @@ -885,10 +899,10 @@ func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener gatev1alp EntryPoints: []string{ep}, } - if listener.Protocol == gatev1alpha2.TLSProtocolType && listener.TLS != nil { + if listener.Protocol == gatev1.TLSProtocolType && listener.TLS != nil { // TODO support let's encrypt router.TLS = &dynamic.RouterTCPTLSConfig{ - Passthrough: listener.TLS.Mode != nil && *listener.TLS.Mode == gatev1alpha2.TLSModePassthrough, + Passthrough: listener.TLS.Mode != nil && *listener.TLS.Mode == gatev1.TLSModePassthrough, } } @@ -898,8 +912,9 @@ func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener gatev1alp if err != nil { // update "ResolvedRefs" status true with "DroppedRoutes" reason conditions = append(conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "InvalidRouterKey", // Should never happen Message: fmt.Sprintf("Skipping TCPRoute %s: cannot make router's key with rule %s: %v", route.Name, router.Rule, err), @@ -923,8 +938,9 @@ func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener gatev1alp if err != nil { // update "ResolvedRefs" status true with "DroppedRoutes" reason conditions = append(conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "InvalidBackendRefs", // TODO check the spec if a proper reason is introduced at some point Message: fmt.Sprintf("Cannot load TCPRoute service %s/%s: %v", route.Namespace, route.Name, err), @@ -969,7 +985,7 @@ func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener gatev1alp return conditions } -func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener gatev1alpha2.Listener, gateway *gatev1alpha2.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { +func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener gatev1.Listener, gateway *gatev1.Gateway, client Client, conf *dynamic.Configuration) []metav1.Condition { if listener.AllowedRoutes == nil { // Should not happen due to validation. return nil @@ -979,8 +995,9 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener gatev1alp if err != nil { // update "ResolvedRefs" status true with "InvalidRoutesRef" reason return []metav1.Condition{{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "InvalidRouteNamespacesSelector", // TODO should never happen as the selector is validated by Kubernetes Message: fmt.Sprintf("Invalid route namespaces selector: %v", err), @@ -991,10 +1008,11 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener gatev1alp if err != nil { // update "ResolvedRefs" status true with "InvalidRoutesRef" reason return []metav1.Condition{{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), - Reason: string(gatev1alpha2.ListenerReasonRefNotPermitted), + Reason: string(gatev1.ListenerReasonRefNotPermitted), Message: fmt.Sprintf("Cannot fetch TLSRoutes: %v", err), }} } @@ -1014,9 +1032,10 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener gatev1alp if len(hostnames) == 0 && listener.Hostname != nil && *listener.Hostname != "" && len(route.Spec.Hostnames) > 0 { for _, parent := range route.Status.Parents { parent.Conditions = append(parent.Conditions, metav1.Condition{ - Type: string(gatev1alpha2.GatewayClassConditionStatusAccepted), + Type: string(gatev1.GatewayClassConditionStatusAccepted), Status: metav1.ConditionFalse, - Reason: string(gatev1alpha2.ListenerReasonRouteConflict), + ObservedGeneration: gateway.Generation, + Reason: string(gatev1.ListenerConditionConflicted), Message: fmt.Sprintf("No hostname match between listener: %v and route: %v", listener.Hostname, route.Spec.Hostnames), LastTransitionTime: metav1.Now(), }) @@ -1029,8 +1048,9 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener gatev1alp if err != nil { // update "ResolvedRefs" status true with "DroppedRoutes" reason conditions = append(conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "InvalidHostnames", // TODO check the spec if a proper reason is introduced at some point Message: fmt.Sprintf("Skipping TLSRoute %s: cannot make route's SNI match: %v", route.Name, err), @@ -1043,7 +1063,7 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener gatev1alp Rule: rule, EntryPoints: []string{ep}, TLS: &dynamic.RouterTCPTLSConfig{ - Passthrough: listener.TLS.Mode != nil && *listener.TLS.Mode == gatev1alpha2.TLSModePassthrough, + Passthrough: listener.TLS.Mode != nil && *listener.TLS.Mode == gatev1.TLSModePassthrough, }, } @@ -1053,8 +1073,9 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener gatev1alp if err != nil { // update "ResolvedRefs" status true with "DroppedRoutes" reason conditions = append(conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "InvalidRouterKey", // Should never happen Message: fmt.Sprintf("Skipping TLSRoute %s: cannot make router's key with rule %s: %v", route.Name, router.Rule, err), @@ -1078,8 +1099,9 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener gatev1alp if err != nil { // update "ResolvedRefs" status true with "DroppedRoutes" reason conditions = append(conditions, metav1.Condition{ - Type: string(gatev1alpha2.ListenerConditionResolvedRefs), + Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, + ObservedGeneration: gateway.Generation, LastTransitionTime: metav1.Now(), Reason: "InvalidBackendRefs", // TODO check the spec if a proper reason is introduced at some point Message: fmt.Sprintf("Cannot load TLSRoute service %s/%s: %v", route.Namespace, route.Name, err), @@ -1126,18 +1148,18 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener gatev1alp // Because of Kubernetes validation we admit that the given Hostnames are valid. // https://github.com/kubernetes-sigs/gateway-api/blob/ff9883da4cad8554cd300394f725ab3a27502785/apis/v1alpha2/shared_types.go#L252 -func matchingHostnames(listener gatev1alpha2.Listener, hostnames []gatev1alpha2.Hostname) []gatev1alpha2.Hostname { +func matchingHostnames(listener gatev1.Listener, hostnames []gatev1.Hostname) []gatev1.Hostname { if listener.Hostname == nil || *listener.Hostname == "" { return hostnames } if len(hostnames) == 0 { - return []gatev1alpha2.Hostname{*listener.Hostname} + return []gatev1.Hostname{*listener.Hostname} } listenerLabels := strings.Split(string(*listener.Hostname), ".") - var matches []gatev1alpha2.Hostname + var matches []gatev1.Hostname for _, hostname := range hostnames { if hostname == *listener.Hostname { @@ -1168,9 +1190,9 @@ func matchingHostnames(listener gatev1alpha2.Listener, hostnames []gatev1alpha2. return matches } -func shouldAttach(gateway *gatev1alpha2.Gateway, listener gatev1alpha2.Listener, routeNamespace string, routeSpec gatev1alpha2.CommonRouteSpec) bool { +func shouldAttach(gateway *gatev1.Gateway, listener gatev1.Listener, routeNamespace string, routeSpec gatev1.CommonRouteSpec) bool { for _, parentRef := range routeSpec.ParentRefs { - if parentRef.Group == nil || *parentRef.Group != gatev1alpha2.GroupName { + if parentRef.Group == nil || *parentRef.Group != gatev1.GroupName { continue } @@ -1195,19 +1217,19 @@ func shouldAttach(gateway *gatev1alpha2.Gateway, listener gatev1alpha2.Listener, return false } -func getRouteBindingSelectorNamespace(client Client, gatewayNamespace string, routeNamespaces *gatev1alpha2.RouteNamespaces) ([]string, error) { +func getRouteBindingSelectorNamespace(client Client, gatewayNamespace string, routeNamespaces *gatev1.RouteNamespaces) ([]string, error) { if routeNamespaces == nil || routeNamespaces.From == nil { return []string{gatewayNamespace}, nil } switch *routeNamespaces.From { - case gatev1alpha2.NamespacesFromAll: + case gatev1.NamespacesFromAll: return []string{metav1.NamespaceAll}, nil - case gatev1alpha2.NamespacesFromSame: + case gatev1.NamespacesFromSame: return []string{gatewayNamespace}, nil - case gatev1alpha2.NamespacesFromSelector: + case gatev1.NamespacesFromSelector: selector, err := metav1.LabelSelectorAsSelector(routeNamespaces.Selector) if err != nil { return nil, fmt.Errorf("malformed selector: %w", err) @@ -1219,7 +1241,7 @@ func getRouteBindingSelectorNamespace(client Client, gatewayNamespace string, ro return nil, fmt.Errorf("unsupported RouteSelectType: %q", *routeNamespaces.From) } -func hostRule(hostnames []gatev1alpha2.Hostname) (string, error) { +func hostRule(hostnames []gatev1.Hostname) (string, error) { var rules []string for _, hostname := range hostnames { @@ -1256,9 +1278,9 @@ func hostRule(hostnames []gatev1alpha2.Hostname) (string, error) { } } -func hostSNIRule(hostnames []gatev1alpha2.Hostname) (string, error) { +func hostSNIRule(hostnames []gatev1.Hostname) (string, error) { rules := make([]string, 0, len(hostnames)) - uniqHostnames := map[gatev1alpha2.Hostname]struct{}{} + uniqHostnames := map[gatev1.Hostname]struct{}{} for _, hostname := range hostnames { if len(hostname) == 0 { @@ -1293,7 +1315,7 @@ func hostSNIRule(hostnames []gatev1alpha2.Hostname) (string, error) { return strings.Join(rules, " || "), nil } -func extractRule(routeRule gatev1alpha2.HTTPRouteRule, hostRule string) (string, error) { +func extractRule(routeRule gatev1.HTTPRouteRule, hostRule string) (string, error) { var rule string var matchesRules []string @@ -1307,9 +1329,9 @@ func extractRule(routeRule gatev1alpha2.HTTPRouteRule, hostRule string) (string, if match.Path != nil && match.Path.Type != nil && match.Path.Value != nil { // TODO handle other path types switch *match.Path.Type { - case gatev1alpha2.PathMatchExact: + case gatev1.PathMatchExact: matchRules = append(matchRules, fmt.Sprintf("Path(`%s`)", *match.Path.Value)) - case gatev1alpha2.PathMatchPathPrefix: + case gatev1.PathMatchPathPrefix: matchRules = append(matchRules, fmt.Sprintf("PathPrefix(`%s`)", *match.Path.Value)) default: return "", fmt.Errorf("unsupported path match %s", *match.Path.Type) @@ -1350,7 +1372,7 @@ func extractRule(routeRule gatev1alpha2.HTTPRouteRule, hostRule string) (string, return rule + "(" + strings.Join(matchesRules, " || ") + ")", nil } -func extractHeaderRules(headers []gatev1alpha2.HTTPHeaderMatch) ([]string, error) { +func extractHeaderRules(headers []gatev1.HTTPHeaderMatch) ([]string, error) { var headerRules []string // TODO handle other headers types @@ -1361,7 +1383,7 @@ func extractHeaderRules(headers []gatev1alpha2.HTTPHeaderMatch) ([]string, error } switch *header.Type { - case gatev1alpha2.HeaderMatchExact: + case gatev1.HeaderMatchExact: headerRules = append(headerRules, fmt.Sprintf("Headers(`%s`,`%s`)", header.Name, header.Value)) default: return nil, fmt.Errorf("unsupported header match type %s", *header.Type) @@ -1390,7 +1412,7 @@ func makeID(namespace, name string) string { return namespace + "-" + name } -func getTLS(k8sClient Client, secretName gatev1alpha2.ObjectName, namespace string) (*tls.CertAndStores, error) { +func getTLS(k8sClient Client, secretName gatev1.ObjectName, namespace string) (*tls.CertAndStores, error) { secret, exists, err := k8sClient.GetSecret(namespace, string(secretName)) if err != nil { return nil, fmt.Errorf("failed to fetch secret %s/%s: %w", namespace, secretName, err) @@ -1464,7 +1486,7 @@ func getCertificateBlocks(secret *corev1.Secret, namespace, secretName string) ( } // loadServices is generating a WRR service, even when there is only one target. -func loadServices(client Client, namespace string, backendRefs []gatev1alpha2.HTTPBackendRef) (*dynamic.Service, map[string]*dynamic.Service, error) { +func loadServices(client Client, namespace string, backendRefs []gatev1.HTTPBackendRef) (*dynamic.Service, map[string]*dynamic.Service, error) { services := map[string]*dynamic.Service{} wrrSvc := &dynamic.Service{ @@ -1483,7 +1505,7 @@ func loadServices(client Client, namespace string, backendRefs []gatev1alpha2.HT return nil, nil, fmt.Errorf("traefik internal service %s is not allowed in a WRR loadbalancer", backendRef.BackendRef.Name) } - weight := int(pointer.Int32Deref(backendRef.Weight, 1)) + weight := int(ptr.Deref(backendRef.Weight, 1)) if isTraefikService(backendRef.BackendRef) { wrrSvc.Weighted.Services = append(wrrSvc.Weighted.Services, dynamic.WRRService{Name: string(backendRef.Name), Weight: &weight}) @@ -1587,7 +1609,7 @@ func loadServices(client Client, namespace string, backendRefs []gatev1alpha2.HT } // loadTCPServices is generating a WRR service, even when there is only one target. -func loadTCPServices(client Client, namespace string, backendRefs []gatev1alpha2.BackendRef) (*dynamic.TCPService, map[string]*dynamic.TCPService, error) { +func loadTCPServices(client Client, namespace string, backendRefs []gatev1.BackendRef) (*dynamic.TCPService, map[string]*dynamic.TCPService, error) { services := map[string]*dynamic.TCPService{} wrrSvc := &dynamic.TCPService{ @@ -1606,7 +1628,7 @@ func loadTCPServices(client Client, namespace string, backendRefs []gatev1alpha2 return nil, nil, fmt.Errorf("traefik internal service %s is not allowed in a WRR loadbalancer", backendRef.Name) } - weight := int(pointer.Int32Deref(backendRef.Weight, 1)) + weight := int(ptr.Deref(backendRef.Weight, 1)) if isTraefikService(backendRef) { wrrSvc.Weighted.Services = append(wrrSvc.Weighted.Services, dynamic.TCPWRRService{Name: string(backendRef.Name), Weight: &weight}) @@ -1705,16 +1727,16 @@ func loadTCPServices(client Client, namespace string, backendRefs []gatev1alpha2 return wrrSvc, services, nil } -func loadMiddlewares(listener gatev1alpha2.Listener, prefix string, filters []gatev1alpha2.HTTPRouteFilter) (map[string]*dynamic.Middleware, error) { +func loadMiddlewares(listener gatev1.Listener, prefix string, filters []gatev1.HTTPRouteFilter) (map[string]*dynamic.Middleware, error) { middlewares := make(map[string]*dynamic.Middleware) // The spec allows for an empty string in which case we should use the // scheme of the request which in this case is the listener scheme. var listenerScheme string switch listener.Protocol { - case gatev1alpha2.HTTPProtocolType: + case gatev1.HTTPProtocolType: listenerScheme = "http" - case gatev1alpha2.HTTPSProtocolType: + case gatev1.HTTPSProtocolType: listenerScheme = "https" default: return nil, fmt.Errorf("invalid listener protocol %s", listener.Protocol) @@ -1723,7 +1745,7 @@ func loadMiddlewares(listener gatev1alpha2.Listener, prefix string, filters []ga for i, filter := range filters { var middleware *dynamic.Middleware switch filter.Type { - case gatev1alpha2.HTTPRouteFilterRequestRedirect: + case gatev1.HTTPRouteFilterRequestRedirect: var err error middleware, err = createRedirectRegexMiddleware(listenerScheme, filter.RequestRedirect) if err != nil { @@ -1745,7 +1767,7 @@ func loadMiddlewares(listener gatev1alpha2.Listener, prefix string, filters []ga return middlewares, nil } -func createRedirectRegexMiddleware(scheme string, filter *gatev1alpha2.HTTPRequestRedirectFilter) (*dynamic.Middleware, error) { +func createRedirectRegexMiddleware(scheme string, filter *gatev1.HTTPRequestRedirectFilter) (*dynamic.Middleware, error) { // Use the HTTPRequestRedirectFilter scheme if defined. filterScheme := scheme if filter.Scheme != nil { @@ -1823,7 +1845,7 @@ func throttleEvents(ctx context.Context, throttleDuration time.Duration, pool *s return eventsChanBuffered } -func isTraefikService(ref gatev1alpha2.BackendRef) bool { +func isTraefikService(ref gatev1.BackendRef) bool { if ref.Kind == nil || ref.Group == nil { return false } @@ -1831,13 +1853,13 @@ func isTraefikService(ref gatev1alpha2.BackendRef) bool { return *ref.Group == traefikv1alpha1.GroupName && *ref.Kind == kindTraefikService } -func isInternalService(ref gatev1alpha2.BackendRef) bool { +func isInternalService(ref gatev1.BackendRef) bool { return isTraefikService(ref) && strings.HasSuffix(string(ref.Name), "@internal") } // makeListenerKey joins protocol, hostname, and port of a listener into a string key. -func makeListenerKey(l gatev1alpha2.Listener) string { - var hostname gatev1alpha2.Hostname +func makeListenerKey(l gatev1.Listener) string { + var hostname gatev1.Hostname if l.Hostname != nil { hostname = *l.Hostname } diff --git a/pkg/provider/kubernetes/gateway/kubernetes_test.go b/pkg/provider/kubernetes/gateway/kubernetes_test.go index 467f22874..1238576d2 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes_test.go +++ b/pkg/provider/kubernetes/gateway/kubernetes_test.go @@ -12,8 +12,8 @@ import ( "github.com/traefik/traefik/v3/pkg/provider" "github.com/traefik/traefik/v3/pkg/tls" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/pointer" - gatev1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + "k8s.io/utils/ptr" + gatev1 "sigs.k8s.io/gateway-api/apis/v1" ) var _ provider.Provider = (*Provider)(nil) @@ -573,7 +573,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -668,7 +668,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -728,7 +728,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -796,7 +796,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -855,7 +855,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -914,7 +914,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -988,7 +988,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -1004,7 +1004,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.4:8080", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -1067,7 +1067,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -1083,7 +1083,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.4:8080", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -1163,7 +1163,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -1252,7 +1252,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -1335,7 +1335,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -1394,7 +1394,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -1468,7 +1468,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -1484,7 +1484,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.12:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -1543,7 +1543,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.12:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -1611,7 +1611,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -1678,7 +1678,7 @@ func TestLoadHTTPRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -3810,7 +3810,7 @@ func TestLoadMixedRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -3989,7 +3989,7 @@ func TestLoadMixedRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -4194,7 +4194,7 @@ func TestLoadMixedRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -4210,7 +4210,7 @@ func TestLoadMixedRoutes(t *testing.T) { URL: "http://10.10.0.12:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -4361,7 +4361,7 @@ func TestLoadMixedRoutes(t *testing.T) { URL: "http://10.10.0.12:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -4513,7 +4513,7 @@ func TestLoadMixedRoutes(t *testing.T) { URL: "http://10.10.0.2:80", }, }, - PassHostHeader: pointer.Bool(true), + PassHostHeader: ptr.To(true), ResponseForwarding: &dynamic.ResponseForwarding{ FlushInterval: ptypes.Duration(100 * time.Millisecond), }, @@ -4555,7 +4555,7 @@ func TestLoadMixedRoutes(t *testing.T) { func Test_hostRule(t *testing.T) { testCases := []struct { desc string - hostnames []gatev1alpha2.Hostname + hostnames []gatev1.Hostname expectedRule string expectErr bool }{ @@ -4565,14 +4565,14 @@ func Test_hostRule(t *testing.T) { }, { desc: "One Host", - hostnames: []gatev1alpha2.Hostname{ + hostnames: []gatev1.Hostname{ "Foo", }, expectedRule: "Host(`Foo`)", }, { desc: "Multiple Hosts", - hostnames: []gatev1alpha2.Hostname{ + hostnames: []gatev1.Hostname{ "Foo", "Bar", "Bir", @@ -4581,7 +4581,7 @@ func Test_hostRule(t *testing.T) { }, { desc: "Multiple Hosts with empty one", - hostnames: []gatev1alpha2.Hostname{ + hostnames: []gatev1.Hostname{ "Foo", "", "Bir", @@ -4590,7 +4590,7 @@ func Test_hostRule(t *testing.T) { }, { desc: "Multiple empty hosts", - hostnames: []gatev1alpha2.Hostname{ + hostnames: []gatev1.Hostname{ "", "", "", @@ -4599,7 +4599,7 @@ func Test_hostRule(t *testing.T) { }, { desc: "Several Host and wildcard", - hostnames: []gatev1alpha2.Hostname{ + hostnames: []gatev1.Hostname{ "*.bar.foo", "bar.foo", "foo.foo", @@ -4608,21 +4608,21 @@ func Test_hostRule(t *testing.T) { }, { desc: "Host with wildcard", - hostnames: []gatev1alpha2.Hostname{ + hostnames: []gatev1.Hostname{ "*.bar.foo", }, expectedRule: "HostRegexp(`^[a-zA-Z0-9-]+\\.bar\\.foo$`)", }, { desc: "Alone wildcard", - hostnames: []gatev1alpha2.Hostname{ + hostnames: []gatev1.Hostname{ "*", "*.foo.foo", }, }, { desc: "Multiple alone Wildcard", - hostnames: []gatev1alpha2.Hostname{ + hostnames: []gatev1.Hostname{ "foo.foo", "*.*", }, @@ -4630,7 +4630,7 @@ func Test_hostRule(t *testing.T) { }, { desc: "Multiple Wildcard", - hostnames: []gatev1alpha2.Hostname{ + hostnames: []gatev1.Hostname{ "foo.foo", "*.toto.*.bar.foo", }, @@ -4638,7 +4638,7 @@ func Test_hostRule(t *testing.T) { }, { desc: "Multiple subdomain with misplaced wildcard", - hostnames: []gatev1alpha2.Hostname{ + hostnames: []gatev1.Hostname{ "foo.foo", "toto.*.bar.foo", }, @@ -4663,7 +4663,7 @@ func Test_hostRule(t *testing.T) { func Test_extractRule(t *testing.T) { testCases := []struct { desc string - routeRule gatev1alpha2.HTTPRouteRule + routeRule gatev1.HTTPRouteRule hostRule string expectedRule string expectedError bool @@ -4679,8 +4679,8 @@ func Test_extractRule(t *testing.T) { }, { desc: "One HTTPRouteMatch with nil HTTPHeaderMatch", - routeRule: gatev1alpha2.HTTPRouteRule{ - Matches: []gatev1alpha2.HTTPRouteMatch{ + routeRule: gatev1.HTTPRouteRule{ + Matches: []gatev1.HTTPRouteMatch{ {Headers: nil}, }, }, @@ -4688,10 +4688,10 @@ func Test_extractRule(t *testing.T) { }, { desc: "One HTTPRouteMatch with nil HTTPHeaderMatch Type", - routeRule: gatev1alpha2.HTTPRouteRule{ - Matches: []gatev1alpha2.HTTPRouteMatch{ + routeRule: gatev1.HTTPRouteRule{ + Matches: []gatev1.HTTPRouteMatch{ { - Headers: []gatev1alpha2.HTTPHeaderMatch{ + Headers: []gatev1.HTTPHeaderMatch{ {Type: nil, Name: "foo", Value: "bar"}, }, }, @@ -4701,8 +4701,8 @@ func Test_extractRule(t *testing.T) { }, { desc: "One HTTPRouteMatch with nil HTTPPathMatch", - routeRule: gatev1alpha2.HTTPRouteRule{ - Matches: []gatev1alpha2.HTTPRouteMatch{ + routeRule: gatev1.HTTPRouteRule{ + Matches: []gatev1.HTTPRouteMatch{ {Path: nil}, }, }, @@ -4710,12 +4710,12 @@ func Test_extractRule(t *testing.T) { }, { desc: "One HTTPRouteMatch with nil HTTPPathMatch Type", - routeRule: gatev1alpha2.HTTPRouteRule{ - Matches: []gatev1alpha2.HTTPRouteMatch{ + routeRule: gatev1.HTTPRouteRule{ + Matches: []gatev1.HTTPRouteMatch{ { - Path: &gatev1alpha2.HTTPPathMatch{ + Path: &gatev1.HTTPPathMatch{ Type: nil, - Value: pointer.String("/foo/"), + Value: ptr.To("/foo/"), }, }, }, @@ -4724,11 +4724,11 @@ func Test_extractRule(t *testing.T) { }, { desc: "One HTTPRouteMatch with nil HTTPPathMatch Values", - routeRule: gatev1alpha2.HTTPRouteRule{ - Matches: []gatev1alpha2.HTTPRouteMatch{ + routeRule: gatev1.HTTPRouteRule{ + Matches: []gatev1.HTTPRouteMatch{ { - Path: &gatev1alpha2.HTTPPathMatch{ - Type: pathMatchTypePtr(gatev1alpha2.PathMatchExact), + Path: &gatev1.HTTPPathMatch{ + Type: pathMatchTypePtr(gatev1.PathMatchExact), Value: nil, }, }, @@ -4738,12 +4738,12 @@ func Test_extractRule(t *testing.T) { }, { desc: "One Path in matches", - routeRule: gatev1alpha2.HTTPRouteRule{ - Matches: []gatev1alpha2.HTTPRouteMatch{ + routeRule: gatev1.HTTPRouteRule{ + Matches: []gatev1.HTTPRouteMatch{ { - Path: &gatev1alpha2.HTTPPathMatch{ - Type: pathMatchTypePtr(gatev1alpha2.PathMatchExact), - Value: pointer.String("/foo/"), + Path: &gatev1.HTTPPathMatch{ + Type: pathMatchTypePtr(gatev1.PathMatchExact), + Value: ptr.To("/foo/"), }, }, }, @@ -4752,18 +4752,18 @@ func Test_extractRule(t *testing.T) { }, { desc: "One Path in matches and another unknown", - routeRule: gatev1alpha2.HTTPRouteRule{ - Matches: []gatev1alpha2.HTTPRouteMatch{ + routeRule: gatev1.HTTPRouteRule{ + Matches: []gatev1.HTTPRouteMatch{ { - Path: &gatev1alpha2.HTTPPathMatch{ - Type: pathMatchTypePtr(gatev1alpha2.PathMatchExact), - Value: pointer.String("/foo/"), + Path: &gatev1.HTTPPathMatch{ + Type: pathMatchTypePtr(gatev1.PathMatchExact), + Value: ptr.To("/foo/"), }, }, { - Path: &gatev1alpha2.HTTPPathMatch{ + Path: &gatev1.HTTPPathMatch{ Type: pathMatchTypePtr("unknown"), - Value: pointer.String("/foo/"), + Value: ptr.To("/foo/"), }, }, }, @@ -4772,12 +4772,12 @@ func Test_extractRule(t *testing.T) { }, { desc: "One Path in matches and another empty", - routeRule: gatev1alpha2.HTTPRouteRule{ - Matches: []gatev1alpha2.HTTPRouteMatch{ + routeRule: gatev1.HTTPRouteRule{ + Matches: []gatev1.HTTPRouteMatch{ { - Path: &gatev1alpha2.HTTPPathMatch{ - Type: pathMatchTypePtr(gatev1alpha2.PathMatchExact), - Value: pointer.String("/foo/"), + Path: &gatev1.HTTPPathMatch{ + Type: pathMatchTypePtr(gatev1.PathMatchExact), + Value: ptr.To("/foo/"), }, }, {}, @@ -4787,18 +4787,18 @@ func Test_extractRule(t *testing.T) { }, { desc: "Path OR Header rules", - routeRule: gatev1alpha2.HTTPRouteRule{ - Matches: []gatev1alpha2.HTTPRouteMatch{ + routeRule: gatev1.HTTPRouteRule{ + Matches: []gatev1.HTTPRouteMatch{ { - Path: &gatev1alpha2.HTTPPathMatch{ - Type: pathMatchTypePtr(gatev1alpha2.PathMatchExact), - Value: pointer.String("/foo/"), + Path: &gatev1.HTTPPathMatch{ + Type: pathMatchTypePtr(gatev1.PathMatchExact), + Value: ptr.To("/foo/"), }, }, { - Headers: []gatev1alpha2.HTTPHeaderMatch{ + Headers: []gatev1.HTTPHeaderMatch{ { - Type: headerMatchTypePtr(gatev1alpha2.HeaderMatchExact), + Type: headerMatchTypePtr(gatev1.HeaderMatchExact), Name: "my-header", Value: "foo", }, @@ -4810,16 +4810,16 @@ func Test_extractRule(t *testing.T) { }, { desc: "Path && Header rules", - routeRule: gatev1alpha2.HTTPRouteRule{ - Matches: []gatev1alpha2.HTTPRouteMatch{ + routeRule: gatev1.HTTPRouteRule{ + Matches: []gatev1.HTTPRouteMatch{ { - Path: &gatev1alpha2.HTTPPathMatch{ - Type: pathMatchTypePtr(gatev1alpha2.PathMatchExact), - Value: pointer.String("/foo/"), + Path: &gatev1.HTTPPathMatch{ + Type: pathMatchTypePtr(gatev1.PathMatchExact), + Value: ptr.To("/foo/"), }, - Headers: []gatev1alpha2.HTTPHeaderMatch{ + Headers: []gatev1.HTTPHeaderMatch{ { - Type: headerMatchTypePtr(gatev1alpha2.HeaderMatchExact), + Type: headerMatchTypePtr(gatev1.HeaderMatchExact), Name: "my-header", Value: "foo", }, @@ -4832,16 +4832,16 @@ func Test_extractRule(t *testing.T) { { desc: "Host && Path && Header rules", hostRule: "Host(`foo.com`)", - routeRule: gatev1alpha2.HTTPRouteRule{ - Matches: []gatev1alpha2.HTTPRouteMatch{ + routeRule: gatev1.HTTPRouteRule{ + Matches: []gatev1.HTTPRouteMatch{ { - Path: &gatev1alpha2.HTTPPathMatch{ - Type: pathMatchTypePtr(gatev1alpha2.PathMatchExact), - Value: pointer.String("/foo/"), + Path: &gatev1.HTTPPathMatch{ + Type: pathMatchTypePtr(gatev1.PathMatchExact), + Value: ptr.To("/foo/"), }, - Headers: []gatev1alpha2.HTTPHeaderMatch{ + Headers: []gatev1.HTTPHeaderMatch{ { - Type: headerMatchTypePtr(gatev1alpha2.HeaderMatchExact), + Type: headerMatchTypePtr(gatev1.HeaderMatchExact), Name: "my-header", Value: "foo", }, @@ -4854,18 +4854,18 @@ func Test_extractRule(t *testing.T) { { desc: "Host && (Path || Header) rules", hostRule: "Host(`foo.com`)", - routeRule: gatev1alpha2.HTTPRouteRule{ - Matches: []gatev1alpha2.HTTPRouteMatch{ + routeRule: gatev1.HTTPRouteRule{ + Matches: []gatev1.HTTPRouteMatch{ { - Path: &gatev1alpha2.HTTPPathMatch{ - Type: pathMatchTypePtr(gatev1alpha2.PathMatchExact), - Value: pointer.String("/foo/"), + Path: &gatev1.HTTPPathMatch{ + Type: pathMatchTypePtr(gatev1.PathMatchExact), + Value: ptr.To("/foo/"), }, }, { - Headers: []gatev1alpha2.HTTPHeaderMatch{ + Headers: []gatev1.HTTPHeaderMatch{ { - Type: headerMatchTypePtr(gatev1alpha2.HeaderMatchExact), + Type: headerMatchTypePtr(gatev1.HeaderMatchExact), Name: "my-header", Value: "foo", }, @@ -4897,7 +4897,7 @@ func Test_extractRule(t *testing.T) { func Test_hostSNIRule(t *testing.T) { testCases := []struct { desc string - hostnames []gatev1alpha2.Hostname + hostnames []gatev1.Hostname expectedRule string expectError bool }{ @@ -4907,47 +4907,47 @@ func Test_hostSNIRule(t *testing.T) { }, { desc: "Empty hostname", - hostnames: []gatev1alpha2.Hostname{""}, + hostnames: []gatev1.Hostname{""}, expectedRule: "HostSNI(`*`)", }, { desc: "Unsupported wildcard", - hostnames: []gatev1alpha2.Hostname{"*"}, + hostnames: []gatev1.Hostname{"*"}, expectError: true, }, { desc: "Supported wildcard", - hostnames: []gatev1alpha2.Hostname{"*.foo"}, + hostnames: []gatev1.Hostname{"*.foo"}, expectedRule: "HostSNIRegexp(`^[a-zA-Z0-9-]+\\.foo$`)", }, { desc: "Multiple malformed wildcard", - hostnames: []gatev1alpha2.Hostname{"*.foo.*"}, + hostnames: []gatev1.Hostname{"*.foo.*"}, expectError: true, }, { desc: "Some empty hostnames", - hostnames: []gatev1alpha2.Hostname{"foo", "", "bar"}, + hostnames: []gatev1.Hostname{"foo", "", "bar"}, expectedRule: "HostSNI(`foo`) || HostSNI(`bar`)", }, { desc: "Valid hostname", - hostnames: []gatev1alpha2.Hostname{"foo"}, + hostnames: []gatev1.Hostname{"foo"}, expectedRule: "HostSNI(`foo`)", }, { desc: "Multiple valid hostnames", - hostnames: []gatev1alpha2.Hostname{"foo", "bar"}, + hostnames: []gatev1.Hostname{"foo", "bar"}, expectedRule: "HostSNI(`foo`) || HostSNI(`bar`)", }, { desc: "Multiple valid hostnames with wildcard", - hostnames: []gatev1alpha2.Hostname{"bar.foo", "foo.foo", "*.foo"}, + hostnames: []gatev1.Hostname{"bar.foo", "foo.foo", "*.foo"}, expectedRule: "HostSNI(`bar.foo`) || HostSNI(`foo.foo`) || HostSNIRegexp(`^[a-zA-Z0-9-]+\\.foo$`)", }, { desc: "Multiple overlapping hostnames", - hostnames: []gatev1alpha2.Hostname{"foo", "bar", "foo", "baz"}, + hostnames: []gatev1.Hostname{"foo", "bar", "foo", "baz"}, expectedRule: "HostSNI(`foo`) || HostSNI(`bar`) || HostSNI(`baz`)", }, } @@ -4972,49 +4972,49 @@ func Test_hostSNIRule(t *testing.T) { func Test_shouldAttach(t *testing.T) { testCases := []struct { desc string - gateway *gatev1alpha2.Gateway - listener gatev1alpha2.Listener + gateway *gatev1.Gateway + listener gatev1.Listener routeNamespace string - routeSpec gatev1alpha2.CommonRouteSpec + routeSpec gatev1.CommonRouteSpec expectedAttach bool }{ { desc: "No ParentRefs", - gateway: &gatev1alpha2.Gateway{ + gateway: &gatev1.Gateway{ ObjectMeta: metav1.ObjectMeta{ Name: "gateway", Namespace: "default", }, }, - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Name: "foo", }, routeNamespace: "default", - routeSpec: gatev1alpha2.CommonRouteSpec{ + routeSpec: gatev1.CommonRouteSpec{ ParentRefs: nil, }, expectedAttach: false, }, { desc: "Unsupported Kind", - gateway: &gatev1alpha2.Gateway{ + gateway: &gatev1.Gateway{ ObjectMeta: metav1.ObjectMeta{ Name: "gateway", Namespace: "default", }, }, - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Name: "foo", }, routeNamespace: "default", - routeSpec: gatev1alpha2.CommonRouteSpec{ - ParentRefs: []gatev1alpha2.ParentRef{ + routeSpec: gatev1.CommonRouteSpec{ + ParentRefs: []gatev1.ParentReference{ { SectionName: sectionNamePtr("bar"), Name: "gateway", Namespace: namespacePtr("default"), Kind: kindPtr("Foo"), - Group: groupPtr(gatev1alpha2.GroupName), + Group: groupPtr(gatev1.GroupName), }, }, }, @@ -5022,18 +5022,18 @@ func Test_shouldAttach(t *testing.T) { }, { desc: "Unsupported Group", - gateway: &gatev1alpha2.Gateway{ + gateway: &gatev1.Gateway{ ObjectMeta: metav1.ObjectMeta{ Name: "gateway", Namespace: "default", }, }, - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Name: "foo", }, routeNamespace: "default", - routeSpec: gatev1alpha2.CommonRouteSpec{ - ParentRefs: []gatev1alpha2.ParentRef{ + routeSpec: gatev1.CommonRouteSpec{ + ParentRefs: []gatev1.ParentReference{ { SectionName: sectionNamePtr("bar"), Name: "gateway", @@ -5047,23 +5047,23 @@ func Test_shouldAttach(t *testing.T) { }, { desc: "Kind is nil", - gateway: &gatev1alpha2.Gateway{ + gateway: &gatev1.Gateway{ ObjectMeta: metav1.ObjectMeta{ Name: "gateway", Namespace: "default", }, }, - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Name: "foo", }, routeNamespace: "default", - routeSpec: gatev1alpha2.CommonRouteSpec{ - ParentRefs: []gatev1alpha2.ParentRef{ + routeSpec: gatev1.CommonRouteSpec{ + ParentRefs: []gatev1.ParentReference{ { SectionName: sectionNamePtr("bar"), Name: "gateway", Namespace: namespacePtr("default"), - Group: groupPtr(gatev1alpha2.GroupName), + Group: groupPtr(gatev1.GroupName), }, }, }, @@ -5071,18 +5071,18 @@ func Test_shouldAttach(t *testing.T) { }, { desc: "Group is nil", - gateway: &gatev1alpha2.Gateway{ + gateway: &gatev1.Gateway{ ObjectMeta: metav1.ObjectMeta{ Name: "gateway", Namespace: "default", }, }, - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Name: "foo", }, routeNamespace: "default", - routeSpec: gatev1alpha2.CommonRouteSpec{ - ParentRefs: []gatev1alpha2.ParentRef{ + routeSpec: gatev1.CommonRouteSpec{ + ParentRefs: []gatev1.ParentReference{ { SectionName: sectionNamePtr("bar"), Name: "gateway", @@ -5095,23 +5095,23 @@ func Test_shouldAttach(t *testing.T) { }, { desc: "SectionName does not match a listener desc", - gateway: &gatev1alpha2.Gateway{ + gateway: &gatev1.Gateway{ ObjectMeta: metav1.ObjectMeta{ Name: "gateway", Namespace: "default", }, }, - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Name: "foo", }, routeNamespace: "default", - routeSpec: gatev1alpha2.CommonRouteSpec{ - ParentRefs: []gatev1alpha2.ParentRef{ + routeSpec: gatev1.CommonRouteSpec{ + ParentRefs: []gatev1.ParentReference{ { SectionName: sectionNamePtr("bar"), Name: "gateway", Namespace: namespacePtr("default"), - Group: groupPtr(gatev1alpha2.GroupName), + Group: groupPtr(gatev1.GroupName), Kind: kindPtr("Gateway"), }, }, @@ -5120,23 +5120,23 @@ func Test_shouldAttach(t *testing.T) { }, { desc: "Namespace does not match the Gateway namespace", - gateway: &gatev1alpha2.Gateway{ + gateway: &gatev1.Gateway{ ObjectMeta: metav1.ObjectMeta{ Name: "gateway", Namespace: "default", }, }, - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Name: "foo", }, routeNamespace: "default", - routeSpec: gatev1alpha2.CommonRouteSpec{ - ParentRefs: []gatev1alpha2.ParentRef{ + routeSpec: gatev1.CommonRouteSpec{ + ParentRefs: []gatev1.ParentReference{ { SectionName: sectionNamePtr("bar"), Name: "gateway", Namespace: namespacePtr("bar"), - Group: groupPtr(gatev1alpha2.GroupName), + Group: groupPtr(gatev1.GroupName), Kind: kindPtr("Gateway"), }, }, @@ -5145,22 +5145,22 @@ func Test_shouldAttach(t *testing.T) { }, { desc: "Route namespace does not match the Gateway namespace", - gateway: &gatev1alpha2.Gateway{ + gateway: &gatev1.Gateway{ ObjectMeta: metav1.ObjectMeta{ Name: "gateway", Namespace: "default", }, }, - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Name: "foo", }, routeNamespace: "bar", - routeSpec: gatev1alpha2.CommonRouteSpec{ - ParentRefs: []gatev1alpha2.ParentRef{ + routeSpec: gatev1.CommonRouteSpec{ + ParentRefs: []gatev1.ParentReference{ { SectionName: sectionNamePtr("bar"), Name: "gateway", - Group: groupPtr(gatev1alpha2.GroupName), + Group: groupPtr(gatev1.GroupName), Kind: kindPtr("Gateway"), }, }, @@ -5169,24 +5169,24 @@ func Test_shouldAttach(t *testing.T) { }, { desc: "Unsupported Kind", - gateway: &gatev1alpha2.Gateway{ + gateway: &gatev1.Gateway{ ObjectMeta: metav1.ObjectMeta{ Name: "gateway", Namespace: "default", }, }, - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Name: "foo", }, routeNamespace: "default", - routeSpec: gatev1alpha2.CommonRouteSpec{ - ParentRefs: []gatev1alpha2.ParentRef{ + routeSpec: gatev1.CommonRouteSpec{ + ParentRefs: []gatev1.ParentReference{ { SectionName: sectionNamePtr("bar"), Name: "gateway", Namespace: namespacePtr("default"), Kind: kindPtr("Gateway"), - Group: groupPtr(gatev1alpha2.GroupName), + Group: groupPtr(gatev1.GroupName), }, }, }, @@ -5194,23 +5194,23 @@ func Test_shouldAttach(t *testing.T) { }, { desc: "Route namespace matches the Gateway namespace", - gateway: &gatev1alpha2.Gateway{ + gateway: &gatev1.Gateway{ ObjectMeta: metav1.ObjectMeta{ Name: "gateway", Namespace: "default", }, }, - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Name: "foo", }, routeNamespace: "default", - routeSpec: gatev1alpha2.CommonRouteSpec{ - ParentRefs: []gatev1alpha2.ParentRef{ + routeSpec: gatev1.CommonRouteSpec{ + ParentRefs: []gatev1.ParentReference{ { SectionName: sectionNamePtr("foo"), Name: "gateway", Kind: kindPtr("Gateway"), - Group: groupPtr(gatev1alpha2.GroupName), + Group: groupPtr(gatev1.GroupName), }, }, }, @@ -5218,24 +5218,24 @@ func Test_shouldAttach(t *testing.T) { }, { desc: "Namespace matches the Gateway namespace", - gateway: &gatev1alpha2.Gateway{ + gateway: &gatev1.Gateway{ ObjectMeta: metav1.ObjectMeta{ Name: "gateway", Namespace: "default", }, }, - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Name: "foo", }, routeNamespace: "bar", - routeSpec: gatev1alpha2.CommonRouteSpec{ - ParentRefs: []gatev1alpha2.ParentRef{ + routeSpec: gatev1.CommonRouteSpec{ + ParentRefs: []gatev1.ParentReference{ { SectionName: sectionNamePtr("foo"), Name: "gateway", Namespace: namespacePtr("default"), Kind: kindPtr("Gateway"), - Group: groupPtr(gatev1alpha2.GroupName), + Group: groupPtr(gatev1.GroupName), }, }, }, @@ -5243,29 +5243,29 @@ func Test_shouldAttach(t *testing.T) { }, { desc: "Only one ParentRef matches the Gateway", - gateway: &gatev1alpha2.Gateway{ + gateway: &gatev1.Gateway{ ObjectMeta: metav1.ObjectMeta{ Name: "gateway", Namespace: "default", }, }, - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Name: "foo", }, routeNamespace: "bar", - routeSpec: gatev1alpha2.CommonRouteSpec{ - ParentRefs: []gatev1alpha2.ParentRef{ + routeSpec: gatev1.CommonRouteSpec{ + ParentRefs: []gatev1.ParentReference{ { Name: "gateway2", Namespace: namespacePtr("default"), Kind: kindPtr("Gateway"), - Group: groupPtr(gatev1alpha2.GroupName), + Group: groupPtr(gatev1.GroupName), }, { Name: "gateway", Namespace: namespacePtr("default"), Kind: kindPtr("Gateway"), - Group: groupPtr(gatev1alpha2.GroupName), + Group: groupPtr(gatev1.GroupName), }, }, }, @@ -5287,93 +5287,93 @@ func Test_shouldAttach(t *testing.T) { func Test_matchingHostnames(t *testing.T) { testCases := []struct { desc string - listener gatev1alpha2.Listener - hostnames []gatev1alpha2.Hostname - want []gatev1alpha2.Hostname + listener gatev1.Listener + hostnames []gatev1.Hostname + want []gatev1.Hostname }{ { desc: "Empty", }, { desc: "Only listener hostname", - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Hostname: hostnamePtr("foo.com"), }, - want: []gatev1alpha2.Hostname{"foo.com"}, + want: []gatev1.Hostname{"foo.com"}, }, { desc: "Only Route hostname", - hostnames: []gatev1alpha2.Hostname{"foo.com"}, - want: []gatev1alpha2.Hostname{"foo.com"}, + hostnames: []gatev1.Hostname{"foo.com"}, + want: []gatev1.Hostname{"foo.com"}, }, { desc: "Matching hostname", - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Hostname: hostnamePtr("foo.com"), }, - hostnames: []gatev1alpha2.Hostname{"foo.com"}, - want: []gatev1alpha2.Hostname{"foo.com"}, + hostnames: []gatev1.Hostname{"foo.com"}, + want: []gatev1.Hostname{"foo.com"}, }, { desc: "Matching hostname with wildcard", - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Hostname: hostnamePtr("*.foo.com"), }, - hostnames: []gatev1alpha2.Hostname{"*.foo.com"}, - want: []gatev1alpha2.Hostname{"*.foo.com"}, + hostnames: []gatev1.Hostname{"*.foo.com"}, + want: []gatev1.Hostname{"*.foo.com"}, }, { desc: "Matching subdomain with listener wildcard", - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Hostname: hostnamePtr("*.foo.com"), }, - hostnames: []gatev1alpha2.Hostname{"bar.foo.com"}, - want: []gatev1alpha2.Hostname{"bar.foo.com"}, + hostnames: []gatev1.Hostname{"bar.foo.com"}, + want: []gatev1.Hostname{"bar.foo.com"}, }, { desc: "Matching subdomain with route hostname wildcard", - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Hostname: hostnamePtr("bar.foo.com"), }, - hostnames: []gatev1alpha2.Hostname{"*.foo.com"}, - want: []gatev1alpha2.Hostname{"bar.foo.com"}, + hostnames: []gatev1.Hostname{"*.foo.com"}, + want: []gatev1.Hostname{"bar.foo.com"}, }, { desc: "Non matching root domain with listener wildcard", - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Hostname: hostnamePtr("*.foo.com"), }, - hostnames: []gatev1alpha2.Hostname{"foo.com"}, + hostnames: []gatev1.Hostname{"foo.com"}, }, { desc: "Non matching root domain with route hostname wildcard", - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Hostname: hostnamePtr("foo.com"), }, - hostnames: []gatev1alpha2.Hostname{"*.foo.com"}, + hostnames: []gatev1.Hostname{"*.foo.com"}, }, { desc: "Multiple route hostnames with one matching route hostname", - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Hostname: hostnamePtr("*.foo.com"), }, - hostnames: []gatev1alpha2.Hostname{"bar.com", "test.foo.com", "test.buz.com"}, - want: []gatev1alpha2.Hostname{"test.foo.com"}, + hostnames: []gatev1.Hostname{"bar.com", "test.foo.com", "test.buz.com"}, + want: []gatev1.Hostname{"test.foo.com"}, }, { desc: "Multiple route hostnames with non matching route hostname", - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Hostname: hostnamePtr("*.fuz.com"), }, - hostnames: []gatev1alpha2.Hostname{"bar.com", "test.foo.com", "test.buz.com"}, + hostnames: []gatev1.Hostname{"bar.com", "test.foo.com", "test.buz.com"}, }, { desc: "Multiple route hostnames with multiple matching route hostnames", - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Hostname: hostnamePtr("*.foo.com"), }, - hostnames: []gatev1alpha2.Hostname{"toto.foo.com", "test.foo.com", "test.buz.com"}, - want: []gatev1alpha2.Hostname{"toto.foo.com", "test.foo.com"}, + hostnames: []gatev1.Hostname{"toto.foo.com", "test.foo.com", "test.buz.com"}, + want: []gatev1.Hostname{"toto.foo.com", "test.foo.com"}, }, } @@ -5391,9 +5391,9 @@ func Test_matchingHostnames(t *testing.T) { func Test_getAllowedRoutes(t *testing.T) { testCases := []struct { desc string - listener gatev1alpha2.Listener - supportedRouteKinds []gatev1alpha2.RouteGroupKind - wantKinds []gatev1alpha2.RouteGroupKind + listener gatev1.Listener + supportedRouteKinds []gatev1.RouteGroupKind + wantKinds []gatev1.RouteGroupKind wantErr bool }{ { @@ -5401,90 +5401,90 @@ func Test_getAllowedRoutes(t *testing.T) { }, { desc: "Empty AllowedRoutes", - supportedRouteKinds: []gatev1alpha2.RouteGroupKind{ - {Kind: kindTLSRoute, Group: groupPtr(gatev1alpha2.GroupName)}, + supportedRouteKinds: []gatev1.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(gatev1.GroupName)}, }, - wantKinds: []gatev1alpha2.RouteGroupKind{ - {Kind: kindTLSRoute, Group: groupPtr(gatev1alpha2.GroupName)}, + wantKinds: []gatev1.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(gatev1.GroupName)}, }, }, { desc: "AllowedRoutes with unsupported Group", - listener: gatev1alpha2.Listener{ - AllowedRoutes: &gatev1alpha2.AllowedRoutes{ - Kinds: []gatev1alpha2.RouteGroupKind{{ + listener: gatev1.Listener{ + AllowedRoutes: &gatev1.AllowedRoutes{ + Kinds: []gatev1.RouteGroupKind{{ Kind: kindTLSRoute, Group: groupPtr("foo"), }}, }, }, - supportedRouteKinds: []gatev1alpha2.RouteGroupKind{ - {Kind: kindTLSRoute, Group: groupPtr(gatev1alpha2.GroupName)}, + supportedRouteKinds: []gatev1.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(gatev1.GroupName)}, }, wantErr: true, }, { desc: "AllowedRoutes with nil Group", - listener: gatev1alpha2.Listener{ - AllowedRoutes: &gatev1alpha2.AllowedRoutes{ - Kinds: []gatev1alpha2.RouteGroupKind{{ + listener: gatev1.Listener{ + AllowedRoutes: &gatev1.AllowedRoutes{ + Kinds: []gatev1.RouteGroupKind{{ Kind: kindTLSRoute, Group: nil, }}, }, }, - supportedRouteKinds: []gatev1alpha2.RouteGroupKind{ - {Kind: kindTLSRoute, Group: groupPtr(gatev1alpha2.GroupName)}, + supportedRouteKinds: []gatev1.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(gatev1.GroupName)}, }, wantErr: true, }, { desc: "AllowedRoutes with unsupported Kind", - listener: gatev1alpha2.Listener{ - AllowedRoutes: &gatev1alpha2.AllowedRoutes{ - Kinds: []gatev1alpha2.RouteGroupKind{{ - Kind: "foo", Group: groupPtr(gatev1alpha2.GroupName), + listener: gatev1.Listener{ + AllowedRoutes: &gatev1.AllowedRoutes{ + Kinds: []gatev1.RouteGroupKind{{ + Kind: "foo", Group: groupPtr(gatev1.GroupName), }}, }, }, - supportedRouteKinds: []gatev1alpha2.RouteGroupKind{ - {Kind: kindTLSRoute, Group: groupPtr(gatev1alpha2.GroupName)}, + supportedRouteKinds: []gatev1.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(gatev1.GroupName)}, }, wantErr: true, }, { desc: "Supported AllowedRoutes", - listener: gatev1alpha2.Listener{ - AllowedRoutes: &gatev1alpha2.AllowedRoutes{ - Kinds: []gatev1alpha2.RouteGroupKind{{ - Kind: kindTLSRoute, Group: groupPtr(gatev1alpha2.GroupName), + listener: gatev1.Listener{ + AllowedRoutes: &gatev1.AllowedRoutes{ + Kinds: []gatev1.RouteGroupKind{{ + Kind: kindTLSRoute, Group: groupPtr(gatev1.GroupName), }}, }, }, - supportedRouteKinds: []gatev1alpha2.RouteGroupKind{ - {Kind: kindTLSRoute, Group: groupPtr(gatev1alpha2.GroupName)}, + supportedRouteKinds: []gatev1.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(gatev1.GroupName)}, }, - wantKinds: []gatev1alpha2.RouteGroupKind{ - {Kind: kindTLSRoute, Group: groupPtr(gatev1alpha2.GroupName)}, + wantKinds: []gatev1.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(gatev1.GroupName)}, }, }, { desc: "Supported AllowedRoutes with duplicates", - listener: gatev1alpha2.Listener{ - AllowedRoutes: &gatev1alpha2.AllowedRoutes{ - Kinds: []gatev1alpha2.RouteGroupKind{ - {Kind: kindTLSRoute, Group: groupPtr(gatev1alpha2.GroupName)}, - {Kind: kindTCPRoute, Group: groupPtr(gatev1alpha2.GroupName)}, - {Kind: kindTLSRoute, Group: groupPtr(gatev1alpha2.GroupName)}, - {Kind: kindTCPRoute, Group: groupPtr(gatev1alpha2.GroupName)}, + listener: gatev1.Listener{ + AllowedRoutes: &gatev1.AllowedRoutes{ + Kinds: []gatev1.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(gatev1.GroupName)}, + {Kind: kindTCPRoute, Group: groupPtr(gatev1.GroupName)}, + {Kind: kindTLSRoute, Group: groupPtr(gatev1.GroupName)}, + {Kind: kindTCPRoute, Group: groupPtr(gatev1.GroupName)}, }, }, }, - supportedRouteKinds: []gatev1alpha2.RouteGroupKind{ - {Kind: kindTLSRoute, Group: groupPtr(gatev1alpha2.GroupName)}, - {Kind: kindTCPRoute, Group: groupPtr(gatev1alpha2.GroupName)}, + supportedRouteKinds: []gatev1.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(gatev1.GroupName)}, + {Kind: kindTCPRoute, Group: groupPtr(gatev1.GroupName)}, }, - wantKinds: []gatev1alpha2.RouteGroupKind{ - {Kind: kindTLSRoute, Group: groupPtr(gatev1alpha2.GroupName)}, - {Kind: kindTCPRoute, Group: groupPtr(gatev1alpha2.GroupName)}, + wantKinds: []gatev1.RouteGroupKind{ + {Kind: kindTLSRoute, Group: groupPtr(gatev1.GroupName)}, + {Kind: kindTCPRoute, Group: groupPtr(gatev1.GroupName)}, }, }, } @@ -5494,7 +5494,7 @@ func Test_getAllowedRoutes(t *testing.T) { t.Run(test.desc, func(t *testing.T) { t.Parallel() - got, conditions := getAllowedRouteKinds(test.listener, test.supportedRouteKinds) + got, conditions := getAllowedRouteKinds(&gatev1.Gateway{}, test.listener, test.supportedRouteKinds) if test.wantErr { require.NotEmpty(t, conditions, "no conditions") return @@ -5509,7 +5509,7 @@ func Test_getAllowedRoutes(t *testing.T) { func Test_makeListenerKey(t *testing.T) { testCases := []struct { desc string - listener gatev1alpha2.Listener + listener gatev1.Listener expectedKey string }{ { @@ -5518,18 +5518,18 @@ func Test_makeListenerKey(t *testing.T) { }, { desc: "listener with port, protocol and hostname", - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Port: 443, - Protocol: gatev1alpha2.HTTPSProtocolType, + Protocol: gatev1.HTTPSProtocolType, Hostname: hostnamePtr("www.example.com"), }, expectedKey: "HTTPS|www.example.com|443", }, { desc: "listener with port, protocol and nil hostname", - listener: gatev1alpha2.Listener{ + listener: gatev1.Listener{ Port: 443, - Protocol: gatev1alpha2.HTTPSProtocolType, + Protocol: gatev1.HTTPSProtocolType, }, expectedKey: "HTTPS||443", }, @@ -5545,26 +5545,26 @@ func Test_makeListenerKey(t *testing.T) { } } -func hostnamePtr(hostname gatev1alpha2.Hostname) *gatev1alpha2.Hostname { +func hostnamePtr(hostname gatev1.Hostname) *gatev1.Hostname { return &hostname } -func groupPtr(group gatev1alpha2.Group) *gatev1alpha2.Group { +func groupPtr(group gatev1.Group) *gatev1.Group { return &group } -func sectionNamePtr(sectionName gatev1alpha2.SectionName) *gatev1alpha2.SectionName { +func sectionNamePtr(sectionName gatev1.SectionName) *gatev1.SectionName { return §ionName } -func namespacePtr(namespace gatev1alpha2.Namespace) *gatev1alpha2.Namespace { +func namespacePtr(namespace gatev1.Namespace) *gatev1.Namespace { return &namespace } -func kindPtr(kind gatev1alpha2.Kind) *gatev1alpha2.Kind { +func kindPtr(kind gatev1.Kind) *gatev1.Kind { return &kind } -func pathMatchTypePtr(p gatev1alpha2.PathMatchType) *gatev1alpha2.PathMatchType { return &p } +func pathMatchTypePtr(p gatev1.PathMatchType) *gatev1.PathMatchType { return &p } -func headerMatchTypePtr(h gatev1alpha2.HeaderMatchType) *gatev1alpha2.HeaderMatchType { return &h } +func headerMatchTypePtr(h gatev1.HeaderMatchType) *gatev1.HeaderMatchType { return &h } diff --git a/pkg/provider/kubernetes/k8s/event_handler.go b/pkg/provider/kubernetes/k8s/event_handler.go index 92b450bec..14475c18c 100644 --- a/pkg/provider/kubernetes/k8s/event_handler.go +++ b/pkg/provider/kubernetes/k8s/event_handler.go @@ -11,7 +11,7 @@ type ResourceEventHandler struct { } // OnAdd is called on Add Events. -func (reh *ResourceEventHandler) OnAdd(obj interface{}) { +func (reh *ResourceEventHandler) OnAdd(obj interface{}, isInInitialList bool) { eventHandlerFunc(reh.Ev, obj) } From ccf3a9995aadc111c543d46cad5c4fe66212ae67 Mon Sep 17 00:00:00 2001 From: Jeremy Fleischman Date: Tue, 9 Jan 2024 11:26:05 -0800 Subject: [PATCH 21/21] Add `rejectStatusCode` option to `IPAllowList` middleware --- docs/content/middlewares/http/ipallowlist.md | 42 +++++++++++++++++++ .../dynamic-configuration/docker-labels.yml | 1 + .../reference/dynamic-configuration/file.toml | 1 + .../reference/dynamic-configuration/file.yaml | 1 + .../kubernetes-crd-definition-v1.yml | 4 ++ .../reference/dynamic-configuration/kv-ref.md | 1 + .../traefik.io_middlewares.yaml | 4 ++ integration/fixtures/k8s/01-traefik-crd.yml | 4 ++ pkg/config/dynamic/middlewares.go | 3 ++ pkg/config/label/label_test.go | 1 + pkg/middlewares/ipallowlist/ip_allowlist.go | 32 ++++++++------ .../ipallowlist/ip_allowlist_test.go | 26 ++++++++++++ 12 files changed, 108 insertions(+), 12 deletions(-) diff --git a/docs/content/middlewares/http/ipallowlist.md b/docs/content/middlewares/http/ipallowlist.md index 703b9f89b..19e1c86bc 100644 --- a/docs/content/middlewares/http/ipallowlist.md +++ b/docs/content/middlewares/http/ipallowlist.md @@ -207,3 +207,45 @@ http: [http.middlewares.test-ipallowlist.ipAllowList.ipStrategy] excludedIPs = ["127.0.0.1/32", "192.168.1.7"] ``` + +### `rejectStatusCode` + +The `rejectStatusCode` option sets HTTP status code for refused requests. If not set, the default is 403 (Forbidden). + +```yaml tab="Docker & Swarm" +# Reject requests with a 404 rather than a 403 +labels: + - "traefik.http.middlewares.test-ipallowlist.ipallowlist.rejectstatuscode=404" +``` + +```yaml tab="Kubernetes" +# Reject requests with a 404 rather than a 403 +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: test-ipallowlist +spec: + ipAllowList: + rejectStatusCode: 404 +``` + +```yaml tab="Consul Catalog" +# Reject requests with a 404 rather than a 403 +- "traefik.http.middlewares.test-ipallowlist.ipallowlist.rejectstatuscode=404" +``` + +```yaml tab="File (YAML)" +# Reject requests with a 404 rather than a 403 +http: + middlewares: + test-ipallowlist: + ipAllowList: + rejectStatusCode: 404 +``` + +```toml tab="File (TOML)" +# Reject requests with a 404 rather than a 403 +[http.middlewares] + [http.middlewares.test-ipallowlist.ipAllowList] + rejectStatusCode = 404 +``` diff --git a/docs/content/reference/dynamic-configuration/docker-labels.yml b/docs/content/reference/dynamic-configuration/docker-labels.yml index 26ef425c7..4f7ef62c7 100644 --- a/docs/content/reference/dynamic-configuration/docker-labels.yml +++ b/docs/content/reference/dynamic-configuration/docker-labels.yml @@ -68,6 +68,7 @@ - "traefik.http.middlewares.middleware11.ipallowlist.ipstrategy.depth=42" - "traefik.http.middlewares.middleware11.ipallowlist.ipstrategy.excludedips=foobar, foobar" - "traefik.http.middlewares.middleware11.ipallowlist.sourcerange=foobar, foobar" +- "traefik.http.middlewares.middleware11.ipallowlist.rejectstatuscode=404" - "traefik.http.middlewares.middleware12.inflightreq.amount=42" - "traefik.http.middlewares.middleware12.inflightreq.sourcecriterion.ipstrategy.depth=42" - "traefik.http.middlewares.middleware12.inflightreq.sourcecriterion.ipstrategy.excludedips=foobar, foobar" diff --git a/docs/content/reference/dynamic-configuration/file.toml b/docs/content/reference/dynamic-configuration/file.toml index 2e72be2aa..4c1e5c593 100644 --- a/docs/content/reference/dynamic-configuration/file.toml +++ b/docs/content/reference/dynamic-configuration/file.toml @@ -199,6 +199,7 @@ [http.middlewares.Middleware11] [http.middlewares.Middleware11.ipAllowList] sourceRange = ["foobar", "foobar"] + rejectStatusCode = 404 [http.middlewares.Middleware11.ipAllowList.ipStrategy] depth = 42 excludedIPs = ["foobar", "foobar"] diff --git a/docs/content/reference/dynamic-configuration/file.yaml b/docs/content/reference/dynamic-configuration/file.yaml index aa61082de..368ea3d5b 100644 --- a/docs/content/reference/dynamic-configuration/file.yaml +++ b/docs/content/reference/dynamic-configuration/file.yaml @@ -225,6 +225,7 @@ http: isDevelopment: true Middleware11: ipAllowList: + rejectStatusCode: 404 sourceRange: - foobar - foobar diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml index 66e5ca1b0..504c5cd9c 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml @@ -1181,6 +1181,10 @@ spec: type: string type: array type: object + rejectStatusCode: + description: RejectStatusCode defines the HTTP status code used + for refused requests. If not set, the default is 403 (Forbidden). + type: integer sourceRange: description: SourceRange defines the set of allowed IPs (or ranges of allowed IPs by using CIDR notation). diff --git a/docs/content/reference/dynamic-configuration/kv-ref.md b/docs/content/reference/dynamic-configuration/kv-ref.md index ce15fb1f2..ef5a7154f 100644 --- a/docs/content/reference/dynamic-configuration/kv-ref.md +++ b/docs/content/reference/dynamic-configuration/kv-ref.md @@ -81,6 +81,7 @@ | `traefik/http/middlewares/Middleware11/ipAllowList/ipStrategy/depth` | `42` | | `traefik/http/middlewares/Middleware11/ipAllowList/ipStrategy/excludedIPs/0` | `foobar` | | `traefik/http/middlewares/Middleware11/ipAllowList/ipStrategy/excludedIPs/1` | `foobar` | +| `traefik/http/middlewares/Middleware11/ipAllowList/rejectStatusCode` | `404` | | `traefik/http/middlewares/Middleware11/ipAllowList/sourceRange/0` | `foobar` | | `traefik/http/middlewares/Middleware11/ipAllowList/sourceRange/1` | `foobar` | | `traefik/http/middlewares/Middleware12/inFlightReq/amount` | `42` | diff --git a/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml b/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml index 4885a6315..1290a6163 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_middlewares.yaml @@ -606,6 +606,10 @@ spec: type: string type: array type: object + rejectStatusCode: + description: RejectStatusCode defines the HTTP status code used + for refused requests. If not set, the default is 403 (Forbidden). + type: integer sourceRange: description: SourceRange defines the set of allowed IPs (or ranges of allowed IPs by using CIDR notation). diff --git a/integration/fixtures/k8s/01-traefik-crd.yml b/integration/fixtures/k8s/01-traefik-crd.yml index 66e5ca1b0..504c5cd9c 100644 --- a/integration/fixtures/k8s/01-traefik-crd.yml +++ b/integration/fixtures/k8s/01-traefik-crd.yml @@ -1181,6 +1181,10 @@ spec: type: string type: array type: object + rejectStatusCode: + description: RejectStatusCode defines the HTTP status code used + for refused requests. If not set, the default is 403 (Forbidden). + type: integer sourceRange: description: SourceRange defines the set of allowed IPs (or ranges of allowed IPs by using CIDR notation). diff --git a/pkg/config/dynamic/middlewares.go b/pkg/config/dynamic/middlewares.go index 6ab6e5a05..a73881a2a 100644 --- a/pkg/config/dynamic/middlewares.go +++ b/pkg/config/dynamic/middlewares.go @@ -383,6 +383,9 @@ type IPAllowList struct { // SourceRange defines the set of allowed IPs (or ranges of allowed IPs by using CIDR notation). SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"` IPStrategy *IPStrategy `json:"ipStrategy,omitempty" toml:"ipStrategy,omitempty" yaml:"ipStrategy,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"` + // RejectStatusCode defines the HTTP status code used for refused requests. + // If not set, the default is 403 (Forbidden). + RejectStatusCode int `json:"rejectStatusCode,omitempty" toml:"rejectStatusCode,omitempty" yaml:"rejectStatusCode,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"` } // +k8s:deepcopy-gen=true diff --git a/pkg/config/label/label_test.go b/pkg/config/label/label_test.go index 334297edc..c55a73c15 100644 --- a/pkg/config/label/label_test.go +++ b/pkg/config/label/label_test.go @@ -1254,6 +1254,7 @@ func TestEncodeConfiguration(t *testing.T) { "traefik.HTTP.Middlewares.Middleware8.Headers.STSSeconds": "42", "traefik.HTTP.Middlewares.Middleware9.IPAllowList.IPStrategy.Depth": "42", "traefik.HTTP.Middlewares.Middleware9.IPAllowList.IPStrategy.ExcludedIPs": "foobar, fiibar", + "traefik.HTTP.Middlewares.Middleware9.IPAllowList.RejectStatusCode": "0", "traefik.HTTP.Middlewares.Middleware9.IPAllowList.SourceRange": "foobar, fiibar", "traefik.HTTP.Middlewares.Middleware10.InFlightReq.Amount": "42", "traefik.HTTP.Middlewares.Middleware10.InFlightReq.SourceCriterion.IPStrategy.Depth": "42", diff --git a/pkg/middlewares/ipallowlist/ip_allowlist.go b/pkg/middlewares/ipallowlist/ip_allowlist.go index ddd7bfe47..3841f3f23 100644 --- a/pkg/middlewares/ipallowlist/ip_allowlist.go +++ b/pkg/middlewares/ipallowlist/ip_allowlist.go @@ -20,10 +20,11 @@ const ( // ipAllowLister is a middleware that provides Checks of the Requesting IP against a set of Allowlists. type ipAllowLister struct { - next http.Handler - allowLister *ip.Checker - strategy ip.Strategy - name string + next http.Handler + allowLister *ip.Checker + strategy ip.Strategy + name string + rejectStatusCode int } // New builds a new IPAllowLister given a list of CIDR-Strings to allow. @@ -35,6 +36,14 @@ func New(ctx context.Context, next http.Handler, config dynamic.IPAllowList, nam return nil, errors.New("sourceRange is empty, IPAllowLister not created") } + rejectStatusCode := config.RejectStatusCode + // If RejectStatusCode is not given, default to Forbidden (403). + if rejectStatusCode == 0 { + rejectStatusCode = http.StatusForbidden + } else if http.StatusText(rejectStatusCode) == "" { + return nil, fmt.Errorf("invalid HTTP status code %d", rejectStatusCode) + } + checker, err := ip.NewChecker(config.SourceRange) if err != nil { return nil, fmt.Errorf("cannot parse CIDRs %s: %w", config.SourceRange, err) @@ -48,10 +57,11 @@ func New(ctx context.Context, next http.Handler, config dynamic.IPAllowList, nam logger.Debug().Msgf("Setting up IPAllowLister with sourceRange: %s", config.SourceRange) return &ipAllowLister{ - strategy: strategy, - allowLister: checker, - next: next, - name: name, + strategy: strategy, + allowLister: checker, + next: next, + name: name, + rejectStatusCode: rejectStatusCode, }, nil } @@ -69,7 +79,7 @@ func (al *ipAllowLister) ServeHTTP(rw http.ResponseWriter, req *http.Request) { msg := fmt.Sprintf("Rejecting IP %s: %v", clientIP, err) logger.Debug().Msg(msg) tracing.SetStatusErrorf(req.Context(), msg) - reject(ctx, rw) + reject(ctx, al.rejectStatusCode, rw) return } logger.Debug().Msgf("Accepting IP %s", clientIP) @@ -77,9 +87,7 @@ func (al *ipAllowLister) ServeHTTP(rw http.ResponseWriter, req *http.Request) { al.next.ServeHTTP(rw, req) } -func reject(ctx context.Context, rw http.ResponseWriter) { - statusCode := http.StatusForbidden - +func reject(ctx context.Context, statusCode int, rw http.ResponseWriter) { rw.WriteHeader(statusCode) _, err := rw.Write([]byte(http.StatusText(statusCode))) if err != nil { diff --git a/pkg/middlewares/ipallowlist/ip_allowlist_test.go b/pkg/middlewares/ipallowlist/ip_allowlist_test.go index 8bd26b3eb..cea46e401 100644 --- a/pkg/middlewares/ipallowlist/ip_allowlist_test.go +++ b/pkg/middlewares/ipallowlist/ip_allowlist_test.go @@ -30,6 +30,14 @@ func TestNewIPAllowLister(t *testing.T) { SourceRange: []string{"10.10.10.10"}, }, }, + { + desc: "invalid HTTP status code", + allowList: dynamic.IPAllowList{ + SourceRange: []string{"10.10.10.10"}, + RejectStatusCode: 600, + }, + expectedError: true, + }, } for _, test := range testCases { @@ -73,6 +81,24 @@ func TestIPAllowLister_ServeHTTP(t *testing.T) { remoteAddr: "20.20.20.21:1234", expected: 403, }, + { + desc: "authorized with remote address, reject 404", + allowList: dynamic.IPAllowList{ + SourceRange: []string{"20.20.20.20"}, + RejectStatusCode: 404, + }, + remoteAddr: "20.20.20.20:1234", + expected: 200, + }, + { + desc: "non authorized with remote address, reject 404", + allowList: dynamic.IPAllowList{ + SourceRange: []string{"20.20.20.20"}, + RejectStatusCode: 404, + }, + remoteAddr: "20.20.20.21:1234", + expected: 404, + }, } for _, test := range testCases {