From c2e8b4908382da3a836447f710640c84433145c2 Mon Sep 17 00:00:00 2001 From: Matthew Booth Date: Thu, 29 Feb 2024 23:30:56 +0000 Subject: [PATCH 1/4] Update ginkgo to 2.15.0 --- go.mod | 16 ++++++++-------- go.sum | 32 ++++++++++++++++---------------- hack/tools/go.mod | 2 +- hack/tools/go.sum | 4 ++-- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index 565999d219..50ebe0a6a8 100644 --- a/go.mod +++ b/go.mod @@ -11,11 +11,11 @@ require ( github.com/gophercloud/gophercloud v1.7.0 github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 github.com/hashicorp/go-version v1.4.0 - github.com/onsi/ginkgo/v2 v2.13.1 + github.com/onsi/ginkgo/v2 v2.15.0 github.com/onsi/gomega v1.30.0 github.com/prometheus/client_golang v1.17.0 github.com/spf13/pflag v1.0.5 - golang.org/x/crypto v0.15.0 + golang.org/x/crypto v0.16.0 golang.org/x/text v0.14.0 gopkg.in/ini.v1 v1.67.0 k8s.io/api v0.28.4 @@ -135,14 +135,14 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.25.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/mod v0.13.0 // indirect - golang.org/x/net v0.18.0 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.19.0 // indirect golang.org/x/oauth2 v0.14.0 // indirect - golang.org/x/sync v0.4.0 // indirect - golang.org/x/sys v0.14.0 // indirect - golang.org/x/term v0.14.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/term v0.15.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.14.0 // indirect + golang.org/x/tools v0.16.1 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect diff --git a/go.sum b/go.sum index c5f22dace3..3da2fa64fd 100644 --- a/go.sum +++ b/go.sum @@ -343,8 +343,8 @@ github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7P 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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/onsi/ginkgo/v2 v2.13.1 h1:LNGfMbR2OVGBfXjvRZIZ2YCTQdGKtPLvuI1rMCCj3OU= -github.com/onsi/ginkgo/v2 v2.13.1/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= +github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= +github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -491,8 +491,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= -golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -530,8 +530,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -567,8 +567,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= -golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -592,8 +592,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -640,13 +640,13 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= -golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -715,8 +715,8 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= 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= diff --git a/hack/tools/go.mod b/hack/tools/go.mod index 5d0c742794..32f7f0856e 100644 --- a/hack/tools/go.mod +++ b/hack/tools/go.mod @@ -7,7 +7,7 @@ require ( github.com/ahmetb/gen-crd-api-reference-docs v0.3.1-0.20220420215017-3f29e6853552 github.com/golang/mock v1.6.0 github.com/itchyny/gojq v0.12.2 - github.com/onsi/ginkgo/v2 v2.13.0 + github.com/onsi/ginkgo/v2 v2.15.0 k8s.io/code-generator v0.29.0 sigs.k8s.io/cluster-api/hack/tools v0.0.0-20221129083400-679ae3e9e6b6 sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20230926180527-c93e2abcb28e diff --git a/hack/tools/go.sum b/hack/tools/go.sum index 54f95cff3e..abac2117f7 100644 --- a/hack/tools/go.sum +++ b/hack/tools/go.sum @@ -220,8 +220,8 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= +github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= From 120bc682203a8b8651cbddb0b09853d2ea83d10d Mon Sep 17 00:00:00 2001 From: Matthew Booth Date: Fri, 1 Mar 2024 00:52:29 +0000 Subject: [PATCH 2/4] ManagedSecurityGroups: fix missing omitemptys on optional fields --- api/v1alpha5/conversion_test.go | 4 ++-- api/v1beta1/openstackcluster_types.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/v1alpha5/conversion_test.go b/api/v1alpha5/conversion_test.go index 3aa5f57d43..1ecbf00a13 100644 --- a/api/v1alpha5/conversion_test.go +++ b/api/v1alpha5/conversion_test.go @@ -51,7 +51,7 @@ func TestConvertFrom(t *testing.T) { }, ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ - "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"},\"managedSecurityGroups\":null,\"network\":{}},\"status\":{\"ready\":false}}", + "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"},\"network\":{}},\"status\":{\"ready\":false}}", }, }, }, @@ -72,7 +72,7 @@ func TestConvertFrom(t *testing.T) { }, ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ - "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"},\"managedSecurityGroups\":null,\"network\":{}}}}}", + "cluster.x-k8s.io/conversion-data": "{\"spec\":{\"template\":{\"spec\":{\"apiServerLoadBalancer\":{},\"controlPlaneEndpoint\":{\"host\":\"\",\"port\":0},\"disableAPIServerFloatingIP\":false,\"disableExternalNetwork\":false,\"externalNetwork\":{},\"identityRef\":{\"cloudName\":\"\",\"name\":\"\"},\"network\":{}}}}}", }, }, }, diff --git a/api/v1beta1/openstackcluster_types.go b/api/v1beta1/openstackcluster_types.go index d5cda0ec1a..7ca146ef70 100644 --- a/api/v1beta1/openstackcluster_types.go +++ b/api/v1beta1/openstackcluster_types.go @@ -123,7 +123,7 @@ type OpenStackClusterSpec struct { // It's possible to add additional rules to the managed security groups. // When defined to an empty struct, the managed security groups will be created with the default rules. // +optional - ManagedSecurityGroups *ManagedSecurityGroups `json:"managedSecurityGroups"` + ManagedSecurityGroups *ManagedSecurityGroups `json:"managedSecurityGroups,omitempty"` // DisablePortSecurity disables the port security of the network created for the // Kubernetes cluster, which also disables SecurityGroups @@ -272,7 +272,7 @@ type ManagedSecurityGroups struct { // +listType=map // +listMapKey=name // +optional - AllNodesSecurityGroupRules []SecurityGroupRuleSpec `json:"allNodesSecurityGroupRules" patchStrategy:"merge" patchMergeKey:"name"` + AllNodesSecurityGroupRules []SecurityGroupRuleSpec `json:"allNodesSecurityGroupRules,omitempty" patchStrategy:"merge" patchMergeKey:"name"` // AllowAllInClusterTraffic allows all ingress and egress traffic between cluster nodes when set to true. // +kubebuilder:default=false From a4e207974a4884449898d83aa1fe0283dd3905ed Mon Sep 17 00:00:00 2001 From: Matthew Booth Date: Fri, 1 Mar 2024 00:59:15 +0000 Subject: [PATCH 3/4] tests: Add TEST_PATHS target for make test TEST_PATHS defaults to the previous hardcoded value of './...', but can now be overridden. e.g. To run just the controller tests: make test TEST_PATHS=./controllers/... --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e33ce59c68..4eb9f5d757 100644 --- a/Makefile +++ b/Makefile @@ -134,12 +134,13 @@ ifdef KUBEBUILDER_ASSETS_DIR endif .PHONY: test +TEST_PATHS ?= ./... test: $(SETUP_ENVTEST) ## Run tests set -xeuf -o pipefail; \ if [ -z "$(KUBEBUILDER_ASSETS)" ]; then \ KUBEBUILDER_ASSETS=`$(SETUP_ENVTEST) use --use-env -p path $(setup_envtest_extra_args) $(KUBEBUILDER_ENVTEST_KUBERNETES_VERSION)`; \ fi; \ - KUBEBUILDER_ASSETS="$$KUBEBUILDER_ASSETS" go test -v ./... $(TEST_ARGS) + KUBEBUILDER_ASSETS="$$KUBEBUILDER_ASSETS" go test -v $(TEST_PATHS) $(TEST_ARGS) E2E_TEMPLATES_DIR=test/e2e/data/infrastructure-openstack E2E_KUSTOMIZE_DIR=test/e2e/data/kustomize From 4d3e79c8cc23dc4d8bab0f77bec8b44e45e5319e Mon Sep 17 00:00:00 2001 From: Matthew Booth Date: Fri, 1 Mar 2024 01:01:08 +0000 Subject: [PATCH 4/4] Add framework for api validation tests using envtest --- .../apivalidations/neutronfilters_test.go | 176 ++++++++++++++++++ .../apivalidations/openstackcluster_test.go | 62 ++++++ .../apivalidations/openstackmachine_test.go | 57 ++++++ test/e2e/suites/apivalidations/suite_test.go | 159 ++++++++++++++++ 4 files changed, 454 insertions(+) create mode 100644 test/e2e/suites/apivalidations/neutronfilters_test.go create mode 100644 test/e2e/suites/apivalidations/openstackcluster_test.go create mode 100644 test/e2e/suites/apivalidations/openstackmachine_test.go create mode 100644 test/e2e/suites/apivalidations/suite_test.go diff --git a/test/e2e/suites/apivalidations/neutronfilters_test.go b/test/e2e/suites/apivalidations/neutronfilters_test.go new file mode 100644 index 0000000000..540cb815c0 --- /dev/null +++ b/test/e2e/suites/apivalidations/neutronfilters_test.go @@ -0,0 +1,176 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package apivalidations + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" +) + +var _ = Describe("Neutron filter API validations", func() { + var ( + namespace *corev1.Namespace + cluster *infrav1.OpenStackCluster + machine *infrav1.OpenStackMachine + ) + + BeforeEach(func() { + namespace = createNamespace() + + // Initialise a basic machine object in the correct namespace + machine = &infrav1.OpenStackMachine{} + machine.Namespace = namespace.Name + machine.GenerateName = "machine-" + + // Initialise a basic cluster object in the correct namespace + cluster = &infrav1.OpenStackCluster{} + cluster.Namespace = namespace.Name + cluster.GenerateName = "cluster-" + }) + + DescribeTable("Allow valid neutron filter tags", func(tags []infrav1.FilterByNeutronTags) { + // Specify the given neutron tags in every filter it is + // possible to specify them in, then create the + // resulting object. It should be valid. + + securityGroups := make([]infrav1.SecurityGroupFilter, len(tags)) + for i := range tags { + securityGroups[i].FilterByNeutronTags = tags[i] + } + machine.Spec.SecurityGroups = securityGroups + + ports := make([]infrav1.PortOpts, len(tags)) + for i := range tags { + port := &ports[i] + port.Network = &infrav1.NetworkFilter{FilterByNeutronTags: tags[i]} + port.FixedIPs = []infrav1.FixedIP{{Subnet: &infrav1.SubnetFilter{FilterByNeutronTags: tags[i]}}} + port.SecurityGroups = []infrav1.SecurityGroupFilter{{FilterByNeutronTags: tags[i]}} + } + Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed") + + // Maximum of 2 subnets are supported + nSubnets := min(len(tags), 2) + subnets := make([]infrav1.SubnetFilter, nSubnets) + for i := 0; i < nSubnets; i++ { + subnets[i].FilterByNeutronTags = tags[i] + } + cluster.Spec.Subnets = subnets + if len(tags) > 0 { + cluster.Spec.Network = infrav1.NetworkFilter{FilterByNeutronTags: tags[0]} + cluster.Spec.ExternalNetwork = infrav1.NetworkFilter{FilterByNeutronTags: tags[0]} + cluster.Spec.Router = &infrav1.RouterFilter{FilterByNeutronTags: tags[0]} + } + Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed") + }, + Entry("empty list", nil), + Entry("single tag", []infrav1.FilterByNeutronTags{ + {Tags: []infrav1.NeutronTag{"foo"}}, + }), + Entry("multiple filters, multiple tags", []infrav1.FilterByNeutronTags{ + {Tags: []infrav1.NeutronTag{"foo", "bar"}}, + {TagsAny: []infrav1.NeutronTag{"foo", "bar"}}, + {NotTags: []infrav1.NeutronTag{"foo", "bar"}}, + {NotTagsAny: []infrav1.NeutronTag{"foo", "bar"}}, + }), + ) + + DescribeTable("Disallow invalid neutron filter tags", func(tags []infrav1.FilterByNeutronTags) { + { + machine := machine.DeepCopy() + securityGroups := make([]infrav1.SecurityGroupFilter, len(tags)) + for i := range tags { + securityGroups[i].FilterByNeutronTags = tags[i] + } + machine.Spec.SecurityGroups = securityGroups + Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail with invalid security group neutron tags") + } + + for i := range tags { + { + machine := machine.DeepCopy() + machine.Spec.Ports = []infrav1.PortOpts{ + {Network: &infrav1.NetworkFilter{FilterByNeutronTags: tags[i]}}, + } + Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail with invalid port network neutron tags") + } + { + machine := machine.DeepCopy() + machine.Spec.Ports = []infrav1.PortOpts{ + {FixedIPs: []infrav1.FixedIP{{Subnet: &infrav1.SubnetFilter{FilterByNeutronTags: tags[i]}}}}, + } + Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail with invalid port subnet neutron tags") + } + { + machine := machine.DeepCopy() + machine.Spec.Ports = []infrav1.PortOpts{ + {SecurityGroups: []infrav1.SecurityGroupFilter{{FilterByNeutronTags: tags[i]}}}, + } + Expect(k8sClient.Create(ctx, machine)).NotTo(Succeed(), "OpenStackMachine creation should fail with invalid port security group neutron tags") + } + } + + if len(tags) > 0 { + tag := tags[0] + + { + cluster := cluster.DeepCopy() + cluster.Spec.Subnets = []infrav1.SubnetFilter{{FilterByNeutronTags: tag}} + Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail with invalid subnet neutron tags") + } + + { + cluster := cluster.DeepCopy() + cluster.Spec.Network = infrav1.NetworkFilter{FilterByNeutronTags: tag} + Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail with invalid network neutron tags") + } + + { + cluster := cluster.DeepCopy() + cluster.Spec.ExternalNetwork = infrav1.NetworkFilter{FilterByNeutronTags: tag} + Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail with invalid external network neutron tags") + } + + { + cluster := cluster.DeepCopy() + cluster.Spec.Router = &infrav1.RouterFilter{FilterByNeutronTags: tag} + Expect(k8sClient.Create(ctx, cluster)).NotTo(Succeed(), "OpenStackCluster creation should fail with invalid router neutron tags") + } + } + }, + Entry("contains leading comma", []infrav1.FilterByNeutronTags{ + {Tags: []infrav1.NeutronTag{",foo"}}, + }), + Entry("contains trailing comma", []infrav1.FilterByNeutronTags{ + {Tags: []infrav1.NeutronTag{"foo,"}}, + }), + Entry("contains comma in middle", []infrav1.FilterByNeutronTags{ + {Tags: []infrav1.NeutronTag{"foo,bar"}}, + }), + Entry("contains multiple commas", []infrav1.FilterByNeutronTags{ + {Tags: []infrav1.NeutronTag{"foo,,bar"}}, + }), + Entry("empty tag", []infrav1.FilterByNeutronTags{ + {Tags: []infrav1.NeutronTag{""}}, + }), + Entry("second tag is invalid", []infrav1.FilterByNeutronTags{ + {Tags: []infrav1.NeutronTag{"foo", ""}}, + }), + ) +}) diff --git a/test/e2e/suites/apivalidations/openstackcluster_test.go b/test/e2e/suites/apivalidations/openstackcluster_test.go new file mode 100644 index 0000000000..00fd97197b --- /dev/null +++ b/test/e2e/suites/apivalidations/openstackcluster_test.go @@ -0,0 +1,62 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package apivalidations + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" +) + +var _ = Describe("OpenStackCluster API validations", func() { + var cluster *infrav1.OpenStackCluster + var namespace *corev1.Namespace + + BeforeEach(func() { + namespace = createNamespace() + + // Initialise a basic cluster object in the correct namespace + cluster = &infrav1.OpenStackCluster{} + cluster.Namespace = namespace.Name + cluster.GenerateName = "cluster-" + }) + + It("should allow the smallest permissible cluster spec", func() { + Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed") + }) + + It("should only allow controlPlaneEndpoint to be set once", func() { + By("Creating a bare cluster") + Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed") + + By("Setting the control plane endpoint") + cluster.Spec.ControlPlaneEndpoint.Host = "foo" + cluster.Spec.ControlPlaneEndpoint.Port = 1234 + Expect(k8sClient.Update(ctx, cluster)).To(Succeed(), "Setting control plane endpoint should succeed") + + By("Modifying the control plane endpoint") + cluster.Spec.ControlPlaneEndpoint.Host = "bar" + Expect(k8sClient.Update(ctx, cluster)).NotTo(Succeed(), "Updating control plane endpoint should fail") + }) + + It("should allow an empty managed security groups definition", func() { + cluster.Spec.ManagedSecurityGroups = &infrav1.ManagedSecurityGroups{} + Expect(k8sClient.Create(ctx, cluster)).To(Succeed(), "OpenStackCluster creation should succeed") + }) +}) diff --git a/test/e2e/suites/apivalidations/openstackmachine_test.go b/test/e2e/suites/apivalidations/openstackmachine_test.go new file mode 100644 index 0000000000..00f262cc0b --- /dev/null +++ b/test/e2e/suites/apivalidations/openstackmachine_test.go @@ -0,0 +1,57 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package apivalidations + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + "k8s.io/utils/pointer" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" +) + +var _ = Describe("OpenStackMachine API validations", func() { + var namespace *corev1.Namespace + var machine *infrav1.OpenStackMachine + + BeforeEach(func() { + namespace = createNamespace() + + // Initialise a basic machine object in the correct namespace + machine = &infrav1.OpenStackMachine{} + machine.Namespace = namespace.Name + machine.GenerateName = "machine-" + }) + + It("should allow the smallest permissible machine spec", func() { + Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed") + }) + + It("should only allow the providerID to be set once", func() { + By("Creating a bare machine") + Expect(k8sClient.Create(ctx, machine)).To(Succeed(), "OpenStackMachine creation should succeed") + + By("Setting the providerID") + machine.Spec.ProviderID = pointer.String("foo") + Expect(k8sClient.Update(ctx, machine)).To(Succeed(), "Setting providerID should succeed") + + By("Modifying the providerID") + machine.Spec.ProviderID = pointer.String("bar") + Expect(k8sClient.Update(ctx, machine)).NotTo(Succeed(), "Updating providerID should fail") + }) +}) diff --git a/test/e2e/suites/apivalidations/suite_test.go b/test/e2e/suites/apivalidations/suite_test.go new file mode 100644 index 0000000000..65a8e69136 --- /dev/null +++ b/test/e2e/suites/apivalidations/suite_test.go @@ -0,0 +1,159 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package apivalidations + +import ( + "context" + "fmt" + "path/filepath" + "strconv" + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/discovery" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + "sigs.k8s.io/controller-runtime/pkg/envtest/komega" + "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" + + infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" +) + +var ( + cfg *rest.Config + k8sClient client.Client + testEnv *envtest.Environment + testScheme *runtime.Scheme + ctx = context.Background() + mgrCancel context.CancelFunc + mgrDone chan struct{} +) + +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecs(t, "API Validation Suite") +} + +var _ = BeforeSuite(func() { + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{ + // NOTE: These are the bare CRDs without conversion webhooks + filepath.Join("..", "..", "..", "..", "config", "crd", "bases"), + }, + ErrorIfCRDPathMissing: true, + WebhookInstallOptions: envtest.WebhookInstallOptions{ + Paths: []string{ + filepath.Join("..", "..", "..", "..", "config", "webhook"), + }, + }, + } + + var err error + cfg, err = testEnv.Start() + Expect(err).NotTo(HaveOccurred(), "test environment should start") + Expect(cfg).NotTo(BeNil(), "test environment should return a configuration") + DeferCleanup(func() error { + By("tearing down the test environment") + return testEnv.Stop() + }) + + testScheme = scheme.Scheme + Expect(infrav1.AddToScheme(testScheme)).To(Succeed()) + + //+kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: testScheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient).NotTo(BeNil()) + + // CEL requires Kube 1.25 and above, so check for the minimum server version. + discoveryClient, err := discovery.NewDiscoveryClientForConfig(cfg) + Expect(err).ToNot(HaveOccurred()) + + serverVersion, err := discoveryClient.ServerVersion() + Expect(err).ToNot(HaveOccurred()) + + Expect(serverVersion.Major).To(Equal("1")) + + minorInt, err := strconv.Atoi(serverVersion.Minor) + Expect(err).ToNot(HaveOccurred()) + Expect(minorInt).To(BeNumerically(">=", 25), fmt.Sprintf("This test suite requires a Kube API server of at least version 1.25, current version is 1.%s", serverVersion.Minor)) + + komega.SetClient(k8sClient) + komega.SetContext(ctx) + + By("Setting up manager and webhooks") + mgr, err := ctrl.NewManager(cfg, ctrl.Options{ + Scheme: testScheme, + Metrics: server.Options{ + BindAddress: "0", + }, + WebhookServer: webhook.NewServer(webhook.Options{ + Port: testEnv.WebhookInstallOptions.LocalServingPort, + Host: testEnv.WebhookInstallOptions.LocalServingHost, + CertDir: testEnv.WebhookInstallOptions.LocalServingCertDir, + }), + }) + Expect(err).ToNot(HaveOccurred(), "Manager setup should succeed") + + Expect((&infrav1.OpenStackMachineTemplateWebhook{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackMachineTemplate webhook should be registered with manager") + Expect((&infrav1.OpenStackMachineTemplateList{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackMachineTemplateList webhook should be registered with manager") + Expect((&infrav1.OpenStackCluster{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackCluster webhook should be registered with manager") + Expect((&infrav1.OpenStackClusterTemplate{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackClusterTemplate webhook should be registered with manager") + Expect((&infrav1.OpenStackMachine{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackMachine webhook should be registered with manager") + Expect((&infrav1.OpenStackMachineList{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackMachineList webhook should be registered with manager") + Expect((&infrav1.OpenStackClusterList{}).SetupWebhookWithManager(mgr)).To(Succeed(), "OpenStackClusterList webhook should be registered with manager") + + By("Starting manager") + var mgrCtx context.Context + mgrDone = make(chan struct{}) + mgrCtx, mgrCancel = context.WithCancel(context.Background()) + + go func() { + defer GinkgoRecover() + defer close(mgrDone) + Expect(mgr.Start(mgrCtx)).To(Succeed(), "Manager should start") + }() + DeferCleanup(func() { + By("Tearing down manager") + mgrCancel() + Eventually(mgrDone).Should(BeClosed(), "Manager should stop") + }) +}) + +func createNamespace() *corev1.Namespace { + By("Creating namespace") + namespace := corev1.Namespace{} + namespace.GenerateName = "test-" + Expect(k8sClient.Create(ctx, &namespace)).To(Succeed(), "Namespace creation should succeed") + DeferCleanup(func() { + By("Deleting namespace") + Expect(k8sClient.Delete(ctx, &namespace, client.PropagationPolicy(metav1.DeletePropagationForeground))).To(Succeed(), "Namespace deletion should succeed") + }) + By(fmt.Sprintf("Using namespace %s", namespace.Name)) + return &namespace +}