From f2a2f97c690c1858f3da0ff820f0211a23a93bb4 Mon Sep 17 00:00:00 2001 From: Wouter Remijn Date: Fri, 30 May 2025 12:24:29 +0200 Subject: [PATCH 1/4] featuretype validation, wgs84 use in capabilities, admission checks test --- api/v2beta1/shared_conversion.go | 4 +- api/v2beta1/wfs_conversion.go | 2 +- api/v3/shared_types.go | 9 +- api/v3/shared_validation.go | 8 + api/v3/wfs_types.go | 12 +- api/v3/wfs_validation.go | 63 +++++++ api/v3/zz_generated.deepcopy.go | 11 +- config/crd/bases/pdok.nl_wfs.yaml | 17 +- config/crd/bases/pdok.nl_wms.yaml | 21 +-- .../capabilities_generator_test.go | 13 +- .../capabilitiesgenerator/mapper.go | 30 ++- .../test_data/wfs_input.yaml | 3 + .../controller/mapfilegenerator/mapper.go | 2 +- internal/controller/mapfilegenerator/types.go | 2 +- .../configmap-capabilities-generator.yaml | 2 +- .../wfs/complete/expected/deployment.yaml | 2 +- .../test_data/wfs/complete/input/wfs.yaml | 5 + .../configmap-capabilities-generator.yaml | 2 +- .../wfs/minimal/expected/deployment.yaml | 2 +- .../configmap-capabilities-generator.yaml | 2 +- .../wfs/noprefetch/expected/deployment.yaml | 2 +- internal/webhook/v3/shared_webhook.go | 2 +- internal/webhook/v3/test_data/v3_wfs.yaml | 71 +++++++ internal/webhook/v3/test_data/v3_wms.yaml | 152 +++++++++++++++ internal/webhook/v3/wfs_webhook_test.go | 175 ++++++++++++++++-- 25 files changed, 529 insertions(+), 85 deletions(-) create mode 100644 internal/webhook/v3/test_data/v3_wfs.yaml create mode 100644 internal/webhook/v3/test_data/v3_wms.yaml diff --git a/api/v2beta1/shared_conversion.go b/api/v2beta1/shared_conversion.go index 091ef6f..d2cdcfa 100644 --- a/api/v2beta1/shared_conversion.go +++ b/api/v2beta1/shared_conversion.go @@ -164,7 +164,7 @@ func ConvertV2DataToV3(v2 Data) pdoknlv3.Data { if v2.Tif != nil { v3.TIF = &pdoknlv3.TIF{ BlobKey: v2.Tif.BlobKey, - Resample: v2.Tif.Resample, + Resample: *v2.Tif.Resample, Offsite: v2.Tif.Offsite, GetFeatureInfoIncludesClass: smoothoperatorutils.PointerVal(v2.Tif.GetFeatureInfoIncludesClass, false), } @@ -201,7 +201,7 @@ func ConvertV3DataToV2(v3 pdoknlv3.Data) Data { v2.Tif = &Tif{ BlobKey: v3.TIF.BlobKey, Offsite: v3.TIF.Offsite, - Resample: v3.TIF.Resample, + Resample: &v3.TIF.Resample, GetFeatureInfoIncludesClass: &v3.TIF.GetFeatureInfoIncludesClass, } } diff --git a/api/v2beta1/wfs_conversion.go b/api/v2beta1/wfs_conversion.go index dbe4b25..fc39d8c 100644 --- a/api/v2beta1/wfs_conversion.go +++ b/api/v2beta1/wfs_conversion.go @@ -180,7 +180,7 @@ func convertV2FeatureTypeToV3(src FeatureType) pdoknlv3.FeatureType { if src.Extent != nil { featureTypeV3.Bbox = &pdoknlv3.FeatureBbox{ - DefaultCRS: smoothoperatormodel.ExtentToBBox(*src.Extent), + DefaultCRS: smoothoperatorutils.Pointer(smoothoperatormodel.ExtentToBBox(*src.Extent)), } } diff --git a/api/v3/shared_types.go b/api/v3/shared_types.go index f46ef58..5b8fa62 100644 --- a/api/v3/shared_types.go +++ b/api/v3/shared_types.go @@ -171,7 +171,6 @@ type Data struct { type Gpkg struct { // Blobkey identifies the location/bucket of the .gpkg file // +kubebuilder:validation:Pattern:=^.+\/.+\/.+\.gpkg$ - // +kubebuilder:validation:MinLength:=1 BlobKey string `json:"blobKey"` // TableName is the table within the geopackage @@ -180,7 +179,6 @@ type Gpkg struct { // GeometryType of the table, must match an OGC type // +kubebuilder:validation:Pattern:=`^(Multi)?(Point|LineString|Polygon)$` - // +kubebuilder:validation:MinLength:=1 GeometryType string `json:"geometryType"` // Columns to visualize for this table @@ -209,18 +207,15 @@ type Postgis struct { // +kubebuilder:validation:Type=object type TIF struct { // BlobKey to the TIFF file - // +kubebuilder:validation:Pattern=`\.(tif?f|vrt)$` - // +kubebuilder:validation:MinLength:=1 + // +kubebuilder:validation:Pattern:=`^.+\/.+\/.+\.(tif?f|vrt)$` BlobKey string `json:"blobKey"` // This option can be used to control the resampling kernel used sampling raster images, optional - // +kubebuilder:validation:MinLength:=1 // +kubebuilder:validation:Pattern=`(NEAREST|AVERAGE|BILINEAR)` // +kubebuilder:default=NEAREST - Resample *string `json:"resample,omitempty"` + Resample string `json:"resample,omitempty"` // Sets the color index to treat as transparent for raster layers, optional, hex or rgb - // +kubebuilder:validation:MinLength:=1 // +kubebuilder:validation:Pattern=`(#[0-9A-F]{6}([0-9A-F]{2})?)|([0-9]{1,3}\s[0-9]{1,3}\s[0-9]{1,3})` Offsite *string `json:"offsite,omitempty"` diff --git a/api/v3/shared_validation.go b/api/v3/shared_validation.go index a9fe797..397a22e 100644 --- a/api/v3/shared_validation.go +++ b/api/v3/shared_validation.go @@ -128,4 +128,12 @@ func ValidateInspire[O WMSWFS](obj O, allErrs *field.ErrorList) { } } + if obj.Type() == ServiceTypeWFS && len(datasetIDs) > 1 { + *allErrs = append(*allErrs, field.Invalid( + field.NewPath("spec").Child("service").Child("featureTypes[*]").Child("datasetMetadataUrl").Child("csw").Child("metadataIdentifier"), + datasetIDs, + "when Inspire, all featureTypes need use the same datasetMetadataUrl.csw.metadataIdentifier", + )) + } + } diff --git a/api/v3/wfs_types.go b/api/v3/wfs_types.go index faa1170..276a882 100644 --- a/api/v3/wfs_types.go +++ b/api/v3/wfs_types.go @@ -137,7 +137,6 @@ type WFSService struct { // Default CRS (DataEPSG) // +kubebuilder:validation:Pattern:="^EPSG:(28992|25831|25832|3034|3035|3857|4258|4326)$" - // +kubebuilder:validation:MinLength:=1 DefaultCrs string `json:"defaultCrs"` // Other supported CRS @@ -169,7 +168,6 @@ func (s WFSService) KeywordsIncludingInspireKeyword() []string { // HealthCheck is the struct with all fields to configure custom healthchecks type HealthCheckWFS struct { - // +kubebuilder:validation:MinLength:=1 // +kubebuilder:validation:XValidation:rule="self.contains('Service=WFS')",message="a valid healthcheck contains 'Service=WFS'" // +kubebuilder:validation:XValidation:rule="self.contains('Request=')",message="a valid healthcheck contains 'Request='" Querystring string `json:"querystring"` @@ -187,7 +185,7 @@ type Bbox struct { // FeatureType defines a WFS feature type FeatureType struct { // Name of the feature - // +kubebuilder:validation:MinLength:=1 + // +kubebuilder:validation:Pattern:=`^\S+$` Name string `json:"name"` // Title of the feature @@ -217,14 +215,14 @@ type FeatureType struct { Data Data `json:"data"` } -// FeatureType bounding box, if provided it overrides the default extent +// FeatureBbox is the optional featureType bounding box, if provided it overrides the default extent type FeatureBbox struct { - // DefaultCRS defines the feature’s bounding box in the service’s own CRS + // DefaultCRS defines the EXTENT/wfs_extent for the featureType for use in the mapfile //nolint:tagliatelle // +kubebuilder:validation:Type=object - DefaultCRS smoothoperatormodel.BBox `json:"defaultCRS"` + DefaultCRS *smoothoperatormodel.BBox `json:"defaultCRS,omitempty"` - // WGS84, if provided, gives the same bounding box reprojected into EPSG:4326. + // WGS84, if provided, gives the same bounding box reprojected into EPSG:4326 for use in the capabilities. // +kubebuilder:validation:Type=object WGS84 *smoothoperatormodel.BBox `json:"wgs84,omitempty"` } diff --git a/api/v3/wfs_validation.go b/api/v3/wfs_validation.go index f4c28e7..46658ae 100644 --- a/api/v3/wfs_validation.go +++ b/api/v3/wfs_validation.go @@ -1,6 +1,7 @@ package v3 import ( + "slices" "strings" sharedValidation "github.com/pdok/smooth-operator/pkg/validation" @@ -69,4 +70,66 @@ func ValidateWFS(wfs *WFS, warnings *[]string, allErrs *field.ErrorList) { podSpecPatch := wfs.Spec.PodSpecPatch ValidateEphemeralStorage(podSpecPatch, allErrs) + + ValidateFeatureTypes(wfs, warnings, allErrs) +} + +func ValidateFeatureTypes(wfs *WFS, warnings *[]string, allErrs *field.ErrorList) { + names := []string{} + path := field.NewPath("spec").Child("service").Child("featureTypes") + for index, featureType := range wfs.Spec.Service.FeatureTypes { + if slices.Contains(names, featureType.Name) { + *allErrs = append(*allErrs, field.Duplicate( + path.Index(index).Child("name"), + featureType.Name, + )) + } + + if !slices.Contains(names, featureType.Name) { + names = append(names, featureType.Name) + } + + if wfs.Spec.Service.Mapfile != nil && featureType.Bbox != nil && featureType.Bbox.DefaultCRS != nil { + sharedValidation.AddWarning( + warnings, + *path.Index(index).Child("bbox").Child("defaultCrs"), + "is not used when service.mapfile is configured", + wfs.GroupVersionKind(), + wfs.GetName(), + ) + } + + if tif := featureType.Data.TIF; tif != nil { + if tif.Resample != "NEAREST" { + sharedValidation.AddWarning( + warnings, + *path.Index(index).Child("data").Child("tif").Child("resample"), + "is not used when service.mapfile is configured", + wfs.GroupVersionKind(), + wfs.GetName(), + ) + } + + if tif.Offsite != nil { + sharedValidation.AddWarning( + warnings, + *path.Index(index).Child("data").Child("tif").Child("offsite"), + "is not used when service.mapfile is configured", + wfs.GroupVersionKind(), + wfs.GetName(), + ) + } + + if tif.GetFeatureInfoIncludesClass { + sharedValidation.AddWarning( + warnings, + *path.Index(index).Child("data").Child("tif").Child("getFeatureInfoIncludesClass"), + "is not used when service.mapfile is configured", + wfs.GroupVersionKind(), + wfs.GetName(), + ) + } + } + + } } diff --git a/api/v3/zz_generated.deepcopy.go b/api/v3/zz_generated.deepcopy.go index 67cb8da..86badb8 100644 --- a/api/v3/zz_generated.deepcopy.go +++ b/api/v3/zz_generated.deepcopy.go @@ -175,7 +175,11 @@ func (in *Data) DeepCopy() *Data { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FeatureBbox) DeepCopyInto(out *FeatureBbox) { *out = *in - out.DefaultCRS = in.DefaultCRS + if in.DefaultCRS != nil { + in, out := &in.DefaultCRS, &out.DefaultCRS + *out = new(model.BBox) + **out = **in + } if in.WGS84 != nil { in, out := &in.WGS84, &out.WGS84 *out = new(model.BBox) @@ -596,11 +600,6 @@ func (in *StylingAssets) DeepCopy() *StylingAssets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TIF) DeepCopyInto(out *TIF) { *out = *in - if in.Resample != nil { - in, out := &in.Resample, &out.Resample - *out = new(string) - **out = **in - } if in.Offsite != nil { in, out := &in.Offsite, &out.Offsite *out = new(string) diff --git a/config/crd/bases/pdok.nl_wfs.yaml b/config/crd/bases/pdok.nl_wfs.yaml index e1e0a72..31c8706 100644 --- a/config/crd/bases/pdok.nl_wfs.yaml +++ b/config/crd/bases/pdok.nl_wfs.yaml @@ -445,7 +445,6 @@ spec: pattern: (image/png|text/xml|text/html) type: string querystring: - minLength: 1 type: string x-kubernetes-validations: - message: a valid healthcheck contains 'Service=WFS' @@ -1126,7 +1125,6 @@ spec: type: integer defaultCrs: description: Default CRS (DataEPSG) - minLength: 1 pattern: ^EPSG:(28992|25831|25832|3034|3035|3857|4258|4326)$ type: string featureTypes: @@ -1142,7 +1140,7 @@ spec: description: Optional feature bbox properties: defaultCRS: - description: DefaultCRS defines the feature’s bounding box in the service’s own CRS + description: DefaultCRS defines the EXTENT/wfs_extent for the featureType for use in the mapfile properties: maxx: description: Rechtsonder X coördinaat @@ -1167,7 +1165,7 @@ spec: - miny type: object wgs84: - description: WGS84, if provided, gives the same bounding box reprojected into EPSG:4326. + description: WGS84, if provided, gives the same bounding box reprojected into EPSG:4326 for use in the capabilities. properties: maxx: description: Rechtsonder X coördinaat @@ -1191,8 +1189,6 @@ spec: - minx - miny type: object - required: - - defaultCRS type: object data: description: FeatureType data connection @@ -1202,7 +1198,6 @@ spec: properties: blobKey: description: Blobkey identifies the location/bucket of the .gpkg file - minLength: 1 pattern: ^.+\/.+\/.+\.gpkg$ type: string columns: @@ -1225,7 +1220,6 @@ spec: type: array geometryType: description: GeometryType of the table, must match an OGC type - minLength: 1 pattern: ^(Multi)?(Point|LineString|Polygon)$ type: string tableName: @@ -1278,8 +1272,7 @@ spec: properties: blobKey: description: BlobKey to the TIFF file - minLength: 1 - pattern: \.(tif?f|vrt)$ + pattern: ^.+\/.+\/.+\.(tif?f|vrt)$ type: string getFeatureInfoIncludesClass: default: false @@ -1287,13 +1280,11 @@ spec: type: boolean offsite: description: Sets the color index to treat as transparent for raster layers, optional, hex or rgb - minLength: 1 pattern: (#[0-9A-F]{6}([0-9A-F]{2})?)|([0-9]{1,3}\s[0-9]{1,3}\s[0-9]{1,3}) type: string resample: default: NEAREST description: This option can be used to control the resampling kernel used sampling raster images, optional - minLength: 1 pattern: (NEAREST|AVERAGE|BILINEAR) type: string required: @@ -1344,7 +1335,7 @@ spec: type: array name: description: Name of the feature - minLength: 1 + pattern: ^\S+$ type: string title: description: Title of the feature diff --git a/config/crd/bases/pdok.nl_wms.yaml b/config/crd/bases/pdok.nl_wms.yaml index 3eb88b9..7c5c711 100644 --- a/config/crd/bases/pdok.nl_wms.yaml +++ b/config/crd/bases/pdok.nl_wms.yaml @@ -1291,7 +1291,6 @@ spec: properties: blobKey: description: Blobkey identifies the location/bucket of the .gpkg file - minLength: 1 pattern: ^.+\/.+\/.+\.gpkg$ type: string columns: @@ -1314,7 +1313,6 @@ spec: type: array geometryType: description: GeometryType of the table, must match an OGC type - minLength: 1 pattern: ^(Multi)?(Point|LineString|Polygon)$ type: string tableName: @@ -1367,8 +1365,7 @@ spec: properties: blobKey: description: BlobKey to the TIFF file - minLength: 1 - pattern: \.(tif?f|vrt)$ + pattern: ^.+\/.+\/.+\.(tif?f|vrt)$ type: string getFeatureInfoIncludesClass: default: false @@ -1376,13 +1373,11 @@ spec: type: boolean offsite: description: Sets the color index to treat as transparent for raster layers, optional, hex or rgb - minLength: 1 pattern: (#[0-9A-F]{6}([0-9A-F]{2})?)|([0-9]{1,3}\s[0-9]{1,3}\s[0-9]{1,3}) type: string resample: default: NEAREST description: This option can be used to control the resampling kernel used sampling raster images, optional - minLength: 1 pattern: (NEAREST|AVERAGE|BILINEAR) type: string required: @@ -1497,7 +1492,6 @@ spec: properties: blobKey: description: Blobkey identifies the location/bucket of the .gpkg file - minLength: 1 pattern: ^.+\/.+\/.+\.gpkg$ type: string columns: @@ -1520,7 +1514,6 @@ spec: type: array geometryType: description: GeometryType of the table, must match an OGC type - minLength: 1 pattern: ^(Multi)?(Point|LineString|Polygon)$ type: string tableName: @@ -1573,8 +1566,7 @@ spec: properties: blobKey: description: BlobKey to the TIFF file - minLength: 1 - pattern: \.(tif?f|vrt)$ + pattern: ^.+\/.+\/.+\.(tif?f|vrt)$ type: string getFeatureInfoIncludesClass: default: false @@ -1582,13 +1574,11 @@ spec: type: boolean offsite: description: Sets the color index to treat as transparent for raster layers, optional, hex or rgb - minLength: 1 pattern: (#[0-9A-F]{6}([0-9A-F]{2})?)|([0-9]{1,3}\s[0-9]{1,3}\s[0-9]{1,3}) type: string resample: default: NEAREST description: This option can be used to control the resampling kernel used sampling raster images, optional - minLength: 1 pattern: (NEAREST|AVERAGE|BILINEAR) type: string required: @@ -1703,7 +1693,6 @@ spec: properties: blobKey: description: Blobkey identifies the location/bucket of the .gpkg file - minLength: 1 pattern: ^.+\/.+\/.+\.gpkg$ type: string columns: @@ -1726,7 +1715,6 @@ spec: type: array geometryType: description: GeometryType of the table, must match an OGC type - minLength: 1 pattern: ^(Multi)?(Point|LineString|Polygon)$ type: string tableName: @@ -1779,8 +1767,7 @@ spec: properties: blobKey: description: BlobKey to the TIFF file - minLength: 1 - pattern: \.(tif?f|vrt)$ + pattern: ^.+\/.+\/.+\.(tif?f|vrt)$ type: string getFeatureInfoIncludesClass: default: false @@ -1788,13 +1775,11 @@ spec: type: boolean offsite: description: Sets the color index to treat as transparent for raster layers, optional, hex or rgb - minLength: 1 pattern: (#[0-9A-F]{6}([0-9A-F]{2})?)|([0-9]{1,3}\s[0-9]{1,3}\s[0-9]{1,3}) type: string resample: default: NEAREST description: This option can be used to control the resampling kernel used sampling raster images, optional - minLength: 1 pattern: (NEAREST|AVERAGE|BILINEAR) type: string required: diff --git a/internal/controller/capabilitiesgenerator/capabilities_generator_test.go b/internal/controller/capabilitiesgenerator/capabilities_generator_test.go index b216bb7..4e7e0d4 100644 --- a/internal/controller/capabilitiesgenerator/capabilities_generator_test.go +++ b/internal/controller/capabilitiesgenerator/capabilities_generator_test.go @@ -4,6 +4,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/pdok/mapserver-operator/api/v2beta1" pdoknlv3 "github.com/pdok/mapserver-operator/api/v3" + capabilitiesgenerator "github.com/pdok/ogc-capabilities-generator/pkg/config" smoothoperatorv1 "github.com/pdok/smooth-operator/api/v1" smoothoperatormodel "github.com/pdok/smooth-operator/model" "github.com/stretchr/testify/assert" @@ -87,6 +88,14 @@ func TestGetInputForWFS(t *testing.T) { MetadataIdentifier: "datadata-data-data-data-datadatadata", }, }, + Bbox: &pdoknlv3.FeatureBbox{ + WGS84: &smoothoperatormodel.BBox{ + MinX: "-180", + MaxX: "180", + MinY: "-90", + MaxY: "90", + }, + }, }, { Name: "featuretype-2-name", @@ -132,8 +141,8 @@ func TestGetInputForWFS(t *testing.T) { return } - wantMap := make(map[string]interface{}) - gotMap := make(map[string]interface{}) + wantMap := capabilitiesgenerator.Config{} + gotMap := capabilitiesgenerator.Config{} err = yaml.Unmarshal([]byte(WFSInput), &wantMap) assert.NoError(t, err) err = yaml.Unmarshal([]byte(gotInput), &gotMap) diff --git a/internal/controller/capabilitiesgenerator/mapper.go b/internal/controller/capabilitiesgenerator/mapper.go index 9930a2e..5ae5c87 100644 --- a/internal/controller/capabilitiesgenerator/mapper.go +++ b/internal/controller/capabilitiesgenerator/mapper.go @@ -133,6 +133,31 @@ func getFeatureTypeList(wfs *pdoknlv3.WFS, ownerInfo *smoothoperatorv1.OwnerInfo otherCRS = append(otherCRS, CRS) } + var wgs84BoundingBox *wsc110.WGS84BoundingBox + if fType.Bbox != nil && fType.Bbox.WGS84 != nil { + minX, err := strconv.ParseFloat(fType.Bbox.WGS84.MinX, 64) + if err != nil { + return nil, err + } + maxX, err := strconv.ParseFloat(fType.Bbox.WGS84.MaxX, 64) + if err != nil { + return nil, err + } + minY, err := strconv.ParseFloat(fType.Bbox.WGS84.MinY, 64) + if err != nil { + return nil, err + } + maxY, err := strconv.ParseFloat(fType.Bbox.WGS84.MaxY, 64) + if err != nil { + return nil, err + } + + wgs84BoundingBox = &wsc110.WGS84BoundingBox{ + LowerCorner: wsc110.Position{minX, minY}, + UpperCorner: wsc110.Position{maxX, maxY}, + } + } + metadataURL, err := replaceMustacheTemplate(ownerInfo.Spec.MetadataUrls.CSW.HrefTemplate, fType.DatasetMetadataURL.CSW.MetadataIdentifier) if err != nil { return nil, err @@ -150,8 +175,9 @@ func getFeatureTypeList(wfs *pdoknlv3.WFS, ownerInfo *smoothoperatorv1.OwnerInfo MetadataURL: wfs200.MetadataHref{ Href: metadataURL, }, - DefaultCRS: defaultCRS, - OtherCRS: otherCRS, + DefaultCRS: defaultCRS, + OtherCRS: otherCRS, + WGS84BoundingBox: wgs84BoundingBox, } typeList.FeatureType = append(typeList.FeatureType, featureType) diff --git a/internal/controller/capabilitiesgenerator/test_data/wfs_input.yaml b/internal/controller/capabilitiesgenerator/test_data/wfs_input.yaml index 9093b8e..556b6f2 100644 --- a/internal/controller/capabilitiesgenerator/test_data/wfs_input.yaml +++ b/internal/controller/capabilitiesgenerator/test_data/wfs_input.yaml @@ -53,6 +53,9 @@ services: - urn:ogc:def:crs:EPSG::3857 - urn:ogc:def:crs:EPSG::4258 - urn:ogc:def:crs:EPSG::4326 + wgs84BoundingBox: + lowerCorner: "-180 -90" + upperCorner: "180 90" metadataUrl: href: https://www.nationaalgeoregister.nl/geonetwork/srv/dut/csw?service=CSW&version=2.0.2&request=GetRecordById&outputschema=http://www.isotc211.org/2005/gmd&elementsetname=full&id=datadata-data-data-data-datadatadata - name: prefix:featuretype-2-name diff --git a/internal/controller/mapfilegenerator/mapper.go b/internal/controller/mapfilegenerator/mapper.go index 992490a..2b90580 100644 --- a/internal/controller/mapfilegenerator/mapper.go +++ b/internal/controller/mapfilegenerator/mapper.go @@ -104,7 +104,7 @@ func getWFSLayers(service pdoknlv3.WFSService) (layers []WFSLayer) { } func getWFSExtent(featureType pdoknlv3.FeatureType, service pdoknlv3.WFSService) string { - if featureType.Bbox != nil { + if featureType.Bbox != nil && featureType.Bbox.DefaultCRS != nil { return featureType.Bbox.DefaultCRS.ToExtent() } if service.Bbox != nil { diff --git a/internal/controller/mapfilegenerator/types.go b/internal/controller/mapfilegenerator/types.go index f59a31d..86e58ea 100644 --- a/internal/controller/mapfilegenerator/types.go +++ b/internal/controller/mapfilegenerator/types.go @@ -123,7 +123,7 @@ func SetDataFields[O pdoknlv3.WMSWFS](obj O, wmsLayer *WMSLayer, data pdoknlv3.D reReplace := regexp.MustCompile(`$[a-zA-Z0-9_]*]/`) wmsLayer.BaseLayer.TifPath = smoothoperatorutils.Pointer(path.Join("/vsiaz", reReplace.ReplaceAllString(tif.BlobKey, ""))) } - wmsLayer.BaseLayer.Resample = tif.Resample + wmsLayer.BaseLayer.Resample = &tif.Resample wmsLayer.Offsite = smoothoperatorutils.PointerVal(tif.Offsite, "") case data.Postgis != nil: postgis := data.Postgis diff --git a/internal/controller/test_data/wfs/complete/expected/configmap-capabilities-generator.yaml b/internal/controller/test_data/wfs/complete/expected/configmap-capabilities-generator.yaml index 95e613a..6ff52b5 100644 --- a/internal/controller/test_data/wfs/complete/expected/configmap-capabilities-generator.yaml +++ b/internal/controller/test_data/wfs/complete/expected/configmap-capabilities-generator.yaml @@ -107,7 +107,7 @@ metadata: service-type: wfs service-version: v1_0 theme: theme - name: complete-wfs-capabilities-generator-hhd58g286k + name: complete-wfs-capabilities-generator-cgh9g4d467 namespace: default ownerReferences: - apiVersion: pdok.nl/v3 diff --git a/internal/controller/test_data/wfs/complete/expected/deployment.yaml b/internal/controller/test_data/wfs/complete/expected/deployment.yaml index 3c18f5c..ef5e355 100644 --- a/internal/controller/test_data/wfs/complete/expected/deployment.yaml +++ b/internal/controller/test_data/wfs/complete/expected/deployment.yaml @@ -261,7 +261,7 @@ spec: name: complete-wfs-init-scripts-fft29bbtdd name: init-scripts - configMap: - name: complete-wfs-capabilities-generator-hhd58g286k + name: complete-wfs-capabilities-generator-cgh9g4d467 defaultMode: 420 name: capabilities-generator-config - configMap: diff --git a/internal/controller/test_data/wfs/complete/input/wfs.yaml b/internal/controller/test_data/wfs/complete/input/wfs.yaml index a80619e..5f97d8c 100644 --- a/internal/controller/test_data/wfs/complete/input/wfs.yaml +++ b/internal/controller/test_data/wfs/complete/input/wfs.yaml @@ -104,6 +104,11 @@ spec: maxy: "0" minx: "1" miny: "2" + wgs84: + maxx: "180" + maxy: "90" + minx: "-180" + miny: "-90" data: postgis: columns: diff --git a/internal/controller/test_data/wfs/minimal/expected/configmap-capabilities-generator.yaml b/internal/controller/test_data/wfs/minimal/expected/configmap-capabilities-generator.yaml index c5dfff7..2e1925c 100644 --- a/internal/controller/test_data/wfs/minimal/expected/configmap-capabilities-generator.yaml +++ b/internal/controller/test_data/wfs/minimal/expected/configmap-capabilities-generator.yaml @@ -11,7 +11,7 @@ metadata: inspire: 'false' service-type: wfs service-version: v1_0 - name: minimal-wfs-capabilities-generator-446d5ddh62 + name: minimal-wfs-capabilities-generator-tk7t48fd89 namespace: default ownerReferences: - apiVersion: pdok.nl/v3 diff --git a/internal/controller/test_data/wfs/minimal/expected/deployment.yaml b/internal/controller/test_data/wfs/minimal/expected/deployment.yaml index 137c665..8d768af 100644 --- a/internal/controller/test_data/wfs/minimal/expected/deployment.yaml +++ b/internal/controller/test_data/wfs/minimal/expected/deployment.yaml @@ -244,7 +244,7 @@ spec: name: minimal-wfs-init-scripts-fft29bbtdd name: init-scripts - configMap: - name: minimal-wfs-capabilities-generator-446d5ddh62 + name: minimal-wfs-capabilities-generator-tk7t48fd89 defaultMode: 420 name: capabilities-generator-config - configMap: diff --git a/internal/controller/test_data/wfs/noprefetch/expected/configmap-capabilities-generator.yaml b/internal/controller/test_data/wfs/noprefetch/expected/configmap-capabilities-generator.yaml index 4014b54..4e91d00 100644 --- a/internal/controller/test_data/wfs/noprefetch/expected/configmap-capabilities-generator.yaml +++ b/internal/controller/test_data/wfs/noprefetch/expected/configmap-capabilities-generator.yaml @@ -11,7 +11,7 @@ metadata: inspire: 'false' service-type: wfs service-version: v1_0 - name: noprefetch-wfs-capabilities-generator-446d5ddh62 + name: noprefetch-wfs-capabilities-generator-tk7t48fd89 namespace: default ownerReferences: - apiVersion: pdok.nl/v3 diff --git a/internal/controller/test_data/wfs/noprefetch/expected/deployment.yaml b/internal/controller/test_data/wfs/noprefetch/expected/deployment.yaml index 6dca0bb..d714f19 100644 --- a/internal/controller/test_data/wfs/noprefetch/expected/deployment.yaml +++ b/internal/controller/test_data/wfs/noprefetch/expected/deployment.yaml @@ -236,7 +236,7 @@ spec: defaultMode: 420 name: mapserver - configMap: - name: noprefetch-wfs-capabilities-generator-446d5ddh62 + name: noprefetch-wfs-capabilities-generator-tk7t48fd89 defaultMode: 420 name: capabilities-generator-config - configMap: diff --git a/internal/webhook/v3/shared_webhook.go b/internal/webhook/v3/shared_webhook.go index 6a74972..f91d64e 100644 --- a/internal/webhook/v3/shared_webhook.go +++ b/internal/webhook/v3/shared_webhook.go @@ -10,7 +10,7 @@ import ( ) const ( - samplesPath = "../../../config/samples/" + samplesPath = "test_data/" ) func getSampleFilename[W pdoknlv3.WMSWFS](webservice W) (string, error) { diff --git a/internal/webhook/v3/test_data/v3_wfs.yaml b/internal/webhook/v3/test_data/v3_wfs.yaml new file mode 100644 index 0000000..45fc647 --- /dev/null +++ b/internal/webhook/v3/test_data/v3_wfs.yaml @@ -0,0 +1,71 @@ +apiVersion: pdok.nl/v3 +kind: WFS +metadata: + name: sample + labels: + sample: sample +spec: + podSpecPatch: + containers: + - name: mapserver + resources: + limits: + ephemeral-storage: 2G + ingressRouteUrls: + - url: "http://host/path" + - url: "http://old/path" + service: + inspire: + language: dut + serviceMetadataUrl: + csw: + metadataIdentifier: 655549bd-8c05-4c69-950b-ad1e346dcac9 + spatialDatasetIdentifier: 90af202c-de3a-4fbf-901c-82ae703904e3 + title: "title" + abstract: "abstract" + defaultCrs: "EPSG:28992" + keywords: + - "keyword" + ownerInfoRef: "owner" + prefix: "prefix" + url: "http://host/path" + bbox: + defaultCRS: + maxx: "1" + maxy: "2" + minx: "3" + miny: "4" + featureTypes: + - name: "name" + title: "title" + abstract: "abstract" + keywords: + - "word" + datasetMetadataUrl: + csw: + metadataIdentifier: 8ec62a28-695f-4f46-a9d5-0aeb8363a0e3 + bbox: + defaultCRS: + maxx: "1" + maxy: "2" + minx: "3" + miny: "4" + data: + gpkg: + blobKey: "container/prefix/file.gpkg" + columns: + - name: column + geometryType: Point + tableName: table + - name: "second_name" + title: "title" + abstract: "abstract" + keywords: + - "word" + datasetMetadataUrl: + csw: + metadataIdentifier: 8ec62a28-695f-4f46-a9d5-0aeb8363a0e3 + data: + tif: + blobKey: "container/prefix/file.vrt" + resample: "NEAREST" diff --git a/internal/webhook/v3/test_data/v3_wms.yaml b/internal/webhook/v3/test_data/v3_wms.yaml new file mode 100644 index 0000000..99dfdc2 --- /dev/null +++ b/internal/webhook/v3/test_data/v3_wms.yaml @@ -0,0 +1,152 @@ +apiVersion: pdok.nl/v3 +kind: WMS +metadata: + labels: + app.kubernetes.io/name: mapserver-operator + app.kubernetes.io/managed-by: kustomize + dataset: dataset + dataset-owner: owner + service-type: wms + service-version: 1.0.0 + name: sample-v3 +spec: + lifecycle: + ttlInDays: 21 + podSpecPatch: + containers: + - name: mapserver + resources: + limits: + memory: 12M + ephemeral-storage: 2G + horizontalPodAutoscalerPatch: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: wms-sample-v3 + maxReplicas: 5 + minReplicas: 2 + metrics: + - type: "Resource" + resource: + name: cpu + target: + type: Utilization + averageUtilization: 60 + options: + automaticCasing: true + prefetchData: false + includeIngress: false + rewriteGroupToDataLayers: true + validateChildStyleNameEqual: true + service: + url: https://service.pdok.nl/owner/dataset/wms/1.0.0 + title: "Dataset" + abstract: "Dataset abstract ..." + keywords: + - keyword1 + - keyword2 + ownerInfoRef: + fees: "" + accessConstraints: "http://creativecommons.org/publicdomain/zero/1.0/deed.nl" + maxSize: + inspire: + serviceMetadataUrl: + csw: + metadataIdentifier: 1234abcd-1234-abcd-1234-abcd1234abcd + spatialDatasetIdentifier: abcd1234-abcd-1234-abcd-1234abcd1234 + language: "dut" + dataEPSG: EPSG:28992 + resolution: + defResolution: + stylingAssets: + mapfile: + layer: + name: top-layer-name + title: Top "Layer" Title + abstract: Top "Layer" Abstract + keywords: + - top-layer-keyword-1 + - top-layer-keyword-2 + boundingBoxes: + - crs: EPSG:28992 + bbox: + minx: "482.06" + maxx: "306602.42" + miny: "284182.97" + maxy: "637049.52" + visible: true + authority: + datasetMetadataUrl: + minscaledenominator: + maxscaledenominator: + style: + labelNoClip: false + data: + layers: + - name: group-layer-name + title: Group "Layer" Title + abstract: Group "Abstract" Abstract + keywords: + - group-layer-keyword-1 + - group-layer-keyword-2 + boundingBoxes: + visible: true + authority: + datasetMetadataUrl: + minscaledenominator: + maxscaledenominator: + styles: + labelNoClip: false + layers: + - name: gpkg-layer-name + title: GPKG "Layer" Title + abstract: GPKG "Abstract" Abstract + keywords: + - gpkg-layer-keyword-1 + - gpkg-layer-keyword-2 + boundingBoxes: + visible: true + authority: + datasetMetadataUrl: + minscaledenominator: + maxscaledenominator: + styles: + - name: gpkg-layer-style-name + title: gpkg-layer-style-title + visualization: gpkg-layer-style.style + labelNoClip: false + data: + gpkg: + blobKey: "geopackages-bucket/key/gpkg-layer-data.gpkg" + tableName: "table-1" + geometryType: "MultiPolygon" + columns: + - name: "column-1" + alias: "alias-column-1" + - name: "column-2" + - name: "column-3" + alias: "alias-column-3" + - name: tif-layer-name + title: TIF "Layer" Title + abstract: TIF "Abstract" Abstract + keywords: + - tif-layer-keyword-1 + - tif-layer-keyword-2 + boundingBoxes: + visible: true + authority: + datasetMetadataUrl: + minscaledenominator: + maxscaledenominator: + styles: + - name: tif-layer-style-1-name + title: tif-layer-style-1-title + visualization: tif-layer-style-1.style + labelNoClip: false + data: + tif: + blobKey: "tifs-bucket/key/tif-layer-data.tif" + offsite: "#FF00FF" + resample: "AVERAGE" + getFeatureInfoIncludesClass: true diff --git a/internal/webhook/v3/wfs_webhook_test.go b/internal/webhook/v3/wfs_webhook_test.go index ecf999f..48a7ae5 100644 --- a/internal/webhook/v3/wfs_webhook_test.go +++ b/internal/webhook/v3/wfs_webhook_test.go @@ -30,6 +30,9 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + smoothoperatormodel "github.com/pdok/smooth-operator/model" + smoothoperatorutils "github.com/pdok/smooth-operator/pkg/util" + corev1 "k8s.io/api/core/v1" pdoknlv3 "github.com/pdok/mapserver-operator/api/v3" ) @@ -64,37 +67,157 @@ var _ = Describe("WFS Webhook", func() { ctx := context.Background() It("Creates the WFS from the sample", func() { - _, err := validator.ValidateCreate(ctx, obj) + warnings, err := validator.ValidateCreate(ctx, obj) Expect(err).To(BeNil()) + Expect(warnings).To(BeEmpty()) }) - It("Warns if the name contains WFS", func() { - obj.Name += "-wfs" + It("Should deny creation if there are no labels", func() { + obj.Labels = nil warnings, err := validator.ValidateCreate(ctx, obj) - Expect(err).To(BeNil()) - Expect(len(warnings)).To(BeNumerically(">", 0)) + Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) }) - It("Should deny creation if there are no labels", func() { - obj.Labels = map[string]string{} - _, err := validator.ValidateCreate(ctx, obj) + It("Should deny creation if Url not in IngressRouteUrls", func() { + Expect(obj.Spec.IngressRouteURLs).NotTo(BeNil()) + url, err := smoothoperatormodel.ParseURL("https://new/new") + Expect(err).To(Not(HaveOccurred())) + obj.Spec.Service.URL = smoothoperatormodel.URL{URL: url} + warnings, err := validator.ValidateCreate(ctx, obj) Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) + }) + + It("Warns if the name contains WFS", func() { + obj.Name += "-wfs" + warnings, err := validator.ValidateCreate(ctx, obj) + Expect(err).To(BeNil()) + Expect(len(warnings)).To(Equal(1)) }) It("Should deny creation if there is no bounding box and the defaultCRS is not EPSG:28992", func() { obj.Spec.Service.DefaultCrs = "EPSG:1234" obj.Spec.Service.Bbox = nil - _, err := validator.ValidateCreate(ctx, obj) + warnings, err := validator.ValidateCreate(ctx, obj) Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) }) - It("Should deny update if a label changed", func() { - for label, val := range obj.Labels { - obj.Labels[label] = val + "-newval" - break + It("Warns if the mapfile and service/featuretype bbox are both set", func() { + Expect(obj.Spec.Service.FeatureTypes[0].Bbox).NotTo(BeNil()) + Expect(obj.Spec.Service.FeatureTypes[0].Bbox.DefaultCRS).NotTo(BeNil()) + Expect(obj.Spec.Service.Bbox).NotTo(BeNil()) + obj.Spec.Service.Mapfile = &pdoknlv3.Mapfile{} + warnings, err := validator.ValidateCreate(ctx, obj) + Expect(err).To(BeNil()) + Expect(len(warnings)).To(Equal(2)) + }) + + It("Should deny creation if SpatialID is also used as a featureType datasetMetadataID", func() { + Expect(obj.Inspire()).NotTo(BeNil()) + Expect(obj.Spec.Service.FeatureTypes[0].DatasetMetadataURL).NotTo(BeNil()) + Expect(obj.Spec.Service.FeatureTypes[0].DatasetMetadataURL.CSW).NotTo(BeNil()) + obj.Spec.Service.Inspire.SpatialDatasetIdentifier = obj.Spec.Service.FeatureTypes[0].DatasetMetadataURL.CSW.MetadataIdentifier + warnings, err := validator.ValidateCreate(ctx, obj) + Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) + }) + + It("Should deny creation if serviceMetadataID is also used as a featureType datasetMetadataID", func() { + Expect(obj.Inspire()).NotTo(BeNil()) + Expect(obj.Inspire().ServiceMetadataURL.CSW).NotTo(BeNil()) + Expect(obj.Spec.Service.FeatureTypes[0].DatasetMetadataURL).NotTo(BeNil()) + Expect(obj.Spec.Service.FeatureTypes[0].DatasetMetadataURL.CSW).NotTo(BeNil()) + obj.Spec.Service.Inspire.ServiceMetadataURL.CSW.MetadataIdentifier = obj.Spec.Service.FeatureTypes[0].DatasetMetadataURL.CSW.MetadataIdentifier + warnings, err := validator.ValidateCreate(ctx, obj) + Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) + }) + + It("Should deny creation if serviceMetadataID is the same as the SpatialID", func() { + Expect(obj.Inspire()).NotTo(BeNil()) + Expect(obj.Inspire().ServiceMetadataURL.CSW).NotTo(BeNil()) + obj.Spec.Service.Inspire.ServiceMetadataURL.CSW.MetadataIdentifier = obj.Spec.Service.Inspire.SpatialDatasetIdentifier + warnings, err := validator.ValidateCreate(ctx, obj) + Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) + }) + + It("Should deny creation if service is Inspire and not all featureTypes have the same datasetMetadataID", func() { + Expect(obj.Inspire()).NotTo(BeNil()) + Expect(obj.Spec.Service.FeatureTypes[0].DatasetMetadataURL).NotTo(BeNil()) + Expect(obj.Spec.Service.FeatureTypes[0].DatasetMetadataURL.CSW).NotTo(BeNil()) + Expect(obj.Spec.Service.FeatureTypes[0].DatasetMetadataURL.CSW).NotTo(BeNil()) + Expect(len(obj.Spec.Service.FeatureTypes)).To(BeNumerically(">", 1)) + Expect(obj.Spec.Service.FeatureTypes[1].DatasetMetadataURL).NotTo(BeNil()) + Expect(obj.Spec.Service.FeatureTypes[1].DatasetMetadataURL.CSW).NotTo(BeNil()) + obj.Spec.Service.FeatureTypes[0].DatasetMetadataURL.CSW.MetadataIdentifier = "" + warnings, err := validator.ValidateCreate(ctx, obj) + Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) + }) + + It("Should deny creation if maxReplicas < minReplicas in HPAPatch", func() { + obj.Spec.HorizontalPodAutoscalerPatch = &pdoknlv3.HorizontalPodAutoscalerPatch{ + MinReplicas: smoothoperatorutils.Pointer(int32(5)), + MaxReplicas: smoothoperatorutils.Pointer(int32(1)), } - _, err := validator.ValidateUpdate(ctx, oldObj, obj) + warnings, err := validator.ValidateCreate(ctx, obj) + Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) + }) + + It("Should deny creation if no ephemeralStorage is set on the mapserver container", func() { + obj.Spec.PodSpecPatch.Containers = []corev1.Container{} + warnings, err := validator.ValidateCreate(ctx, obj) Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) + }) + + It("Should deny creation if multiple featureTypes have the same name", func() { + Expect(len(obj.Spec.Service.FeatureTypes)).To(BeNumerically(">", 1)) + obj.Spec.Service.FeatureTypes[1].Name = obj.Spec.Service.FeatureTypes[0].Name + warnings, err := validator.ValidateCreate(ctx, obj) + Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) + }) + + It("Warns if the mapfile and featuretype.tif extra settings are both set", func() { + Expect(len(obj.Spec.Service.FeatureTypes)).To(BeNumerically(">", 1)) + Expect(obj.Spec.Service.FeatureTypes[1].Data.TIF).NotTo(BeNil()) + obj.Spec.Service.FeatureTypes[1].Data.TIF = &pdoknlv3.TIF{ + BlobKey: obj.Spec.Service.FeatureTypes[1].Data.TIF.BlobKey, + Resample: "AVERAGE", + Offsite: smoothoperatorutils.Pointer("#555555"), + GetFeatureInfoIncludesClass: true, + } + warnings, err := validator.ValidateCreate(ctx, obj) + Expect(err).To(BeNil()) + Expect(len(warnings)).To(Equal(3)) + }) + + It("Should deny update if a url was changed and ingressRouteUrls = nil", func() { + url, err := smoothoperatormodel.ParseURL("http://old/path") + Expect(err).To(BeNil()) + obj.Spec.Service.URL = smoothoperatormodel.URL{URL: url} + warnings, err := validator.ValidateUpdate(ctx, oldObj, obj) + Expect(err).To(BeNil()) + Expect(warnings).To(BeEmpty()) + + oldObj.Spec.IngressRouteURLs = nil + obj.Spec.IngressRouteURLs = nil + warnings, err = validator.ValidateUpdate(ctx, oldObj, obj) + Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) + }) + + It("Should deny update if a ingressRouteURL was removed", func() { + Expect(len(oldObj.Spec.IngressRouteURLs)).To(Equal(2)) + obj.Spec.IngressRouteURLs = []smoothoperatormodel.IngressRouteURL{{URL: obj.URL()}} + warnings, err := validator.ValidateUpdate(ctx, oldObj, obj) + Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) }) It("Should deny update if a label was removed", func() { @@ -102,26 +225,42 @@ var _ = Describe("WFS Webhook", func() { delete(obj.Labels, label) break } - _, err := validator.ValidateUpdate(ctx, oldObj, obj) + warnings, err := validator.ValidateUpdate(ctx, oldObj, obj) + Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) + }) + + It("Should deny update if a label changed", func() { + for label, val := range obj.Labels { + obj.Labels[label] = val + "-newval" + break + } + warnings, err := validator.ValidateUpdate(ctx, oldObj, obj) Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) }) It("Should deny update if a label was added", func() { obj.Labels["new-label"] = "test" - _, err := validator.ValidateUpdate(ctx, oldObj, obj) + warnings, err := validator.ValidateUpdate(ctx, oldObj, obj) Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) }) It("Should deny update if an inspire block was added", func() { + Expect(obj.Spec.Service.Inspire).NotTo(BeNil()) oldObj.Spec.Service.Inspire = nil - _, err := validator.ValidateUpdate(ctx, oldObj, obj) + warnings, err := validator.ValidateUpdate(ctx, oldObj, obj) Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) }) It("Should deny update if an inspire block was removed", func() { + Expect(oldObj.Spec.Service.Inspire).NotTo(BeNil()) obj.Spec.Service.Inspire = nil - _, err := validator.ValidateUpdate(ctx, oldObj, obj) + warnings, err := validator.ValidateUpdate(ctx, oldObj, obj) Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) }) }) From b79c3a7fd1831ae134e51a35ae9979d4bf0761c5 Mon Sep 17 00:00:00 2001 From: Wouter Remijn Date: Fri, 30 May 2025 13:01:02 +0200 Subject: [PATCH 2/4] dependencies update --- cmd/main.go | 2 +- config/crd/bases/pdok.nl_wfs.yaml | 46 ++++- config/crd/bases/pdok.nl_wms.yaml | 46 ++++- go.mod | 119 ++++++------- go.sum | 279 ++++++++++++++---------------- 5 files changed, 279 insertions(+), 213 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 148a283..ecebf10 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -57,7 +57,7 @@ const ( defaultMultitoolImage = "acrpdokprodman.azurecr.io/pdok/docker-multitool:0.9.4" defaultMapfileGeneratorImage = "acrpdokprodman.azurecr.io/pdok/mapfile-generator:1.9.5" defaultMapserverImage = "acrpdokprodman.azurecr.io/mirror/docker.io/pdok/mapserver:8.4.0-4-nl" - defaultCapabilitiesGeneratorImage = "acrpdokprodman.azurecr.io/mirror/docker.io/pdok/ogc-capabilities-generator:1.0.0-beta8" + defaultCapabilitiesGeneratorImage = "acrpdokprodman.azurecr.io/mirror/docker.io/pdok/ogc-capabilities-generator:1.0.0-beta9" defaultFeatureinfoGeneratorImage = "acrpdokprodman.azurecr.io/mirror/docker.io/pdok/featureinfo-generator:1.4.0-beta1" defaultOgcWebserviceProxyImage = "acrpdokprodman.azurecr.io/pdok/ogc-webservice-proxy:0.1.8" defaultApacheExporterImage = "acrpdokprodman.azurecr.io/mirror/docker.io/lusotycoon/apache-exporter:v0.7.0" diff --git a/config/crd/bases/pdok.nl_wfs.yaml b/config/crd/bases/pdok.nl_wfs.yaml index 31c8706..d88840b 100644 --- a/config/crd/bases/pdok.nl_wfs.yaml +++ b/config/crd/bases/pdok.nl_wfs.yaml @@ -475,7 +475,9 @@ spec: policies: description: |- policies is a list of potential scaling polices which can be used during scaling. - At least one policy must be specified, otherwise the HPAScalingRules will be discarded as invalid + If not set, use the default values: + - For scale up: allow doubling the number of pods, or an absolute change of 4 pods in a 15s window. + - For scale down: allow all pods to be removed in a 15s window. items: description: HPAScalingPolicy is a single policy which must hold true for a specified past interval. properties: @@ -516,6 +518,24 @@ spec: - For scale down: 300 (i.e. the stabilization window is 300 seconds long). format: int32 type: integer + tolerance: + anyOf: + - type: integer + - type: string + description: |- + tolerance is the tolerance on the ratio between the current and desired + metric value under which no updates are made to the desired number of + replicas (e.g. 0.01 for 1%). Must be greater than or equal to zero. If not + set, the default cluster-wide tolerance is applied (by default 10%). + + For example, if autoscaling is configured with a memory consumption target of 100Mi, + and scale-down and scale-up tolerances of 5% and 1% respectively, scaling will be + triggered when the actual consumption falls below 95Mi or exceeds 101Mi. + + This is an alpha field and requires enabling the HPAConfigurableTolerance + feature gate. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true type: object scaleUp: description: |- @@ -528,7 +548,9 @@ spec: policies: description: |- policies is a list of potential scaling polices which can be used during scaling. - At least one policy must be specified, otherwise the HPAScalingRules will be discarded as invalid + If not set, use the default values: + - For scale up: allow doubling the number of pods, or an absolute change of 4 pods in a 15s window. + - For scale down: allow all pods to be removed in a 15s window. items: description: HPAScalingPolicy is a single policy which must hold true for a specified past interval. properties: @@ -569,6 +591,24 @@ spec: - For scale down: 300 (i.e. the stabilization window is 300 seconds long). format: int32 type: integer + tolerance: + anyOf: + - type: integer + - type: string + description: |- + tolerance is the tolerance on the ratio between the current and desired + metric value under which no updates are made to the desired number of + replicas (e.g. 0.01 for 1%). Must be greater than or equal to zero. If not + set, the default cluster-wide tolerance is applied (by default 10%). + + For example, if autoscaling is configured with a memory consumption target of 100Mi, + and scale-down and scale-up tolerances of 5% and 1% respectively, scaling will be + triggered when the actual consumption falls below 95Mi or exceeds 101Mi. + + This is an alpha field and requires enabling the HPAConfigurableTolerance + feature gate. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true type: object type: object maxReplicas: @@ -1539,7 +1579,7 @@ spec: type: array operationResults: additionalProperties: - description: OperationResult is the action result of a CreateOrUpdate call. + description: OperationResult is the action result of a CreateOrUpdate or CreateOrPatch call. type: string description: The result of creating or updating of each derived resource for this Atom. type: object diff --git a/config/crd/bases/pdok.nl_wms.yaml b/config/crd/bases/pdok.nl_wms.yaml index 7c5c711..59c3a72 100644 --- a/config/crd/bases/pdok.nl_wms.yaml +++ b/config/crd/bases/pdok.nl_wms.yaml @@ -552,7 +552,9 @@ spec: policies: description: |- policies is a list of potential scaling polices which can be used during scaling. - At least one policy must be specified, otherwise the HPAScalingRules will be discarded as invalid + If not set, use the default values: + - For scale up: allow doubling the number of pods, or an absolute change of 4 pods in a 15s window. + - For scale down: allow all pods to be removed in a 15s window. items: description: HPAScalingPolicy is a single policy which must hold true for a specified past interval. properties: @@ -593,6 +595,24 @@ spec: - For scale down: 300 (i.e. the stabilization window is 300 seconds long). format: int32 type: integer + tolerance: + anyOf: + - type: integer + - type: string + description: |- + tolerance is the tolerance on the ratio between the current and desired + metric value under which no updates are made to the desired number of + replicas (e.g. 0.01 for 1%). Must be greater than or equal to zero. If not + set, the default cluster-wide tolerance is applied (by default 10%). + + For example, if autoscaling is configured with a memory consumption target of 100Mi, + and scale-down and scale-up tolerances of 5% and 1% respectively, scaling will be + triggered when the actual consumption falls below 95Mi or exceeds 101Mi. + + This is an alpha field and requires enabling the HPAConfigurableTolerance + feature gate. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true type: object scaleUp: description: |- @@ -605,7 +625,9 @@ spec: policies: description: |- policies is a list of potential scaling polices which can be used during scaling. - At least one policy must be specified, otherwise the HPAScalingRules will be discarded as invalid + If not set, use the default values: + - For scale up: allow doubling the number of pods, or an absolute change of 4 pods in a 15s window. + - For scale down: allow all pods to be removed in a 15s window. items: description: HPAScalingPolicy is a single policy which must hold true for a specified past interval. properties: @@ -646,6 +668,24 @@ spec: - For scale down: 300 (i.e. the stabilization window is 300 seconds long). format: int32 type: integer + tolerance: + anyOf: + - type: integer + - type: string + description: |- + tolerance is the tolerance on the ratio between the current and desired + metric value under which no updates are made to the desired number of + replicas (e.g. 0.01 for 1%). Must be greater than or equal to zero. If not + set, the default cluster-wide tolerance is applied (by default 10%). + + For example, if autoscaling is configured with a memory consumption target of 100Mi, + and scale-down and scale-up tolerances of 5% and 1% respectively, scaling will be + triggered when the actual consumption falls below 95Mi or exceeds 101Mi. + + This is an alpha field and requires enabling the HPAConfigurableTolerance + feature gate. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true type: object type: object maxReplicas: @@ -2200,7 +2240,7 @@ spec: type: array operationResults: additionalProperties: - description: OperationResult is the action result of a CreateOrUpdate call. + description: OperationResult is the action result of a CreateOrUpdate or CreateOrPatch call. type: string description: The result of creating or updating of each derived resource for this Atom. type: object diff --git a/go.mod b/go.mod index 7876da8..5410d10 100644 --- a/go.mod +++ b/go.mod @@ -8,29 +8,29 @@ godebug default=go1.23 require ( github.com/cbroglie/mustache v1.4.0 - github.com/onsi/ginkgo/v2 v2.22.2 - github.com/onsi/gomega v1.36.2 + github.com/onsi/ginkgo/v2 v2.23.4 + github.com/onsi/gomega v1.37.0 github.com/pdok/featureinfo-generator v1.4.0-beta1 - github.com/pdok/ogc-capabilities-generator v1.0.0-beta8 - github.com/pdok/ogc-specifications v1.0.0-beta9 + github.com/pdok/ogc-capabilities-generator v1.0.0-beta9 + github.com/pdok/ogc-specifications v1.0.0-beta10 github.com/pdok/smooth-operator v0.1.3 github.com/peterbourgon/ff v1.7.1 github.com/stretchr/testify v1.10.0 - github.com/traefik/traefik/v3 v3.3.4 - k8s.io/api v0.32.3 - k8s.io/apimachinery v0.32.3 - k8s.io/client-go v0.32.3 - sigs.k8s.io/controller-runtime v0.20.4 + github.com/traefik/traefik/v3 v3.4.1 + k8s.io/api v0.33.1 + k8s.io/apimachinery v0.33.1 + k8s.io/client-go v0.33.1 + sigs.k8s.io/controller-runtime v0.21.0 sigs.k8s.io/yaml v1.4.0 ) replace github.com/abbot/go-http-auth => github.com/abbot/go-http-auth v0.4.0 // for github.com/traefik/traefik/v3 require ( - github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect - github.com/aws/aws-sdk-go v1.44.327 // indirect - github.com/go-acme/lego/v4 v4.22.2 // indirect - github.com/go-jose/go-jose/v4 v4.0.4 // indirect + github.com/aws/smithy-go v1.22.2 // indirect + github.com/cenkalti/backoff/v5 v5.0.2 // indirect + github.com/go-acme/lego/v4 v4.23.1 // indirect + github.com/go-jose/go-jose/v4 v4.0.5 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/google/go-github/v28 v28.1.1 // indirect @@ -38,58 +38,59 @@ require ( github.com/gorilla/mux v1.8.1 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/http-wasm/http-wasm-host-go v0.7.0 // indirect - github.com/klauspost/compress v1.17.11 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/miekg/dns v1.1.62 // indirect + github.com/miekg/dns v1.1.64 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rs/zerolog v1.33.0 // indirect github.com/traefik/paerser v0.2.2 // indirect github.com/unrolled/render v1.0.2 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.6.0 // indirect + go.etcd.io/etcd/client/v3 v3.6.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 // indirect go.opentelemetry.io/otel/log v0.8.0 // indirect go.opentelemetry.io/otel/sdk/log v0.8.0 // indirect - golang.org/x/crypto v0.36.0 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect + golang.org/x/crypto v0.38.0 // indirect golang.org/x/mod v0.24.0 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect ) require ( - cel.dev/expr v0.19.1 // indirect + cel.dev/expr v0.24.0 // indirect github.com/antlr4-go/antlr/v4 v4.13.1 // indirect - github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/go-restful/v3 v3.12.1 // indirect + github.com/emicklei/go-restful/v3 v3.12.2 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.8.0 // indirect; indirectC - github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect; indirectC + github.com/fxamacker/cbor/v2 v2.8.0 // indirect github.com/go-errors/errors v1.5.1 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 - github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonpointer v0.21.1 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect - github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-openapi/swag v0.23.1 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.1.3 // indirect - github.com/google/cel-go v0.22.1 // indirect + github.com/google/cel-go v0.25.0 // indirect github.com/google/gnostic-models v0.6.9 // indirect github.com/google/go-cmp v0.7.0 - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect + github.com/google/pprof v0.0.0-20250501235452-c0086092b71a // indirect github.com/google/uuid v1.6.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -98,50 +99,50 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.21.1 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.62.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect + github.com/prometheus/client_golang v1.22.0 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.64.0 // indirect + github.com/prometheus/procfs v0.16.1 // indirect github.com/spf13/cobra v1.9.1 // indirect github.com/spf13/pflag v1.0.6 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect github.com/x448/float16 v0.8.4 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect - go.opentelemetry.io/otel v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect - go.opentelemetry.io/otel/metric v1.35.0 // indirect - go.opentelemetry.io/otel/sdk v1.35.0 // indirect - go.opentelemetry.io/otel/trace v1.35.0 // indirect - go.opentelemetry.io/proto/otlp v1.5.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect + go.opentelemetry.io/otel v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 // indirect + go.opentelemetry.io/otel/metric v1.36.0 // indirect + go.opentelemetry.io/otel/sdk v1.36.0 // indirect + go.opentelemetry.io/otel/trace v1.36.0 // indirect + go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 - golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e // indirect - golang.org/x/net v0.38.0 // indirect - golang.org/x/oauth2 v0.28.0 // indirect - golang.org/x/sync v0.12.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/term v0.30.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect + golang.org/x/net v0.40.0 // indirect + golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/sync v0.14.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/term v0.32.0 // indirect + golang.org/x/text v0.25.0 // indirect golang.org/x/time v0.11.0 // indirect - golang.org/x/tools v0.31.0 + golang.org/x/tools v0.33.0 gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect - google.golang.org/grpc v1.71.1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect + google.golang.org/grpc v1.72.2 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 - k8s.io/apiextensions-apiserver v0.32.3 - k8s.io/apiserver v0.32.3 // indirect - k8s.io/component-base v0.32.3 // indirect + k8s.io/apiextensions-apiserver v0.33.1 + k8s.io/apiserver v0.33.1 // indirect + k8s.io/component-base v0.33.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect - k8s.io/utils v0.0.0-20241210054802-24370beab758 - sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.1 // indirect + k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect + k8s.io/utils v0.0.0-20250502105355-0f33e8f1c979 + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0 // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/kustomize/api v0.19.0 // indirect sigs.k8s.io/kustomize/kyaml v0.19.0 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect ) diff --git a/go.sum b/go.sum index 10c4d0b..a0493da 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,12 @@ -cel.dev/expr v0.19.1 h1:NciYrtDRIR0lNCnH1LFJegdjspNx9fI59O7TWcua/W4= -cel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= +cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= +cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= -github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= +github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go v1.44.327 h1:ZS8oO4+7MOBLhkdwIhgtVeDzCeWOlTfKJS7EgggbIEY= -github.com/aws/aws-sdk-go v1.44.327/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ= +github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= @@ -17,6 +15,8 @@ github.com/cbroglie/mustache v1.4.0 h1:Azg0dVhxTml5me+7PsZ7WPrQq1Gkf3WApcHMjMprY github.com/cbroglie/mustache v1.4.0/go.mod h1:SS1FTIghy0sjse4DUVGV1k/40B1qE1XkD9DtDsHo9iM= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= +github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= @@ -30,41 +30,41 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= -github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= +github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= 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 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= -github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/go-acme/lego/v4 v4.22.2 h1:ck+HllWrV/rZGeYohsKQ5iKNnU/WAZxwOdiu6cxky+0= -github.com/go-acme/lego/v4 v4.22.2/go.mod h1:E2FndyI3Ekv0usNJt46mFb9LVpV/XBYT+4E3tz02Tzo= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU= +github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/go-acme/lego/v4 v4.23.1 h1:lZ5fGtGESA2L9FB8dNTvrQUq3/X4QOb8ExkKyY7LSV4= +github.com/go-acme/lego/v4 v4.23.1/go.mod h1:7UMVR7oQbIYw6V7mTgGwi4Er7B6Ww0c+c8feiBM0EgI= github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= -github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= +github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= +github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/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 v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= -github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic= +github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk= github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= -github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= -github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= +github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -75,8 +75,8 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/cel-go v0.22.1 h1:AfVXx3chM2qwoSbM7Da8g8hX8OVSkBFwX+rz2+PcK40= -github.com/google/cel-go v0.22.1/go.mod h1:BuznPXXfQDpXKWQ9sPW3TzlAJN5zzFe+i9tIs0yC4s8= +github.com/google/cel-go v0.25.0 h1:jsFw9Fhn+3y2kBbltZR4VEz5xKkcIFRPDnuEzAGv5GY= +github.com/google/cel-go v0.25.0/go.mod h1:hjEb6r5SuOSlhCHmFoLzu8HGCERvIsDAbxDAyNU/MmI= github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -91,33 +91,30 @@ github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20250501235452-c0086092b71a h1:rDA3FfmxwXR+BVKKdz55WwMJ1pD2hJQNW31d+l3mPk4= +github.com/google/pprof v0.0.0-20250501235452-c0086092b71a/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/http-wasm/http-wasm-host-go v0.7.0 h1:+1KrRyOO6tWiDB24QrtSYyDmzFLBBs3jioKaUT0mq1c= github.com/http-wasm/http-wasm-host-go v0.7.0/go.mod h1:adXKcLmL7yuavH/e0kBAp7b3TgAHTo/enCduyN5bXGM= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= 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/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= -github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -133,8 +130,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= -github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= +github.com/miekg/dns v1.1.64 h1:wuZgD9wwCE6XMT05UU/mlSko71eRSXEAm2EbjQXLKnQ= +github.com/miekg/dns v1.1.64/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= @@ -143,18 +140,18 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= -github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= -github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= -github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus= +github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8= +github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= +github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pdok/featureinfo-generator v1.4.0-beta1 h1:ZZO5OtK7yW5ozXFrl1OaxKl0MK3XF5YGFh2692JZVN8= github.com/pdok/featureinfo-generator v1.4.0-beta1/go.mod h1:02Ryu7ZRkeha8SCfS6VYWCdKYZh0llskrfFgp6xRCjk= -github.com/pdok/ogc-capabilities-generator v1.0.0-beta8 h1:8UAv64fArp8wjpwuRIzjjpr5aGLtEhBS7vbi0l5gMao= -github.com/pdok/ogc-capabilities-generator v1.0.0-beta8/go.mod h1:2yUZlJikf5gGH6S33FszUiI9+j85gpIINfAFsCF/eNk= -github.com/pdok/ogc-specifications v1.0.0-beta9 h1:VrdggKg4d2tSway/deztAfZTviXKX0AftfUuZTXx5j8= -github.com/pdok/ogc-specifications v1.0.0-beta9/go.mod h1:YDngwkwrWOfc5MYnEYseiv97K1Y9bZXlVzwi/8EaIl8= +github.com/pdok/ogc-capabilities-generator v1.0.0-beta9 h1:CxAV4jFCsitczuQlX4MNRL5K6ZCFOm9li+gbOnYNLuA= +github.com/pdok/ogc-capabilities-generator v1.0.0-beta9/go.mod h1:4lKxsIm9QSOYOsRuh0f1zJhUPpsEZCuDIs2S8hORtA8= +github.com/pdok/ogc-specifications v1.0.0-beta10 h1:VGZ4k4h8blyuRMNAvKSyxEDKVfQBSpDBAo0YRjNstPY= +github.com/pdok/ogc-specifications v1.0.0-beta10/go.mod h1:YDngwkwrWOfc5MYnEYseiv97K1Y9bZXlVzwi/8EaIl8= github.com/pdok/smooth-operator v0.1.3 h1:Y+JvbFLlyb6pMNFVgAd8G6QsXL0Y6F0srTaROabRnm0= github.com/pdok/smooth-operator v0.1.3/go.mod h1:przwM7mBGmNPqabyhImKVZ15WL4zbqLqH4ExbuWKhWE= github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= @@ -165,14 +162,16 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk= -github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= -github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= +github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= +github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4= +github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= @@ -188,6 +187,8 @@ github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8w github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -196,55 +197,56 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/traefik/paerser v0.2.2 h1:cpzW/ZrQrBh3mdwD/jnp6aXASiUFKOVr6ldP+keJTcQ= github.com/traefik/paerser v0.2.2/go.mod h1:7BBDd4FANoVgaTZG+yh26jI6CA2nds7D/4VTEdIsh24= -github.com/traefik/traefik/v3 v3.3.4 h1:U9gc+aYMMnDCiaWgEc8YKc3MIwfMKwQfqRrfF7VFGOI= -github.com/traefik/traefik/v3 v3.3.4/go.mod h1:Zml3KqgpxNEKFh/jNHcLQm9ehJKNKIulLLQbbPQbp6s= +github.com/traefik/traefik/v3 v3.4.1 h1:QBO/C9ILViPVBhsmY8nEnoobTULxg6oW1jUTX8FFh8w= +github.com/traefik/traefik/v3 v3.4.1/go.mod h1:8FHoFbX5P+zMQ3UUjjfrDH87BDSbHllcUQyiI2wCP3o= github.com/unrolled/render v1.0.2 h1:dGS3EmChQP3yOi1YeFNO/Dx+MbWZhdvhQJTXochM5bs= github.com/unrolled/render v1.0.2/go.mod h1:gN9T0NhL4Bfbwu8ann7Ry/TGHYfosul+J0obPf6NBdM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.etcd.io/etcd/api/v3 v3.5.16 h1:WvmyJVbjWqK4R1E+B12RRHz3bRGy9XVfh++MgbN+6n0= -go.etcd.io/etcd/api/v3 v3.5.16/go.mod h1:1P4SlIP/VwkDmGo3OlOD7faPeP8KDIFhqvciH5EfN28= -go.etcd.io/etcd/client/pkg/v3 v3.5.16 h1:ZgY48uH6UvB+/7R9Yf4x574uCO3jIx0TRDyetSfId3Q= -go.etcd.io/etcd/client/pkg/v3 v3.5.16/go.mod h1:V8acl8pcEK0Y2g19YlOV9m9ssUe6MgiDSobSoaBAM0E= -go.etcd.io/etcd/client/v3 v3.5.16 h1:sSmVYOAHeC9doqi0gv7v86oY/BTld0SEFGaxsU9eRhE= -go.etcd.io/etcd/client/v3 v3.5.16/go.mod h1:X+rExSGkyqxvu276cr2OwPLBaeqFu1cIl4vmRjAD/50= +go.etcd.io/etcd/api/v3 v3.6.0 h1:vdbkcUBGLf1vfopoGE/uS3Nv0KPyIpUV/HM6w9yx2kM= +go.etcd.io/etcd/api/v3 v3.6.0/go.mod h1:Wt5yZqEmxgTNJGHob7mTVBJDZNXiHPtXTcPab37iFOw= +go.etcd.io/etcd/client/pkg/v3 v3.6.0 h1:nchnPqpuxvv3UuGGHaz0DQKYi5EIW5wOYsgUNRc365k= +go.etcd.io/etcd/client/pkg/v3 v3.6.0/go.mod h1:Jv5SFWMnGvIBn8o3OaBq/PnT0jjsX8iNokAUessNjoA= +go.etcd.io/etcd/client/v3 v3.6.0 h1:/yjKzD+HW5v/3DVj9tpwFxzNbu8hjcKID183ug9duWk= +go.etcd.io/etcd/client/v3 v3.6.0/go.mod h1:Jzk/Knqe06pkOZPHXsQ0+vNDvMQrgIqJ0W8DwPdMJMg= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/collector/pdata v1.10.0 h1:oLyPLGvPTQrcRT64ZVruwvmH/u3SHTfNo01pteS4WOE= go.opentelemetry.io/collector/pdata v1.10.0/go.mod h1:IHxHsp+Jq/xfjORQMDJjSH6jvedOSTOyu3nbxqhWSYE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 h1:WzNab7hOOLzdDF/EoWCt4glhrbMPVMOO5JYTmpz36Ls= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0/go.mod h1:hKvJwTzJdp90Vh7p6q/9PAOd55dI6WA6sWj62a/JvSs= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 h1:S+LdBGiQXtJdowoJoQPEtI52syEP/JYBUpjO49EQhV8= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0/go.mod h1:5KXybFvPGds3QinJWQT7pmXf+TN5YIa7CNYObWRkj50= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 h1:JgtbA0xkWHnTmYk7YusopJFX6uleBmAuZ8n05NEh8nQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0/go.mod h1:179AK5aar5R3eS9FucPy6rggvU0g52cvKId8pv4+v0c= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk= go.opentelemetry.io/otel/log v0.8.0 h1:egZ8vV5atrUWUbnSsHn6vB8R21G2wrKqNiDt3iWertk= go.opentelemetry.io/otel/log v0.8.0/go.mod h1:M9qvDdUTRCopJcGRKg57+JSQ9LgLBrwwfC32epk5NX8= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= -go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= +go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= go.opentelemetry.io/otel/sdk/log v0.8.0 h1:zg7GUYXqxk1jnGF/dTdLPrK06xJdrXgqgFLnI4Crxvs= go.opentelemetry.io/otel/sdk/log v0.8.0/go.mod h1:50iXr0UVwQrYS45KbruFrEt4LvAdCaWWgIrsN3ZQggo= -go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= -go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= -go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= -go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= +go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= +go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= +go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= +go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os= +go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= 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/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -254,14 +256,12 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= -golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e h1:4qufH0hlUYs6AO6XmZC3GqfDPGSXHVXUFR6OND+iJX4= -golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= +golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI= +golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ= 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -269,54 +269,39 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -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.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= -golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/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.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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-20220722155257-8c9f86f7a55f/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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/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.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= -golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= +golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= 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= @@ -325,12 +310,12 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0= gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 h1:hE3bRWtU6uceqlh4fhrSnUyjKHMKB9KrTLLG+bc0ddM= -google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463/go.mod h1:U90ffi8eUL9MwPcrJylN5+Mk2v3vuPDptd5yyNUiRR8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= -google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a h1:SGktgSolFCo75dnHJF2yMvnns6jCmHFJ0vE4Vn2JKvQ= +google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8= +google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -341,41 +326,41 @@ gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWM gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= -k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= -k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= -k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY= -k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss= -k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= -k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= -k8s.io/apiserver v0.32.3 h1:kOw2KBuHOA+wetX1MkmrxgBr648ksz653j26ESuWNY8= -k8s.io/apiserver v0.32.3/go.mod h1:q1x9B8E/WzShF49wh3ADOh6muSfpmFL0I2t+TG0Zdgc= -k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= -k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY= -k8s.io/component-base v0.32.3 h1:98WJvvMs3QZ2LYHBzvltFSeJjEx7t5+8s71P7M74u8k= -k8s.io/component-base v0.32.3/go.mod h1:LWi9cR+yPAv7cu2X9rZanTiFKB2kHA+JjmhkKjCZRpI= +k8s.io/api v0.33.1 h1:tA6Cf3bHnLIrUK4IqEgb2v++/GYUtqiu9sRVk3iBXyw= +k8s.io/api v0.33.1/go.mod h1:87esjTn9DRSRTD4fWMXamiXxJhpOIREjWOSjsW1kEHw= +k8s.io/apiextensions-apiserver v0.33.1 h1:N7ccbSlRN6I2QBcXevB73PixX2dQNIW0ZRuguEE91zI= +k8s.io/apiextensions-apiserver v0.33.1/go.mod h1:uNQ52z1A1Gu75QSa+pFK5bcXc4hq7lpOXbweZgi4dqA= +k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4= +k8s.io/apimachinery v0.33.1/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= +k8s.io/apiserver v0.33.1 h1:yLgLUPDVC6tHbNcw5uE9mo1T6ELhJj7B0geifra3Qdo= +k8s.io/apiserver v0.33.1/go.mod h1:VMbE4ArWYLO01omz+k8hFjAdYfc3GVAYPrhP2tTKccs= +k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4= +k8s.io/client-go v0.33.1/go.mod h1:JAsUrl1ArO7uRVFWfcj6kOomSlCv+JpvIsp6usAGefA= +k8s.io/component-base v0.33.1 h1:EoJ0xA+wr77T+G8p6T3l4efT2oNwbqBVKR71E0tBIaI= +k8s.io/component-base v0.33.1/go.mod h1:guT/w/6piyPfTgq7gfvgetyXMIh10zuXA6cRRm3rDuY= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg= -k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas= -k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= -k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.1 h1:uOuSLOMBWkJH0TWa9X6l+mj5nZdm6Ay6Bli8HL8rNfk= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.1/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= -sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= -sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= +k8s.io/utils v0.0.0-20250502105355-0f33e8f1c979 h1:jgJW5IePPXLGB8e/1wvd0Ich9QE97RvvF3a8J3fP/Lg= +k8s.io/utils v0.0.0-20250502105355-0f33e8f1c979/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0 h1:qPrZsv1cwQiFeieFlRqT627fVZ+tyfou/+S5S0H5ua0= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= +sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8= +sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/kustomize/api v0.19.0 h1:F+2HB2mU1MSiR9Hp1NEgoU2q9ItNOaBJl0I4Dlus5SQ= sigs.k8s.io/kustomize/api v0.19.0/go.mod h1:/BbwnivGVcBh1r+8m3tH1VNxJmHSk1PzP5fkP6lbL1o= sigs.k8s.io/kustomize/kyaml v0.19.0 h1:RFge5qsO1uHhwJsu3ipV7RNolC7Uozc0jUBC/61XSlA= sigs.k8s.io/kustomize/kyaml v0.19.0/go.mod h1:FeKD5jEOH+FbZPpqUghBP8mrLjJ3+zD3/rf9NNu1cwY= -sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016 h1:kXv6kKdoEtedwuqMmkqhbkgvYKeycVbC8+iPCP9j5kQ= sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc= -sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI= +sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= From 233016aeb308504c52db75dab84854458dd58184 Mon Sep 17 00:00:00 2001 From: Wouter Remijn Date: Tue, 3 Jun 2025 14:53:14 +0200 Subject: [PATCH 3/4] update tests --- internal/webhook/v3/wfs_webhook_test.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/internal/webhook/v3/wfs_webhook_test.go b/internal/webhook/v3/wfs_webhook_test.go index 48a7ae5..95607b5 100644 --- a/internal/webhook/v3/wfs_webhook_test.go +++ b/internal/webhook/v3/wfs_webhook_test.go @@ -220,6 +220,23 @@ var _ = Describe("WFS Webhook", func() { Expect(warnings).To(BeEmpty()) }) + It("Should deny update url was changed but not added to ingressRouteURLs", func() { + url, err := smoothoperatormodel.ParseURL("http://old/changed") + Expect(err).ToNot(HaveOccurred()) + oldObj.Spec.IngressRouteURLs = nil + obj.Spec.IngressRouteURLs = []smoothoperatormodel.IngressRouteURL{{URL: oldObj.Spec.Service.URL}} + obj.Spec.Service.URL = smoothoperatormodel.URL{URL: url} + warnings, err := validator.ValidateUpdate(ctx, oldObj, obj) + Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) + + obj.Spec.IngressRouteURLs = []smoothoperatormodel.IngressRouteURL{{URL: smoothoperatormodel.URL{URL: url}}} + warnings, err = validator.ValidateUpdate(ctx, oldObj, obj) + Expect(err).To(HaveOccurred()) + Expect(warnings).To(BeEmpty()) + + }) + It("Should deny update if a label was removed", func() { for label := range obj.Labels { delete(obj.Labels, label) From 3ec1fc3fafd861b581cf55ea416eb8f72573bbab Mon Sep 17 00:00:00 2001 From: Wouter Remijn Date: Wed, 4 Jun 2025 08:56:19 +0200 Subject: [PATCH 4/4] review --- api/v3/wfs_validation.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/api/v3/wfs_validation.go b/api/v3/wfs_validation.go index 46658ae..900e254 100644 --- a/api/v3/wfs_validation.go +++ b/api/v3/wfs_validation.go @@ -83,9 +83,7 @@ func ValidateFeatureTypes(wfs *WFS, warnings *[]string, allErrs *field.ErrorList path.Index(index).Child("name"), featureType.Name, )) - } - - if !slices.Contains(names, featureType.Name) { + } else { names = append(names, featureType.Name) }