From 71e7f7ff4822a62a398c8156df8e2a5d0cd5b658 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Wed, 3 May 2023 19:56:49 +0300 Subject: [PATCH 01/57] feat: cron job template field (#132) (#133) * feat: cron job template field * fix: dep update --- apis/tests/v3/test_types.go | 2 + apis/testsuite/v2/testsuite_types.go | 2 + config/crd/bases/tests.testkube.io_tests.yaml | 3 + .../bases/tests.testkube.io_testsuites.yaml | 3 + controllers/tests/test_controller.go | 14 ++- controllers/testsuite/testsuite_controller.go | 14 ++- go.mod | 26 +++--- go.sum | 64 +++++++------ pkg/cronjob/client.go | 90 ++++++++++++------- 9 files changed, 136 insertions(+), 82 deletions(-) diff --git a/apis/tests/v3/test_types.go b/apis/tests/v3/test_types.go index 6bf2a729..1e09340f 100644 --- a/apis/tests/v3/test_types.go +++ b/apis/tests/v3/test_types.go @@ -193,6 +193,8 @@ type ExecutionRequest struct { ArtifactRequest *ArtifactRequest `json:"artifactRequest,omitempty"` // job template extensions JobTemplate string `json:"jobTemplate,omitempty"` + // cron job template extensions + CronJobTemplate string `json:"cronJobTemplate,omitempty"` // script to run before test execution PreRunScript string `json:"preRunScript,omitempty"` // scraper template extensions diff --git a/apis/testsuite/v2/testsuite_types.go b/apis/testsuite/v2/testsuite_types.go index 151540eb..b59936bf 100644 --- a/apis/testsuite/v2/testsuite_types.go +++ b/apis/testsuite/v2/testsuite_types.go @@ -115,6 +115,8 @@ type TestSuiteExecutionRequest struct { // timeout for test suite execution Timeout int32 `json:"timeout,omitempty"` RunningContext *RunningContext `json:"runningContext,omitempty"` + // cron job template extensions + CronJobTemplate string `json:"cronJobTemplate,omitempty"` } // +kubebuilder:validation:Enum=queued;running;passed;failed;aborting;aborted;timeout diff --git a/config/crd/bases/tests.testkube.io_tests.yaml b/config/crd/bases/tests.testkube.io_tests.yaml index 2b26065b..0915b42c 100644 --- a/config/crd/bases/tests.testkube.io_tests.yaml +++ b/config/crd/bases/tests.testkube.io_tests.yaml @@ -475,6 +475,9 @@ spec: items: type: string type: array + cronJobTemplate: + description: cron job template extensions + type: string envConfigMaps: description: config map references items: diff --git a/config/crd/bases/tests.testkube.io_testsuites.yaml b/config/crd/bases/tests.testkube.io_testsuites.yaml index 187e2b52..19f2db29 100644 --- a/config/crd/bases/tests.testkube.io_testsuites.yaml +++ b/config/crd/bases/tests.testkube.io_testsuites.yaml @@ -330,6 +330,9 @@ spec: executionRequest: description: test suite execution request body properties: + cronJobTemplate: + description: cron job template extensions + type: string executionLabels: additionalProperties: type: string diff --git a/controllers/tests/test_controller.go b/controllers/tests/test_controller.go index 3d6f48f7..8bc6368f 100644 --- a/controllers/tests/test_controller.go +++ b/controllers/tests/test_controller.go @@ -89,11 +89,17 @@ func (r *TestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl. return ctrl.Result{}, err } + jobTemplate := "" + if test.Spec.ExecutionRequest != nil { + jobTemplate = test.Spec.ExecutionRequest.CronJobTemplate + } + options := cronjob.CronJobOptions{ - Schedule: test.Spec.Schedule, - Resource: cronjob.TestResourceURI, - Data: string(data), - Labels: test.Labels, + Schedule: test.Spec.Schedule, + Resource: cronjob.TestResourceURI, + Data: string(data), + Labels: test.Labels, + CronJobTemplateExtensions: jobTemplate, } // Create CronJob if it was not created before for provided Test schedule diff --git a/controllers/testsuite/testsuite_controller.go b/controllers/testsuite/testsuite_controller.go index c05835a8..556a4919 100644 --- a/controllers/testsuite/testsuite_controller.go +++ b/controllers/testsuite/testsuite_controller.go @@ -90,11 +90,17 @@ func (r *TestSuiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( return ctrl.Result{}, err } + jobTemplate := "" + if testSuite.Spec.ExecutionRequest != nil { + jobTemplate = testSuite.Spec.ExecutionRequest.CronJobTemplate + } + options := cronjob.CronJobOptions{ - Schedule: testSuite.Spec.Schedule, - Resource: cronjob.TestSuiteResourceURI, - Data: string(data), - Labels: testSuite.Labels, + Schedule: testSuite.Spec.Schedule, + Resource: cronjob.TestSuiteResourceURI, + Data: string(data), + Labels: testSuite.Labels, + CronJobTemplateExtensions: jobTemplate, } // Create CronJob if it was not created before for provided TestSuite schedule diff --git a/go.mod b/go.mod index c8d62e0f..4f657db3 100644 --- a/go.mod +++ b/go.mod @@ -7,14 +7,15 @@ require ( github.com/google/uuid v1.3.0 github.com/kelseyhightower/envconfig v1.4.0 github.com/onsi/ginkgo v1.16.5 - github.com/onsi/gomega v1.18.1 + github.com/onsi/gomega v1.19.0 github.com/pkg/errors v0.9.1 - github.com/stretchr/testify v1.8.0 + github.com/stretchr/testify v1.8.1 go.uber.org/zap v1.21.0 k8s.io/api v0.24.1 k8s.io/apimachinery v0.24.1 k8s.io/client-go v0.24.1 sigs.k8s.io/controller-runtime v0.12.1 + sigs.k8s.io/kustomize/kyaml v0.14.1 ) require ( @@ -28,14 +29,15 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/emicklei/go-restful/v3 v3.7.5-0.20220308211933-7c971ca4d0fd // indirect + github.com/emicklei/go-restful/v3 v3.8.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/go-errors/errors v1.4.2 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/zapr v1.2.3 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.20.0 // indirect - github.com/go-openapi/swag v0.21.1 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.1 // indirect + github.com/go-openapi/swag v0.22.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.4.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -61,11 +63,11 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.8.0 // indirect golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect - golang.org/x/net v0.0.0-20220531201128-c960675eff93 // indirect + golang.org/x/net v0.4.0 // indirect golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401 // indirect - golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect - golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect - golang.org/x/text v0.3.7 // indirect + golang.org/x/sys v0.3.0 // indirect + golang.org/x/term v0.3.0 // indirect + golang.org/x/text v0.5.0 // indirect golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect @@ -77,9 +79,9 @@ require ( k8s.io/apiextensions-apiserver v0.24.1 // indirect k8s.io/component-base v0.24.1 // indirect k8s.io/klog/v2 v2.60.1 // indirect - k8s.io/kube-openapi v0.0.0-20220603121420-31174f50af60 // indirect + k8s.io/kube-openapi v0.0.0-20230109183929-3758b55a6596 // indirect k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index b805407f..508d9710 100644 --- a/go.sum +++ b/go.sum @@ -144,8 +144,8 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful/v3 v3.7.5-0.20220308211933-7c971ca4d0fd h1:iKIUl3SetleviJ07WJdKqdvVBzmfYgaADXHHrONYPOY= -github.com/emicklei/go-restful/v3 v3.7.5-0.20220308211933-7c971ca4d0fd/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= +github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -171,6 +171,8 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -192,16 +194,17 @@ github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQ github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8= +github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU= -github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -293,7 +296,6 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= @@ -371,6 +373,8 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -405,13 +409,13 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 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/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= @@ -421,17 +425,14 @@ github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ= -github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= -github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -507,6 +508,7 @@ github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -514,8 +516,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -523,6 +526,7 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -669,7 +673,6 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -680,8 +683,8 @@ golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220531201128-c960675eff93 h1:MYimHLfoXEpOhqd/zgoA/uoXzHB86AEky4LAx5ij9xA= -golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= 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= @@ -791,12 +794,12 @@ golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.0.0-20220526004731-065cf7ba2467 h1:CBpWXWQpIRjzmkkA+M7q9Fqnwd2mZr3AFqexg8YTfoM= -golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= 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= @@ -805,8 +808,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1050,8 +1054,9 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= @@ -1106,8 +1111,8 @@ k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc= k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kube-openapi v0.0.0-20220603121420-31174f50af60 h1:cE/M8rmDQgibspuSm+X1iW16ByTImtEaapgaHoVSLX4= -k8s.io/kube-openapi v0.0.0-20220603121420-31174f50af60/go.mod h1:ouUzE1U2mEv//HRoBwYLFE5pdqjIebvtX361vtEIlBI= +k8s.io/kube-openapi v0.0.0-20230109183929-3758b55a6596 h1:8cNCQs+WqqnSpZ7y0LMQPKD+RZUHU17VqLPMW3qxnxc= +k8s.io/kube-openapi v0.0.0-20230109183929-3758b55a6596/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= @@ -1120,9 +1125,12 @@ sigs.k8s.io/controller-runtime v0.12.1/go.mod h1:BKhxlA4l7FPK4AQcsuL4X6vZeWnKDXe sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124 h1:2sgAQQcY0dEW2SsQwTXhQV4vO6+rSslYx8K3XmM5hqQ= sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= +sigs.k8s.io/kustomize/kyaml v0.14.1 h1:c8iibius7l24G2wVAGZn/Va2wNys03GXLjYVIcFVxKA= +sigs.k8s.io/kustomize/kyaml v0.14.1/go.mod h1:AN1/IpawKilWD7V+YvQwRGUvuUOOWpjsHu6uHwonSF4= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y= sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/pkg/cronjob/client.go b/pkg/cronjob/client.go index 4769ee19..ccb4db57 100644 --- a/pkg/cronjob/client.go +++ b/pkg/cronjob/client.go @@ -12,6 +12,8 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/yaml" "sigs.k8s.io/controller-runtime/pkg/client" + kyaml "sigs.k8s.io/kustomize/kyaml/yaml" + "sigs.k8s.io/kustomize/kyaml/yaml/merge2" ) const ( @@ -30,23 +32,25 @@ type Client struct { } type CronJobOptions struct { - Schedule string - Resource string - Data string - Labels map[string]string + Schedule string + Resource string + Data string + Labels map[string]string + CronJobTemplateExtensions string } type templateParameters struct { - Id string - Name string - Namespace string - ServiceName string - ServicePort int - Schedule string - Resource string - CronJobTemplate string - Data string - Labels map[string]string + Id string + Name string + Namespace string + ServiceName string + ServicePort int + Schedule string + Resource string + CronJobTemplate string + CronJobTemplateExtensions string + Data string + Labels map[string]string } // NewClient is a method to create new cron job client @@ -72,16 +76,17 @@ func (c *Client) Get(ctx context.Context, name, namespace string) (*batchv1.Cron // Create is a method to create a cron job func (c *Client) Create(ctx context.Context, id, name, namespace string, options CronJobOptions) error { parameters := templateParameters{ - Id: id, - Name: name, - Namespace: namespace, - ServiceName: c.serviceName, - ServicePort: c.servicePort, - Schedule: options.Schedule, - Resource: options.Resource, - CronJobTemplate: c.cronJobTemplate, - Data: options.Data, - Labels: options.Labels, + Id: id, + Name: name, + Namespace: namespace, + ServiceName: c.serviceName, + ServicePort: c.servicePort, + Schedule: options.Schedule, + Resource: options.Resource, + CronJobTemplate: c.cronJobTemplate, + CronJobTemplateExtensions: options.CronJobTemplateExtensions, + Data: options.Data, + Labels: options.Labels, } cronJobSpec, err := NewCronJobSpec(parameters) @@ -99,16 +104,17 @@ func (c *Client) Create(ctx context.Context, id, name, namespace string, options // Update is a method to update an existing cron job func (c *Client) Update(ctx context.Context, cronJob *batchv1.CronJob, id, name, namespace string, options CronJobOptions) error { parameters := templateParameters{ - Id: id, - Name: name, - Namespace: namespace, - ServiceName: c.serviceName, - ServicePort: c.servicePort, - Schedule: options.Schedule, - Resource: options.Resource, - CronJobTemplate: c.cronJobTemplate, - Data: options.Data, - Labels: options.Labels, + Id: id, + Name: name, + Namespace: namespace, + ServiceName: c.serviceName, + ServicePort: c.servicePort, + Schedule: options.Schedule, + Resource: options.Resource, + CronJobTemplate: c.cronJobTemplate, + CronJobTemplateExtensions: options.CronJobTemplateExtensions, + Data: options.Data, + Labels: options.Labels, } cronJobSpec, err := NewCronJobSpec(parameters) @@ -160,6 +166,22 @@ func NewCronJobSpec(parameters templateParameters) (*batchv1.CronJob, error) { var cronJob batchv1.CronJob cronJobSpec := buffer.String() + if parameters.CronJobTemplateExtensions != "" { + tmplExt, err := template.New("cronJobExt").Parse(parameters.CronJobTemplateExtensions) + if err != nil { + return nil, fmt.Errorf("creating cron job extensions spec from default template error: %w", err) + } + + var bufferExt bytes.Buffer + if err = tmplExt.ExecuteTemplate(&bufferExt, "cronJobExt", parameters); err != nil { + return nil, fmt.Errorf("executing cron job extensions spec default template: %w", err) + } + + if cronJobSpec, err = merge2.MergeStrings(bufferExt.String(), cronJobSpec, false, kyaml.MergeOptions{}); err != nil { + return nil, fmt.Errorf("merging cron job spec templates: %w", err) + } + } + decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewBufferString(cronJobSpec), len(cronJobSpec)) if err := decoder.Decode(&cronJob); err != nil { return nil, fmt.Errorf("decoding cron job spec error: %w", err) From b1213c70c7b7d5347c3e66d66c1c52d02468f68f Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Wed, 3 May 2023 20:36:04 +0300 Subject: [PATCH 02/57] feat: deprecate args (#130) * feat: add args mode * fix: add args mode type * fix: change artifact support --- apis/executor/v1/executor_types.go | 4 ++-- apis/tests/v3/test_types.go | 23 +++++++++++++++---- .../bases/executor.testkube.io_executors.yaml | 4 ++-- config/crd/bases/tests.testkube.io_tests.yaml | 17 +++++++++----- 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/apis/executor/v1/executor_types.go b/apis/executor/v1/executor_types.go index 75b64366..6d40d09b 100644 --- a/apis/executor/v1/executor_types.go +++ b/apis/executor/v1/executor_types.go @@ -40,9 +40,9 @@ type ExecutorSpec struct { // Image for kube-job Image string `json:"image,omitempty"` - // container executor binary arguments + // executor binary arguments Args []string `json:"args,omitempty"` - // container executor default binary command + // executor default binary command Command []string `json:"command,omitempty"` // container executor default image pull secrets ImagePullSecrets []v1.LocalObjectReference `json:"imagePullSecrets,omitempty"` diff --git a/apis/tests/v3/test_types.go b/apis/tests/v3/test_types.go index 1e09340f..0b51d51c 100644 --- a/apis/tests/v3/test_types.go +++ b/apis/tests/v3/test_types.go @@ -115,13 +115,13 @@ const ( GitAuthTypeHeader GitAuthType = "header" ) -// artifact request body for container executors with test artifacts +// artifact request body with test artifacts type ArtifactRequest struct { - // artifact storage class name + // artifact storage class name for container executor StorageClassName string `json:"storageClassName"` - // artifact volume mount path + // artifact volume mount path for container executor VolumeMountPath string `json:"volumeMountPath"` - // artifact directories + // artifact directories for scraping Dirs []string `json:"dirs,omitempty"` } @@ -166,7 +166,9 @@ type ExecutionRequest struct { TestSuiteSecretUUID string `json:"testSuiteSecretUUID,omitempty"` // additional executor binary arguments Args []string `json:"args,omitempty"` - // container executor binary command + // usage mode for arguments + ArgsMode ArgsModeType `json:"argsMode,omitempty"` + // executor binary command Command []string `json:"command,omitempty"` // container executor image Image string `json:"image,omitempty"` @@ -206,6 +208,17 @@ type ExecutionRequest struct { RunningContext *RunningContext `json:"runningContext,omitempty"` } +// ArgsModeType defines args mode type +// +kubebuilder:validation:Enum=append;override +type ArgsModeType string + +const ( + // ArgsModeTypeAppend for append args mode + ArgsModeTypeAppend ArgsModeType = "append" + // ArgsModeTypeOverride for override args mode + ArgsModeTypeOverride ArgsModeType = "override" +) + // Reference to env resource type EnvReference struct { v1.LocalObjectReference `json:"reference"` diff --git a/config/crd/bases/executor.testkube.io_executors.yaml b/config/crd/bases/executor.testkube.io_executors.yaml index 37e9fabe..6e5848e4 100644 --- a/config/crd/bases/executor.testkube.io_executors.yaml +++ b/config/crd/bases/executor.testkube.io_executors.yaml @@ -36,12 +36,12 @@ spec: description: ExecutorSpec defines the desired state of Executor properties: args: - description: container executor binary arguments + description: executor binary arguments items: type: string type: array command: - description: container executor default binary command + description: executor default binary command items: type: string type: array diff --git a/config/crd/bases/tests.testkube.io_tests.yaml b/config/crd/bases/tests.testkube.io_tests.yaml index 0915b42c..2cb69c27 100644 --- a/config/crd/bases/tests.testkube.io_tests.yaml +++ b/config/crd/bases/tests.testkube.io_tests.yaml @@ -451,27 +451,32 @@ spec: items: type: string type: array + argsMode: + description: usage mode for arguments + enum: + - append + - override + type: string artifactRequest: - description: artifact request body for container executors with - test artifacts + description: artifact request body with test artifacts properties: dirs: - description: artifact directories + description: artifact directories for scraping items: type: string type: array storageClassName: - description: artifact storage class name + description: artifact storage class name for container executor type: string volumeMountPath: - description: artifact volume mount path + description: artifact volume mount path for container executor type: string required: - storageClassName - volumeMountPath type: object command: - description: container executor binary command + description: executor binary command items: type: string type: array From 42249450d65a8996c76081b7a5baa098a93c12c7 Mon Sep 17 00:00:00 2001 From: Lilla Vass Date: Thu, 4 May 2023 16:50:01 +0200 Subject: [PATCH 03/57] fix: upload variables file (#135) --- apis/tests/v3/test_types.go | 2 +- config/crd/bases/tests.testkube.io_tests.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apis/tests/v3/test_types.go b/apis/tests/v3/test_types.go index 0b51d51c..45a6a09b 100644 --- a/apis/tests/v3/test_types.go +++ b/apis/tests/v3/test_types.go @@ -158,7 +158,7 @@ type ExecutionRequest struct { Namespace string `json:"namespace,omitempty"` // variables file content - need to be in format for particular executor (e.g. postman envs file) VariablesFile string `json:"variablesFile,omitempty"` - IsVariablesFileArchived bool `json:"isVariablesFileArchived,omitempty"` + IsVariablesFileUploaded bool `json:"isVariablesFileUploaded,omitempty"` Variables map[string]Variable `json:"variables,omitempty"` // test secret uuid TestSecretUUID string `json:"testSecretUUID,omitempty"` diff --git a/config/crd/bases/tests.testkube.io_tests.yaml b/config/crd/bases/tests.testkube.io_tests.yaml index 2cb69c27..f2684bb9 100644 --- a/config/crd/bases/tests.testkube.io_tests.yaml +++ b/config/crd/bases/tests.testkube.io_tests.yaml @@ -571,7 +571,7 @@ spec: type: string type: object type: array - isVariablesFileArchived: + isVariablesFileUploaded: type: boolean jobTemplate: description: job template extensions From 3306a20db097cc9884434004b3f621d8ca2ebb55 Mon Sep 17 00:00:00 2001 From: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Date: Fri, 5 May 2023 11:58:58 +0300 Subject: [PATCH 04/57] add tests for develop branch (#136) --- .github/workflows/go.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index e11b74a1..378193dd 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -2,9 +2,9 @@ name: Go on: push: - branches: [ main ] + branches: [ main, develop ] pull_request: - branches: [ main ] + branches: [ main, develop ] jobs: From 861c0ac69208ba8b0e79c473c60cade2dec08809 Mon Sep 17 00:00:00 2001 From: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Date: Mon, 8 May 2023 19:42:25 +0300 Subject: [PATCH 05/57] add check fir release branch (#137) --- .github/workflows/docker-build-tag.yaml | 34 +++++++++++++++++-------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/.github/workflows/docker-build-tag.yaml b/.github/workflows/docker-build-tag.yaml index 235aa33b..301ffeb0 100644 --- a/.github/workflows/docker-build-tag.yaml +++ b/.github/workflows/docker-build-tag.yaml @@ -58,24 +58,38 @@ jobs: run: | # Setting up Git: - git clone https://kubeshop-bot:$GH_PUSH_TOKEN@github.com/kubeshop/helm-charts cd ./helm-charts git config user.name "kubeshop-bot" git config user.email "kubeshop-bot@kubeshop.io" - git fetch origin "release-$RELEASE_VERSION" - git checkout "release-$RELEASE_VERSION" - - # Calling chart releaser script by passing needed folder name: - # E.G. in order to relase api-server": - # -->> ./chart_releaser.sh --helm-chart-folder api-server - export GH_PUSH_TOKEN export RELEASE_VERSION - cd ./scripts - ./chart_releaser.sh --helm-chart-folder testkube-operator --main-chart false + # Check if release branch exists + REPO_OWNER=kubeshop + REPO_NAME=helm-charts + RELEASE_BRANCH_NAME=release-$RELEASE_VERSION + echo $RELEASE_VERSION + STATUS=$(curl -s -o /dev/null -w '%{http_code}' -H "${AUTH_HEADER}" "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/branches/${RELEASE_BRANCH_NAME}") + + if [ "${STATUS}" -eq 404 ]; then + git fetch origin main + git checkout main + cd ./scripts + ./chart_releaser.sh --helm-chart-folder testkube-operator + else + git fetch origin "release-$RELEASE_VERSION" + git checkout "release-$RELEASE_VERSION" + echo "Switched to release branch" + cd ./scripts + ./chart_releaser.sh --helm-chart-folder testkube-operator --branch true + + git checkout main + git merge "release-$RELEASE_VERSION" + git push --set-upstream https://kubeshop-bot:$GH_PUSH_TOKEN@github.com/kubeshop/helm-charts main + git push origin -d "release-$RELEASE_VERSION" + fi env: GH_PUSH_TOKEN: ${{ secrets.CI_BOT_TOKEN }} From ffa9d741ebffb752e9695b9043fde1198d801da2 Mon Sep 17 00:00:00 2001 From: ypoplavs Date: Wed, 10 May 2023 09:40:32 +0300 Subject: [PATCH 06/57] comment out the automatic merge of release branch for now --- .github/workflows/docker-build-tag.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker-build-tag.yaml b/.github/workflows/docker-build-tag.yaml index 301ffeb0..74ab92c1 100644 --- a/.github/workflows/docker-build-tag.yaml +++ b/.github/workflows/docker-build-tag.yaml @@ -85,10 +85,10 @@ jobs: cd ./scripts ./chart_releaser.sh --helm-chart-folder testkube-operator --branch true - git checkout main - git merge "release-$RELEASE_VERSION" - git push --set-upstream https://kubeshop-bot:$GH_PUSH_TOKEN@github.com/kubeshop/helm-charts main - git push origin -d "release-$RELEASE_VERSION" +# git checkout main +# git merge "release-$RELEASE_VERSION" +# git push --set-upstream https://kubeshop-bot:$GH_PUSH_TOKEN@github.com/kubeshop/helm-charts main +# git push origin -d "release-$RELEASE_VERSION" fi env: From 8f9bb9d97ad14bf05a66d754a0bf630ae30822ce Mon Sep 17 00:00:00 2001 From: ypoplavs Date: Wed, 10 May 2023 12:18:45 +0300 Subject: [PATCH 07/57] fix release branch naming --- .github/workflows/docker-build-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-build-release.yaml b/.github/workflows/docker-build-release.yaml index b0b0a2e2..15cd461d 100644 --- a/.github/workflows/docker-build-release.yaml +++ b/.github/workflows/docker-build-release.yaml @@ -2,7 +2,7 @@ name: Release build on: push: branches: - - release_** + - release-** jobs: docker: From bbb6fc0aa97f5b7c7fb36708ca936f0129a3dfb5 Mon Sep 17 00:00:00 2001 From: ypoplavs Date: Wed, 10 May 2023 14:46:20 +0300 Subject: [PATCH 08/57] fix typo --- .github/workflows/docker-build-tag.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/docker-build-tag.yaml b/.github/workflows/docker-build-tag.yaml index 74ab92c1..84c0a271 100644 --- a/.github/workflows/docker-build-tag.yaml +++ b/.github/workflows/docker-build-tag.yaml @@ -85,10 +85,6 @@ jobs: cd ./scripts ./chart_releaser.sh --helm-chart-folder testkube-operator --branch true -# git checkout main -# git merge "release-$RELEASE_VERSION" -# git push --set-upstream https://kubeshop-bot:$GH_PUSH_TOKEN@github.com/kubeshop/helm-charts main -# git push origin -d "release-$RELEASE_VERSION" fi env: From 0222b15063d9ddd0ab59420abe452121a5c6b361 Mon Sep 17 00:00:00 2001 From: ypoplavs Date: Tue, 16 May 2023 19:26:11 +0300 Subject: [PATCH 09/57] fix path for goreleaser file --- .github/workflows/docker-build-tag.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-build-tag.yaml b/.github/workflows/docker-build-tag.yaml index 84c0a271..526ea1c0 100644 --- a/.github/workflows/docker-build-tag.yaml +++ b/.github/workflows/docker-build-tag.yaml @@ -41,7 +41,7 @@ jobs: with: distribution: goreleaser version: latest - args: release -f .goreleaser.yml + args: release -f goreleaser/.goreleaser.yml env: GITHUB_TOKEN: ${{ secrets.CI_BOT_TOKEN }} DOCKER_BUILDX_BUILDER: "${{ steps.buildx.outputs.name }}" From 2f1e170ffced667f149e714ea2bb4167da7b9741 Mon Sep 17 00:00:00 2001 From: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Date: Tue, 16 May 2023 19:51:14 +0300 Subject: [PATCH 10/57] rename release branch (#142) --- .github/workflows/docker-build-release.yaml | 18 +++++++++++------- .github/workflows/docker-build-tag.yaml | 16 ++++++++-------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/.github/workflows/docker-build-release.yaml b/.github/workflows/docker-build-release.yaml index 15cd461d..ab0278a2 100644 --- a/.github/workflows/docker-build-release.yaml +++ b/.github/workflows/docker-build-release.yaml @@ -2,7 +2,7 @@ name: Release build on: push: branches: - - release-** + - release/** jobs: docker: @@ -60,20 +60,24 @@ jobs: # Set up variables for repository and branch name REPO_OWNER=kubeshop REPO_NAME=helm-charts - BRANCH_NAME=${GITHUB_REF} + OLD_BRANCH_NAME=${GITHUB_REF} + RELEASE_TAG=$(basename "${OLD_BRANCH_NAME}") + + # Set up the new branch name + NEW_BRANCH_NAME="refs/heads/release/operator/${RELEASE_TAG}" # Set up authentication using a personal access token AUTH_HEADER="Authorization: Bearer ${{ secrets.CI_BOT_TOKEN }}" # Check if branch already exists - STATUS=$(curl -s -o /dev/null -w '%{http_code}' -H "${AUTH_HEADER}" "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/branches/${BRANCH_NAME}") + STATUS=$(curl -s -o /dev/null -w '%{http_code}' -H "${AUTH_HEADER}" "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/branches/${NEW_BRANCH_NAME}") # If branch doesn't exist, create it if [ "${STATUS}" -eq 404 ]; then - curl -X POST -H "${AUTH_HEADER}" -d '{"ref": "'"${BRANCH_NAME}"'","sha": "'"$(curl -s -H "${AUTH_HEADER}" "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/git/refs/heads/main" | jq -r '.object.sha')"'"}' "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/git/refs" - echo "Created branch ${BRANCH_NAME} in ${REPO_OWNER}/${REPO_NAME}" + curl -X POST -H "${AUTH_HEADER}" -d '{"ref": "'"${NEW_BRANCH_NAME}"'","sha": "'"$(curl -s -H "${AUTH_HEADER}" "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/git/refs/heads/main" | jq -r '.object.sha')"'"}' "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/git/refs" + echo "Created branch ${NEW_BRANCH_NAME} in ${REPO_OWNER}/${REPO_NAME}" else - echo "Branch ${BRANCH_NAME} already exists in ${REPO_OWNER}/${REPO_NAME}" + echo "Branch ${NEW_BRANCH_NAME} already exists in ${REPO_OWNER}/${REPO_NAME}" fi - name: Repository Dispatch @@ -82,4 +86,4 @@ jobs: token: ${{ secrets.CI_BOT_TOKEN }} repository: kubeshop/helm-charts event-type: trigger-workflow-operator-release - client-payload: '{"image_tag_operator": "${{ steps.github_sha.outputs.sha_short }}"}' + client-payload: '{"image_tag_operator": "${{ steps.github_sha.outputs.sha_short }}"}' \ No newline at end of file diff --git a/.github/workflows/docker-build-tag.yaml b/.github/workflows/docker-build-tag.yaml index 526ea1c0..159c9285 100644 --- a/.github/workflows/docker-build-tag.yaml +++ b/.github/workflows/docker-build-tag.yaml @@ -66,10 +66,10 @@ jobs: export GH_PUSH_TOKEN export RELEASE_VERSION - # Check if release branch exists + # Check if release branch exists in helm-charts repository REPO_OWNER=kubeshop REPO_NAME=helm-charts - RELEASE_BRANCH_NAME=release-$RELEASE_VERSION + RELEASE_BRANCH_NAME=release/$SERVICE/$RELEASE_VERSION echo $RELEASE_VERSION STATUS=$(curl -s -o /dev/null -w '%{http_code}' -H "${AUTH_HEADER}" "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/branches/${RELEASE_BRANCH_NAME}") @@ -77,16 +77,16 @@ jobs: git fetch origin main git checkout main cd ./scripts - ./chart_releaser.sh --helm-chart-folder testkube-operator + ./chart_releaser.sh --helm-chart-folder testkube-$SERVICE else - git fetch origin "release-$RELEASE_VERSION" - git checkout "release-$RELEASE_VERSION" + git fetch origin "release/$SERVICE/$RELEASE_VERSION" + git checkout "release/$SERVICE/$RELEASE_VERSION" echo "Switched to release branch" cd ./scripts - ./chart_releaser.sh --helm-chart-folder testkube-operator --branch true - + ./chart_releaser.sh --helm-chart-folder testkube-$SERVICE --branch true fi env: + SERVICE: operator GH_PUSH_TOKEN: ${{ secrets.CI_BOT_TOKEN }} - RELEASE_VERSION: ${{ steps.tag.outputs.tag }} + RELEASE_VERSION: ${{ steps.tag.outputs.tag }} \ No newline at end of file From 355e4bf7513ebd9c9d57cb403b53bcde0ecd3e82 Mon Sep 17 00:00:00 2001 From: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Date: Thu, 25 May 2023 11:52:38 +0300 Subject: [PATCH 11/57] ci: parametrize alpine (#144) * parametrize alpine image --- .github/workflows/docker-build-beta-tag.yaml | 4 ++++ .github/workflows/docker-build-develop.yaml | 5 +++++ .github/workflows/docker-build-release.yaml | 4 ++++ .github/workflows/docker-build-tag.yaml | 4 ++++ Dockerfile | 4 +++- goreleaser/.goreleaser-snapshot.yaml | 2 +- goreleaser/.goreleaser.yml | 1 + 7 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-build-beta-tag.yaml b/.github/workflows/docker-build-beta-tag.yaml index ad222293..be74c693 100644 --- a/.github/workflows/docker-build-beta-tag.yaml +++ b/.github/workflows/docker-build-beta-tag.yaml @@ -4,6 +4,9 @@ on: tags: - "v[0-9]+.[0-9]+.[0-9]+-*" +env: + ALPINE_IMAGE: alpine:3.18.0 + jobs: docker: runs-on: ubuntu-latest @@ -47,6 +50,7 @@ jobs: DOCKER_BUILDX_BUILDER: "${{ steps.buildx.outputs.name }}" DOCKER_BUILDX_CACHE_FROM: "type=gha" DOCKER_BUILDX_CACHE_TO: "type=gha,mode=max" + ALPINE_IMAGE: ${{ env.ALPINE_IMAGE }} - name: Get tag id: tag diff --git a/.github/workflows/docker-build-develop.yaml b/.github/workflows/docker-build-develop.yaml index a22e63ff..c5d440b6 100644 --- a/.github/workflows/docker-build-develop.yaml +++ b/.github/workflows/docker-build-develop.yaml @@ -3,6 +3,10 @@ on: push: branches: - develop + - ci/parametrize-alpine + +env: + ALPINE_IMAGE: alpine:3.18.0 jobs: docker: @@ -49,6 +53,7 @@ jobs: DOCKER_BUILDX_BUILDER: "${{ steps.buildx.outputs.name }}" DOCKER_BUILDX_CACHE_FROM: "type=gha" DOCKER_BUILDX_CACHE_TO: "type=gha,mode=max" + ALPINE_IMAGE: ${{ env.ALPINE_IMAGE }} - name: Push Docker images run: | diff --git a/.github/workflows/docker-build-release.yaml b/.github/workflows/docker-build-release.yaml index ab0278a2..cb7506f5 100644 --- a/.github/workflows/docker-build-release.yaml +++ b/.github/workflows/docker-build-release.yaml @@ -4,6 +4,9 @@ on: branches: - release/** +env: + ALPINE_IMAGE: alpine:3.18.0 + jobs: docker: runs-on: ubuntu-latest @@ -49,6 +52,7 @@ jobs: DOCKER_BUILDX_BUILDER: "${{ steps.buildx.outputs.name }}" DOCKER_BUILDX_CACHE_FROM: "type=gha" DOCKER_BUILDX_CACHE_TO: "type=gha,mode=max" + ALPINE_IMAGE: ${{ env.ALPINE_IMAGE }} - name: Push Docker images run: | diff --git a/.github/workflows/docker-build-tag.yaml b/.github/workflows/docker-build-tag.yaml index 159c9285..ccea453c 100644 --- a/.github/workflows/docker-build-tag.yaml +++ b/.github/workflows/docker-build-tag.yaml @@ -4,6 +4,9 @@ on: tags: - "v[0-9]+.[0-9]+.[0-9]+" +env: + ALPINE_IMAGE: alpine:3.18.0 + jobs: docker: runs-on: ubuntu-latest @@ -47,6 +50,7 @@ jobs: DOCKER_BUILDX_BUILDER: "${{ steps.buildx.outputs.name }}" DOCKER_BUILDX_CACHE_FROM: "type=gha" DOCKER_BUILDX_CACHE_TO: "type=gha,mode=max" + ALPINE_IMAGE: ${{ env.ALPINE_IMAGE }} - name: Get tag id: tag diff --git a/Dockerfile b/Dockerfile index ffded64b..aa17b0fb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,5 @@ -FROM alpine +ARG ALPINE_IMAGE +FROM ${ALPINE_IMAGE} + COPY testkube-operator /manager ENTRYPOINT ["/manager"] diff --git a/goreleaser/.goreleaser-snapshot.yaml b/goreleaser/.goreleaser-snapshot.yaml index 38fe2c02..a3a8e618 100644 --- a/goreleaser/.goreleaser-snapshot.yaml +++ b/goreleaser/.goreleaser-snapshot.yaml @@ -25,7 +25,6 @@ dockers: goos: linux goarch: amd64 image_templates: - - "kubeshop/testkube-operator:{{ .Branch }}" - "kubeshop/testkube-operator:{{ .ShortCommit }}" build_flag_templates: - "--platform=linux/amd64" @@ -35,6 +34,7 @@ dockers: - "--builder={{ .Env.DOCKER_BUILDX_BUILDER }}" - "--cache-to={{ .Env.DOCKER_BUILDX_CACHE_TO }}" - "--cache-from={{ .Env.DOCKER_BUILDX_CACHE_FROM }}" + - "--build-arg=ALPINE_IMAGE={{ .Env.ALPINE_IMAGE }}" release: disable: true diff --git a/goreleaser/.goreleaser.yml b/goreleaser/.goreleaser.yml index 514681e2..8ef9dad9 100644 --- a/goreleaser/.goreleaser.yml +++ b/goreleaser/.goreleaser.yml @@ -38,6 +38,7 @@ dockers: - "--builder={{ .Env.DOCKER_BUILDX_BUILDER }}" - "--cache-to={{ .Env.DOCKER_BUILDX_CACHE_TO }}" - "--cache-from={{ .Env.DOCKER_BUILDX_CACHE_FROM }}" + - "--build-arg=ALPINE_IMAGE={{ .Env.ALPINE_IMAGE }}" - dockerfile: Dockerfile use: buildx From b8c83006d32367e7e90cfec5641fa151e4042560 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 25 May 2023 12:24:54 +0300 Subject: [PATCH 12/57] fix: ttl for trigger condition (#143) --- apis/testtriggers/v1/testtrigger_types.go | 2 ++ config/crd/bases/tests.testkube.io_testtriggers.yaml | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/apis/testtriggers/v1/testtrigger_types.go b/apis/testtriggers/v1/testtrigger_types.go index b794a3c8..1ad9301b 100644 --- a/apis/testtriggers/v1/testtrigger_types.go +++ b/apis/testtriggers/v1/testtrigger_types.go @@ -145,6 +145,8 @@ type TestTriggerCondition struct { Type_ string `json:"type"` // test trigger condition reason Reason string `json:"reason,omitempty"` + // duration in seconds in the past from current time when the condition is still valid + Ttl int32 `json:"ttl,omitempty"` } // TestTriggerConditionSpec defines the condition specification for TestTrigger diff --git a/config/crd/bases/tests.testkube.io_testtriggers.yaml b/config/crd/bases/tests.testkube.io_testtriggers.yaml index 26ffb39e..d336a351 100644 --- a/config/crd/bases/tests.testkube.io_testtriggers.yaml +++ b/config/crd/bases/tests.testkube.io_testtriggers.yaml @@ -74,6 +74,11 @@ spec: - "False" - Unknown type: string + ttl: + description: duration in seconds in the past from current + time when the condition is still valid + format: int32 + type: integer type: description: test trigger condition type: string From 4168152133d795000509d4eb3ee059c6a9297cdc Mon Sep 17 00:00:00 2001 From: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Date: Thu, 25 May 2023 18:47:04 +0300 Subject: [PATCH 13/57] ci: rename gh token var (#145) * rename gh token var --- .github/workflows/docker-build-tag.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker-build-tag.yaml b/.github/workflows/docker-build-tag.yaml index ccea453c..e593b26c 100644 --- a/.github/workflows/docker-build-tag.yaml +++ b/.github/workflows/docker-build-tag.yaml @@ -62,13 +62,14 @@ jobs: run: | # Setting up Git: - git clone https://kubeshop-bot:$GH_PUSH_TOKEN@github.com/kubeshop/helm-charts + git clone https://kubeshop-bot:$GH_TOKEN@github.com/kubeshop/helm-charts cd ./helm-charts git config user.name "kubeshop-bot" git config user.email "kubeshop-bot@kubeshop.io" - export GH_PUSH_TOKEN + export GH_TOKEN export RELEASE_VERSION + export SERVICE # Check if release branch exists in helm-charts repository REPO_OWNER=kubeshop @@ -92,5 +93,5 @@ jobs: env: SERVICE: operator - GH_PUSH_TOKEN: ${{ secrets.CI_BOT_TOKEN }} + GH_TOKEN: ${{ secrets.CI_BOT_TOKEN }} RELEASE_VERSION: ${{ steps.tag.outputs.tag }} \ No newline at end of file From 508744006c30b66738b24b7a67ed8c3ba97e2bad Mon Sep 17 00:00:00 2001 From: ypoplavs Date: Fri, 26 May 2023 14:02:32 +0300 Subject: [PATCH 14/57] fix: add missing var for alpine image for arm64 arch --- goreleaser/.goreleaser.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/goreleaser/.goreleaser.yml b/goreleaser/.goreleaser.yml index 8ef9dad9..aac8375e 100644 --- a/goreleaser/.goreleaser.yml +++ b/goreleaser/.goreleaser.yml @@ -57,6 +57,7 @@ dockers: - "--builder={{ .Env.DOCKER_BUILDX_BUILDER }}" - "--cache-to={{ .Env.DOCKER_BUILDX_CACHE_TO }}" - "--cache-from={{ .Env.DOCKER_BUILDX_CACHE_FROM }}" + - "--build-arg=ALPINE_IMAGE={{ .Env.ALPINE_IMAGE }}" docker_manifests: - name_template: kubeshop/testkube-operator:{{ .ShortCommit }} From 1e9a3cffe0463dc9a2712ce822034e1ebf69f7af Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Fri, 26 May 2023 14:20:32 +0300 Subject: [PATCH 15/57] fix: remove empty username and token (#147) --- client/tests/v3/test.go | 14 ++++++++++++-- client/testsources/v1/testsources.go | 10 ++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/client/tests/v3/test.go b/client/tests/v3/test.go index b835861c..fa9c2548 100644 --- a/client/tests/v3/test.go +++ b/client/tests/v3/test.go @@ -556,6 +556,11 @@ func updateTestSecrets(test *testsv3.Test, secretName string, secrets map[string Key: gitUsernameSecretName, } } + } else { + if test.Spec.Content != nil && test.Spec.Content.Repository != nil && test.Spec.Content.Repository.UsernameSecret != nil && + test.Spec.Content.Repository.UsernameSecret.Name == secretName { + test.Spec.Content.Repository.UsernameSecret = nil + } } if _, ok := secrets[gitTokenSecretName]; ok { @@ -565,16 +570,21 @@ func updateTestSecrets(test *testsv3.Test, secretName string, secrets map[string Key: gitTokenSecretName, } } + } else { + if test.Spec.Content != nil && test.Spec.Content.Repository != nil && test.Spec.Content.Repository.TokenSecret != nil && + test.Spec.Content.Repository.TokenSecret.Name == secretName { + test.Spec.Content.Repository.TokenSecret = nil + } } } func clearTestSecrets(test *testsv3.Test, secretName string) { - if test.Spec.Content != nil && test.Spec.Content.Repository != nil && test.Spec.Content.Repository.UsernameSecret == nil && + if test.Spec.Content != nil && test.Spec.Content.Repository != nil && test.Spec.Content.Repository.UsernameSecret != nil && test.Spec.Content.Repository.UsernameSecret.Name == secretName { test.Spec.Content.Repository.UsernameSecret = nil } - if test.Spec.Content != nil && test.Spec.Content.Repository != nil && test.Spec.Content.Repository.TokenSecret == nil && + if test.Spec.Content != nil && test.Spec.Content.Repository != nil && test.Spec.Content.Repository.TokenSecret != nil && test.Spec.Content.Repository.TokenSecret.Name == secretName { test.Spec.Content.Repository.TokenSecret = nil } diff --git a/client/testsources/v1/testsources.go b/client/testsources/v1/testsources.go index 930475b7..0e48c194 100644 --- a/client/testsources/v1/testsources.go +++ b/client/testsources/v1/testsources.go @@ -181,6 +181,11 @@ func updateTestSourceSecrets(testSource *testsourcev1.TestSource, secretName str Key: gitUsernameSecretName, } } + } else { + if testSource.Spec.Repository != nil && testSource.Spec.Repository.UsernameSecret != nil && + testSource.Spec.Repository.UsernameSecret.Name == secretName { + testSource.Spec.Repository.UsernameSecret = nil + } } if _, ok := secrets[gitTokenSecretName]; ok { @@ -190,6 +195,11 @@ func updateTestSourceSecrets(testSource *testsourcev1.TestSource, secretName str Key: gitTokenSecretName, } } + } else { + if testSource.Spec.Repository != nil && testSource.Spec.Repository.TokenSecret != nil && + testSource.Spec.Repository.TokenSecret.Name == secretName { + testSource.Spec.Repository.TokenSecret = nil + } } } From e3870b07c9b8fed56d63ec4209a8c5a8585bd889 Mon Sep 17 00:00:00 2001 From: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Date: Fri, 26 May 2023 14:26:20 +0300 Subject: [PATCH 16/57] ci: add docker registry description (#146) * ci: add GH action to update readme for Docker registry --- .github/workflows/docker-build-develop.yaml | 1 - .github/workflows/docker-build-tag.yaml | 11 +++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker-build-develop.yaml b/.github/workflows/docker-build-develop.yaml index c5d440b6..5be850d4 100644 --- a/.github/workflows/docker-build-develop.yaml +++ b/.github/workflows/docker-build-develop.yaml @@ -3,7 +3,6 @@ on: push: branches: - develop - - ci/parametrize-alpine env: ALPINE_IMAGE: alpine:3.18.0 diff --git a/.github/workflows/docker-build-tag.yaml b/.github/workflows/docker-build-tag.yaml index e593b26c..48910458 100644 --- a/.github/workflows/docker-build-tag.yaml +++ b/.github/workflows/docker-build-tag.yaml @@ -39,6 +39,17 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Push README to Dockerhub + uses: christian-korneck/update-container-description-action@v1 + env: + DOCKER_USER: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKER_PASS: ${{ secrets.DOCKERHUB_TOKEN }} + with: + destination_container_repo: ${{ github.repository }} + provider: dockerhub + short_description: 'Testkube Kubernetes Operator' + readme_file: './README.md' + - name: Release uses: goreleaser/goreleaser-action@v4 with: From 86b5aba21946b39c3034ad8680b630ca3d7ce48d Mon Sep 17 00:00:00 2001 From: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Date: Wed, 31 May 2023 09:32:04 +0300 Subject: [PATCH 17/57] ci: add workflow dispatch (#149) --- .github/workflows/docker-build-release.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/docker-build-release.yaml b/.github/workflows/docker-build-release.yaml index cb7506f5..d220c4ee 100644 --- a/.github/workflows/docker-build-release.yaml +++ b/.github/workflows/docker-build-release.yaml @@ -1,5 +1,6 @@ name: Release build on: + workflow_dispatch: push: branches: - release/** From eed35fe7656d8b5bfc9eb7e2030161eaaf6a238f Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Fri, 2 Jun 2023 13:28:31 +0300 Subject: [PATCH 18/57] fix: support external secrets for tests (#148) * fix: support external secrets for tests * fix: support external secrets for test suite * fix: rename interface method * fix: test mock --- client/tests/v3/test.go | 19 ++++---- client/testsuites/v2/mock_testsuites.go | 12 ++--- client/testsuites/v2/testsuites.go | 63 ++++++++++++++++--------- 3 files changed, 59 insertions(+), 35 deletions(-) diff --git a/client/tests/v3/test.go b/client/tests/v3/test.go index fa9c2548..df530116 100644 --- a/client/tests/v3/test.go +++ b/client/tests/v3/test.go @@ -224,8 +224,10 @@ func (s TestsClient) Delete(name string) error { } // delete secret only if exists ignore otherwise - if secretExists && secretObj != nil { - return s.k8sClient.Delete(context.Background(), secretObj) + if err == nil && secretObj != nil { + if err = s.k8sClient.Delete(context.Background(), secretObj); err != nil { + return err + } } secretName := secret.GetMetadataName(test.Name, secretKind) @@ -300,7 +302,7 @@ func (s TestsClient) UpdateTestSecrets(test *testsv3.Test) error { return err } - if secret == nil { + if err == nil && secret == nil { return nil } @@ -340,7 +342,8 @@ func (s TestsClient) TestHasSecrets(test *testsv3.Test) (has bool) { } for _, v := range test.Spec.ExecutionRequest.Variables { - if v.Type_ == commonv1.VariableTypeSecret { + if v.Type_ == commonv1.VariableTypeSecret && + (v.ValueFrom.SecretKeyRef != nil && (v.ValueFrom.SecretKeyRef.Name == secretName(test.Name))) { return true } } @@ -430,10 +433,6 @@ func testVarsToSecret(test *testsv3.Test, secret *corev1.Secret) error { for k := range test.Spec.ExecutionRequest.Variables { v := test.Spec.ExecutionRequest.Variables[k] if v.Type_ == commonv1.VariableTypeSecret { - secret.StringData[v.Name] = v.Value - secretMap[v.Name] = v.Value - // clear passed test variable secret value and save as reference o secret - v.Value = "" if v.ValueFrom.SecretKeyRef != nil { v.ValueFrom = corev1.EnvVarSource{ SecretKeyRef: &corev1.SecretKeySelector{ @@ -444,6 +443,10 @@ func testVarsToSecret(test *testsv3.Test, secret *corev1.Secret) error { }, } } else { + secret.StringData[v.Name] = v.Value + secretMap[v.Name] = v.Value + // clear passed test variable secret value and save as reference o secret + v.Value = "" v.ValueFrom = corev1.EnvVarSource{ SecretKeyRef: &corev1.SecretKeySelector{ Key: v.Name, diff --git a/client/testsuites/v2/mock_testsuites.go b/client/testsuites/v2/mock_testsuites.go index 93289a6d..f249ab5c 100644 --- a/client/testsuites/v2/mock_testsuites.go +++ b/client/testsuites/v2/mock_testsuites.go @@ -181,19 +181,19 @@ func (mr *MockInterfaceMockRecorder) ListLabels() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListLabels", reflect.TypeOf((*MockInterface)(nil).ListLabels)) } -// LoadTestVariablesSecret mocks base method. -func (m *MockInterface) LoadTestVariablesSecret(arg0 *v2.TestSuite) (*v1.Secret, error) { +// LoadTestsuiteVariablesSecret mocks base method. +func (m *MockInterface) LoadTestsuiteVariablesSecret(arg0 *v2.TestSuite) (*v1.Secret, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LoadTestVariablesSecret", arg0) + ret := m.ctrl.Call(m, "LoadTestsuiteVariablesSecret", arg0) ret0, _ := ret[0].(*v1.Secret) ret1, _ := ret[1].(error) return ret0, ret1 } -// LoadTestVariablesSecret indicates an expected call of LoadTestVariablesSecret. -func (mr *MockInterfaceMockRecorder) LoadTestVariablesSecret(arg0 interface{}) *gomock.Call { +// LoadTestsuiteVariablesSecret indicates an expected call of LoadTestsuiteVariablesSecret. +func (mr *MockInterfaceMockRecorder) LoadTestsuiteVariablesSecret(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadTestVariablesSecret", reflect.TypeOf((*MockInterface)(nil).LoadTestVariablesSecret), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadTestsuiteVariablesSecret", reflect.TypeOf((*MockInterface)(nil).LoadTestsuiteVariablesSecret), arg0) } // Update mocks base method. diff --git a/client/testsuites/v2/testsuites.go b/client/testsuites/v2/testsuites.go index 2afef09d..75c0f394 100644 --- a/client/testsuites/v2/testsuites.go +++ b/client/testsuites/v2/testsuites.go @@ -38,7 +38,7 @@ type Interface interface { DeleteAll() error CreateTestsuiteSecrets(testsuite *testsuitev2.TestSuite) error UpdateTestsuiteSecrets(testsuite *testsuitev2.TestSuite) error - LoadTestVariablesSecret(testsuite *testsuitev2.TestSuite) (*corev1.Secret, error) + LoadTestsuiteVariablesSecret(testsuite *testsuitev2.TestSuite) (*corev1.Secret, error) GetCurrentSecretUUID(testSuiteName string) (string, error) GetSecretTestSuiteVars(testSuiteName, secretUUID string) (map[string]string, error) DeleteByLabels(selector string) error @@ -77,13 +77,13 @@ func (s TestSuitesClient) List(selector string) (*testsuitev2.TestSuiteList, err } for i := range list.Items { - secret, err := s.LoadTestVariablesSecret(&list.Items[i]) + secret, err := s.LoadTestsuiteVariablesSecret(&list.Items[i]) secretExists := !errors.IsNotFound(err) if err != nil && secretExists { return list, err } - secretToTestVars(secret, &list.Items[i]) + secretToTestsuiteVars(secret, &list.Items[i]) } return list, nil @@ -98,8 +98,8 @@ func (s TestSuitesClient) ListLabels() (map[string][]string, error) { return labels, err } - for _, test := range list.Items { - for key, value := range test.Labels { + for _, testsuite := range list.Items { + for key, value := range testsuite.Labels { if values, ok := labels[key]; !ok { labels[key] = []string{value} } else { @@ -124,13 +124,13 @@ func (s TestSuitesClient) Get(name string) (*testsuitev2.TestSuite, error) { return nil, err } - secret, err := s.LoadTestVariablesSecret(testsuite) + secret, err := s.LoadTestsuiteVariablesSecret(testsuite) secretExists := !errors.IsNotFound(err) if err != nil && secretExists { return nil, err } - secretToTestVars(secret, testsuite) + secretToTestsuiteVars(secret, testsuite) return testsuite, nil } @@ -164,20 +164,23 @@ func (s TestSuitesClient) Delete(name string) error { return err } - secret, err := s.LoadTestVariablesSecret(testsuite) + secret, err := s.LoadTestsuiteVariablesSecret(testsuite) secretExists := !errors.IsNotFound(err) if err != nil && secretExists { return err } + if err == nil && secret != nil { + if err = s.Client.Delete(context.Background(), secret); err != nil { + return err + } + } + err = s.Client.Delete(context.Background(), testsuite) if err != nil { return err } - if secretExists && secret != nil { - return s.Client.Delete(context.Background(), secret) - } return nil } @@ -226,13 +229,13 @@ func (s TestSuitesClient) CreateTestsuiteSecrets(testsuite *testsuitev2.TestSuit } func (s TestSuitesClient) UpdateTestsuiteSecrets(testsuite *testsuitev2.TestSuite) error { - secret, err := s.LoadTestVariablesSecret(testsuite) + secret, err := s.LoadTestsuiteVariablesSecret(testsuite) secretExists := !errors.IsNotFound(err) if err != nil && secretExists { return err } - if secret == nil { + if err == nil && secret == nil { return nil } @@ -262,7 +265,25 @@ func (s TestSuitesClient) UpdateTestsuiteSecrets(testsuite *testsuitev2.TestSuit return nil } -func (s TestSuitesClient) LoadTestVariablesSecret(testsuite *testsuitev2.TestSuite) (*corev1.Secret, error) { +func (s TestSuitesClient) TestsuiteHasSecrets(testsuite *testsuitev2.TestSuite) (has bool) { + if testsuite.Spec.ExecutionRequest == nil { + return + } + + for _, v := range testsuite.Spec.ExecutionRequest.Variables { + if v.Type_ == commonv1.VariableTypeSecret && + (v.ValueFrom.SecretKeyRef != nil && (v.ValueFrom.SecretKeyRef.Name == secretName(testsuite.Name))) { + return true + } + } + + return +} + +func (s TestSuitesClient) LoadTestsuiteVariablesSecret(testsuite *testsuitev2.TestSuite) (*corev1.Secret, error) { + if !s.TestsuiteHasSecrets(testsuite) { + return nil, nil + } secret := &corev1.Secret{} err := s.Client.Get(context.Background(), client.ObjectKey{Namespace: s.Namespace, Name: secretName(testsuite.Name)}, secret) return secret, err @@ -329,10 +350,6 @@ func testVarsToSecret(testsuite *testsuitev2.TestSuite, secret *corev1.Secret) e for k := range testsuite.Spec.ExecutionRequest.Variables { v := testsuite.Spec.ExecutionRequest.Variables[k] if v.Type_ == commonv1.VariableTypeSecret { - secret.StringData[v.Name] = v.Value - secretMap[v.Name] = v.Value - // clear passed test variable secret value and save as reference o secret - v.Value = "" if v.ValueFrom.SecretKeyRef != nil { v.ValueFrom = corev1.EnvVarSource{ SecretKeyRef: &corev1.SecretKeySelector{ @@ -343,6 +360,10 @@ func testVarsToSecret(testsuite *testsuitev2.TestSuite, secret *corev1.Secret) e }, } } else { + secret.StringData[v.Name] = v.Value + secretMap[v.Name] = v.Value + // clear passed test variable secret value and save as reference o secret + v.Value = "" v.ValueFrom = corev1.EnvVarSource{ SecretKeyRef: &corev1.SecretKeySelector{ Key: v.Name, @@ -375,9 +396,9 @@ func testVarsToSecret(testsuite *testsuitev2.TestSuite, secret *corev1.Secret) e return nil } -// secretToTestVars loads secrets data passed into TestSuite CRD and remove plain text data -func secretToTestVars(secret *corev1.Secret, testsuite *testsuitev2.TestSuite) { - if secret.Data == nil { +// secretToTestsuiteVars loads secrets data passed into TestSuite CRD and remove plain text data +func secretToTestsuiteVars(secret *corev1.Secret, testsuite *testsuitev2.TestSuite) { + if testsuite == nil || secret == nil || secret.Data == nil { return } From afea4265b6ea0a290a743209e9d6f6424bc54ae4 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Wed, 7 Jun 2023 17:20:25 +0300 Subject: [PATCH 19/57] feat: webhook templlate and headers (#152) * feat: webhook templlate and headers * fix: description typo --- apis/executor/v1/webhook_types.go | 4 ++++ apis/executor/v1/zz_generated.deepcopy.go | 8 +++++++- config/crd/bases/executor.testkube.io_webhooks.yaml | 8 ++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/apis/executor/v1/webhook_types.go b/apis/executor/v1/webhook_types.go index 569d6149..1f5bd29d 100644 --- a/apis/executor/v1/webhook_types.go +++ b/apis/executor/v1/webhook_types.go @@ -36,6 +36,10 @@ type WebhookSpec struct { Selector string `json:"selector,omitempty"` // will load the generated payload for notification inside the object PayloadObjectField string `json:"payloadObjectField,omitempty"` + // golang based template for notification payload + PayloadTemplate string `json:"payloadTemplate,omitempty"` + // webhook headers + Headers map[string]string `json:"headers,omitempty"` } // +kubebuilder:validation:Enum=start-test;end-test-success;end-test-failed;end-test-aborted;end-test-timeout;start-testsuite;end-testsuite-success;end-testsuite-failed;end-testsuite-aborted;end-testsuite-timeout diff --git a/apis/executor/v1/zz_generated.deepcopy.go b/apis/executor/v1/zz_generated.deepcopy.go index 6e3b6c81..b04aca4e 100644 --- a/apis/executor/v1/zz_generated.deepcopy.go +++ b/apis/executor/v1/zz_generated.deepcopy.go @@ -1,4 +1,3 @@ -//go:build !ignore_autogenerated // +build !ignore_autogenerated /* @@ -254,6 +253,13 @@ func (in *WebhookSpec) DeepCopyInto(out *WebhookSpec) { *out = make([]EventType, len(*in)) copy(*out, *in) } + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookSpec. diff --git a/config/crd/bases/executor.testkube.io_webhooks.yaml b/config/crd/bases/executor.testkube.io_webhooks.yaml index 4166b997..fe69e09e 100644 --- a/config/crd/bases/executor.testkube.io_webhooks.yaml +++ b/config/crd/bases/executor.testkube.io_webhooks.yaml @@ -52,10 +52,18 @@ spec: - end-testsuite-timeout type: string type: array + headers: + additionalProperties: + type: string + description: webhook headers + type: object payloadObjectField: description: will load the generated payload for notification inside the object type: string + payloadTemplate: + description: golang based template for notification payload + type: string selector: description: Labels to filter for tests and test suites type: string From 033b0486ee322c4c6194a4ffa478314914b917a8 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Fri, 9 Jun 2023 14:10:37 +0300 Subject: [PATCH 20/57] fix: secret check (#153) * fix: secret check * fix: remove wrong condition --- client/tests/v3/test.go | 4 ++-- client/testsuites/v2/testsuites.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/tests/v3/test.go b/client/tests/v3/test.go index df530116..5bd6dea8 100644 --- a/client/tests/v3/test.go +++ b/client/tests/v3/test.go @@ -342,8 +342,8 @@ func (s TestsClient) TestHasSecrets(test *testsv3.Test) (has bool) { } for _, v := range test.Spec.ExecutionRequest.Variables { - if v.Type_ == commonv1.VariableTypeSecret && - (v.ValueFrom.SecretKeyRef != nil && (v.ValueFrom.SecretKeyRef.Name == secretName(test.Name))) { + if v.Type_ == commonv1.VariableTypeSecret && (v.ValueFrom.SecretKeyRef == nil || + (v.ValueFrom.SecretKeyRef != nil && (v.ValueFrom.SecretKeyRef.Name == secretName(test.Name)))) { return true } } diff --git a/client/testsuites/v2/testsuites.go b/client/testsuites/v2/testsuites.go index 75c0f394..1741080c 100644 --- a/client/testsuites/v2/testsuites.go +++ b/client/testsuites/v2/testsuites.go @@ -250,7 +250,7 @@ func (s TestSuitesClient) UpdateTestsuiteSecrets(testsuite *testsuitev2.TestSuit return err } - if secretExists && len(secret.StringData) > 0 { + if len(secret.StringData) > 0 { if !secretExists { err = s.Client.Create(context.Background(), secret) } else { @@ -271,8 +271,8 @@ func (s TestSuitesClient) TestsuiteHasSecrets(testsuite *testsuitev2.TestSuite) } for _, v := range testsuite.Spec.ExecutionRequest.Variables { - if v.Type_ == commonv1.VariableTypeSecret && - (v.ValueFrom.SecretKeyRef != nil && (v.ValueFrom.SecretKeyRef.Name == secretName(testsuite.Name))) { + if v.Type_ == commonv1.VariableTypeSecret && (v.ValueFrom.SecretKeyRef == nil || + (v.ValueFrom.SecretKeyRef != nil && (v.ValueFrom.SecretKeyRef.Name == secretName(testsuite.Name)))) { return true } } From 48fd2fa202861c5b180a23364c7f5383ef81b407 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Tue, 13 Jun 2023 14:36:07 +0300 Subject: [PATCH 21/57] feat: provide known condition types (#155) * feat: provide known condition types * fix: rename util method --- pkg/validation/tests/v1/testtrigger/types.go | 8 ++++++++ pkg/validation/tests/v1/testtrigger/util.go | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/pkg/validation/tests/v1/testtrigger/types.go b/pkg/validation/tests/v1/testtrigger/types.go index ba501644..9ee96156 100644 --- a/pkg/validation/tests/v1/testtrigger/types.go +++ b/pkg/validation/tests/v1/testtrigger/types.go @@ -24,4 +24,12 @@ const ( CauseDeploymentImageUpdate Cause = "deployment-image-update" CauseDeploymentEnvUpdate Cause = "deployment-env-update" CauseDeploymentContainersModified Cause = "deployment-containers-modified" + ConditionAvailable = "Available" + ConditionProgressing = "Progressing" + ConditionReplicaFailure = "ReplicaFailure" + ConditionPodScheduled = "PodScheduled" + ConditionPodHasNetwork = "PodHasNetwork" + ConditionContainersReady = "ContainersReady" + ConditionInitialized = "Initialized" + ConditionReady = "Ready" ) diff --git a/pkg/validation/tests/v1/testtrigger/util.go b/pkg/validation/tests/v1/testtrigger/util.go index 9adc8846..f32a4d42 100644 --- a/pkg/validation/tests/v1/testtrigger/util.go +++ b/pkg/validation/tests/v1/testtrigger/util.go @@ -32,3 +32,8 @@ func GetSupportedConditionStatuses() []string { string(testtriggerv1.UNKNOWN_TestTriggerConditionStatuses), } } + +func GetSupportedConditions() []string { + return []string{ConditionAvailable, ConditionContainersReady, ConditionInitialized, ConditionPodHasNetwork, + ConditionPodScheduled, ConditionProgressing, ConditionReady, ConditionReplicaFailure} +} From 95faaa73d0127fec2d5a773afa85c6ed508216cc Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 15 Jun 2023 13:54:05 +0300 Subject: [PATCH 22/57] feat: parallel testsuite (#109) * feat: test suite v3 * feat: test suite v3 client and watcher * fix: dep update * Update config/crd/bases/tests.testkube.io_tests.yaml Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> * fix: conversion typo * fix: test suite v3 sample * fix: use proper informer version * fix: v3 informer * fix: typo func name * add a separate workflow to test parallel testsuite images * add a separate workflow to test parallel testsuite images * fix: typo test suite version * fix: make steps optional * fix: sync recent changes * fix: solve merge errors * fix: rename fields * fix: tune crd fields * fix: rename vars and methods * fix: refresh mock * fix: rename vars * fix: duration format * fix: change test suite step object * fix: secret var check * fix: modify test suite example v3 * fix: update delay type --------- Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> Co-authored-by: ypoplavs --- PROJECT | 19 +- apis/testsuite/v1/testsuite_conversion.go | 166 ++++++- apis/testsuite/v2/testsuite_conversion.go | 166 +------ apis/testsuite/v2/testsuite_types.go | 1 - apis/testsuite/v3/groupversion_info.go | 48 ++ apis/testsuite/v3/testsuite_conversion.go | 181 ++++++++ apis/testsuite/v3/testsuite_types.go | 166 +++++++ apis/testsuite/v3/testsuite_webhook.go | 25 + apis/testsuite/v3/zz_generated.deepcopy.go | 255 ++++++++++ client/client.go | 2 + client/testsuites/v3/mock_testsuites.go | 240 ++++++++++ client/testsuites/v3/testsuites.go | 434 ++++++++++++++++++ client/testsuites/v3/testsuites_test.go | 131 ++++++ .../bases/tests.testkube.io_testsuites.yaml | 270 +++++++++++ config/samples/tests_v2_testsuite.yaml | 6 +- config/samples/tests_v3_testsuite.yaml | 13 + controllers/testsuite/suite_test.go | 4 +- controllers/testsuite/testsuite_controller.go | 12 +- main.go | 6 + pkg/clientset/versioned/fake/register.go | 4 +- pkg/clientset/versioned/scheme/register.go | 4 +- .../typed/tests/v3/fake/fake_tests_client.go | 4 + .../typed/tests/v3/fake/fake_testsuite.go | 72 +++ .../typed/tests/v3/generated_expansion.go | 2 + .../versioned/typed/tests/v3/tests_client.go | 5 + .../versioned/typed/tests/v3/testsuite.go | 88 ++++ pkg/informers/externalversions/generic.go | 12 +- .../externalversions/tests/v3/interface.go | 7 + .../externalversions/tests/v3/testsuite.go | 94 ++++ pkg/listers/tests/v3/expansion_generated.go | 7 + pkg/listers/tests/v3/testsuites.go | 101 ++++ 31 files changed, 2355 insertions(+), 190 deletions(-) create mode 100644 apis/testsuite/v3/groupversion_info.go create mode 100644 apis/testsuite/v3/testsuite_conversion.go create mode 100644 apis/testsuite/v3/testsuite_types.go create mode 100644 apis/testsuite/v3/testsuite_webhook.go create mode 100644 apis/testsuite/v3/zz_generated.deepcopy.go create mode 100644 client/testsuites/v3/mock_testsuites.go create mode 100644 client/testsuites/v3/testsuites.go create mode 100644 client/testsuites/v3/testsuites_test.go create mode 100644 config/samples/tests_v3_testsuite.yaml create mode 100644 pkg/clientset/versioned/typed/tests/v3/fake/fake_testsuite.go create mode 100644 pkg/clientset/versioned/typed/tests/v3/testsuite.go create mode 100644 pkg/informers/externalversions/tests/v3/testsuite.go create mode 100644 pkg/listers/tests/v3/testsuites.go diff --git a/PROJECT b/PROJECT index 43a55746..f0fcf684 100644 --- a/PROJECT +++ b/PROJECT @@ -64,7 +64,7 @@ resources: domain: testkube.io group: tests kind: TestSuite - path: github.com/kubeshop/testkube-operator/apis/tests/v2 + path: github.com/kubeshop/testkube-operator/apis/testsuite/v2 version: v2 - api: crdVersion: v1 @@ -87,4 +87,21 @@ resources: kind: TestSource path: github.com/kubeshop/testkube-operator/apis/tests/v1 version: v1 +- api: + crdVersion: v1 + namespaced: true + domain: testkube.io + group: tests + kind: Test + path: github.com/kubeshop/testkube-operator/apis/tests/v2 + version: v2 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: testkube.io + group: tests + kind: TestSuite + path: github.com/kubeshop/testkube-operator/apis/testsuite/v3 + version: v3 version: "3" diff --git a/apis/testsuite/v1/testsuite_conversion.go b/apis/testsuite/v1/testsuite_conversion.go index aa333f7a..1c147532 100644 --- a/apis/testsuite/v1/testsuite_conversion.go +++ b/apis/testsuite/v1/testsuite_conversion.go @@ -13,5 +13,167 @@ limitations under the License. package v1 -// Hub marks this type as a conversion hub. -func (*TestSuite) Hub() {} +import ( + "sigs.k8s.io/controller-runtime/pkg/conversion" + + commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" + testkubev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" +) + +// ConvertTo converts this Script to the Hub version (v2). +func (src *TestSuite) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*testkubev2.TestSuite) + + // ObjectMeta + dst.ObjectMeta = src.ObjectMeta + + // Spec + dst.Spec.Repeats = src.Spec.Repeats + dst.Spec.Description = src.Spec.Description + dst.Spec.Schedule = src.Spec.Schedule + + dst.Spec.Before = make([]testkubev2.TestSuiteStepSpec, len(src.Spec.Before)) + dst.Spec.Steps = make([]testkubev2.TestSuiteStepSpec, len(src.Spec.Steps)) + dst.Spec.After = make([]testkubev2.TestSuiteStepSpec, len(src.Spec.After)) + + var stepTypes = []struct { + Source []TestSuiteStepSpec + Destinaton []testkubev2.TestSuiteStepSpec + }{ + { + Source: src.Spec.Before, + Destinaton: dst.Spec.Before, + }, + { + Source: src.Spec.Steps, + Destinaton: dst.Spec.Steps, + }, + { + Source: src.Spec.After, + Destinaton: dst.Spec.After, + }, + } + + for _, stepType := range stepTypes { + for i := range stepType.Source { + value := stepType.Source[i] + step := testkubev2.TestSuiteStepSpec{ + Type: testkubev2.TestSuiteStepType(value.Type), + } + + if value.Delay != nil { + step.Delay = &testkubev2.TestSuiteStepDelay{ + Duration: value.Delay.Duration, + } + } + + if value.Execute != nil { + step.Execute = &testkubev2.TestSuiteStepExecute{ + Namespace: value.Execute.Namespace, + Name: value.Execute.Name, + StopOnFailure: value.Execute.StopOnFailure, + } + } + + stepType.Destinaton[i] = step + } + } + + if len(src.Spec.Variables) != 0 || len(src.Spec.Params) != 0 { + dst.Spec.ExecutionRequest = &testkubev2.TestSuiteExecutionRequest{} + dst.Spec.ExecutionRequest.Variables = make(map[string]testkubev2.Variable, len(src.Spec.Variables)+len(src.Spec.Params)) + for key, value := range src.Spec.Params { + dst.Spec.ExecutionRequest.Variables[key] = testkubev2.Variable{ + Type_: commonv1.VariableTypeBasic, + Name: key, + Value: value, + } + } + + for key, value := range src.Spec.Variables { + dst.Spec.ExecutionRequest.Variables[key] = testkubev2.Variable{ + Type_: value.Type_, + Name: value.Name, + Value: value.Value, + ValueFrom: value.ValueFrom, + } + } + } + + return nil +} + +// ConvertFrom converts Script from the Hub version (v2) to this version. +func (dst *TestSuite) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*testkubev2.TestSuite) + + // ObjectMeta + dst.ObjectMeta = src.ObjectMeta + + // Spec + dst.Spec.Repeats = src.Spec.Repeats + dst.Spec.Description = src.Spec.Description + dst.Spec.Schedule = src.Spec.Schedule + + dst.Spec.Before = make([]TestSuiteStepSpec, len(src.Spec.Before)) + dst.Spec.Steps = make([]TestSuiteStepSpec, len(src.Spec.Steps)) + dst.Spec.After = make([]TestSuiteStepSpec, len(src.Spec.After)) + + var stepTypes = []struct { + source []testkubev2.TestSuiteStepSpec + destinaton []TestSuiteStepSpec + }{ + { + source: src.Spec.Before, + destinaton: dst.Spec.Before, + }, + { + source: src.Spec.Steps, + destinaton: dst.Spec.Steps, + }, + { + source: src.Spec.After, + destinaton: dst.Spec.After, + }, + } + + for _, stepType := range stepTypes { + for i := range stepType.source { + value := stepType.source[i] + step := TestSuiteStepSpec{ + Type: string(value.Type), + } + + if value.Delay != nil { + step.Delay = &TestSuiteStepDelay{ + Duration: value.Delay.Duration, + } + } + + if value.Execute != nil { + step.Execute = &TestSuiteStepExecute{ + Namespace: value.Execute.Namespace, + Name: value.Execute.Name, + StopOnFailure: value.Execute.StopOnFailure, + } + } + + stepType.destinaton[i] = step + } + } + + if src.Spec.ExecutionRequest != nil { + dst.Spec.Variables = make(map[string]Variable, len(src.Spec.ExecutionRequest.Variables)) + for key, value := range src.Spec.ExecutionRequest.Variables { + dst.Spec.Variables[key] = Variable{ + Type_: value.Type_, + Name: value.Name, + Value: value.Value, + ValueFrom: value.ValueFrom, + } + } + } + + // Status + return nil +} diff --git a/apis/testsuite/v2/testsuite_conversion.go b/apis/testsuite/v2/testsuite_conversion.go index d8c5c73c..fd0b8a45 100644 --- a/apis/testsuite/v2/testsuite_conversion.go +++ b/apis/testsuite/v2/testsuite_conversion.go @@ -13,167 +13,5 @@ limitations under the License. package v2 -import ( - "sigs.k8s.io/controller-runtime/pkg/conversion" - - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" - testkubev1 "github.com/kubeshop/testkube-operator/apis/testsuite/v1" -) - -// ConvertTo converts this Script to the Hub version (v1). -func (src *TestSuite) ConvertTo(dstRaw conversion.Hub) error { - dst := dstRaw.(*testkubev1.TestSuite) - - // ObjectMeta - dst.ObjectMeta = src.ObjectMeta - - // Spec - dst.Spec.Repeats = src.Spec.Repeats - dst.Spec.Description = src.Spec.Description - dst.Spec.Schedule = src.Spec.Schedule - - dst.Spec.Before = make([]testkubev1.TestSuiteStepSpec, len(src.Spec.Before)) - dst.Spec.Steps = make([]testkubev1.TestSuiteStepSpec, len(src.Spec.Steps)) - dst.Spec.After = make([]testkubev1.TestSuiteStepSpec, len(src.Spec.After)) - - var stepTypes = []struct { - Source []TestSuiteStepSpec - Destinaton []testkubev1.TestSuiteStepSpec - }{ - { - Source: src.Spec.Before, - Destinaton: dst.Spec.Before, - }, - { - Source: src.Spec.Steps, - Destinaton: dst.Spec.Steps, - }, - { - Source: src.Spec.After, - Destinaton: dst.Spec.After, - }, - } - - for _, stepType := range stepTypes { - for i := range stepType.Source { - value := stepType.Source[i] - step := testkubev1.TestSuiteStepSpec{ - Type: string(value.Type), - } - - if value.Delay != nil { - step.Delay = &testkubev1.TestSuiteStepDelay{ - Duration: value.Delay.Duration, - } - } - - if value.Execute != nil { - step.Execute = &testkubev1.TestSuiteStepExecute{ - Namespace: value.Execute.Namespace, - Name: value.Execute.Name, - StopOnFailure: value.Execute.StopOnFailure, - } - } - - stepType.Destinaton[i] = step - } - } - - if src.Spec.ExecutionRequest != nil { - dst.Spec.Variables = make(map[string]testkubev1.Variable, len(src.Spec.ExecutionRequest.Variables)) - for key, value := range src.Spec.ExecutionRequest.Variables { - dst.Spec.Variables[key] = testkubev1.Variable{ - Type_: value.Type_, - Name: value.Name, - Value: value.Value, - ValueFrom: value.ValueFrom, - } - } - } - - return nil -} - -// ConvertFrom converts Script from the Hub version (v1) to this version. -func (dst *TestSuite) ConvertFrom(srcRaw conversion.Hub) error { - src := srcRaw.(*testkubev1.TestSuite) - - // ObjectMeta - dst.ObjectMeta = src.ObjectMeta - - // Spec - dst.Spec.Repeats = src.Spec.Repeats - dst.Spec.Description = src.Spec.Description - dst.Spec.Schedule = src.Spec.Schedule - - dst.Spec.Before = make([]TestSuiteStepSpec, len(src.Spec.Before)) - dst.Spec.Steps = make([]TestSuiteStepSpec, len(src.Spec.Steps)) - dst.Spec.After = make([]TestSuiteStepSpec, len(src.Spec.After)) - - var stepTypes = []struct { - source []testkubev1.TestSuiteStepSpec - destinaton []TestSuiteStepSpec - }{ - { - source: src.Spec.Before, - destinaton: dst.Spec.Before, - }, - { - source: src.Spec.Steps, - destinaton: dst.Spec.Steps, - }, - { - source: src.Spec.After, - destinaton: dst.Spec.After, - }, - } - - for _, stepType := range stepTypes { - for i := range stepType.source { - value := stepType.source[i] - step := TestSuiteStepSpec{ - Type: TestSuiteStepType(value.Type), - } - - if value.Delay != nil { - step.Delay = &TestSuiteStepDelay{ - Duration: value.Delay.Duration, - } - } - - if value.Execute != nil { - step.Execute = &TestSuiteStepExecute{ - Namespace: value.Execute.Namespace, - Name: value.Execute.Name, - StopOnFailure: value.Execute.StopOnFailure, - } - } - - stepType.destinaton[i] = step - } - } - - if len(src.Spec.Variables) != 0 || len(src.Spec.Params) != 0 { - dst.Spec.ExecutionRequest = &TestSuiteExecutionRequest{} - dst.Spec.ExecutionRequest.Variables = make(map[string]Variable, len(src.Spec.Variables)+len(src.Spec.Params)) - for key, value := range src.Spec.Params { - dst.Spec.ExecutionRequest.Variables[key] = Variable{ - Type_: commonv1.VariableTypeBasic, - Name: key, - Value: value, - } - } - - for key, value := range src.Spec.Variables { - dst.Spec.ExecutionRequest.Variables[key] = Variable{ - Type_: value.Type_, - Name: value.Name, - Value: value.Value, - ValueFrom: value.ValueFrom, - } - } - } - - // Status - return nil -} +// Hub marks this type as a conversion hub. +func (*TestSuite) Hub() {} diff --git a/apis/testsuite/v2/testsuite_types.go b/apis/testsuite/v2/testsuite_types.go index b59936bf..bd65b0ba 100644 --- a/apis/testsuite/v2/testsuite_types.go +++ b/apis/testsuite/v2/testsuite_types.go @@ -155,7 +155,6 @@ type TestSuiteStatus struct { //+kubebuilder:object:root=true //+kubebuilder:subresource:status -//+kubebuilder:storageversion // TestSuite is the Schema for the testsuites API type TestSuite struct { diff --git a/apis/testsuite/v3/groupversion_info.go b/apis/testsuite/v3/groupversion_info.go new file mode 100644 index 00000000..af1ed053 --- /dev/null +++ b/apis/testsuite/v3/groupversion_info.go @@ -0,0 +1,48 @@ +/* +Copyright 2021. + +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 v1 contains API Schema definitions for the tests v1 API group +// +kubebuilder:object:generate=true +// +groupName=tests.testkube.io +package v3 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // Group represents the API Group + Group = "tests.testkube.io" + + // Version represents the Resource version + Version = "v3" + + // Resource corresponds to the CRD Kind + Resource = "TestSuite" + + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: Group, Version: Version} + + // GroupVersionResource is group, version and resource used to register these objects + GroupVersionResource = schema.GroupVersionResource{Group: Group, Version: Version, Resource: Resource} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/apis/testsuite/v3/testsuite_conversion.go b/apis/testsuite/v3/testsuite_conversion.go new file mode 100644 index 00000000..fbb8be5f --- /dev/null +++ b/apis/testsuite/v3/testsuite_conversion.go @@ -0,0 +1,181 @@ +/* +Copyright 2021. +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 v3 + +import ( + "time" + + "sigs.k8s.io/controller-runtime/pkg/conversion" + + testkubev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ConvertTo converts this Script to the Hub version (v2). +func (src *TestSuite) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*testkubev2.TestSuite) + + // ObjectMeta + dst.ObjectMeta = src.ObjectMeta + + // Spec + dst.Spec.Repeats = src.Spec.Repeats + dst.Spec.Description = src.Spec.Description + dst.Spec.Schedule = src.Spec.Schedule + + var stepTypes = []struct { + Source []TestSuiteBatchStep + Destinaton []testkubev2.TestSuiteStepSpec + }{ + { + Source: src.Spec.Before, + Destinaton: dst.Spec.Before, + }, + { + Source: src.Spec.Steps, + Destinaton: dst.Spec.Steps, + }, + { + Source: src.Spec.After, + Destinaton: dst.Spec.After, + }, + } + + for _, stepType := range stepTypes { + for i := range stepType.Source { + for _, value := range stepType.Source[i].Execute { + step := testkubev2.TestSuiteStepSpec{} + + if value.Delay.Duration != 0 { + step.Delay = &testkubev2.TestSuiteStepDelay{ + Duration: int32(value.Delay.Duration / time.Millisecond), + } + } + + if value.Test != "" { + step.Execute = &testkubev2.TestSuiteStepExecute{ + Name: value.Test, + StopOnFailure: stepType.Source[i].StopOnFailure, + } + } + + stepType.Destinaton = append(stepType.Destinaton, step) + } + } + } + + if src.Spec.ExecutionRequest != nil { + variables := make(map[string]testkubev2.Variable, len(src.Spec.ExecutionRequest.Variables)) + for key, value := range src.Spec.ExecutionRequest.Variables { + variables[key] = testkubev2.Variable(value) + } + + dst.Spec.ExecutionRequest = &testkubev2.TestSuiteExecutionRequest{ + Name: src.Spec.ExecutionRequest.Name, + Namespace: src.Spec.ExecutionRequest.Namespace, + Variables: variables, + SecretUUID: src.Spec.ExecutionRequest.SecretUUID, + Labels: src.Spec.ExecutionRequest.Labels, + ExecutionLabels: src.Spec.ExecutionRequest.ExecutionLabels, + Sync: src.Spec.ExecutionRequest.Sync, + HttpProxy: src.Spec.ExecutionRequest.HttpProxy, + HttpsProxy: src.Spec.ExecutionRequest.HttpsProxy, + Timeout: src.Spec.ExecutionRequest.Timeout, + CronJobTemplate: src.Spec.ExecutionRequest.CronJobTemplate, + } + } + + return nil +} + +// ConvertFrom converts Script from the Hub version (v2) to this version. +func (dst *TestSuite) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*testkubev2.TestSuite) + + // ObjectMeta + dst.ObjectMeta = src.ObjectMeta + + // Spec + dst.Spec.Repeats = src.Spec.Repeats + dst.Spec.Description = src.Spec.Description + dst.Spec.Schedule = src.Spec.Schedule + + dst.Spec.Before = make([]TestSuiteBatchStep, len(src.Spec.Before)) + dst.Spec.Steps = make([]TestSuiteBatchStep, len(src.Spec.Steps)) + dst.Spec.After = make([]TestSuiteBatchStep, len(src.Spec.After)) + + var stepTypes = []struct { + source []testkubev2.TestSuiteStepSpec + destinaton []TestSuiteBatchStep + }{ + { + source: src.Spec.Before, + destinaton: dst.Spec.Before, + }, + { + source: src.Spec.Steps, + destinaton: dst.Spec.Steps, + }, + { + source: src.Spec.After, + destinaton: dst.Spec.After, + }, + } + + for _, stepType := range stepTypes { + for i := range stepType.source { + value := stepType.source[i] + step := TestSuiteStepSpec{} + + if value.Delay != nil { + step.Delay = metav1.Duration{Duration: time.Duration(value.Delay.Duration) * time.Millisecond} + } + + var stopOnFailure bool + if value.Execute != nil { + step.Test = value.Execute.Name + stopOnFailure = value.Execute.StopOnFailure + } + + stepType.destinaton[i] = TestSuiteBatchStep{ + StopOnFailure: stopOnFailure, + Execute: []TestSuiteStepSpec{step}, + } + } + } + + if src.Spec.ExecutionRequest != nil { + variables := make(map[string]Variable, len(src.Spec.ExecutionRequest.Variables)) + for key, value := range src.Spec.ExecutionRequest.Variables { + variables[key] = Variable(value) + } + + dst.Spec.ExecutionRequest = &TestSuiteExecutionRequest{ + Name: src.Spec.ExecutionRequest.Name, + Namespace: src.Spec.ExecutionRequest.Namespace, + Variables: variables, + SecretUUID: src.Spec.ExecutionRequest.SecretUUID, + Labels: src.Spec.ExecutionRequest.Labels, + ExecutionLabels: src.Spec.ExecutionRequest.ExecutionLabels, + Sync: src.Spec.ExecutionRequest.Sync, + HttpProxy: src.Spec.ExecutionRequest.HttpProxy, + HttpsProxy: src.Spec.ExecutionRequest.HttpsProxy, + Timeout: src.Spec.ExecutionRequest.Timeout, + CronJobTemplate: src.Spec.ExecutionRequest.CronJobTemplate, + } + } + + // Status + return nil +} diff --git a/apis/testsuite/v3/testsuite_types.go b/apis/testsuite/v3/testsuite_types.go new file mode 100644 index 00000000..c3dcc379 --- /dev/null +++ b/apis/testsuite/v3/testsuite_types.go @@ -0,0 +1,166 @@ +/* +Copyright 2021. + +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 v3 + +import ( + commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// TestSuiteSpec defines the desired state of TestSuite +type TestSuiteSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // Before batch steps is list of batch tests which will be sequentially orchestrated for parallel tests in each batch + Before []TestSuiteBatchStep `json:"before,omitempty"` + // Batch steps is list of batch tests which will be sequentially orchestrated for parallel tests in each batch + Steps []TestSuiteBatchStep `json:"steps,omitempty"` + // After batch steps is list of batch tests which will be sequentially orchestrated for parallel tests in each batch + After []TestSuiteBatchStep `json:"after,omitempty"` + + Repeats int `json:"repeats,omitempty"` + Description string `json:"description,omitempty"` + // schedule in cron job format for scheduled test execution + Schedule string `json:"schedule,omitempty"` + ExecutionRequest *TestSuiteExecutionRequest `json:"executionRequest,omitempty"` +} + +type Variable commonv1.Variable + +// TestSuiteStepSpec for particular type will have config for possible step types +type TestSuiteStepSpec struct { + // object name + Test string `json:"test,omitempty"` + // delay duration in time units + // +kubebuilder:validation:Type:=string + // +kubebuilder:validation:Format:=duration + Delay metav1.Duration `json:"delay,omitempty"` +} + +// set of steps run in parallel +type TestSuiteBatchStep struct { + StopOnFailure bool `json:"stopOnFailure"` + Execute []TestSuiteStepSpec `json:"execute,omitempty"` +} + +// running context for test or test suite execution +type RunningContext struct { + // One of possible context types + Type_ RunningContextType `json:"type"` + // Context value depending from its type + Context string `json:"context,omitempty"` +} + +type RunningContextType string + +const ( + RunningContextTypeUserCLI RunningContextType = "user-cli" + RunningContextTypeUserUI RunningContextType = "user-ui" + RunningContextTypeTestSuite RunningContextType = "testsuite" + RunningContextTypeTestTrigger RunningContextType = "testtrigger" + RunningContextTypeScheduler RunningContextType = "scheduler" + RunningContextTypeEmpty RunningContextType = "" +) + +// test suite execution request body +type TestSuiteExecutionRequest struct { + // test execution custom name + Name string `json:"name,omitempty"` + // test kubernetes namespace (\"testkube\" when not set) + Namespace string `json:"namespace,omitempty"` + Variables map[string]Variable `json:"variables,omitempty"` + // secret uuid + SecretUUID string `json:"secretUUID,omitempty"` + // test suite labels + Labels map[string]string `json:"labels,omitempty"` + // execution labels + ExecutionLabels map[string]string `json:"executionLabels,omitempty"` + // whether to start execution sync or async + Sync bool `json:"sync,omitempty"` + // http proxy for executor containers + HttpProxy string `json:"httpProxy,omitempty"` + // https proxy for executor containers + HttpsProxy string `json:"httpsProxy,omitempty"` + // timeout for test suite execution + Timeout int32 `json:"timeout,omitempty"` + RunningContext *RunningContext `json:"runningContext,omitempty"` + // cron job template extensions + CronJobTemplate string `json:"cronJobTemplate,omitempty"` +} + +type TestSuiteExecutionStatus string + +// List of TestSuiteExecutionStatus +const ( + QUEUED_TestSuiteExecutionStatus TestSuiteExecutionStatus = "queued" + RUNNING_TestSuiteExecutionStatus TestSuiteExecutionStatus = "running" + PASSED_TestSuiteExecutionStatus TestSuiteExecutionStatus = "passed" + FAILED_TestSuiteExecutionStatus TestSuiteExecutionStatus = "failed" + ABORTING_TestSuiteExecutionStatus TestSuiteExecutionStatus = "aborting" + ABORTED_TestSuiteExecutionStatus TestSuiteExecutionStatus = "aborted" + TIMEOUT_TestSuiteExecutionStatus TestSuiteExecutionStatus = "timeout" +) + +// test suite execution core +type TestSuiteExecutionCore struct { + // execution id + Id string `json:"id,omitempty"` + // test suite execution start time + StartTime metav1.Time `json:"startTime,omitempty"` + // test suite execution end time + EndTime metav1.Time `json:"endTime,omitempty"` + Status *TestSuiteExecutionStatus `json:"status,omitempty"` +} + +// TestSuiteStatus defines the observed state of TestSuite +type TestSuiteStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // latest execution result + LatestExecution *TestSuiteExecutionCore `json:"latestExecution,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status +//+kubebuilder:storageversion + +// TestSuite is the Schema for the testsuites API +type TestSuite struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec TestSuiteSpec `json:"spec,omitempty"` + Status TestSuiteStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// TestSuiteList contains a list of TestSuite +type TestSuiteList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []TestSuite `json:"items"` +} + +func init() { + SchemeBuilder.Register(&TestSuite{}, &TestSuiteList{}) +} diff --git a/apis/testsuite/v3/testsuite_webhook.go b/apis/testsuite/v3/testsuite_webhook.go new file mode 100644 index 00000000..7ef571a1 --- /dev/null +++ b/apis/testsuite/v3/testsuite_webhook.go @@ -0,0 +1,25 @@ +/* +Copyright 2021. +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 v3 + +import ( + ctrl "sigs.k8s.io/controller-runtime" +) + +// SetupWebhookWithManager sets up webhook with manager +func (t *TestSuite) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(t). + Complete() +} diff --git a/apis/testsuite/v3/zz_generated.deepcopy.go b/apis/testsuite/v3/zz_generated.deepcopy.go new file mode 100644 index 00000000..a1491ef4 --- /dev/null +++ b/apis/testsuite/v3/zz_generated.deepcopy.go @@ -0,0 +1,255 @@ +// +build !ignore_autogenerated + +/* +Copyright 2021. + +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v3 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuite) DeepCopyInto(out *TestSuite) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuite. +func (in *TestSuite) DeepCopy() *TestSuite { + if in == nil { + return nil + } + out := new(TestSuite) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TestSuite) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteBatchStep) DeepCopyInto(out *TestSuiteBatchStep) { + *out = *in + if in.Execute != nil { + in, out := &in.Execute, &out.Execute + *out = make([]TestSuiteStepSpec, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteBatchStep. +func (in *TestSuiteBatchStep) DeepCopy() *TestSuiteBatchStep { + if in == nil { + return nil + } + out := new(TestSuiteBatchStep) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteExecutionCore) DeepCopyInto(out *TestSuiteExecutionCore) { + *out = *in + in.StartTime.DeepCopyInto(&out.StartTime) + in.EndTime.DeepCopyInto(&out.EndTime) + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(TestSuiteExecutionStatus) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteExecutionCore. +func (in *TestSuiteExecutionCore) DeepCopy() *TestSuiteExecutionCore { + if in == nil { + return nil + } + out := new(TestSuiteExecutionCore) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteExecutionRequest) DeepCopyInto(out *TestSuiteExecutionRequest) { + *out = *in + if in.Variables != nil { + in, out := &in.Variables, &out.Variables + *out = make(map[string]Variable, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.ExecutionLabels != nil { + in, out := &in.ExecutionLabels, &out.ExecutionLabels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteExecutionRequest. +func (in *TestSuiteExecutionRequest) DeepCopy() *TestSuiteExecutionRequest { + if in == nil { + return nil + } + out := new(TestSuiteExecutionRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteList) DeepCopyInto(out *TestSuiteList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]TestSuite, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteList. +func (in *TestSuiteList) DeepCopy() *TestSuiteList { + if in == nil { + return nil + } + out := new(TestSuiteList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TestSuiteList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteSpec) DeepCopyInto(out *TestSuiteSpec) { + *out = *in + if in.Before != nil { + in, out := &in.Before, &out.Before + *out = make([]TestSuiteBatchStep, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Steps != nil { + in, out := &in.Steps, &out.Steps + *out = make([]TestSuiteBatchStep, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.After != nil { + in, out := &in.After, &out.After + *out = make([]TestSuiteBatchStep, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ExecutionRequest != nil { + in, out := &in.ExecutionRequest, &out.ExecutionRequest + *out = new(TestSuiteExecutionRequest) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteSpec. +func (in *TestSuiteSpec) DeepCopy() *TestSuiteSpec { + if in == nil { + return nil + } + out := new(TestSuiteSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteStatus) DeepCopyInto(out *TestSuiteStatus) { + *out = *in + if in.LatestExecution != nil { + in, out := &in.LatestExecution, &out.LatestExecution + *out = new(TestSuiteExecutionCore) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteStatus. +func (in *TestSuiteStatus) DeepCopy() *TestSuiteStatus { + if in == nil { + return nil + } + out := new(TestSuiteStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteStepSpec) DeepCopyInto(out *TestSuiteStepSpec) { + *out = *in + out.Delay = in.Delay +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteStepSpec. +func (in *TestSuiteStepSpec) DeepCopy() *TestSuiteStepSpec { + if in == nil { + return nil + } + out := new(TestSuiteStepSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Variable) DeepCopyInto(out *Variable) { + *out = *in + in.ValueFrom.DeepCopyInto(&out.ValueFrom) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Variable. +func (in *Variable) DeepCopy() *Variable { + if in == nil { + return nil + } + out := new(Variable) + in.DeepCopyInto(out) + return out +} diff --git a/client/client.go b/client/client.go index e22e4654..289bf265 100644 --- a/client/client.go +++ b/client/client.go @@ -10,6 +10,7 @@ import ( testsourcev1 "github.com/kubeshop/testkube-operator/apis/testsource/v1" testsuitev1 "github.com/kubeshop/testkube-operator/apis/testsuite/v1" testsuitev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" + testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" _ "k8s.io/client-go/plugin/pkg/client/auth" @@ -30,6 +31,7 @@ func GetClient() (client.Client, error) { testsuitev1.AddToScheme(scheme) corev1.AddToScheme(scheme) testsuitev2.AddToScheme(scheme) + testsuitev3.AddToScheme(scheme) testsourcev1.AddToScheme(scheme) kubeconfig, err := ctrl.GetConfig() diff --git a/client/testsuites/v3/mock_testsuites.go b/client/testsuites/v3/mock_testsuites.go new file mode 100644 index 00000000..e5ce0d63 --- /dev/null +++ b/client/testsuites/v3/mock_testsuites.go @@ -0,0 +1,240 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/kubeshop/testkube-operator/client/testsuites/v3 (interfaces: Interface) + +// Package v3 is a generated GoMock package. +package v3 + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + v3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + v1 "k8s.io/api/core/v1" +) + +// MockInterface is a mock of Interface interface. +type MockInterface struct { + ctrl *gomock.Controller + recorder *MockInterfaceMockRecorder +} + +// MockInterfaceMockRecorder is the mock recorder for MockInterface. +type MockInterfaceMockRecorder struct { + mock *MockInterface +} + +// NewMockInterface creates a new mock instance. +func NewMockInterface(ctrl *gomock.Controller) *MockInterface { + mock := &MockInterface{ctrl: ctrl} + mock.recorder = &MockInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder { + return m.recorder +} + +// Create mocks base method. +func (m *MockInterface) Create(arg0 *v3.TestSuite) (*v3.TestSuite, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Create", arg0) + ret0, _ := ret[0].(*v3.TestSuite) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Create indicates an expected call of Create. +func (mr *MockInterfaceMockRecorder) Create(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockInterface)(nil).Create), arg0) +} + +// CreateTestsuiteSecrets mocks base method. +func (m *MockInterface) CreateTestsuiteSecrets(arg0 *v3.TestSuite) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateTestsuiteSecrets", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateTestsuiteSecrets indicates an expected call of CreateTestsuiteSecrets. +func (mr *MockInterfaceMockRecorder) CreateTestsuiteSecrets(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateTestsuiteSecrets", reflect.TypeOf((*MockInterface)(nil).CreateTestsuiteSecrets), arg0) +} + +// Delete mocks base method. +func (m *MockInterface) Delete(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockInterfaceMockRecorder) Delete(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockInterface)(nil).Delete), arg0) +} + +// DeleteAll mocks base method. +func (m *MockInterface) DeleteAll() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteAll") + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteAll indicates an expected call of DeleteAll. +func (mr *MockInterfaceMockRecorder) DeleteAll() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAll", reflect.TypeOf((*MockInterface)(nil).DeleteAll)) +} + +// DeleteByLabels mocks base method. +func (m *MockInterface) DeleteByLabels(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteByLabels", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteByLabels indicates an expected call of DeleteByLabels. +func (mr *MockInterfaceMockRecorder) DeleteByLabels(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteByLabels", reflect.TypeOf((*MockInterface)(nil).DeleteByLabels), arg0) +} + +// Get mocks base method. +func (m *MockInterface) Get(arg0 string) (*v3.TestSuite, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", arg0) + ret0, _ := ret[0].(*v3.TestSuite) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Get indicates an expected call of Get. +func (mr *MockInterfaceMockRecorder) Get(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockInterface)(nil).Get), arg0) +} + +// GetCurrentSecretUUID mocks base method. +func (m *MockInterface) GetCurrentSecretUUID(arg0 string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentSecretUUID", arg0) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCurrentSecretUUID indicates an expected call of GetCurrentSecretUUID. +func (mr *MockInterfaceMockRecorder) GetCurrentSecretUUID(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentSecretUUID", reflect.TypeOf((*MockInterface)(nil).GetCurrentSecretUUID), arg0) +} + +// GetSecretTestSuiteVars mocks base method. +func (m *MockInterface) GetSecretTestSuiteVars(arg0, arg1 string) (map[string]string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSecretTestSuiteVars", arg0, arg1) + ret0, _ := ret[0].(map[string]string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSecretTestSuiteVars indicates an expected call of GetSecretTestSuiteVars. +func (mr *MockInterfaceMockRecorder) GetSecretTestSuiteVars(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSecretTestSuiteVars", reflect.TypeOf((*MockInterface)(nil).GetSecretTestSuiteVars), arg0, arg1) +} + +// List mocks base method. +func (m *MockInterface) List(arg0 string) (*v3.TestSuiteList, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "List", arg0) + ret0, _ := ret[0].(*v3.TestSuiteList) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// List indicates an expected call of List. +func (mr *MockInterfaceMockRecorder) List(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockInterface)(nil).List), arg0) +} + +// ListLabels mocks base method. +func (m *MockInterface) ListLabels() (map[string][]string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListLabels") + ret0, _ := ret[0].(map[string][]string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListLabels indicates an expected call of ListLabels. +func (mr *MockInterfaceMockRecorder) ListLabels() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListLabels", reflect.TypeOf((*MockInterface)(nil).ListLabels)) +} + +// LoadTestsuiteVariablesSecret mocks base method. +func (m *MockInterface) LoadTestsuiteVariablesSecret(arg0 *v3.TestSuite) (*v1.Secret, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LoadTestsuiteVariablesSecret", arg0) + ret0, _ := ret[0].(*v1.Secret) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// LoadTestsuiteVariablesSecret indicates an expected call of LoadTestsuiteVariablesSecret. +func (mr *MockInterfaceMockRecorder) LoadTestsuiteVariablesSecret(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadTestsuiteVariablesSecret", reflect.TypeOf((*MockInterface)(nil).LoadTestsuiteVariablesSecret), arg0) +} + +// Update mocks base method. +func (m *MockInterface) Update(arg0 *v3.TestSuite) (*v3.TestSuite, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", arg0) + ret0, _ := ret[0].(*v3.TestSuite) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Update indicates an expected call of Update. +func (mr *MockInterfaceMockRecorder) Update(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockInterface)(nil).Update), arg0) +} + +// UpdateStatus mocks base method. +func (m *MockInterface) UpdateStatus(arg0 *v3.TestSuite) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateStatus", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// UpdateStatus indicates an expected call of UpdateStatus. +func (mr *MockInterfaceMockRecorder) UpdateStatus(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateStatus", reflect.TypeOf((*MockInterface)(nil).UpdateStatus), arg0) +} + +// UpdateTestsuiteSecrets mocks base method. +func (m *MockInterface) UpdateTestsuiteSecrets(arg0 *v3.TestSuite) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateTestsuiteSecrets", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// UpdateTestsuiteSecrets indicates an expected call of UpdateTestsuiteSecrets. +func (mr *MockInterfaceMockRecorder) UpdateTestsuiteSecrets(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTestsuiteSecrets", reflect.TypeOf((*MockInterface)(nil).UpdateTestsuiteSecrets), arg0) +} diff --git a/client/testsuites/v3/testsuites.go b/client/testsuites/v3/testsuites.go new file mode 100644 index 00000000..5ca405fa --- /dev/null +++ b/client/testsuites/v3/testsuites.go @@ -0,0 +1,434 @@ +package v3 + +import ( + "context" + "encoding/json" + "fmt" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/labels" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/google/uuid" + commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" + testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" +) + +const ( + testkubeTestsuiteSecretLabel = "testsuites-secrets" + currentSecretKey = "current-secret" +) + +var testsuiteSecretDefaultLabels = map[string]string{ + "testkube": testkubeTestsuiteSecretLabel, + "testkubeSecretType": "variables", +} + +//go:generate mockgen -destination=./mock_testsuites.go -package=v3 "github.com/kubeshop/testkube-operator/client/testsuites/v3" Interface +type Interface interface { + List(selector string) (*testsuitev3.TestSuiteList, error) + ListLabels() (map[string][]string, error) + Get(name string) (*testsuitev3.TestSuite, error) + Create(testsuite *testsuitev3.TestSuite) (*testsuitev3.TestSuite, error) + Update(testsuite *testsuitev3.TestSuite) (*testsuitev3.TestSuite, error) + Delete(name string) error + DeleteAll() error + CreateTestsuiteSecrets(testsuite *testsuitev3.TestSuite) error + UpdateTestsuiteSecrets(testsuite *testsuitev3.TestSuite) error + LoadTestsuiteVariablesSecret(testsuite *testsuitev3.TestSuite) (*corev1.Secret, error) + GetCurrentSecretUUID(testsuiteName string) (string, error) + GetSecretTestSuiteVars(testsuiteName, secretUUID string) (map[string]string, error) + DeleteByLabels(selector string) error + UpdateStatus(testsuite *testsuitev3.TestSuite) error +} + +// NewClient creates new TestSuite client +func NewClient(client client.Client, namespace string) *TestSuitesClient { + return &TestSuitesClient{ + Client: client, + Namespace: namespace, + } +} + +// TestSuitesClient implements methods to work with TestSuites +type TestSuitesClient struct { + Client client.Client + Namespace string +} + +// List lists TestSuites +func (s TestSuitesClient) List(selector string) (*testsuitev3.TestSuiteList, error) { + list := &testsuitev3.TestSuiteList{} + reqs, err := labels.ParseToRequirements(selector) + if err != nil { + return list, err + } + + options := &client.ListOptions{ + Namespace: s.Namespace, + LabelSelector: labels.NewSelector().Add(reqs...), + } + + if err = s.Client.List(context.Background(), list, options); err != nil { + return list, err + } + + for i := range list.Items { + secret, err := s.LoadTestsuiteVariablesSecret(&list.Items[i]) + secretExists := !errors.IsNotFound(err) + if err != nil && secretExists { + return list, err + } + + secretToTestsuiteVars(secret, &list.Items[i]) + } + + return list, nil +} + +// ListLabelslists labels for TestSuites +func (s TestSuitesClient) ListLabels() (map[string][]string, error) { + labels := map[string][]string{} + list := &testsuitev3.TestSuiteList{} + err := s.Client.List(context.Background(), list, &client.ListOptions{Namespace: s.Namespace}) + if err != nil { + return labels, err + } + + for _, testsuite := range list.Items { + for key, value := range testsuite.Labels { + if values, ok := labels[key]; !ok { + labels[key] = []string{value} + } else { + for _, v := range values { + if v == value { + continue + } + } + labels[key] = append(labels[key], value) + } + } + } + + return labels, nil +} + +// Get returns TestSuite +func (s TestSuitesClient) Get(name string) (*testsuitev3.TestSuite, error) { + testsuite := &testsuitev3.TestSuite{} + err := s.Client.Get(context.Background(), client.ObjectKey{Namespace: s.Namespace, Name: name}, testsuite) + if err != nil { + return nil, err + } + + secret, err := s.LoadTestsuiteVariablesSecret(testsuite) + secretExists := !errors.IsNotFound(err) + if err != nil && secretExists { + return nil, err + } + + secretToTestsuiteVars(secret, testsuite) + + return testsuite, nil +} + +// Create creates new TestSuite +func (s TestSuitesClient) Create(testsuite *testsuitev3.TestSuite) (*testsuitev3.TestSuite, error) { + err := s.CreateTestsuiteSecrets(testsuite) + if err != nil { + return nil, err + } + + err = s.Client.Create(context.Background(), testsuite) + return testsuite, err +} + +// Update updates existing TestSuite +func (s TestSuitesClient) Update(testsuite *testsuitev3.TestSuite) (*testsuitev3.TestSuite, error) { + err := s.UpdateTestsuiteSecrets(testsuite) + if err != nil { + return nil, err + } + + err = s.Client.Update(context.Background(), testsuite) + return testsuite, err +} + +// Delete deletes existing TestSuite +func (s TestSuitesClient) Delete(name string) error { + testsuite, err := s.Get(name) + if err != nil { + return err + } + + secret, err := s.LoadTestsuiteVariablesSecret(testsuite) + secretExists := !errors.IsNotFound(err) + if err != nil && secretExists { + return err + } + + if err == nil && secret != nil { + if err = s.Client.Delete(context.Background(), secret); err != nil { + return err + } + } + + err = s.Client.Delete(context.Background(), testsuite) + if err != nil { + return err + } + + return nil +} + +// DeleteAll delete all TestSuites +func (s TestSuitesClient) DeleteAll() error { + u := &unstructured.Unstructured{} + u.SetKind("TestSuite") + u.SetAPIVersion("tests.testkube.io/v3") + err := s.Client.DeleteAllOf(context.Background(), u, client.InNamespace(s.Namespace)) + if err != nil { + return err + } + + u = &unstructured.Unstructured{} + u.SetKind("Secret") + u.SetAPIVersion("v1") + return s.Client.DeleteAllOf(context.Background(), u, client.InNamespace(s.Namespace), + client.MatchingLabels(testsuiteSecretDefaultLabels)) +} + +// CreateTestsuiteSecrets creates corresponding TestSuite vars secrets +func (s TestSuitesClient) CreateTestsuiteSecrets(testsuite *testsuitev3.TestSuite) error { + secretName := secretName(testsuite.Name) + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Namespace: s.Namespace, + Labels: testsuiteSecretDefaultLabels, + }, + Type: corev1.SecretTypeOpaque, + StringData: map[string]string{}, + } + + if err := testsuiteVarsToSecret(testsuite, secret); err != nil { + return err + } + + if len(secret.StringData) > 0 { + err := s.Client.Create(context.Background(), secret) + if err != nil { + return err + } + } + + return nil +} + +func (s TestSuitesClient) UpdateTestsuiteSecrets(testsuite *testsuitev3.TestSuite) error { + secret, err := s.LoadTestsuiteVariablesSecret(testsuite) + secretExists := !errors.IsNotFound(err) + if err != nil && secretExists { + return err + } + + if err == nil && secret == nil { + return nil + } + + if !secretExists { + secret.Name = secretName(testsuite.Name) + secret.Namespace = s.Namespace + secret.Labels = testsuiteSecretDefaultLabels + secret.Type = corev1.SecretTypeOpaque + } + + if err = testsuiteVarsToSecret(testsuite, secret); err != nil { + return err + } + + if secretExists && len(secret.StringData) > 0 { + if !secretExists { + err = s.Client.Create(context.Background(), secret) + } else { + err = s.Client.Update(context.Background(), secret) + } + + if err != nil { + return err + } + } + + return nil +} + +func (s TestSuitesClient) TestsuiteHasSecrets(testsuite *testsuitev3.TestSuite) (has bool) { + if testsuite.Spec.ExecutionRequest == nil { + return + } + + for _, v := range testsuite.Spec.ExecutionRequest.Variables { + if v.Type_ == commonv1.VariableTypeSecret && (v.ValueFrom.SecretKeyRef == nil || + (v.ValueFrom.SecretKeyRef != nil && (v.ValueFrom.SecretKeyRef.Name == secretName(testsuite.Name)))) { + return true + } + } + + return +} + +func (s TestSuitesClient) LoadTestsuiteVariablesSecret(testsuite *testsuitev3.TestSuite) (*corev1.Secret, error) { + if !s.TestsuiteHasSecrets(testsuite) { + return nil, nil + } + secret := &corev1.Secret{} + err := s.Client.Get(context.Background(), client.ObjectKey{Namespace: s.Namespace, Name: secretName(testsuite.Name)}, secret) + return secret, err +} + +// GetCurrentSecretUUID returns current secret uuid +func (s TestSuitesClient) GetCurrentSecretUUID(testsuiteName string) (string, error) { + secret := &corev1.Secret{} + if err := s.Client.Get(context.Background(), client.ObjectKey{ + Namespace: s.Namespace, Name: secretName(testsuiteName)}, secret); err != nil && !errors.IsNotFound(err) { + return "", err + } + + secretUUID := "" + if secret.Data != nil { + if value, ok := secret.Data[currentSecretKey]; ok { + secretUUID = string(value) + } + } + + return secretUUID, nil +} + +// GetSecretTestSuiteVars returns secret test suite vars +func (s TestSuitesClient) GetSecretTestSuiteVars(testsuiteName, secretUUID string) (map[string]string, error) { + secret := &corev1.Secret{} + if err := s.Client.Get(context.Background(), client.ObjectKey{ + Namespace: s.Namespace, Name: secretName(testsuiteName)}, secret); err != nil && !errors.IsNotFound(err) { + return nil, err + } + + secrets := make(map[string]string) + if secret.Data != nil { + if value, ok := secret.Data[secretUUID]; ok { + if err := json.Unmarshal(value, &secrets); err != nil { + return nil, err + } + } + } + + return secrets, nil +} + +// UpdateStatus updates existing TestSuite status +func (s TestSuitesClient) UpdateStatus(testsuite *testsuitev3.TestSuite) error { + return s.Client.Status().Update(context.Background(), testsuite) +} + +// testsuiteVarsToSecret loads secrets data passed into TestSuite CRD and remove plain text data +func testsuiteVarsToSecret(testsuite *testsuitev3.TestSuite, secret *corev1.Secret) error { + if secret == nil { + return nil + } + + if secret.StringData == nil { + secret.StringData = map[string]string{} + } + + if testsuite.Spec.ExecutionRequest == nil { + return nil + } + + secretMap := make(map[string]string) + for k := range testsuite.Spec.ExecutionRequest.Variables { + v := testsuite.Spec.ExecutionRequest.Variables[k] + if v.Type_ == commonv1.VariableTypeSecret { + if v.ValueFrom.SecretKeyRef != nil { + v.ValueFrom = corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + Key: v.ValueFrom.SecretKeyRef.Key, + LocalObjectReference: corev1.LocalObjectReference{ + Name: v.ValueFrom.SecretKeyRef.Name, + }, + }, + } + } else { + secret.StringData[v.Name] = v.Value + secretMap[v.Name] = v.Value + // clear passed test suite variable secret value and save as reference o secret + v.Value = "" + v.ValueFrom = corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + Key: v.Name, + LocalObjectReference: corev1.LocalObjectReference{ + Name: secret.Name, + }, + }, + } + } + + testsuite.Spec.ExecutionRequest.Variables[k] = v + } + } + + if len(secretMap) != 0 { + random, err := uuid.NewRandom() + if err != nil { + return err + } + + data, err := json.Marshal(secretMap) + if err != nil { + return err + } + + secret.StringData[random.String()] = string(data) + secret.StringData[currentSecretKey] = random.String() + } + + return nil +} + +// secretToTestsuiteVars loads secrets data passed into TestSuite CRD and remove plain text data +func secretToTestsuiteVars(secret *corev1.Secret, testsuite *testsuitev3.TestSuite) { + if testsuite == nil || secret == nil || secret.Data == nil { + return + } + + if testsuite.Spec.ExecutionRequest == nil { + return + } + + for k, v := range secret.Data { + if variable, ok := testsuite.Spec.ExecutionRequest.Variables[k]; ok { + variable.Value = string(v) + testsuite.Spec.ExecutionRequest.Variables[k] = variable + } + } +} + +func secretName(testsuiteName string) string { + return fmt.Sprintf("%s-testsuitevars", testsuiteName) +} + +// DeleteByLabels deletes TestSuites by labels +func (s TestSuitesClient) DeleteByLabels(selector string) error { + reqs, err := labels.ParseToRequirements(selector) + if err != nil { + return err + } + + u := &unstructured.Unstructured{} + u.SetKind("TestSuite") + u.SetAPIVersion("tests.testkube.io/v3") + err = s.Client.DeleteAllOf(context.Background(), u, client.InNamespace(s.Namespace), + client.MatchingLabelsSelector{Selector: labels.NewSelector().Add(reqs...)}) + return err +} diff --git a/client/testsuites/v3/testsuites_test.go b/client/testsuites/v3/testsuites_test.go new file mode 100644 index 00000000..b975f389 --- /dev/null +++ b/client/testsuites/v3/testsuites_test.go @@ -0,0 +1,131 @@ +//go:build k8sIntegration + +// TODO set-up workflows which can run kubernetes related tests + +package v3 + +import ( + "testing" + + commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" + testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + kubeclient "github.com/kubeshop/testkube-operator/client" + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestClient_IntegrationWithSecrets(t *testing.T) { + const testsuiteName = "testsuite-example-with-secrets" + // given test client and example test + client, err := kubeclient.GetClient() + assert.NoError(t, err) + + c := NewClient(client, "testkube") + + tst0, err := c.Create(&testsuitev3.TestSuite{ + ObjectMeta: metav1.ObjectMeta{ + Name: testsuiteName, + Namespace: "testkube", + }, + Spec: testsuitev3.TestSuiteSpec{ + ExecutionRequest: &testsuitev3.TestSuiteExecutionRequest{ + Variables: map[string]testsuitev3.Variable{ + "secretVar1": { + Type_: commonv1.VariableTypeSecret, + Name: "secretVar1", + Value: "SECR3t", + }, + "secretVar2": { + Type_: commonv1.VariableTypeSecret, + Name: "secretVar2", + Value: "SomeOtherSecretVar", + }, + }, + }, + }, + }) + + assert.NoError(t, err) + + // when update test secret variable + secret := tst0.Spec.ExecutionRequest.Variables["secretVar1"] + secret.Value = "UpdatedSecretValue" + tst0.Spec.ExecutionRequest.Variables["secretVar1"] = secret + + secret = tst0.Spec.ExecutionRequest.Variables["secretVar2"] + secret.Value = "SomeOtherSecretVar" + tst0.Spec.ExecutionRequest.Variables["secretVar2"] = secret + + tstUpdated, err := c.Update(tst0) + assert.NoError(t, err) + + // then value should be updated + tst1, err := c.Get(tst0.Name) + assert.NoError(t, err) + + assert.Equal(t, "UpdatedSecretValue", tst1.Spec.ExecutionRequest.Variables["secretVar1"].Value) + assert.Equal(t, "SomeOtherSecretVar", tst1.Spec.ExecutionRequest.Variables["secretVar2"].Value) + + // when test is deleted + err = c.Delete(tstUpdated.Name) + assert.NoError(t, err) + + // then there should be no test anymore + tst2, err := c.Get(tst0.Name) + assert.Nil(t, tst2) + assert.Error(t, err) + +} + +func TestClient_IntegrationWithoutSecrets(t *testing.T) { + const testsuiteName = "testsuite-example-without-secrets" + // given test client and example test + client, err := kubeclient.GetClient() + assert.NoError(t, err) + + c := NewClient(client, "testkube") + + tst0, err := c.Create(&testsuitev3.TestSuite{ + ObjectMeta: metav1.ObjectMeta{ + Name: testsuiteName, + Namespace: "testkube", + }, + Spec: testsuitev3.TestSuiteSpec{ + ExecutionRequest: &testsuitev3.TestSuiteExecutionRequest{ + Variables: map[string]testsuitev3.Variable{ + "secretVar1": { + Type_: commonv1.VariableTypeBasic, + Name: "var1", + Value: "val1", + }, + }, + }, + }, + }) + + assert.NoError(t, err) + + // when update test secret variable + secret := tst0.Spec.ExecutionRequest.Variables["secretVar1"] + secret.Value = "updatedval" + tst0.Spec.ExecutionRequest.Variables["var1"] = secret + + tstUpdated, err := c.Update(tst0) + assert.NoError(t, err) + + // then value should be updated + tst1, err := c.Get(tst0.Name) + assert.NoError(t, err) + + assert.Equal(t, "updatedval", tst1.Spec.ExecutionRequest.Variables["var1"].Value) + + // when test is deleted + err = c.Delete(tstUpdated.Name) + assert.NoError(t, err) + + // then there should be no test anymore + tst2, err := c.Get(tst0.Name) + assert.Nil(t, tst2) + assert.Error(t, err) + +} diff --git a/config/crd/bases/tests.testkube.io_testsuites.yaml b/config/crd/bases/tests.testkube.io_testsuites.yaml index 19f2db29..4420562e 100644 --- a/config/crd/bases/tests.testkube.io_testsuites.yaml +++ b/config/crd/bases/tests.testkube.io_testsuites.yaml @@ -535,6 +535,276 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - name: v3 + schema: + openAPIV3Schema: + description: TestSuite is the Schema for the testsuites API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: TestSuiteSpec defines the desired state of TestSuite + properties: + after: + description: After batch steps is list of batch tests which will be + sequentially orchestrated for parallel tests in each batch + items: + description: set of steps run in parallel + properties: + execute: + items: + description: TestSuiteStepSpec for particular type will have + config for possible step types + properties: + delay: + description: delay duration in time units + format: duration + type: string + test: + description: object name + type: string + type: object + type: array + stopOnFailure: + type: boolean + required: + - stopOnFailure + type: object + type: array + before: + description: Before batch steps is list of batch tests which will + be sequentially orchestrated for parallel tests in each batch + items: + description: set of steps run in parallel + properties: + execute: + items: + description: TestSuiteStepSpec for particular type will have + config for possible step types + properties: + delay: + description: delay duration in time units + format: duration + type: string + test: + description: object name + type: string + type: object + type: array + stopOnFailure: + type: boolean + required: + - stopOnFailure + type: object + type: array + description: + type: string + executionRequest: + description: test suite execution request body + properties: + cronJobTemplate: + description: cron job template extensions + type: string + executionLabels: + additionalProperties: + type: string + description: execution labels + type: object + httpProxy: + description: http proxy for executor containers + type: string + httpsProxy: + description: https proxy for executor containers + type: string + labels: + additionalProperties: + type: string + description: test suite labels + type: object + name: + description: test execution custom name + type: string + namespace: + description: test kubernetes namespace (\"testkube\" when not + set) + type: string + secretUUID: + description: secret uuid + type: string + sync: + description: whether to start execution sync or async + type: boolean + timeout: + description: timeout for test suite execution + format: int32 + type: integer + variables: + additionalProperties: + properties: + name: + description: variable name + type: string + type: + description: variable type + type: string + value: + description: variable string value + type: string + valueFrom: + description: or load it from var source + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + type: object + type: object + type: object + type: object + repeats: + type: integer + schedule: + description: schedule in cron job format for scheduled test execution + type: string + steps: + description: Batch steps is list of batch tests which will be sequentially + orchestrated for parallel tests in each batch + items: + description: set of steps run in parallel + properties: + execute: + items: + description: TestSuiteStepSpec for particular type will have + config for possible step types + properties: + delay: + description: delay duration in time units + format: duration + type: string + test: + description: object name + type: string + type: object + type: array + stopOnFailure: + type: boolean + required: + - stopOnFailure + type: object + type: array + type: object + status: + description: TestSuiteStatus defines the observed state of TestSuite + properties: + latestExecution: + description: latest execution result + properties: + endTime: + description: test suite execution end time + format: date-time + type: string + id: + description: execution id + type: string + startTime: + description: test suite execution start time + format: date-time + type: string + status: + type: string + type: object + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/config/samples/tests_v2_testsuite.yaml b/config/samples/tests_v2_testsuite.yaml index fa9cc751..04799ccc 100644 --- a/config/samples/tests_v2_testsuite.yaml +++ b/config/samples/tests_v2_testsuite.yaml @@ -5,11 +5,9 @@ metadata: spec: steps: - - type: delay - delay: + - delay: duration: 1000 - - type: executeTest - execute: + - execute: namespace: testkube name: sanity diff --git a/config/samples/tests_v3_testsuite.yaml b/config/samples/tests_v3_testsuite.yaml new file mode 100644 index 00000000..64792c1e --- /dev/null +++ b/config/samples/tests_v3_testsuite.yaml @@ -0,0 +1,13 @@ +apiVersion: tests.testkube.io/v3 +kind: TestSuite +metadata: + name: testsuite-sample +spec: + description: "Sample test suite" + steps: + - stopOnFailure: false + execute: + - test: test-sample + - stopOnFailure: false + execute: + - delay: 1s diff --git a/controllers/testsuite/suite_test.go b/controllers/testsuite/suite_test.go index bdc6ac9c..61b50fb0 100644 --- a/controllers/testsuite/suite_test.go +++ b/controllers/testsuite/suite_test.go @@ -30,7 +30,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - testsuitev1 "github.com/kubeshop/testkube-operator/apis/testsuite/v1" + testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" //+kubebuilder:scaffold:imports ) @@ -63,7 +63,7 @@ var _ = BeforeSuite(func() { Expect(err).NotTo(HaveOccurred()) Expect(cfg).NotTo(BeNil()) - err = testsuitev1.AddToScheme(scheme.Scheme) + err = testsuitev3.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) //+kubebuilder:scaffold:scheme diff --git a/controllers/testsuite/testsuite_controller.go b/controllers/testsuite/testsuite_controller.go index 556a4919..e6d90eef 100644 --- a/controllers/testsuite/testsuite_controller.go +++ b/controllers/testsuite/testsuite_controller.go @@ -26,7 +26,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" - testsuitev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" + testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" "github.com/kubeshop/testkube-operator/pkg/cronjob" ) @@ -54,7 +54,7 @@ func (r *TestSuiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( _ = log.FromContext(ctx) // Delete CronJob if it was created for deleted TestSuite - var testSuite testsuitev2.TestSuite + var testSuite testsuitev3.TestSuite err := r.Get(ctx, req.NamespacedName, &testSuite) if err != nil { if errors.IsNotFound(err) { @@ -79,9 +79,9 @@ func (r *TestSuiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( return ctrl.Result{}, nil } - data, err := json.Marshal(testsuitev2.TestSuiteExecutionRequest{ - RunningContext: &testsuitev2.RunningContext{ - Type_: testsuitev2.RunningContextTypeScheduler, + data, err := json.Marshal(testsuitev3.TestSuiteExecutionRequest{ + RunningContext: &testsuitev3.RunningContext{ + Type_: testsuitev3.RunningContextTypeScheduler, Context: testSuite.Spec.Schedule, }, }) @@ -129,6 +129,6 @@ func (r *TestSuiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( // SetupWithManager sets up the controller with the Manager. func (r *TestSuiteReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). - For(&testsuitev2.TestSuite{}). + For(&testsuitev3.TestSuite{}). Complete(r) } diff --git a/main.go b/main.go index 04baec6c..f450c090 100644 --- a/main.go +++ b/main.go @@ -47,6 +47,7 @@ import ( testsourcev1 "github.com/kubeshop/testkube-operator/apis/testsource/v1" testsuitev1 "github.com/kubeshop/testkube-operator/apis/testsuite/v1" testsuitev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" + testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" executorcontrollers "github.com/kubeshop/testkube-operator/controllers/executor" scriptcontrollers "github.com/kubeshop/testkube-operator/controllers/script" testscontrollers "github.com/kubeshop/testkube-operator/controllers/tests" @@ -82,6 +83,7 @@ func init() { utilruntime.Must(testsuitev2.AddToScheme(scheme)) utilruntime.Must(testtriggersv1.AddToScheme(scheme)) utilruntime.Must(testsourcev1.AddToScheme(scheme)) + utilruntime.Must(testsuitev3.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } @@ -211,6 +213,10 @@ func main() { setupLog.Error(err, "unable to create webhook", "webhook", "TestSuite") os.Exit(1) } + if err = (&testsuitev3.TestSuite{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "TestSuite") + os.Exit(1) + } testtriggerValidator := testtriggerscontrollers.NewValidator(mgr.GetClient()) if err = (&testtriggersv1.TestTrigger{}).SetupWebhookWithManager(mgr, testtriggerValidator); err != nil { setupLog.Error(err, "unable to create webhook", "webhook", "TestTrigger") diff --git a/pkg/clientset/versioned/fake/register.go b/pkg/clientset/versioned/fake/register.go index ad45cb14..8cbb55a3 100644 --- a/pkg/clientset/versioned/fake/register.go +++ b/pkg/clientset/versioned/fake/register.go @@ -18,7 +18,7 @@ package fake import ( testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" - testsuitev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" + testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" testtriggersv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" @@ -32,7 +32,7 @@ var codecs = serializer.NewCodecFactory(scheme) var localSchemeBuilder = runtime.SchemeBuilder{ testtriggersv1.AddToScheme, - testsuitev2.AddToScheme, + testsuitev3.AddToScheme, testsv3.AddToScheme, } diff --git a/pkg/clientset/versioned/scheme/register.go b/pkg/clientset/versioned/scheme/register.go index 47313a91..4b006c21 100644 --- a/pkg/clientset/versioned/scheme/register.go +++ b/pkg/clientset/versioned/scheme/register.go @@ -18,7 +18,7 @@ package scheme import ( testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" - testsuitev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" + testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" testtriggersv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" @@ -32,7 +32,7 @@ var Codecs = serializer.NewCodecFactory(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme) var localSchemeBuilder = runtime.SchemeBuilder{ testtriggersv1.AddToScheme, - testsuitev2.AddToScheme, + testsuitev3.AddToScheme, testsv3.AddToScheme, } diff --git a/pkg/clientset/versioned/typed/tests/v3/fake/fake_tests_client.go b/pkg/clientset/versioned/typed/tests/v3/fake/fake_tests_client.go index 3d8127d9..2762fe3a 100644 --- a/pkg/clientset/versioned/typed/tests/v3/fake/fake_tests_client.go +++ b/pkg/clientset/versioned/typed/tests/v3/fake/fake_tests_client.go @@ -30,6 +30,10 @@ func (c *FakeTestsV3) Tests(namespace string) v3.TestInterface { return &FakeTests{c, namespace} } +func (c *FakeTestsV3) TestSuites(namespace string) v3.TestSuiteInterface { + return &FakeTestSuites{c, namespace} +} + // RESTClient returns a RESTClient that is used to communicate // with API server by this client implementation. func (c *FakeTestsV3) RESTClient() rest.Interface { diff --git a/pkg/clientset/versioned/typed/tests/v3/fake/fake_testsuite.go b/pkg/clientset/versioned/typed/tests/v3/fake/fake_testsuite.go new file mode 100644 index 00000000..ac2ce3d0 --- /dev/null +++ b/pkg/clientset/versioned/typed/tests/v3/fake/fake_testsuite.go @@ -0,0 +1,72 @@ +/* +Copyright 2021. + +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 fake + +import ( + "context" + "fmt" + + testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/testing" +) + +// FakeTestSuites implements TestSuiteInterface +type FakeTestSuites struct { + Fake *FakeTestsV3 + ns string +} + +var testSuitesResource = schema.GroupVersionResource{Group: "tests.testkube.io", Version: "v3", Resource: "TestSuite"} + +var testSuitesKind = schema.GroupVersionKind{Group: "tests.testkube.io", Version: "v3", Kind: "TestSuite"} + +// List takes label and field selectors, and returns the list of TestSuites that match those selectors. +func (c *FakeTestSuites) List(ctx context.Context, opts v1.ListOptions) (result *testsuitev3.TestSuiteList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(testSuitesResource, testSuitesKind, c.ns, opts), &testsuitev3.TestSuiteList{}) + + if err != nil { + return nil, err + } + + if obj == nil { + return nil, fmt.Errorf("empty object") + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &testsuitev3.TestSuiteList{ListMeta: obj.(*testsuitev3.TestSuiteList).ListMeta} + for _, item := range obj.(*testsuitev3.TestSuiteList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested testSuites. +func (c *FakeTestSuites) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(testSuitesResource, c.ns, opts)) +} diff --git a/pkg/clientset/versioned/typed/tests/v3/generated_expansion.go b/pkg/clientset/versioned/typed/tests/v3/generated_expansion.go index 9e09a912..f80f350f 100644 --- a/pkg/clientset/versioned/typed/tests/v3/generated_expansion.go +++ b/pkg/clientset/versioned/typed/tests/v3/generated_expansion.go @@ -17,3 +17,5 @@ limitations under the License. package v3 type TestExpansion interface{} + +type TestSuiteExpansion interface{} diff --git a/pkg/clientset/versioned/typed/tests/v3/tests_client.go b/pkg/clientset/versioned/typed/tests/v3/tests_client.go index d448bdee..e2b817ab 100644 --- a/pkg/clientset/versioned/typed/tests/v3/tests_client.go +++ b/pkg/clientset/versioned/typed/tests/v3/tests_client.go @@ -28,6 +28,7 @@ import ( type TestsV3Interface interface { RESTClient() rest.Interface TestsGetter + TestSuitesGetter } // TestsV3Client is used to interact with features provided by the tests.testkube.io group. @@ -39,6 +40,10 @@ func (c *TestsV3Client) Tests(namespace string) TestInterface { return newTests(c, namespace) } +func (c *TestsV3Client) TestSuites(namespace string) TestSuiteInterface { + return newTestSuites(c, namespace) +} + // NewForConfig creates a new TestsV3Client for the given config. // NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), // where httpClient was generated with rest.HTTPClientFor(c). diff --git a/pkg/clientset/versioned/typed/tests/v3/testsuite.go b/pkg/clientset/versioned/typed/tests/v3/testsuite.go new file mode 100644 index 00000000..9d3bbfa6 --- /dev/null +++ b/pkg/clientset/versioned/typed/tests/v3/testsuite.go @@ -0,0 +1,88 @@ +/* +Copyright 2021. + +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 v3 + +import ( + "context" + "time" + + testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/scheme" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/rest" +) + +// TestSuitesGetter has a method to return a TestSuiteInterface. +// A group's client should implement this interface. +type TestSuitesGetter interface { + TestSuites(namespace string) TestSuiteInterface +} + +// TestSuiteInterface has methods to work with TestSuite resources. +type TestSuiteInterface interface { + List(ctx context.Context, opts v1.ListOptions) (*testsuitev3.TestSuiteList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + TestSuiteExpansion +} + +// testSuites implements TestSuiteInterface +type testSuites struct { + client rest.Interface + ns string +} + +// newTestSuites returns a TestSuites +func newTestSuites(c *TestsV3Client, namespace string) *testSuites { + return &testSuites{ + client: c.RESTClient(), + ns: namespace, + } +} + +// List takes label and field selectors, and returns the list of TestSuites that match those selectors. +func (c *testSuites) List(ctx context.Context, opts v1.ListOptions) (result *testsuitev3.TestSuiteList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &testsuitev3.TestSuiteList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("testsuites"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested testSuites. +func (c *testSuites) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("testsuites"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} diff --git a/pkg/informers/externalversions/generic.go b/pkg/informers/externalversions/generic.go index 1948a10b..0ce0e452 100644 --- a/pkg/informers/externalversions/generic.go +++ b/pkg/informers/externalversions/generic.go @@ -18,8 +18,8 @@ package externalversions import ( testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" - testsv2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" - testsv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" + testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + testtriggersv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" "github.com/pkg/errors" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -53,16 +53,16 @@ func (f *genericInformer) Lister() cache.GenericLister { func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { // Group=tests.testkube.io, Version=v1 - case testsv1.GroupVersionResource: + case testtriggersv1.GroupVersionResource: return &genericInformer{ resource: resource.GroupResource(), informer: f.Tests().V1().TestTriggers().Informer(), }, nil - // Group=tests.testkube.io, Version=v2 - case testsv2.GroupVersionResource: + // Group=tests.testkube.io, Version=v3 + case testsuitev3.GroupVersionResource: return &genericInformer{ resource: resource.GroupResource(), - informer: f.Tests().V2().TestSuites().Informer(), + informer: f.Tests().V3().TestSuites().Informer(), }, nil // Group=tests.testkube.io, Version=v3 case testsv3.GroupVersionResource: diff --git a/pkg/informers/externalversions/tests/v3/interface.go b/pkg/informers/externalversions/tests/v3/interface.go index e03ca32a..c5c1e9c1 100644 --- a/pkg/informers/externalversions/tests/v3/interface.go +++ b/pkg/informers/externalversions/tests/v3/interface.go @@ -22,6 +22,8 @@ import "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/int type Interface interface { // Tests returns a TestInformer. Tests() TestInformer + // TestSuites returns a TestSuiteInformer. + TestSuites() TestSuiteInformer } type version struct { @@ -43,3 +45,8 @@ func New( func (v *version) Tests() TestInformer { return &testInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } + +// TestSuites returns a TestSuiteInformer. +func (v *version) TestSuites() TestSuiteInformer { + return &testSuiteInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/informers/externalversions/tests/v3/testsuite.go b/pkg/informers/externalversions/tests/v3/testsuite.go new file mode 100644 index 00000000..b62bb70a --- /dev/null +++ b/pkg/informers/externalversions/tests/v3/testsuite.go @@ -0,0 +1,94 @@ +/* +Copyright 2021. + +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 v3 + +import ( + "context" + "time" + + testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + "github.com/kubeshop/testkube-operator/pkg/clientset/versioned" + "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/internalinterfaces" + testsuiteslisterv3 "github.com/kubeshop/testkube-operator/pkg/listers/tests/v3" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/tools/cache" +) + +// TestSuiteInformer provides access to a shared informer and lister for TestSuite. +type TestSuiteInformer interface { + Informer() cache.SharedIndexInformer + Lister() testsuiteslisterv3.TestSuiteLister +} + +type testSuiteInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewTestSuiteInformer constructs a new informer for TestSuite type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory print and number of connections to the server. +func NewTestSuiteInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredTestSuiteInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredTestSuiteInformer constructs a new informer for TestSuite type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory print and number of connections to the server. +func NewFilteredTestSuiteInformer( + client versioned.Interface, + namespace string, + resyncPeriod time.Duration, + indexers cache.Indexers, + tweakListOptions internalinterfaces.TweakListOptionsFunc, +) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TestsV3().TestSuites(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TestsV3().TestSuites(namespace).Watch(context.TODO(), options) + }, + }, + &testsuitev3.TestSuite{}, + resyncPeriod, + indexers, + ) +} + +func (f *testSuiteInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredTestSuiteInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *testSuiteInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&testsuitev3.TestSuite{}, f.defaultInformer) +} + +func (f *testSuiteInformer) Lister() testsuiteslisterv3.TestSuiteLister { + return testsuiteslisterv3.NewTestSuiteLister(f.Informer().GetIndexer()) +} diff --git a/pkg/listers/tests/v3/expansion_generated.go b/pkg/listers/tests/v3/expansion_generated.go index 489fe037..0f662dee 100644 --- a/pkg/listers/tests/v3/expansion_generated.go +++ b/pkg/listers/tests/v3/expansion_generated.go @@ -22,3 +22,10 @@ type TestListerExpansion interface{} // TestNamespaceListerExpansion allows custom methods to be added to // TestNamespaceLister. type TestNamespaceListerExpansion interface{} + +// TestSuiteListerExpansion allows custom methods to be added to TestSuiteLister. +type TestSuiteListerExpansion interface{} + +// TestSuiteNamespaceListerExpansion allows custom methods to be added to +// TestSuiteNamespaceLister. +type TestSuiteNamespaceListerExpansion interface{} diff --git a/pkg/listers/tests/v3/testsuites.go b/pkg/listers/tests/v3/testsuites.go new file mode 100644 index 00000000..68913d65 --- /dev/null +++ b/pkg/listers/tests/v3/testsuites.go @@ -0,0 +1,101 @@ +/* +Copyright 2021. + +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 v3 + +import ( + testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/tools/cache" +) + +// TestSuiteLister helps list TestSuites. +// All objects returned here must be treated as read-only. +type TestSuiteLister interface { + // List lists all TestSuites in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*testsuitev3.TestSuite, err error) + // TestSuites returns an object that can list and get TestSuites. + TestSuites(namespace string) TestSuiteNamespaceLister + TestSuiteListerExpansion +} + +// testSuiteLister implements the TestSuiteLister interface. +type testSuiteLister struct { + indexer cache.Indexer +} + +// NewTestSuiteLister returns a new TestSuiteLister. +func NewTestSuiteLister(indexer cache.Indexer) TestSuiteLister { + return &testSuiteLister{indexer: indexer} +} + +// List lists all TestSuites in the indexer. +func (s *testSuiteLister) List(selector labels.Selector) (ret []*testsuitev3.TestSuite, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*testsuitev3.TestSuite)) + }) + return ret, err +} + +// TestSuites returns an object that can list and get TestSuites. +func (s *testSuiteLister) TestSuites(namespace string) TestSuiteNamespaceLister { + return testSuiteNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// TestSuiteNamespaceLister helps list and get TestSuites. +// All objects returned here must be treated as read-only. +type TestSuiteNamespaceLister interface { + // List lists all TestSuites in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*testsuitev3.TestSuite, err error) + // Get retrieves the TestSuite from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*testsuitev3.TestSuite, error) + TestSuiteNamespaceListerExpansion +} + +// testSuiteNamespaceLister implements the TestSuiteNamespaceLister +// interface. +type testSuiteNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all TestSuites in the indexer for a given namespace. +func (s testSuiteNamespaceLister) List(selector labels.Selector) (ret []*testsuitev3.TestSuite, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*testsuitev3.TestSuite)) + }) + return ret, err +} + +// Get retrieves the TestSuite from the indexer for a given namespace and name. +func (s testSuiteNamespaceLister) Get(name string) (*testsuitev3.TestSuite, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound( + schema.GroupResource{Group: testsuitev3.GroupVersion.Group, Resource: testsuitev3.Resource}, + name, + ) + } + return obj.(*testsuitev3.TestSuite), nil +} From a2224e7e966e08a7c09785b487cf0144dc5bd300 Mon Sep 17 00:00:00 2001 From: nicufk <89570185+nicufk@users.noreply.github.com> Date: Thu, 22 Jun 2023 00:11:51 +0300 Subject: [PATCH 23/57] fix: remove run secrets as well (#139) debug fix: on deletion do not quit if something related to test could not be deleted, put in a single error fix: remove logging and improve errors fix: delete dependency error and delete test first --- client/tests/v3/test.go | 59 ++++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/client/tests/v3/test.go b/client/tests/v3/test.go index 5bd6dea8..a83bb35f 100644 --- a/client/tests/v3/test.go +++ b/client/tests/v3/test.go @@ -53,6 +53,19 @@ type Interface interface { UpdateStatus(test *testsv3.Test) error } +type DeleteDependenciesError struct { + testName string + allErrors []error +} + +func (e *DeleteDependenciesError) Error() string { + return fmt.Errorf("removing dependencies of test %s returned errors: %v", e.testName, e.allErrors).Error() +} + +func NewDeleteDependenciesError(testName string, allErrors []error) error { + return &DeleteDependenciesError{testName: testName, allErrors: allErrors} +} + // Option contain test source options type Option struct { Secrets map[string]string @@ -217,27 +230,47 @@ func (s TestsClient) Delete(name string) error { return err } - secretObj, err := s.LoadTestVariablesSecret(test) - secretExists := !errors.IsNotFound(err) - if err != nil && secretExists { + err = s.k8sClient.Delete(context.Background(), test) + if err != nil { return err } + var allErrors []error + + secretObj, err := s.LoadTestVariablesSecret(test) + if err != nil { + allErrors = append(allErrors, err) + } + // delete secret only if exists ignore otherwise - if err == nil && secretObj != nil { - if err = s.k8sClient.Delete(context.Background(), secretObj); err != nil { - return err + if err != nil && secretObj != nil { + err = s.k8sClient.Delete(context.Background(), secretObj) + if err != nil { + allErrors = append(allErrors, err) + } + } + + runSecrets, err := s.LoadTestRunSecrets(test) + runSecretsExists := !errors.IsNotFound(err) + if err != nil { + allErrors = append(allErrors, err) + } + + if runSecretsExists && runSecrets != nil { + for _, secret := range runSecrets.Items { + if err := s.k8sClient.Delete(context.Background(), &secret); err != nil && !errors.IsNotFound(err) { + allErrors = append(allErrors, err) + } } } secretName := secret.GetMetadataName(test.Name, secretKind) if err := s.secretClient.Delete(secretName); err != nil && !errors.IsNotFound(err) { - return err + allErrors = append(allErrors, err) } - err = s.k8sClient.Delete(context.Background(), test) - if err != nil { - return err + if len(allErrors) != 0 { + return NewDeleteDependenciesError(name, allErrors) } return nil @@ -360,6 +393,12 @@ func (s TestsClient) LoadTestVariablesSecret(test *testsv3.Test) (*corev1.Secret return secret, err } +func (s TestsClient) LoadTestRunSecrets(test *testsv3.Test) (*corev1.SecretList, error) { + secret := &corev1.SecretList{} + err := s.k8sClient.List(context.Background(), secret, &client.ListOptions{Namespace: s.namespace, LabelSelector: labels.SelectorFromSet(labels.Set{"testName": test.Name})}) + return secret, err +} + // GetCurrentSecretUUID returns current secret uuid func (s TestsClient) GetCurrentSecretUUID(testName string) (string, error) { secret := &corev1.Secret{} From 30d80e4cc3a459677253aa5e04320c48162f810f Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 22 Jun 2023 18:47:18 +0300 Subject: [PATCH 24/57] feat: postrun script (#156) * fix: post run scipt model * fix: add postrun script to crd --- apis/tests/v3/test_types.go | 4 +++- config/crd/bases/tests.testkube.io_tests.yaml | 13 ++++++------- config/crd/bases/tests.testkube.io_testsources.yaml | 6 ------ 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/apis/tests/v3/test_types.go b/apis/tests/v3/test_types.go index 45a6a09b..e3a63ac5 100644 --- a/apis/tests/v3/test_types.go +++ b/apis/tests/v3/test_types.go @@ -197,8 +197,10 @@ type ExecutionRequest struct { JobTemplate string `json:"jobTemplate,omitempty"` // cron job template extensions CronJobTemplate string `json:"cronJobTemplate,omitempty"` - // script to run before test execution + // script to run before test execution (not supported for container executors) PreRunScript string `json:"preRunScript,omitempty"` + // script to run after test execution (not supported for container executors) + PostRunScript string `json:"postRunScript,omitempty"` // scraper template extensions ScraperTemplate string `json:"scraperTemplate,omitempty"` // config map references diff --git a/config/crd/bases/tests.testkube.io_tests.yaml b/config/crd/bases/tests.testkube.io_tests.yaml index f2684bb9..1f9c63cf 100644 --- a/config/crd/bases/tests.testkube.io_tests.yaml +++ b/config/crd/bases/tests.testkube.io_tests.yaml @@ -388,9 +388,6 @@ spec: name: description: object name type: string - namespace: - description: object kubernetes namespace - type: string required: - key - name @@ -411,9 +408,6 @@ spec: name: description: object name type: string - namespace: - description: object kubernetes namespace - type: string required: - key - name @@ -591,8 +585,13 @@ spec: description: test execution number format: int32 type: integer + postRunScript: + description: script to run after test execution (not supported + for container executors) + type: string preRunScript: - description: script to run before test execution + description: script to run before test execution (not supported + for container executors) type: string scraperTemplate: description: scraper template extensions diff --git a/config/crd/bases/tests.testkube.io_testsources.yaml b/config/crd/bases/tests.testkube.io_testsources.yaml index 378a50f2..f801d513 100644 --- a/config/crd/bases/tests.testkube.io_testsources.yaml +++ b/config/crd/bases/tests.testkube.io_testsources.yaml @@ -70,9 +70,6 @@ spec: name: description: object name type: string - namespace: - description: object kubernetes namespace - type: string required: - key - name @@ -93,9 +90,6 @@ spec: name: description: object name type: string - namespace: - description: object kubernetes namespace - type: string required: - key - name From 89ba17b6973b0d9bab7dafcee12568d85bd08d59 Mon Sep 17 00:00:00 2001 From: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Date: Tue, 27 Jun 2023 13:51:14 +0300 Subject: [PATCH 25/57] ci: remove release branch creation in helm-charts repo (#157) --- .github/workflows/docker-build-release.yaml | 26 --------------------- .github/workflows/docker-build-tag.yaml | 23 ++++-------------- 2 files changed, 4 insertions(+), 45 deletions(-) diff --git a/.github/workflows/docker-build-release.yaml b/.github/workflows/docker-build-release.yaml index d220c4ee..cc63fa03 100644 --- a/.github/workflows/docker-build-release.yaml +++ b/.github/workflows/docker-build-release.yaml @@ -59,32 +59,6 @@ jobs: run: | docker push kubeshop/testkube-operator:${{ steps.github_sha.outputs.sha_short }} - - name: Create a release branch in helm-chars repo - run: | - - # Set up variables for repository and branch name - REPO_OWNER=kubeshop - REPO_NAME=helm-charts - OLD_BRANCH_NAME=${GITHUB_REF} - RELEASE_TAG=$(basename "${OLD_BRANCH_NAME}") - - # Set up the new branch name - NEW_BRANCH_NAME="refs/heads/release/operator/${RELEASE_TAG}" - - # Set up authentication using a personal access token - AUTH_HEADER="Authorization: Bearer ${{ secrets.CI_BOT_TOKEN }}" - - # Check if branch already exists - STATUS=$(curl -s -o /dev/null -w '%{http_code}' -H "${AUTH_HEADER}" "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/branches/${NEW_BRANCH_NAME}") - - # If branch doesn't exist, create it - if [ "${STATUS}" -eq 404 ]; then - curl -X POST -H "${AUTH_HEADER}" -d '{"ref": "'"${NEW_BRANCH_NAME}"'","sha": "'"$(curl -s -H "${AUTH_HEADER}" "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/git/refs/heads/main" | jq -r '.object.sha')"'"}' "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/git/refs" - echo "Created branch ${NEW_BRANCH_NAME} in ${REPO_OWNER}/${REPO_NAME}" - else - echo "Branch ${NEW_BRANCH_NAME} already exists in ${REPO_OWNER}/${REPO_NAME}" - fi - - name: Repository Dispatch uses: peter-evans/repository-dispatch@v2 with: diff --git a/.github/workflows/docker-build-tag.yaml b/.github/workflows/docker-build-tag.yaml index 48910458..bd2beb89 100644 --- a/.github/workflows/docker-build-tag.yaml +++ b/.github/workflows/docker-build-tag.yaml @@ -82,25 +82,10 @@ jobs: export RELEASE_VERSION export SERVICE - # Check if release branch exists in helm-charts repository - REPO_OWNER=kubeshop - REPO_NAME=helm-charts - RELEASE_BRANCH_NAME=release/$SERVICE/$RELEASE_VERSION - echo $RELEASE_VERSION - STATUS=$(curl -s -o /dev/null -w '%{http_code}' -H "${AUTH_HEADER}" "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/branches/${RELEASE_BRANCH_NAME}") - - if [ "${STATUS}" -eq 404 ]; then - git fetch origin main - git checkout main - cd ./scripts - ./chart_releaser.sh --helm-chart-folder testkube-$SERVICE - else - git fetch origin "release/$SERVICE/$RELEASE_VERSION" - git checkout "release/$SERVICE/$RELEASE_VERSION" - echo "Switched to release branch" - cd ./scripts - ./chart_releaser.sh --helm-chart-folder testkube-$SERVICE --branch true - fi + git fetch origin main + git checkout main + cd ./scripts + ./chart_releaser.sh --helm-chart-folder testkube-$SERVICE env: SERVICE: operator From e416a8cfd884ea859385f2727f52cfc569c4fa39 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 3 Jul 2023 16:10:03 +0300 Subject: [PATCH 26/57] feat: probe conditions (#158) * feat: probe spec model * feat: test trigger crd with probes * fix: refactor probe definition * fix: unit tests --- apis/testtriggers/v1/testtrigger_types.go | 28 ++++++++++ apis/testtriggers/v1/zz_generated.deepcopy.go | 49 +++++++++++++++++ .../bases/tests.testkube.io_testtriggers.yaml | 48 ++++++++++++++++ .../testtriggers/testtrigger_validator.go | 35 ++++++++++++ .../testtrigger_validator_test.go | 55 +++++++++++++++++++ 5 files changed, 215 insertions(+) diff --git a/apis/testtriggers/v1/testtrigger_types.go b/apis/testtriggers/v1/testtrigger_types.go index 1ad9301b..89fd2f78 100644 --- a/apis/testtriggers/v1/testtrigger_types.go +++ b/apis/testtriggers/v1/testtrigger_types.go @@ -49,6 +49,8 @@ type TestTriggerSpec struct { Event TestTriggerEvent `json:"event"` // What resource conditions should be matched ConditionSpec *TestTriggerConditionSpec `json:"conditionSpec,omitempty"` + // What resource probes should be matched + ProbeSpec *TestTriggerProbeSpec `json:"probeSpec,omitempty"` // Action represents what needs to be executed for selected Execution Action TestTriggerAction `json:"action"` // Execution identifies for which test execution should an Action be executed @@ -155,6 +157,32 @@ type TestTriggerConditionSpec struct { Conditions []TestTriggerCondition `json:"conditions,omitempty"` // duration in seconds the test trigger waits for conditions, until its stopped Timeout int32 `json:"timeout,omitempty"` + // duration in seconds the test trigger waits between condition check + Delay int32 `json:"delay,omitempty"` +} + +// TestTriggerProbe is used for definition of the probe for test triggers +type TestTriggerProbe struct { + // test trigger condition probe scheme to connect to host, default is http + Scheme string `json:"scheme,omitempty"` + // test trigger condition probe host, default is pod ip or service name + Host string `json:"host,omitempty"` + // test trigger condition probe path to check, default is / + Path string `json:"path,omitempty"` + // test trigger condition probe port to connect + Port int32 `json:"port,omitempty"` + // test trigger condition probe headers to submit + Headers map[string]string `json:"headers,omitempty"` +} + +// TestTriggerProbeSpec defines the probe specification for TestTrigger +type TestTriggerProbeSpec struct { + // list of test trigger probes + Probes []TestTriggerProbe `json:"probes,omitempty"` + // duration in seconds the test trigger waits for probes, until its stopped + Timeout int32 `json:"timeout,omitempty"` + // duration in seconds the test trigger waits between probes + Delay int32 `json:"delay,omitempty"` } //+kubebuilder:object:root=true diff --git a/apis/testtriggers/v1/zz_generated.deepcopy.go b/apis/testtriggers/v1/zz_generated.deepcopy.go index ed105f73..de6b839b 100644 --- a/apis/testtriggers/v1/zz_generated.deepcopy.go +++ b/apis/testtriggers/v1/zz_generated.deepcopy.go @@ -127,6 +127,50 @@ func (in *TestTriggerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestTriggerProbe) DeepCopyInto(out *TestTriggerProbe) { + *out = *in + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestTriggerProbe. +func (in *TestTriggerProbe) DeepCopy() *TestTriggerProbe { + if in == nil { + return nil + } + out := new(TestTriggerProbe) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestTriggerProbeSpec) DeepCopyInto(out *TestTriggerProbeSpec) { + *out = *in + if in.Probes != nil { + in, out := &in.Probes, &out.Probes + *out = make([]TestTriggerProbe, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestTriggerProbeSpec. +func (in *TestTriggerProbeSpec) DeepCopy() *TestTriggerProbeSpec { + if in == nil { + return nil + } + out := new(TestTriggerProbeSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TestTriggerSelector) DeepCopyInto(out *TestTriggerSelector) { *out = *in @@ -156,6 +200,11 @@ func (in *TestTriggerSpec) DeepCopyInto(out *TestTriggerSpec) { *out = new(TestTriggerConditionSpec) (*in).DeepCopyInto(*out) } + if in.ProbeSpec != nil { + in, out := &in.ProbeSpec, &out.ProbeSpec + *out = new(TestTriggerProbeSpec) + (*in).DeepCopyInto(*out) + } in.TestSelector.DeepCopyInto(&out.TestSelector) if in.Delay != nil { in, out := &in.Delay, &out.Delay diff --git a/config/crd/bases/tests.testkube.io_testtriggers.yaml b/config/crd/bases/tests.testkube.io_testtriggers.yaml index d336a351..0bd9b881 100644 --- a/config/crd/bases/tests.testkube.io_testtriggers.yaml +++ b/config/crd/bases/tests.testkube.io_testtriggers.yaml @@ -87,6 +87,11 @@ spec: - type type: object type: array + delay: + description: duration in seconds the test trigger waits between + condition check + format: int32 + type: integer timeout: description: duration in seconds the test trigger waits for conditions, until its stopped @@ -116,6 +121,49 @@ spec: - test - testsuite type: string + probeSpec: + description: What resource probes should be matched + properties: + delay: + description: duration in seconds the test trigger waits between + probes + format: int32 + type: integer + probes: + description: list of test trigger probes + items: + description: TestTriggerProbe is used for definition of the + probe for test triggers + properties: + headers: + additionalProperties: + type: string + description: test trigger condition probe headers to submit + type: object + host: + description: test trigger condition probe host, default + is pod ip or service name + type: string + path: + description: test trigger condition probe path to check, + default is / + type: string + port: + description: test trigger condition probe port to connect + format: int32 + type: integer + scheme: + description: test trigger condition probe scheme to connect + to host, default is http + type: string + type: object + type: array + timeout: + description: duration in seconds the test trigger waits for probes, + until its stopped + format: int32 + type: integer + type: object resource: description: For which Resource do we monitor Event which triggers an Action on certain conditions diff --git a/controllers/testtriggers/testtrigger_validator.go b/controllers/testtriggers/testtrigger_validator.go index e147ed15..6ac53494 100644 --- a/controllers/testtriggers/testtrigger_validator.go +++ b/controllers/testtriggers/testtrigger_validator.go @@ -53,6 +53,10 @@ func (v *Validator) ValidateCreate(ctx context.Context, t *testtriggerv1.TestTri allErrs = append(allErrs, errs...) } + if errs := v.validateProbes(t.Spec.ProbeSpec); errs != nil { + allErrs = append(allErrs, errs...) + } + if err := v.validateExecution(t.Spec.Execution); err != nil { allErrs = append(allErrs, err) } @@ -94,6 +98,10 @@ func (v *Validator) ValidateUpdate(ctx context.Context, old runtime.Object, new allErrs = append(allErrs, errs...) } + if errs := v.validateProbes(new.Spec.ProbeSpec); errs != nil { + allErrs = append(allErrs, errs...) + } + if err := v.validateExecution(new.Spec.Execution); err != nil { allErrs = append(allErrs, err) } @@ -212,6 +220,12 @@ func (v *Validator) validateConditions(conditionSpec *testtriggerv1.TestTriggerC allErrs = append(allErrs, verr) } + if conditionSpec.Delay < 0 { + fld := field.NewPath("spec").Child("conditionSpec").Child("delay") + verr := field.Invalid(fld, conditionSpec.Delay, "delay is negative") + allErrs = append(allErrs, verr) + } + for _, condition := range conditionSpec.Conditions { if condition.Type_ == "" { fld := field.NewPath("spec").Child("conditionSpec").Child("conditions").Child("condition") @@ -235,4 +249,25 @@ func (v *Validator) validateConditions(conditionSpec *testtriggerv1.TestTriggerC return allErrs } +func (v *Validator) validateProbes(probeSpec *testtriggerv1.TestTriggerProbeSpec) field.ErrorList { + var allErrs field.ErrorList + if probeSpec == nil { + return allErrs + } + + if probeSpec.Timeout < 0 { + fld := field.NewPath("spec").Child("probeSpec").Child("timeout") + verr := field.Invalid(fld, probeSpec.Timeout, "timeout is negative") + allErrs = append(allErrs, verr) + } + + if probeSpec.Delay < 0 { + fld := field.NewPath("spec").Child("probeSpec").Child("delay") + verr := field.Invalid(fld, probeSpec.Delay, "delay is negative") + allErrs = append(allErrs, verr) + } + + return allErrs +} + var _ testtriggerv1.TestTriggerValidator = &Validator{} diff --git a/controllers/testtriggers/testtrigger_validator_test.go b/controllers/testtriggers/testtrigger_validator_test.go index 0895c4e9..f2b1d446 100644 --- a/controllers/testtriggers/testtrigger_validator_test.go +++ b/controllers/testtriggers/testtrigger_validator_test.go @@ -215,6 +215,17 @@ func TestValidator_validateConditions(t *testing.T) { assert.ErrorContains(t, verrs[0], "spec.conditionSpec.timeout: Invalid value: -100: timeout is negative") }) + t.Run("error for invalid delay", func(t *testing.T) { + t.Parallel() + + verrs := v.validateConditions(&testtriggerv1.TestTriggerConditionSpec{ + Delay: -1, + }) + + assert.Len(t, verrs, 1) + assert.ErrorContains(t, verrs[0], "spec.conditionSpec.delay: Invalid value: -1: delay is negative") + }) + t.Run("error for invalid condition type", func(t *testing.T) { t.Parallel() @@ -253,3 +264,47 @@ func TestValidator_validateConditions(t *testing.T) { assert.ErrorContains(t, verrs[0], "spec.conditionSpec.conditions.condition: Unsupported value: \"\": supported values: \"True\", \"False\", \"Unknown\"") }) } + +func TestValidator_validateProbes(t *testing.T) { + t.Parallel() + + v := NewValidator(buildFakeK8sClient(t)) + + t.Run("no error for valid probe spec", func(t *testing.T) { + t.Parallel() + + verrs := v.validateProbes(&testtriggerv1.TestTriggerProbeSpec{ + Timeout: 50, + Probes: []testtriggerv1.TestTriggerProbe{ + { + Host: "testkube-api-server", + Path: "/health", + Port: 8088, + }, + }}) + + assert.Nil(t, verrs) + }) + + t.Run("error for invalid timeout", func(t *testing.T) { + t.Parallel() + + verrs := v.validateProbes(&testtriggerv1.TestTriggerProbeSpec{ + Timeout: -100, + }) + + assert.Len(t, verrs, 1) + assert.ErrorContains(t, verrs[0], "spec.probeSpec.timeout: Invalid value: -100: timeout is negative") + }) + + t.Run("error for invalid delay", func(t *testing.T) { + t.Parallel() + + verrs := v.validateProbes(&testtriggerv1.TestTriggerProbeSpec{ + Delay: -1, + }) + + assert.Len(t, verrs, 1) + assert.ErrorContains(t, verrs[0], "spec.probeSpec.delay: Invalid value: -1: delay is negative") + }) +} From 8815bd839764b5ec028bd02a216f88e3ec171f1d Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 6 Jul 2023 13:53:20 +0300 Subject: [PATCH 27/57] fix: don't remove non Testkube secrets (#160) --- client/tests/v3/test.go | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/client/tests/v3/test.go b/client/tests/v3/test.go index a83bb35f..e8858672 100644 --- a/client/tests/v3/test.go +++ b/client/tests/v3/test.go @@ -238,32 +238,18 @@ func (s TestsClient) Delete(name string) error { var allErrors []error secretObj, err := s.LoadTestVariablesSecret(test) - if err != nil { + if err != nil && !errors.IsNotFound(err) { allErrors = append(allErrors, err) } // delete secret only if exists ignore otherwise - if err != nil && secretObj != nil { + if err == nil && secretObj != nil { err = s.k8sClient.Delete(context.Background(), secretObj) if err != nil { allErrors = append(allErrors, err) } } - runSecrets, err := s.LoadTestRunSecrets(test) - runSecretsExists := !errors.IsNotFound(err) - if err != nil { - allErrors = append(allErrors, err) - } - - if runSecretsExists && runSecrets != nil { - for _, secret := range runSecrets.Items { - if err := s.k8sClient.Delete(context.Background(), &secret); err != nil && !errors.IsNotFound(err) { - allErrors = append(allErrors, err) - } - } - } - secretName := secret.GetMetadataName(test.Name, secretKind) if err := s.secretClient.Delete(secretName); err != nil && !errors.IsNotFound(err) { allErrors = append(allErrors, err) @@ -393,12 +379,6 @@ func (s TestsClient) LoadTestVariablesSecret(test *testsv3.Test) (*corev1.Secret return secret, err } -func (s TestsClient) LoadTestRunSecrets(test *testsv3.Test) (*corev1.SecretList, error) { - secret := &corev1.SecretList{} - err := s.k8sClient.List(context.Background(), secret, &client.ListOptions{Namespace: s.namespace, LabelSelector: labels.SelectorFromSet(labels.Set{"testName": test.Name})}) - return secret, err -} - // GetCurrentSecretUUID returns current secret uuid func (s TestsClient) GetCurrentSecretUUID(testName string) (string, error) { secret := &corev1.Secret{} From bc8cd9f59dc6cbf5952cfea5e969f213c094128f Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 17 Jul 2023 20:25:22 +0300 Subject: [PATCH 28/57] feat: remove outdated description (#164) --- apis/tests/v3/test_types.go | 4 ++-- config/crd/bases/tests.testkube.io_tests.yaml | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/apis/tests/v3/test_types.go b/apis/tests/v3/test_types.go index e3a63ac5..a3a654b7 100644 --- a/apis/tests/v3/test_types.go +++ b/apis/tests/v3/test_types.go @@ -197,9 +197,9 @@ type ExecutionRequest struct { JobTemplate string `json:"jobTemplate,omitempty"` // cron job template extensions CronJobTemplate string `json:"cronJobTemplate,omitempty"` - // script to run before test execution (not supported for container executors) + // script to run before test execution PreRunScript string `json:"preRunScript,omitempty"` - // script to run after test execution (not supported for container executors) + // script to run after test execution PostRunScript string `json:"postRunScript,omitempty"` // scraper template extensions ScraperTemplate string `json:"scraperTemplate,omitempty"` diff --git a/config/crd/bases/tests.testkube.io_tests.yaml b/config/crd/bases/tests.testkube.io_tests.yaml index 1f9c63cf..f377b380 100644 --- a/config/crd/bases/tests.testkube.io_tests.yaml +++ b/config/crd/bases/tests.testkube.io_tests.yaml @@ -586,12 +586,10 @@ spec: format: int32 type: integer postRunScript: - description: script to run after test execution (not supported - for container executors) + description: script to run after test execution type: string preRunScript: - description: script to run before test execution (not supported - for container executors) + description: script to run before test execution type: string scraperTemplate: description: scraper template extensions From edf3c1dc7c8cab30bbce9a8539020d122dc87c04 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 7 Aug 2023 13:00:13 +0300 Subject: [PATCH 29/57] fix: image registry (#166) --- main.go | 5 +++-- pkg/cronjob/client.go | 7 ++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index f450c090..a482a2f7 100644 --- a/main.go +++ b/main.go @@ -68,6 +68,7 @@ type config struct { Port int Fullname string TemplateCronjob string `split_words:"true"` + Registry string } func init() { @@ -147,7 +148,7 @@ func main() { if err = (&testscontrollers.TestReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), - CronJobClient: cronjob.NewClient(mgr.GetClient(), httpConfig.Fullname, httpConfig.Port, templateCronjob), + CronJobClient: cronjob.NewClient(mgr.GetClient(), httpConfig.Fullname, httpConfig.Port, templateCronjob, httpConfig.Registry), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Test") os.Exit(1) @@ -155,7 +156,7 @@ func main() { if err = (&testsuitecontrollers.TestSuiteReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), - CronJobClient: cronjob.NewClient(mgr.GetClient(), httpConfig.Fullname, httpConfig.Port, templateCronjob), + CronJobClient: cronjob.NewClient(mgr.GetClient(), httpConfig.Fullname, httpConfig.Port, templateCronjob, httpConfig.Registry), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "TestSuite") os.Exit(1) diff --git a/pkg/cronjob/client.go b/pkg/cronjob/client.go index ccb4db57..21dc2191 100644 --- a/pkg/cronjob/client.go +++ b/pkg/cronjob/client.go @@ -29,6 +29,7 @@ type Client struct { serviceName string servicePort int cronJobTemplate string + registry string } type CronJobOptions struct { @@ -51,15 +52,17 @@ type templateParameters struct { CronJobTemplateExtensions string Data string Labels map[string]string + Registry string } // NewClient is a method to create new cron job client -func NewClient(cli client.Client, serviceName string, servicePort int, cronJobTemplate string) *Client { +func NewClient(cli client.Client, serviceName string, servicePort int, cronJobTemplate, registry string) *Client { return &Client{ Client: cli, serviceName: serviceName, servicePort: servicePort, cronJobTemplate: cronJobTemplate, + registry: registry, } } @@ -87,6 +90,7 @@ func (c *Client) Create(ctx context.Context, id, name, namespace string, options CronJobTemplateExtensions: options.CronJobTemplateExtensions, Data: options.Data, Labels: options.Labels, + Registry: c.registry, } cronJobSpec, err := NewCronJobSpec(parameters) @@ -115,6 +119,7 @@ func (c *Client) Update(ctx context.Context, cronJob *batchv1.CronJob, id, name, CronJobTemplateExtensions: options.CronJobTemplateExtensions, Data: options.Data, Labels: options.Labels, + Registry: c.registry, } cronJobSpec, err := NewCronJobSpec(parameters) From 071c677e571a659a7f5029c372cd46a037694550 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Fri, 11 Aug 2023 12:58:59 +0300 Subject: [PATCH 30/57] feat: basic test execution crd (#165) * feat: basic test execution crd * feat: test execution CRD spec * fix: test execution client * fix: remove output * fix: update status method * fix: update get method * feat: test execution reconciler * fix: url port * fix: test name * fix: ignore status update * feat: test suite execution core * feat: test suite execution crd * feat: add unit tests * fix: test status * fix: remove not used structure * fix: api url typo * fix: running context * fix: generation field * fix: remove unused fields * fix: examples --- PROJECT | 24 +- apis/testexecution/v1/groupversion_info.go | 36 + apis/testexecution/v1/testexecution_types.go | 372 +++++ .../testexecution/v1/zz_generated.deepcopy.go | 506 +++++++ apis/tests/v3/test_types.go | 3 +- apis/testsource/v1/groupversion_info.go | 2 +- apis/testsuite/v3/zz_generated.deepcopy.go | 1 + .../v1/groupversion_info.go | 36 + .../v1/testsuiteexecution_types.go | 444 ++++++ .../v1/zz_generated.deepcopy.go | 736 +++++++++ client/client.go | 15 +- client/executors/v1/webhooks_test.go | 10 +- .../testexecutions/v1/mock_testexecutions.go | 108 ++ client/testexecutions/v1/testexecutions.go | 83 + .../testexecutions/v1/testexecutions_test.go | 130 ++ .../v1/mock_testsuiteexecutions.go | 108 ++ .../v1/testsuiteexecutions.go | 79 + .../v1/testsuiteexecutions_test.go | 130 ++ .../tests.testkube.io_testexecutions.yaml | 757 +++++++++ ...tests.testkube.io_testsuiteexecutions.yaml | 1348 +++++++++++++++++ config/crd/kustomization.yaml | 4 + .../patches/webhook_in_testexecutions.yaml | 16 + .../webhook_in_testsuiteexecutions.yaml | 16 + config/rbac/role.yaml | 53 + config/rbac/testexecution_editor_role.yaml | 24 + config/rbac/testexecution_viewer_role.yaml | 20 + .../rbac/testsuiteexecution_editor_role.yaml | 24 + .../rbac/testsuiteexecution_viewer_role.yaml | 20 + config/samples/tests_v1_testexecution.yaml | 13 + .../samples/tests_v1_testsuiteexecution.yaml | 14 + controllers/testexecution/suite_test.go | 80 + .../testexecution/testexecution_controller.go | 129 ++ controllers/tests/test_controller.go | 3 + controllers/testsuite/testsuite_controller.go | 3 + controllers/testsuiteexecution/suite_test.go | 80 + .../testsuiteexecution_controllller.go | 129 ++ go.mod | 1 + go.sum | 1 + main.go | 24 + 39 files changed, 5569 insertions(+), 13 deletions(-) create mode 100644 apis/testexecution/v1/groupversion_info.go create mode 100644 apis/testexecution/v1/testexecution_types.go create mode 100644 apis/testexecution/v1/zz_generated.deepcopy.go create mode 100644 apis/testsuiteexecution/v1/groupversion_info.go create mode 100644 apis/testsuiteexecution/v1/testsuiteexecution_types.go create mode 100644 apis/testsuiteexecution/v1/zz_generated.deepcopy.go create mode 100644 client/testexecutions/v1/mock_testexecutions.go create mode 100644 client/testexecutions/v1/testexecutions.go create mode 100644 client/testexecutions/v1/testexecutions_test.go create mode 100644 client/testsuiteexecutions/v1/mock_testsuiteexecutions.go create mode 100644 client/testsuiteexecutions/v1/testsuiteexecutions.go create mode 100644 client/testsuiteexecutions/v1/testsuiteexecutions_test.go create mode 100644 config/crd/bases/tests.testkube.io_testexecutions.yaml create mode 100644 config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml create mode 100644 config/crd/patches/webhook_in_testexecutions.yaml create mode 100644 config/crd/patches/webhook_in_testsuiteexecutions.yaml create mode 100644 config/rbac/testexecution_editor_role.yaml create mode 100644 config/rbac/testexecution_viewer_role.yaml create mode 100644 config/rbac/testsuiteexecution_editor_role.yaml create mode 100644 config/rbac/testsuiteexecution_viewer_role.yaml create mode 100644 config/samples/tests_v1_testexecution.yaml create mode 100644 config/samples/tests_v1_testsuiteexecution.yaml create mode 100644 controllers/testexecution/suite_test.go create mode 100644 controllers/testexecution/testexecution_controller.go create mode 100644 controllers/testsuiteexecution/suite_test.go create mode 100644 controllers/testsuiteexecution/testsuiteexecution_controllller.go diff --git a/PROJECT b/PROJECT index f0fcf684..57c4981c 100644 --- a/PROJECT +++ b/PROJECT @@ -1,3 +1,7 @@ +# Code generated by tool. DO NOT EDIT. +# This file is used to track the info used to scaffold your project +# and allow the plugins properly work. +# More info: https://book.kubebuilder.io/reference/project-config.html domain: testkube.io layout: - go.kubebuilder.io/v3 @@ -85,7 +89,7 @@ resources: domain: testkube.io group: tests kind: TestSource - path: github.com/kubeshop/testkube-operator/apis/tests/v1 + path: github.com/kubeshop/testkube-operator/apis/testsource/v1 version: v1 - api: crdVersion: v1 @@ -104,4 +108,22 @@ resources: kind: TestSuite path: github.com/kubeshop/testkube-operator/apis/testsuite/v3 version: v3 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: testkube.io + group: tests + kind: TestExecution + path: github.com/kubeshop/testkube-operator/apis/testexecution/v1 + version: v1 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: testkube.io + group: tests + kind: TestSuiteExecution + path: github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1 + version: v1 version: "3" diff --git a/apis/testexecution/v1/groupversion_info.go b/apis/testexecution/v1/groupversion_info.go new file mode 100644 index 00000000..87e950bb --- /dev/null +++ b/apis/testexecution/v1/groupversion_info.go @@ -0,0 +1,36 @@ +/* +Copyright 2021. + +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 v1 contains API Schema definitions for the test executions v1 API group +// +kubebuilder:object:generate=true +// +groupName=tests.testkube.io +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "tests.testkube.io", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/apis/testexecution/v1/testexecution_types.go b/apis/testexecution/v1/testexecution_types.go new file mode 100644 index 00000000..54370807 --- /dev/null +++ b/apis/testexecution/v1/testexecution_types.go @@ -0,0 +1,372 @@ +/* +Copyright 2021. + +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 v1 + +import ( + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +type Variable commonv1.Variable + +// artifact request body with test artifacts +type ArtifactRequest struct { + // artifact storage class name for container executor + StorageClassName string `json:"storageClassName"` + // artifact volume mount path for container executor + VolumeMountPath string `json:"volumeMountPath"` + // artifact directories for scraping + Dirs []string `json:"dirs,omitempty"` +} + +// running context for test or test suite execution +type RunningContext struct { + // One of possible context types + Type_ RunningContextType `json:"type"` + // Context value depending from its type + Context string `json:"context,omitempty"` +} + +// RunningContextType defines running context type +// +kubebuilder:validation:Enum=user-cli;user-ui;testsuite;testtrigger;scheduler;testexecution;testsuiteexecution +type RunningContextType string + +const ( + RunningContextTypeUserCLI RunningContextType = "user-cli" + RunningContextTypeUserUI RunningContextType = "user-ui" + RunningContextTypeTestSuite RunningContextType = "testsuite" + RunningContextTypeTestTrigger RunningContextType = "testtrigger" + RunningContextTypeScheduler RunningContextType = "scheduler" + RunningContextTypeTestExecution RunningContextType = "testexecution" + RunningContextTypeTestSuiteExecution RunningContextType = "testsuiteexecution" + RunningContextTypeEmpty RunningContextType = "" +) + +// test execution request body +type ExecutionRequest struct { + // test execution custom name + Name string `json:"name,omitempty"` + // unique test suite name (CRD Test suite name), if it's run as a part of test suite + TestSuiteName string `json:"testSuiteName,omitempty"` + // test execution number + Number int32 `json:"number,omitempty"` + // test execution labels + ExecutionLabels map[string]string `json:"executionLabels,omitempty"` + // test kubernetes namespace (\"testkube\" when not set) + Namespace string `json:"namespace,omitempty"` + // variables file content - need to be in format for particular executor (e.g. postman envs file) + VariablesFile string `json:"variablesFile,omitempty"` + IsVariablesFileUploaded bool `json:"isVariablesFileUploaded,omitempty"` + Variables map[string]Variable `json:"variables,omitempty"` + // test secret uuid + TestSecretUUID string `json:"testSecretUUID,omitempty"` + // test suite secret uuid, if it's run as a part of test suite + TestSuiteSecretUUID string `json:"testSuiteSecretUUID,omitempty"` + // additional executor binary arguments + Args []string `json:"args,omitempty"` + // usage mode for arguments + ArgsMode ArgsModeType `json:"argsMode,omitempty"` + // executor binary command + Command []string `json:"command,omitempty"` + // container executor image + Image string `json:"image,omitempty"` + // container executor image pull secrets + ImagePullSecrets []v1.LocalObjectReference `json:"imagePullSecrets,omitempty"` + // Environment variables passed to executor. + // Deprecated: use Basic Variables instead + Envs map[string]string `json:"envs,omitempty"` + // Execution variables passed to executor from secrets. + // Deprecated: use Secret Variables instead + SecretEnvs map[string]string `json:"secretEnvs,omitempty"` + // whether to start execution sync or async + Sync bool `json:"sync,omitempty"` + // http proxy for executor containers + HttpProxy string `json:"httpProxy,omitempty"` + // https proxy for executor containers + HttpsProxy string `json:"httpsProxy,omitempty"` + // negative test will fail the execution if it is a success and it will succeed if it is a failure + NegativeTest bool `json:"negativeTest,omitempty"` + // Optional duration in seconds the pod may be active on the node relative to + // StartTime before the system will actively try to mark it failed and kill associated containers. + // Value must be a positive integer. + ActiveDeadlineSeconds int64 `json:"activeDeadlineSeconds,omitempty"` + ArtifactRequest *ArtifactRequest `json:"artifactRequest,omitempty"` + // job template extensions + JobTemplate string `json:"jobTemplate,omitempty"` + // cron job template extensions + CronJobTemplate string `json:"cronJobTemplate,omitempty"` + // script to run before test execution + PreRunScript string `json:"preRunScript,omitempty"` + // script to run after test execution + PostRunScript string `json:"postRunScript,omitempty"` + // scraper template extensions + ScraperTemplate string `json:"scraperTemplate,omitempty"` + // config map references + EnvConfigMaps []EnvReference `json:"envConfigMaps,omitempty"` + // secret references + EnvSecrets []EnvReference `json:"envSecrets,omitempty"` + RunningContext *RunningContext `json:"runningContext,omitempty"` +} + +// ArgsModeType defines args mode type +// +kubebuilder:validation:Enum=append;override +type ArgsModeType string + +const ( + // ArgsModeTypeAppend for append args mode + ArgsModeTypeAppend ArgsModeType = "append" + // ArgsModeTypeOverride for override args mode + ArgsModeTypeOverride ArgsModeType = "override" +) + +// Reference to env resource +type EnvReference struct { + v1.LocalObjectReference `json:"reference"` + // whether we shoud mount resource + Mount bool `json:"mount,omitempty"` + // where we shoud mount resource + MountPath string `json:"mountPath,omitempty"` + // whether we shoud map to variables from resource + MapToVariables bool `json:"mapToVariables,omitempty"` +} + +type ObjectRef struct { + // object kubernetes namespace + Namespace string `json:"namespace,omitempty"` + // object name + Name string `json:"name"` +} + +// TestExecutionSpec defines the desired state of TestExecution +type TestExecutionSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + Test *ObjectRef `json:"test"` + ExecutionRequest *ExecutionRequest `json:"executionRequest,omitempty"` +} + +// test execution +type Execution struct { + // execution id + Id string `json:"id,omitempty"` + // unique test name (CRD Test name) + TestName string `json:"testName,omitempty"` + // unique test suite name (CRD Test suite name), if it's run as a part of test suite + TestSuiteName string `json:"testSuiteName,omitempty"` + // test namespace + TestNamespace string `json:"testNamespace,omitempty"` + // test type e.g. postman/collection + TestType string `json:"testType,omitempty"` + // execution name + Name string `json:"name,omitempty"` + // execution number + Number int32 `json:"number,omitempty"` + // Environment variables passed to executor. + // Deprecated: use Basic Variables instead + Envs map[string]string `json:"envs,omitempty"` + // executor image command + Command []string `json:"command,omitempty"` + // additional arguments/flags passed to executor binary + Args []string `json:"args,omitempty"` + // usage mode for arguments + ArgsMode ArgsModeType `json:"args_mode,omitempty"` + Variables map[string]Variable `json:"variables,omitempty"` + // in case the variables file is too big, it will be uploaded to storage + IsVariablesFileUploaded bool `json:"isVariablesFileUploaded,omitempty"` + // variables file content - need to be in format for particular executor (e.g. postman envs file) + VariablesFile string `json:"variablesFile,omitempty"` + // test secret uuid + TestSecretUUID string `json:"testSecretUUID,omitempty"` + // test suite secret uuid, if it's run as a part of test suite + TestSuiteSecretUUID string `json:"testSuiteSecretUUID,omitempty"` + Content *TestContent `json:"content,omitempty"` + // test start time + StartTime metav1.Time `json:"startTime,omitempty"` + // test end time + EndTime metav1.Time `json:"endTime,omitempty"` + // test duration + Duration string `json:"duration,omitempty"` + // test duration in milliseconds + DurationMs int32 `json:"durationMs,omitempty"` + ExecutionResult *ExecutionResult `json:"executionResult,omitempty"` + // test and execution labels + Labels map[string]string `json:"labels,omitempty"` + // list of file paths that need to be copied into the test from uploads + Uploads []string `json:"uploads,omitempty"` + // minio bucket name to get uploads from + BucketName string `json:"bucketName,omitempty"` + ArtifactRequest *ArtifactRequest `json:"artifactRequest,omitempty"` + // script to run before test execution + PreRunScript string `json:"preRunScript,omitempty"` + // script to run after test execution + PostRunScript string `json:"postRunScript,omitempty"` + RunningContext *RunningContext `json:"runningContext,omitempty"` + // shell used in container executor + ContainerShell string `json:"containerShell,omitempty"` +} + +// TestContent defines test content +type TestContent struct { + // test type + Type_ TestContentType `json:"type,omitempty"` + // repository of test content + Repository *Repository `json:"repository,omitempty"` + // test content body + Data string `json:"data,omitempty"` + // uri of test content + Uri string `json:"uri,omitempty"` +} + +// +kubebuilder:validation:Enum=string;file-uri;git-file;git-dir;git +type TestContentType string + +const ( + TestContentTypeString TestContentType = "string" + TestContentTypeFileURI TestContentType = "file-uri" + // Deprecated: use git instead + TestContentTypeGitFile TestContentType = "git-file" + // Deprecated: use git instead + TestContentTypeGitDir TestContentType = "git-dir" + TestContentTypeGit TestContentType = "git" +) + +// Testkube internal reference for secret storage in Kubernetes secrets +type SecretRef struct { + // object kubernetes namespace + Namespace string `json:"namespace,omitempty"` + // object name + Name string `json:"name"` + // object key + Key string `json:"key"` +} + +// Repository represents VCS repo, currently we're handling Git only +type Repository struct { + // VCS repository type + Type_ string `json:"type,omitempty"` + // uri of content file or git directory + Uri string `json:"uri,omitempty"` + // branch/tag name for checkout + Branch string `json:"branch,omitempty"` + // commit id (sha) for checkout + Commit string `json:"commit,omitempty"` + // if needed we can checkout particular path (dir or file) in case of BIG/mono repositories + Path string `json:"path,omitempty"` + UsernameSecret *SecretRef `json:"usernameSecret,omitempty"` + TokenSecret *SecretRef `json:"tokenSecret,omitempty"` + // git auth certificate secret for private repositories + CertificateSecret string `json:"certificateSecret,omitempty"` + // if provided we checkout the whole repository and run test from this directory + WorkingDir string `json:"workingDir,omitempty"` + // auth type for git requests + AuthType GitAuthType `json:"authType,omitempty"` +} + +// GitAuthType defines git auth type +// +kubebuilder:validation:Enum=basic;header +type GitAuthType string + +const ( + // GitAuthTypeBasic for git basic auth requests + GitAuthTypeBasic GitAuthType = "basic" + // GitAuthTypeHeader for git header auth requests + GitAuthTypeHeader GitAuthType = "header" +) + +// execution result returned from executor +type ExecutionResult struct { + Status *ExecutionStatus `json:"status"` + // error message when status is error, separate to output as output can be partial in case of error + ErrorMessage string `json:"errorMessage,omitempty"` + // execution steps (for collection of requests) + Steps []ExecutionStepResult `json:"steps,omitempty"` + Reports *ExecutionResultReports `json:"reports,omitempty"` +} + +// execution result data +type ExecutionStepResult struct { + // step name + Name string `json:"name"` + Duration string `json:"duration,omitempty"` + // execution step status + Status string `json:"status"` + AssertionResults []AssertionResult `json:"assertionResults,omitempty"` +} + +// execution result data +type AssertionResult struct { + Name string `json:"name,omitempty"` + Status string `json:"status,omitempty"` + ErrorMessage string `json:"errorMessage,omitempty"` +} + +type ExecutionResultReports struct { + Junit string `json:"junit,omitempty"` +} + +// +kubebuilder:validation:Enum=queued;running;passed;failed;aborted;timeout +type ExecutionStatus string + +// List of ExecutionStatus +const ( + QUEUED_ExecutionStatus ExecutionStatus = "queued" + RUNNING_ExecutionStatus ExecutionStatus = "running" + PASSED_ExecutionStatus ExecutionStatus = "passed" + FAILED_ExecutionStatus ExecutionStatus = "failed" + ABORTED_ExecutionStatus ExecutionStatus = "aborted" + TIMEOUT_ExecutionStatus ExecutionStatus = "timeout" +) + +// TestExecutionStatus defines the observed state of TestExecution +type TestExecutionStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file + LatestExecution *Execution `json:"latestExecution,omitempty"` + // test execution generation + Generation int64 `json:"generation,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status + +// TestExecution is the Schema for the testexecutions API +type TestExecution struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec TestExecutionSpec `json:"spec,omitempty"` + Status TestExecutionStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// TestExecutionList contains a list of TestExecution +type TestExecutionList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []TestExecution `json:"items"` +} + +func init() { + SchemeBuilder.Register(&TestExecution{}, &TestExecutionList{}) +} diff --git a/apis/testexecution/v1/zz_generated.deepcopy.go b/apis/testexecution/v1/zz_generated.deepcopy.go new file mode 100644 index 00000000..91370918 --- /dev/null +++ b/apis/testexecution/v1/zz_generated.deepcopy.go @@ -0,0 +1,506 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2021. + +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1 + +import ( + corev1 "k8s.io/api/core/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ArtifactRequest) DeepCopyInto(out *ArtifactRequest) { + *out = *in + if in.Dirs != nil { + in, out := &in.Dirs, &out.Dirs + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArtifactRequest. +func (in *ArtifactRequest) DeepCopy() *ArtifactRequest { + if in == nil { + return nil + } + out := new(ArtifactRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AssertionResult) DeepCopyInto(out *AssertionResult) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AssertionResult. +func (in *AssertionResult) DeepCopy() *AssertionResult { + if in == nil { + return nil + } + out := new(AssertionResult) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnvReference) DeepCopyInto(out *EnvReference) { + *out = *in + out.LocalObjectReference = in.LocalObjectReference +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvReference. +func (in *EnvReference) DeepCopy() *EnvReference { + if in == nil { + return nil + } + out := new(EnvReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Execution) DeepCopyInto(out *Execution) { + *out = *in + if in.Envs != nil { + in, out := &in.Envs, &out.Envs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Command != nil { + in, out := &in.Command, &out.Command + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Args != nil { + in, out := &in.Args, &out.Args + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Variables != nil { + in, out := &in.Variables, &out.Variables + *out = make(map[string]Variable, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } + if in.Content != nil { + in, out := &in.Content, &out.Content + *out = new(TestContent) + (*in).DeepCopyInto(*out) + } + in.StartTime.DeepCopyInto(&out.StartTime) + in.EndTime.DeepCopyInto(&out.EndTime) + if in.ExecutionResult != nil { + in, out := &in.ExecutionResult, &out.ExecutionResult + *out = new(ExecutionResult) + (*in).DeepCopyInto(*out) + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Uploads != nil { + in, out := &in.Uploads, &out.Uploads + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ArtifactRequest != nil { + in, out := &in.ArtifactRequest, &out.ArtifactRequest + *out = new(ArtifactRequest) + (*in).DeepCopyInto(*out) + } + if in.RunningContext != nil { + in, out := &in.RunningContext, &out.RunningContext + *out = new(RunningContext) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Execution. +func (in *Execution) DeepCopy() *Execution { + if in == nil { + return nil + } + out := new(Execution) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExecutionRequest) DeepCopyInto(out *ExecutionRequest) { + *out = *in + if in.ExecutionLabels != nil { + in, out := &in.ExecutionLabels, &out.ExecutionLabels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Variables != nil { + in, out := &in.Variables, &out.Variables + *out = make(map[string]Variable, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } + if in.Args != nil { + in, out := &in.Args, &out.Args + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Command != nil { + in, out := &in.Command, &out.Command + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ImagePullSecrets != nil { + in, out := &in.ImagePullSecrets, &out.ImagePullSecrets + *out = make([]corev1.LocalObjectReference, len(*in)) + copy(*out, *in) + } + if in.Envs != nil { + in, out := &in.Envs, &out.Envs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretEnvs != nil { + in, out := &in.SecretEnvs, &out.SecretEnvs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.ArtifactRequest != nil { + in, out := &in.ArtifactRequest, &out.ArtifactRequest + *out = new(ArtifactRequest) + (*in).DeepCopyInto(*out) + } + if in.EnvConfigMaps != nil { + in, out := &in.EnvConfigMaps, &out.EnvConfigMaps + *out = make([]EnvReference, len(*in)) + copy(*out, *in) + } + if in.EnvSecrets != nil { + in, out := &in.EnvSecrets, &out.EnvSecrets + *out = make([]EnvReference, len(*in)) + copy(*out, *in) + } + if in.RunningContext != nil { + in, out := &in.RunningContext, &out.RunningContext + *out = new(RunningContext) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecutionRequest. +func (in *ExecutionRequest) DeepCopy() *ExecutionRequest { + if in == nil { + return nil + } + out := new(ExecutionRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExecutionResult) DeepCopyInto(out *ExecutionResult) { + *out = *in + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(ExecutionStatus) + **out = **in + } + if in.Steps != nil { + in, out := &in.Steps, &out.Steps + *out = make([]ExecutionStepResult, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Reports != nil { + in, out := &in.Reports, &out.Reports + *out = new(ExecutionResultReports) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecutionResult. +func (in *ExecutionResult) DeepCopy() *ExecutionResult { + if in == nil { + return nil + } + out := new(ExecutionResult) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExecutionResultReports) DeepCopyInto(out *ExecutionResultReports) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecutionResultReports. +func (in *ExecutionResultReports) DeepCopy() *ExecutionResultReports { + if in == nil { + return nil + } + out := new(ExecutionResultReports) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExecutionStepResult) DeepCopyInto(out *ExecutionStepResult) { + *out = *in + if in.AssertionResults != nil { + in, out := &in.AssertionResults, &out.AssertionResults + *out = make([]AssertionResult, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecutionStepResult. +func (in *ExecutionStepResult) DeepCopy() *ExecutionStepResult { + if in == nil { + return nil + } + out := new(ExecutionStepResult) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObjectRef) DeepCopyInto(out *ObjectRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectRef. +func (in *ObjectRef) DeepCopy() *ObjectRef { + if in == nil { + return nil + } + out := new(ObjectRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Repository) DeepCopyInto(out *Repository) { + *out = *in + if in.UsernameSecret != nil { + in, out := &in.UsernameSecret, &out.UsernameSecret + *out = new(SecretRef) + **out = **in + } + if in.TokenSecret != nil { + in, out := &in.TokenSecret, &out.TokenSecret + *out = new(SecretRef) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Repository. +func (in *Repository) DeepCopy() *Repository { + if in == nil { + return nil + } + out := new(Repository) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RunningContext) DeepCopyInto(out *RunningContext) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunningContext. +func (in *RunningContext) DeepCopy() *RunningContext { + if in == nil { + return nil + } + out := new(RunningContext) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretRef) DeepCopyInto(out *SecretRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretRef. +func (in *SecretRef) DeepCopy() *SecretRef { + if in == nil { + return nil + } + out := new(SecretRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestContent) DeepCopyInto(out *TestContent) { + *out = *in + if in.Repository != nil { + in, out := &in.Repository, &out.Repository + *out = new(Repository) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestContent. +func (in *TestContent) DeepCopy() *TestContent { + if in == nil { + return nil + } + out := new(TestContent) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestExecution) DeepCopyInto(out *TestExecution) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestExecution. +func (in *TestExecution) DeepCopy() *TestExecution { + if in == nil { + return nil + } + out := new(TestExecution) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TestExecution) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestExecutionList) DeepCopyInto(out *TestExecutionList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]TestExecution, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestExecutionList. +func (in *TestExecutionList) DeepCopy() *TestExecutionList { + if in == nil { + return nil + } + out := new(TestExecutionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TestExecutionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestExecutionSpec) DeepCopyInto(out *TestExecutionSpec) { + *out = *in + if in.Test != nil { + in, out := &in.Test, &out.Test + *out = new(ObjectRef) + **out = **in + } + if in.ExecutionRequest != nil { + in, out := &in.ExecutionRequest, &out.ExecutionRequest + *out = new(ExecutionRequest) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestExecutionSpec. +func (in *TestExecutionSpec) DeepCopy() *TestExecutionSpec { + if in == nil { + return nil + } + out := new(TestExecutionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestExecutionStatus) DeepCopyInto(out *TestExecutionStatus) { + *out = *in + if in.LatestExecution != nil { + in, out := &in.LatestExecution, &out.LatestExecution + *out = new(Execution) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestExecutionStatus. +func (in *TestExecutionStatus) DeepCopy() *TestExecutionStatus { + if in == nil { + return nil + } + out := new(TestExecutionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Variable) DeepCopyInto(out *Variable) { + *out = *in + in.ValueFrom.DeepCopyInto(&out.ValueFrom) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Variable. +func (in *Variable) DeepCopy() *Variable { + if in == nil { + return nil + } + out := new(Variable) + in.DeepCopyInto(out) + return out +} diff --git a/apis/tests/v3/test_types.go b/apis/tests/v3/test_types.go index a3a654b7..6d9c9bca 100644 --- a/apis/tests/v3/test_types.go +++ b/apis/tests/v3/test_types.go @@ -17,9 +17,10 @@ limitations under the License. package v3 import ( - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" ) // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! diff --git a/apis/testsource/v1/groupversion_info.go b/apis/testsource/v1/groupversion_info.go index 948ec14a..c1627d50 100644 --- a/apis/testsource/v1/groupversion_info.go +++ b/apis/testsource/v1/groupversion_info.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Package v1 contains API Schema definitions for the tests v1 API group +// Package v1 contains API Schema definitions for the test sources v1 API group // +kubebuilder:object:generate=true // +groupName=tests.testkube.io package v1 diff --git a/apis/testsuite/v3/zz_generated.deepcopy.go b/apis/testsuite/v3/zz_generated.deepcopy.go index a1491ef4..e82521f6 100644 --- a/apis/testsuite/v3/zz_generated.deepcopy.go +++ b/apis/testsuite/v3/zz_generated.deepcopy.go @@ -1,3 +1,4 @@ +//go:build !ignore_autogenerated // +build !ignore_autogenerated /* diff --git a/apis/testsuiteexecution/v1/groupversion_info.go b/apis/testsuiteexecution/v1/groupversion_info.go new file mode 100644 index 00000000..dd23934e --- /dev/null +++ b/apis/testsuiteexecution/v1/groupversion_info.go @@ -0,0 +1,36 @@ +/* +Copyright 2021. + +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 v1 contains API Schema definitions for the test suite executions v1 API group +// +kubebuilder:object:generate=true +// +groupName=tests.testkube.io +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "tests.testkube.io", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/apis/testsuiteexecution/v1/testsuiteexecution_types.go b/apis/testsuiteexecution/v1/testsuiteexecution_types.go new file mode 100644 index 00000000..7c39d4af --- /dev/null +++ b/apis/testsuiteexecution/v1/testsuiteexecution_types.go @@ -0,0 +1,444 @@ +/* +Copyright 2021. + +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 v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +type Variable commonv1.Variable + +// test content request body +type TestContentRequest struct { + Repository *RepositoryParameters `json:"repository,omitempty"` +} + +// repository parameters for tests in git repositories +type RepositoryParameters struct { + // branch/tag name for checkout + Branch string `json:"branch,omitempty"` + // commit id (sha) for checkout + Commit string `json:"commit,omitempty"` + // if needed we can checkout particular path (dir or file) in case of BIG/mono repositories + Path string `json:"path,omitempty"` + // if provided we checkout the whole repository and run test from this directory + WorkingDir string `json:"workingDir,omitempty"` +} + +// running context for test or test suite execution +type RunningContext struct { + // One of possible context types + Type_ RunningContextType `json:"type"` + // Context value depending from its type + Context string `json:"context,omitempty"` +} + +// RunningContextType defines running context type +// +kubebuilder:validation:Enum=user-cli;user-ui;testsuite;testtrigger;scheduler;testexecution;testsuiteexecution +type RunningContextType string + +const ( + RunningContextTypeUserCLI RunningContextType = "user-cli" + RunningContextTypeUserUI RunningContextType = "user-ui" + RunningContextTypeTestSuite RunningContextType = "testsuite" + RunningContextTypeTestTrigger RunningContextType = "testtrigger" + RunningContextTypeScheduler RunningContextType = "scheduler" + RunningContextTypeTestExecution RunningContextType = "testexecution" + RunningContextTypeTestSuiteExecution RunningContextType = "testsuiteexecution" + RunningContextTypeEmpty RunningContextType = "" +) + +// test suite execution request body +type TestSuiteExecutionRequest struct { + // test execution custom name + Name string `json:"name,omitempty"` + // test suite execution number + Number int32 `json:"number,omitempty"` + // test kubernetes namespace (\"testkube\" when not set) + Namespace string `json:"namespace,omitempty"` + Variables map[string]Variable `json:"variables,omitempty"` + // secret uuid + SecretUUID string `json:"secretUUID,omitempty"` + // test suite labels + Labels map[string]string `json:"labels,omitempty"` + // execution labels + ExecutionLabels map[string]string `json:"executionLabels,omitempty"` + // whether to start execution sync or async + Sync bool `json:"sync,omitempty"` + // http proxy for executor containers + HttpProxy string `json:"httpProxy,omitempty"` + // https proxy for executor containers + HttpsProxy string `json:"httpsProxy,omitempty"` + // duration in seconds the test suite may be active, until its stopped + Timeout int32 `json:"timeout,omitempty"` + ContentRequest *TestContentRequest `json:"contentRequest,omitempty"` + RunningContext *RunningContext `json:"runningContext,omitempty"` + // cron job template extensions + CronJobTemplate string `json:"cronJobTemplate,omitempty"` + // number of tests run in parallel + ConcurrencyLevel int32 `json:"concurrencyLevel,omitempty"` + // test suite execution name started the test suite execution + TestSuiteExecutionName string `json:"testSuiteExecutionName,omitempty"` +} + +type ObjectRef struct { + // object kubernetes namespace + Namespace string `json:"namespace,omitempty"` + // object name + Name string `json:"name"` +} + +// TestSuiteExecutionSpec defines the desired state of TestSuiteExecution +type TestSuiteExecutionSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + TestSuite *ObjectRef `json:"testSuite"` + ExecutionRequest *TestSuiteExecutionRequest `json:"executionRequest,omitempty"` +} + +// TestSuiteExecutionStatus defines the observed state of TestSuiteExecution +type TestSuiteExecutionStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file + LatestExecution *SuiteExecution `json:"latestExecution,omitempty"` + // test status execution generation + Generation int64 `json:"generation,omitempty"` +} + +// SuiteExecutions data +type SuiteExecution struct { + // execution id + Id string `json:"id"` + // execution name + Name string `json:"name"` + TestSuite *ObjectRef `json:"testSuite"` + Status *SuiteExecutionStatus `json:"status,omitempty"` + // Environment variables passed to executor. + // Deprecated: use Basic Variables instead + Envs map[string]string `json:"envs,omitempty"` + Variables map[string]Variable `json:"variables,omitempty"` + // secret uuid + SecretUUID string `json:"secretUUID,omitempty"` + // test start time + StartTime metav1.Time `json:"startTime,omitempty"` + // test end time + EndTime metav1.Time `json:"endTime,omitempty"` + // test duration + Duration string `json:"duration,omitempty"` + // test duration in ms + DurationMs int32 `json:"durationMs,omitempty"` + // steps execution results + StepResults []TestSuiteStepExecutionResultV2 `json:"stepResults,omitempty"` + // batch steps execution results + ExecuteStepResults []TestSuiteBatchStepExecutionResult `json:"executeStepResults,omitempty"` + // test suite labels + Labels map[string]string `json:"labels,omitempty"` + RunningContext *RunningContext `json:"runningContext,omitempty"` + // test suite execution name started the test suite execution + TestSuiteExecutionName string `json:"testSuiteExecutionName,omitempty"` +} + +// execution result returned from executor +type TestSuiteStepExecutionResultV2 struct { + Step *TestSuiteStepV2 `json:"step,omitempty"` + Test *ObjectRef `json:"test,omitempty"` + Execution *Execution `json:"execution,omitempty"` +} + +type TestSuiteStepV2 struct { + StopTestOnFailure bool `json:"stopTestOnFailure"` + Execute *TestSuiteStepExecuteTestV2 `json:"execute,omitempty"` + Delay *TestSuiteStepDelayV2 `json:"delay,omitempty"` +} + +type TestSuiteStepExecuteTestV2 struct { + // object kubernetes namespace + Namespace string `json:"namespace,omitempty"` + // object name + Name string `json:"name"` +} + +type TestSuiteStepDelayV2 struct { + // delay duration in milliseconds + Duration int32 `json:"duration"` +} + +// ArgsModeType defines args mode type +// +kubebuilder:validation:Enum=append;override +type ArgsModeType string + +const ( + // ArgsModeTypeAppend for append args mode + ArgsModeTypeAppend ArgsModeType = "append" + // ArgsModeTypeOverride for override args mode + ArgsModeTypeOverride ArgsModeType = "override" +) + +// test execution +type Execution struct { + // execution id + Id string `json:"id,omitempty"` + // unique test name (CRD Test name) + TestName string `json:"testName,omitempty"` + // unique test suite name (CRD Test suite name), if it's run as a part of test suite + TestSuiteName string `json:"testSuiteName,omitempty"` + // test namespace + TestNamespace string `json:"testNamespace,omitempty"` + // test type e.g. postman/collection + TestType string `json:"testType,omitempty"` + // execution name + Name string `json:"name,omitempty"` + // execution number + Number int32 `json:"number,omitempty"` + // Environment variables passed to executor. + // Deprecated: use Basic Variables instead + Envs map[string]string `json:"envs,omitempty"` + // executor image command + Command []string `json:"command,omitempty"` + // additional arguments/flags passed to executor binary + Args []string `json:"args,omitempty"` + // usage mode for arguments + ArgsMode ArgsModeType `json:"args_mode,omitempty"` + Variables map[string]Variable `json:"variables,omitempty"` + // in case the variables file is too big, it will be uploaded to storage + IsVariablesFileUploaded bool `json:"isVariablesFileUploaded,omitempty"` + // variables file content - need to be in format for particular executor (e.g. postman envs file) + VariablesFile string `json:"variablesFile,omitempty"` + // test secret uuid + TestSecretUUID string `json:"testSecretUUID,omitempty"` + // test suite secret uuid, if it's run as a part of test suite + TestSuiteSecretUUID string `json:"testSuiteSecretUUID,omitempty"` + Content *TestContent `json:"content,omitempty"` + // test start time + StartTime metav1.Time `json:"startTime,omitempty"` + // test end time + EndTime metav1.Time `json:"endTime,omitempty"` + // test duration + Duration string `json:"duration,omitempty"` + // test duration in milliseconds + DurationMs int32 `json:"durationMs,omitempty"` + ExecutionResult *ExecutionResult `json:"executionResult,omitempty"` + // test and execution labels + Labels map[string]string `json:"labels,omitempty"` + // list of file paths that need to be copied into the test from uploads + Uploads []string `json:"uploads,omitempty"` + // minio bucket name to get uploads from + BucketName string `json:"bucketName,omitempty"` + ArtifactRequest *ArtifactRequest `json:"artifactRequest,omitempty"` + // script to run before test execution + PreRunScript string `json:"preRunScript,omitempty"` + // script to run after test execution + PostRunScript string `json:"postRunScript,omitempty"` + RunningContext *RunningContext `json:"runningContext,omitempty"` + // shell used in container executor + ContainerShell string `json:"containerShell,omitempty"` + // test execution name started the test execution + TestExecutionName string `json:"testExecutionName,omitempty"` +} + +// artifact request body with test artifacts +type ArtifactRequest struct { + // artifact storage class name for container executor + StorageClassName string `json:"storageClassName"` + // artifact volume mount path for container executor + VolumeMountPath string `json:"volumeMountPath"` + // artifact directories for scraping + Dirs []string `json:"dirs,omitempty"` +} + +// TestContent defines test content +type TestContent struct { + // test type + Type_ TestContentType `json:"type,omitempty"` + // repository of test content + Repository *Repository `json:"repository,omitempty"` + // test content body + Data string `json:"data,omitempty"` + // uri of test content + Uri string `json:"uri,omitempty"` +} + +// +kubebuilder:validation:Enum=string;file-uri;git-file;git-dir;git +type TestContentType string + +const ( + TestContentTypeString TestContentType = "string" + TestContentTypeFileURI TestContentType = "file-uri" + // Deprecated: use git instead + TestContentTypeGitFile TestContentType = "git-file" + // Deprecated: use git instead + TestContentTypeGitDir TestContentType = "git-dir" + TestContentTypeGit TestContentType = "git" +) + +// Testkube internal reference for secret storage in Kubernetes secrets +type SecretRef struct { + // object kubernetes namespace + Namespace string `json:"namespace,omitempty"` + // object name + Name string `json:"name"` + // object key + Key string `json:"key"` +} + +// Repository represents VCS repo, currently we're handling Git only +type Repository struct { + // VCS repository type + Type_ string `json:"type,omitempty"` + // uri of content file or git directory + Uri string `json:"uri,omitempty"` + // branch/tag name for checkout + Branch string `json:"branch,omitempty"` + // commit id (sha) for checkout + Commit string `json:"commit,omitempty"` + // if needed we can checkout particular path (dir or file) in case of BIG/mono repositories + Path string `json:"path,omitempty"` + UsernameSecret *SecretRef `json:"usernameSecret,omitempty"` + TokenSecret *SecretRef `json:"tokenSecret,omitempty"` + // git auth certificate secret for private repositories + CertificateSecret string `json:"certificateSecret,omitempty"` + // if provided we checkout the whole repository and run test from this directory + WorkingDir string `json:"workingDir,omitempty"` + // auth type for git requests + AuthType GitAuthType `json:"authType,omitempty"` +} + +// GitAuthType defines git auth type +// +kubebuilder:validation:Enum=basic;header +type GitAuthType string + +const ( + // GitAuthTypeBasic for git basic auth requests + GitAuthTypeBasic GitAuthType = "basic" + // GitAuthTypeHeader for git header auth requests + GitAuthTypeHeader GitAuthType = "header" +) + +// execution result returned from executor +type ExecutionResult struct { + Status *ExecutionStatus `json:"status"` + // error message when status is error, separate to output as output can be partial in case of error + ErrorMessage string `json:"errorMessage,omitempty"` + // execution steps (for collection of requests) + Steps []ExecutionStepResult `json:"steps,omitempty"` + Reports *ExecutionResultReports `json:"reports,omitempty"` +} + +// execution result data +type ExecutionStepResult struct { + // step name + Name string `json:"name"` + Duration string `json:"duration,omitempty"` + // execution step status + Status string `json:"status"` + AssertionResults []AssertionResult `json:"assertionResults,omitempty"` +} + +// execution result data +type AssertionResult struct { + Name string `json:"name,omitempty"` + Status string `json:"status,omitempty"` + ErrorMessage string `json:"errorMessage,omitempty"` +} + +type ExecutionResultReports struct { + Junit string `json:"junit,omitempty"` +} + +// +kubebuilder:validation:Enum=queued;running;passed;failed;aborted;timeout +type ExecutionStatus string + +// List of ExecutionStatus +const ( + QUEUED_ExecutionStatus ExecutionStatus = "queued" + RUNNING_ExecutionStatus ExecutionStatus = "running" + PASSED_ExecutionStatus ExecutionStatus = "passed" + FAILED_ExecutionStatus ExecutionStatus = "failed" + ABORTED_ExecutionStatus ExecutionStatus = "aborted" + TIMEOUT_ExecutionStatus ExecutionStatus = "timeout" +) + +// execution result returned from executor +type TestSuiteBatchStepExecutionResult struct { + Step *TestSuiteBatchStep `json:"step,omitempty"` + Execute []TestSuiteStepExecutionResult `json:"execute,omitempty"` +} + +// set of steps run in parallel +type TestSuiteBatchStep struct { + StopOnFailure bool `json:"stopOnFailure"` + Execute []TestSuiteStep `json:"execute,omitempty"` +} + +type TestSuiteStep struct { + // object name + Test string `json:"test,omitempty"` + // delay duration in time units + Delay string `json:"delay,omitempty"` +} + +// execution result returned from executor +type TestSuiteStepExecutionResult struct { + Step *TestSuiteStep `json:"step,omitempty"` + Test *ObjectRef `json:"test,omitempty"` + Execution *Execution `json:"execution,omitempty"` +} + +// +kubebuilder:validation:Enum=queued;running;passed;failed;aborting;aborted;timeout +type SuiteExecutionStatus string + +// List of SuiteExecutionStatus +const ( + QUEUED_SuiteExecutionStatus SuiteExecutionStatus = "queued" + RUNNING_SuiteExecutionStatus SuiteExecutionStatus = "running" + PASSED_SuiteExecutionStatus SuiteExecutionStatus = "passed" + FAILED_SuiteExecutionStatus SuiteExecutionStatus = "failed" + ABORTING_SuiteExecutionStatus SuiteExecutionStatus = "aborting" + ABORTED_SuiteExecutionStatus SuiteExecutionStatus = "aborted" + TIMEOUT_SuiteExecutionStatus SuiteExecutionStatus = "timeout" +) + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status + +// TestSuiteExecution is the Schema for the testsuiteexecutions API +type TestSuiteExecution struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec TestSuiteExecutionSpec `json:"spec,omitempty"` + Status TestSuiteExecutionStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// TestSuiteExecutionList contains a list of TestSuiteExecution +type TestSuiteExecutionList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []TestSuiteExecution `json:"items"` +} + +func init() { + SchemeBuilder.Register(&TestSuiteExecution{}, &TestSuiteExecutionList{}) +} diff --git a/apis/testsuiteexecution/v1/zz_generated.deepcopy.go b/apis/testsuiteexecution/v1/zz_generated.deepcopy.go new file mode 100644 index 00000000..5e2c1176 --- /dev/null +++ b/apis/testsuiteexecution/v1/zz_generated.deepcopy.go @@ -0,0 +1,736 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2021. + +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ArtifactRequest) DeepCopyInto(out *ArtifactRequest) { + *out = *in + if in.Dirs != nil { + in, out := &in.Dirs, &out.Dirs + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArtifactRequest. +func (in *ArtifactRequest) DeepCopy() *ArtifactRequest { + if in == nil { + return nil + } + out := new(ArtifactRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AssertionResult) DeepCopyInto(out *AssertionResult) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AssertionResult. +func (in *AssertionResult) DeepCopy() *AssertionResult { + if in == nil { + return nil + } + out := new(AssertionResult) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Execution) DeepCopyInto(out *Execution) { + *out = *in + if in.Envs != nil { + in, out := &in.Envs, &out.Envs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Command != nil { + in, out := &in.Command, &out.Command + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Args != nil { + in, out := &in.Args, &out.Args + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Variables != nil { + in, out := &in.Variables, &out.Variables + *out = make(map[string]Variable, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } + if in.Content != nil { + in, out := &in.Content, &out.Content + *out = new(TestContent) + (*in).DeepCopyInto(*out) + } + in.StartTime.DeepCopyInto(&out.StartTime) + in.EndTime.DeepCopyInto(&out.EndTime) + if in.ExecutionResult != nil { + in, out := &in.ExecutionResult, &out.ExecutionResult + *out = new(ExecutionResult) + (*in).DeepCopyInto(*out) + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Uploads != nil { + in, out := &in.Uploads, &out.Uploads + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ArtifactRequest != nil { + in, out := &in.ArtifactRequest, &out.ArtifactRequest + *out = new(ArtifactRequest) + (*in).DeepCopyInto(*out) + } + if in.RunningContext != nil { + in, out := &in.RunningContext, &out.RunningContext + *out = new(RunningContext) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Execution. +func (in *Execution) DeepCopy() *Execution { + if in == nil { + return nil + } + out := new(Execution) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExecutionResult) DeepCopyInto(out *ExecutionResult) { + *out = *in + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(ExecutionStatus) + **out = **in + } + if in.Steps != nil { + in, out := &in.Steps, &out.Steps + *out = make([]ExecutionStepResult, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Reports != nil { + in, out := &in.Reports, &out.Reports + *out = new(ExecutionResultReports) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecutionResult. +func (in *ExecutionResult) DeepCopy() *ExecutionResult { + if in == nil { + return nil + } + out := new(ExecutionResult) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExecutionResultReports) DeepCopyInto(out *ExecutionResultReports) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecutionResultReports. +func (in *ExecutionResultReports) DeepCopy() *ExecutionResultReports { + if in == nil { + return nil + } + out := new(ExecutionResultReports) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExecutionStepResult) DeepCopyInto(out *ExecutionStepResult) { + *out = *in + if in.AssertionResults != nil { + in, out := &in.AssertionResults, &out.AssertionResults + *out = make([]AssertionResult, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecutionStepResult. +func (in *ExecutionStepResult) DeepCopy() *ExecutionStepResult { + if in == nil { + return nil + } + out := new(ExecutionStepResult) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObjectRef) DeepCopyInto(out *ObjectRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectRef. +func (in *ObjectRef) DeepCopy() *ObjectRef { + if in == nil { + return nil + } + out := new(ObjectRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Repository) DeepCopyInto(out *Repository) { + *out = *in + if in.UsernameSecret != nil { + in, out := &in.UsernameSecret, &out.UsernameSecret + *out = new(SecretRef) + **out = **in + } + if in.TokenSecret != nil { + in, out := &in.TokenSecret, &out.TokenSecret + *out = new(SecretRef) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Repository. +func (in *Repository) DeepCopy() *Repository { + if in == nil { + return nil + } + out := new(Repository) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RepositoryParameters) DeepCopyInto(out *RepositoryParameters) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RepositoryParameters. +func (in *RepositoryParameters) DeepCopy() *RepositoryParameters { + if in == nil { + return nil + } + out := new(RepositoryParameters) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RunningContext) DeepCopyInto(out *RunningContext) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunningContext. +func (in *RunningContext) DeepCopy() *RunningContext { + if in == nil { + return nil + } + out := new(RunningContext) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretRef) DeepCopyInto(out *SecretRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretRef. +func (in *SecretRef) DeepCopy() *SecretRef { + if in == nil { + return nil + } + out := new(SecretRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SuiteExecution) DeepCopyInto(out *SuiteExecution) { + *out = *in + if in.TestSuite != nil { + in, out := &in.TestSuite, &out.TestSuite + *out = new(ObjectRef) + **out = **in + } + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(SuiteExecutionStatus) + **out = **in + } + if in.Envs != nil { + in, out := &in.Envs, &out.Envs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Variables != nil { + in, out := &in.Variables, &out.Variables + *out = make(map[string]Variable, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } + in.StartTime.DeepCopyInto(&out.StartTime) + in.EndTime.DeepCopyInto(&out.EndTime) + if in.StepResults != nil { + in, out := &in.StepResults, &out.StepResults + *out = make([]TestSuiteStepExecutionResultV2, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ExecuteStepResults != nil { + in, out := &in.ExecuteStepResults, &out.ExecuteStepResults + *out = make([]TestSuiteBatchStepExecutionResult, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.RunningContext != nil { + in, out := &in.RunningContext, &out.RunningContext + *out = new(RunningContext) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SuiteExecution. +func (in *SuiteExecution) DeepCopy() *SuiteExecution { + if in == nil { + return nil + } + out := new(SuiteExecution) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestContent) DeepCopyInto(out *TestContent) { + *out = *in + if in.Repository != nil { + in, out := &in.Repository, &out.Repository + *out = new(Repository) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestContent. +func (in *TestContent) DeepCopy() *TestContent { + if in == nil { + return nil + } + out := new(TestContent) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestContentRequest) DeepCopyInto(out *TestContentRequest) { + *out = *in + if in.Repository != nil { + in, out := &in.Repository, &out.Repository + *out = new(RepositoryParameters) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestContentRequest. +func (in *TestContentRequest) DeepCopy() *TestContentRequest { + if in == nil { + return nil + } + out := new(TestContentRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteBatchStep) DeepCopyInto(out *TestSuiteBatchStep) { + *out = *in + if in.Execute != nil { + in, out := &in.Execute, &out.Execute + *out = make([]TestSuiteStep, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteBatchStep. +func (in *TestSuiteBatchStep) DeepCopy() *TestSuiteBatchStep { + if in == nil { + return nil + } + out := new(TestSuiteBatchStep) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteBatchStepExecutionResult) DeepCopyInto(out *TestSuiteBatchStepExecutionResult) { + *out = *in + if in.Step != nil { + in, out := &in.Step, &out.Step + *out = new(TestSuiteBatchStep) + (*in).DeepCopyInto(*out) + } + if in.Execute != nil { + in, out := &in.Execute, &out.Execute + *out = make([]TestSuiteStepExecutionResult, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteBatchStepExecutionResult. +func (in *TestSuiteBatchStepExecutionResult) DeepCopy() *TestSuiteBatchStepExecutionResult { + if in == nil { + return nil + } + out := new(TestSuiteBatchStepExecutionResult) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteExecution) DeepCopyInto(out *TestSuiteExecution) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteExecution. +func (in *TestSuiteExecution) DeepCopy() *TestSuiteExecution { + if in == nil { + return nil + } + out := new(TestSuiteExecution) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TestSuiteExecution) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteExecutionList) DeepCopyInto(out *TestSuiteExecutionList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]TestSuiteExecution, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteExecutionList. +func (in *TestSuiteExecutionList) DeepCopy() *TestSuiteExecutionList { + if in == nil { + return nil + } + out := new(TestSuiteExecutionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TestSuiteExecutionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteExecutionRequest) DeepCopyInto(out *TestSuiteExecutionRequest) { + *out = *in + if in.Variables != nil { + in, out := &in.Variables, &out.Variables + *out = make(map[string]Variable, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.ExecutionLabels != nil { + in, out := &in.ExecutionLabels, &out.ExecutionLabels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.ContentRequest != nil { + in, out := &in.ContentRequest, &out.ContentRequest + *out = new(TestContentRequest) + (*in).DeepCopyInto(*out) + } + if in.RunningContext != nil { + in, out := &in.RunningContext, &out.RunningContext + *out = new(RunningContext) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteExecutionRequest. +func (in *TestSuiteExecutionRequest) DeepCopy() *TestSuiteExecutionRequest { + if in == nil { + return nil + } + out := new(TestSuiteExecutionRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteExecutionSpec) DeepCopyInto(out *TestSuiteExecutionSpec) { + *out = *in + if in.TestSuite != nil { + in, out := &in.TestSuite, &out.TestSuite + *out = new(ObjectRef) + **out = **in + } + if in.ExecutionRequest != nil { + in, out := &in.ExecutionRequest, &out.ExecutionRequest + *out = new(TestSuiteExecutionRequest) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteExecutionSpec. +func (in *TestSuiteExecutionSpec) DeepCopy() *TestSuiteExecutionSpec { + if in == nil { + return nil + } + out := new(TestSuiteExecutionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteExecutionStatus) DeepCopyInto(out *TestSuiteExecutionStatus) { + *out = *in + if in.LatestExecution != nil { + in, out := &in.LatestExecution, &out.LatestExecution + *out = new(SuiteExecution) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteExecutionStatus. +func (in *TestSuiteExecutionStatus) DeepCopy() *TestSuiteExecutionStatus { + if in == nil { + return nil + } + out := new(TestSuiteExecutionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteStep) DeepCopyInto(out *TestSuiteStep) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteStep. +func (in *TestSuiteStep) DeepCopy() *TestSuiteStep { + if in == nil { + return nil + } + out := new(TestSuiteStep) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteStepDelayV2) DeepCopyInto(out *TestSuiteStepDelayV2) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteStepDelayV2. +func (in *TestSuiteStepDelayV2) DeepCopy() *TestSuiteStepDelayV2 { + if in == nil { + return nil + } + out := new(TestSuiteStepDelayV2) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteStepExecuteTestV2) DeepCopyInto(out *TestSuiteStepExecuteTestV2) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteStepExecuteTestV2. +func (in *TestSuiteStepExecuteTestV2) DeepCopy() *TestSuiteStepExecuteTestV2 { + if in == nil { + return nil + } + out := new(TestSuiteStepExecuteTestV2) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteStepExecutionResult) DeepCopyInto(out *TestSuiteStepExecutionResult) { + *out = *in + if in.Step != nil { + in, out := &in.Step, &out.Step + *out = new(TestSuiteStep) + **out = **in + } + if in.Test != nil { + in, out := &in.Test, &out.Test + *out = new(ObjectRef) + **out = **in + } + if in.Execution != nil { + in, out := &in.Execution, &out.Execution + *out = new(Execution) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteStepExecutionResult. +func (in *TestSuiteStepExecutionResult) DeepCopy() *TestSuiteStepExecutionResult { + if in == nil { + return nil + } + out := new(TestSuiteStepExecutionResult) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteStepExecutionResultV2) DeepCopyInto(out *TestSuiteStepExecutionResultV2) { + *out = *in + if in.Step != nil { + in, out := &in.Step, &out.Step + *out = new(TestSuiteStepV2) + (*in).DeepCopyInto(*out) + } + if in.Test != nil { + in, out := &in.Test, &out.Test + *out = new(ObjectRef) + **out = **in + } + if in.Execution != nil { + in, out := &in.Execution, &out.Execution + *out = new(Execution) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteStepExecutionResultV2. +func (in *TestSuiteStepExecutionResultV2) DeepCopy() *TestSuiteStepExecutionResultV2 { + if in == nil { + return nil + } + out := new(TestSuiteStepExecutionResultV2) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestSuiteStepV2) DeepCopyInto(out *TestSuiteStepV2) { + *out = *in + if in.Execute != nil { + in, out := &in.Execute, &out.Execute + *out = new(TestSuiteStepExecuteTestV2) + **out = **in + } + if in.Delay != nil { + in, out := &in.Delay, &out.Delay + *out = new(TestSuiteStepDelayV2) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteStepV2. +func (in *TestSuiteStepV2) DeepCopy() *TestSuiteStepV2 { + if in == nil { + return nil + } + out := new(TestSuiteStepV2) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Variable) DeepCopyInto(out *Variable) { + *out = *in + in.ValueFrom.DeepCopyInto(&out.ValueFrom) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Variable. +func (in *Variable) DeepCopy() *Variable { + if in == nil { + return nil + } + out := new(Variable) + in.DeepCopyInto(out) + return out +} diff --git a/client/client.go b/client/client.go index 289bf265..435e8550 100644 --- a/client/client.go +++ b/client/client.go @@ -1,9 +1,16 @@ package client import ( + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + _ "k8s.io/client-go/plugin/pkg/client/auth" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + executorv1 "github.com/kubeshop/testkube-operator/apis/executor/v1" scriptv1 "github.com/kubeshop/testkube-operator/apis/script/v1" scriptv2 "github.com/kubeshop/testkube-operator/apis/script/v2" + testexecutionv1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" testsv1 "github.com/kubeshop/testkube-operator/apis/tests/v1" testsv2 "github.com/kubeshop/testkube-operator/apis/tests/v2" testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" @@ -11,11 +18,7 @@ import ( testsuitev1 "github.com/kubeshop/testkube-operator/apis/testsuite/v1" testsuitev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" - _ "k8s.io/client-go/plugin/pkg/client/auth" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" + testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" ) // GetClient returns kubernetes CRD client with registered schemes @@ -33,6 +36,8 @@ func GetClient() (client.Client, error) { testsuitev2.AddToScheme(scheme) testsuitev3.AddToScheme(scheme) testsourcev1.AddToScheme(scheme) + testexecutionv1.AddToScheme(scheme) + testsuiteexecutionv1.AddToScheme(scheme) kubeconfig, err := ctrl.GetConfig() if err != nil { diff --git a/client/executors/v1/webhooks_test.go b/client/executors/v1/webhooks_test.go index 499650dc..6686c37f 100644 --- a/client/executors/v1/webhooks_test.go +++ b/client/executors/v1/webhooks_test.go @@ -65,7 +65,7 @@ func TestWebhooks(t *testing.T) { assert.NotEmpty(t, wClient) assert.Equal(t, testNamespace, wClient.Namespace) }) - t.Run("TestCreate", func(t *testing.T) { + t.Run("WebhookCreate", func(t *testing.T) { t.Run("Create new webhooks", func(t *testing.T) { for _, w := range testWebhooks { created, err := wClient.Create(w) @@ -93,14 +93,14 @@ func TestWebhooks(t *testing.T) { assert.Error(t, err) }) }) - t.Run("TestList", func(t *testing.T) { + t.Run("WebhookList", func(t *testing.T) { t.Run("List without selector", func(t *testing.T) { l, err := wClient.List("") assert.NoError(t, err) assert.Equal(t, len(testWebhooks), len(l.Items)) }) }) - t.Run("TestGet", func(t *testing.T) { + t.Run("WebhookGet", func(t *testing.T) { t.Run("Get webhook with empty name", func(t *testing.T) { t.Parallel() _, err := wClient.Get("") @@ -119,7 +119,7 @@ func TestWebhooks(t *testing.T) { assert.Equal(t, testWebhooks[0].Name, res.Name) }) }) - t.Run("TestGetByEvent", func(t *testing.T) { + t.Run("WebhookGetByEvent", func(t *testing.T) { t.Run("GetByEvent with non-existent event", func(t *testing.T) { res, err := wClient.GetByEvent("no-event") assert.NoError(t, err) @@ -137,7 +137,7 @@ func TestWebhooks(t *testing.T) { assert.Equal(t, 2, len(res.Items)) }) }) - t.Run("TestDelete", func(t *testing.T) { + t.Run("WebhookDelete", func(t *testing.T) { t.Run("Delete items", func(t *testing.T) { for _, webhook := range testWebhooks { w, err := wClient.Get(webhook.Name) diff --git a/client/testexecutions/v1/mock_testexecutions.go b/client/testexecutions/v1/mock_testexecutions.go new file mode 100644 index 00000000..7da7bafc --- /dev/null +++ b/client/testexecutions/v1/mock_testexecutions.go @@ -0,0 +1,108 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/kubeshop/testkube-operator/client/testexecutions/v1 (interfaces: Interface) + +// Package testexecutions is a generated GoMock package. +package testexecutions + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + v1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" +) + +// MockInterface is a mock of Interface interface. +type MockInterface struct { + ctrl *gomock.Controller + recorder *MockInterfaceMockRecorder +} + +// MockInterfaceMockRecorder is the mock recorder for MockInterface. +type MockInterfaceMockRecorder struct { + mock *MockInterface +} + +// NewMockInterface creates a new mock instance. +func NewMockInterface(ctrl *gomock.Controller) *MockInterface { + mock := &MockInterface{ctrl: ctrl} + mock.recorder = &MockInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder { + return m.recorder +} + +// Create mocks base method. +func (m *MockInterface) Create(arg0 *v1.TestExecution) (*v1.TestExecution, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Create", arg0) + ret0, _ := ret[0].(*v1.TestExecution) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Create indicates an expected call of Create. +func (mr *MockInterfaceMockRecorder) Create(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockInterface)(nil).Create), arg0) +} + +// Delete mocks base method. +func (m *MockInterface) Delete(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockInterfaceMockRecorder) Delete(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockInterface)(nil).Delete), arg0) +} + +// Get mocks base method. +func (m *MockInterface) Get(arg0 string) (*v1.TestExecution, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", arg0) + ret0, _ := ret[0].(*v1.TestExecution) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Get indicates an expected call of Get. +func (mr *MockInterfaceMockRecorder) Get(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockInterface)(nil).Get), arg0) +} + +// Update mocks base method. +func (m *MockInterface) Update(arg0 *v1.TestExecution) (*v1.TestExecution, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", arg0) + ret0, _ := ret[0].(*v1.TestExecution) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Update indicates an expected call of Update. +func (mr *MockInterfaceMockRecorder) Update(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockInterface)(nil).Update), arg0) +} + +// UpdateStatus mocks base method. +func (m *MockInterface) UpdateStatus(arg0 *v1.TestExecution) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateStatus", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// UpdateStatus indicates an expected call of UpdateStatus. +func (mr *MockInterfaceMockRecorder) UpdateStatus(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateStatus", reflect.TypeOf((*MockInterface)(nil).UpdateStatus), arg0) +} diff --git a/client/testexecutions/v1/testexecutions.go b/client/testexecutions/v1/testexecutions.go new file mode 100644 index 00000000..d6938a33 --- /dev/null +++ b/client/testexecutions/v1/testexecutions.go @@ -0,0 +1,83 @@ +package testexecutions + +import ( + "context" + + testexecutionv1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +//go:generate mockgen -destination=./mock_testexecutions.go -package=testexecutions "github.com/kubeshop/testkube-operator/client/testexecutions/v1" Interface +type Interface interface { + Get(name string) (*testexecutionv1.TestExecution, error) + Create(testExecution *testexecutionv1.TestExecution) (*testexecutionv1.TestExecution, error) + Update(testExecution *testexecutionv1.TestExecution) (*testexecutionv1.TestExecution, error) + Delete(name string) error + UpdateStatus(testЕxecution *testexecutionv1.TestExecution) error +} + +// Option contain test execution options +type Option struct { + Secrets map[string]string +} + +// NewClient returns new client instance, needs kubernetes client to be passed as dependecy +func NewClient(client client.Client, namespace string) *TestExecutionsClient { + return &TestExecutionsClient{ + k8sClient: client, + namespace: namespace, + } +} + +// TestExecutionsClient client for getting test executions CRs +type TestExecutionsClient struct { + k8sClient client.Client + namespace string +} + +// Get gets test execution by name in given namespace +func (s TestExecutionsClient) Get(name string) (*testexecutionv1.TestExecution, error) { + testExecution := &testexecutionv1.TestExecution{} + if err := s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: s.namespace, Name: name}, testExecution); err != nil { + return nil, err + } + + return testExecution, nil +} + +// Create creates new test execution CRD +func (s TestExecutionsClient) Create(testExecution *testexecutionv1.TestExecution) (*testexecutionv1.TestExecution, error) { + if err := s.k8sClient.Create(context.Background(), testExecution); err != nil { + return nil, err + } + + return testExecution, nil +} + +// Update updates test execution +func (s TestExecutionsClient) Update(testExecution *testexecutionv1.TestExecution) (*testexecutionv1.TestExecution, error) { + if err := s.k8sClient.Update(context.Background(), testExecution); err != nil { + return nil, err + } + + return testExecution, nil +} + +// Delete deletes test execution by name +func (s TestExecutionsClient) Delete(name string) error { + testExecution := &testexecutionv1.TestExecution{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: s.namespace, + }, + } + + err := s.k8sClient.Delete(context.Background(), testExecution) + return err +} + +// UpdateStatus updates existing test execution status +func (s TestExecutionsClient) UpdateStatus(testExecution *testexecutionv1.TestExecution) error { + return s.k8sClient.Status().Update(context.Background(), testExecution) +} diff --git a/client/testexecutions/v1/testexecutions_test.go b/client/testexecutions/v1/testexecutions_test.go new file mode 100644 index 00000000..f3a92f27 --- /dev/null +++ b/client/testexecutions/v1/testexecutions_test.go @@ -0,0 +1,130 @@ +package testexecutions + +import ( + "testing" + + testexecutionv1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" + "github.com/stretchr/testify/assert" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +func TestTestExecutions(t *testing.T) { + var teClient *TestExecutionsClient + testTestExecutions := []*testexecutionv1.TestExecution{ + { + ObjectMeta: v1.ObjectMeta{ + Name: "test-testexecution1", + Namespace: "test-ns", + }, + Spec: testexecutionv1.TestExecutionSpec{}, + Status: testexecutionv1.TestExecutionStatus{}, + }, + { + ObjectMeta: v1.ObjectMeta{ + Name: "test-testexecution2", + Namespace: "test-ns", + }, + Spec: testexecutionv1.TestExecutionSpec{}, + Status: testexecutionv1.TestExecutionStatus{}, + }, + { + ObjectMeta: v1.ObjectMeta{ + Name: "test-testexecution3", + Namespace: "test-ns", + }, + Spec: testexecutionv1.TestExecutionSpec{}, + Status: testexecutionv1.TestExecutionStatus{}, + }, + } + + t.Run("NewTestExecutionsClient", func(t *testing.T) { + clientBuilder := fake.NewClientBuilder() + + groupVersion := schema.GroupVersion{Group: "tests.testkube.io", Version: "v1"} + schemaBuilder := scheme.Builder{GroupVersion: groupVersion} + schemaBuilder.Register(&testexecutionv1.TestExecutionList{}) + schemaBuilder.Register(&testexecutionv1.TestExecution{}) + + schema, err := schemaBuilder.Build() + assert.NoError(t, err) + assert.NotEmpty(t, schema) + clientBuilder.WithScheme(schema) + + kClient := clientBuilder.Build() + testNamespace := "test-ns" + teClient = NewClient(kClient, testNamespace) + assert.NotEmpty(t, teClient) + assert.Equal(t, testNamespace, teClient.namespace) + }) + t.Run("TestExecutionCreate", func(t *testing.T) { + t.Run("Create new testexecutions", func(t *testing.T) { + for _, w := range testTestExecutions { + created, err := teClient.Create(w) + assert.NoError(t, err) + assert.Equal(t, w.Name, created.Name) + + res, err := teClient.Get(w.ObjectMeta.Name) + assert.NoError(t, err) + assert.Equal(t, w.Name, res.Name) + } + }) + }) + t.Run("TestExecutionUpdate", func(t *testing.T) { + t.Run("Update new testexecutions", func(t *testing.T) { + for _, w := range testTestExecutions { + res, err := teClient.Get(w.ObjectMeta.Name) + assert.NoError(t, err) + assert.Equal(t, w.Name, res.Name) + + updated, err := teClient.Update(w) + assert.NoError(t, err) + assert.Equal(t, w.Name, updated.Name) + } + }) + }) + t.Run("TestExecutionGet", func(t *testing.T) { + t.Run("Get testexecution with empty name", func(t *testing.T) { + t.Parallel() + _, err := teClient.Get("") + assert.Error(t, err) + }) + + t.Run("Get testexecution with non existent name", func(t *testing.T) { + t.Parallel() + _, err := teClient.Get("no-testexecution") + assert.Error(t, err) + }) + + t.Run("Get existing testexecution", func(t *testing.T) { + res, err := teClient.Get(testTestExecutions[0].Name) + assert.NoError(t, err) + assert.Equal(t, testTestExecutions[0].Name, res.Name) + }) + }) + t.Run("TestExecutionDelete", func(t *testing.T) { + t.Run("Delete items", func(t *testing.T) { + for _, testexecution := range testTestExecutions { + w, err := teClient.Get(testexecution.Name) + assert.NoError(t, err) + assert.Equal(t, w.Name, testexecution.Name) + + err = teClient.Delete(testexecution.Name) + assert.NoError(t, err) + + _, err = teClient.Get(testexecution.Name) + assert.Error(t, err) + } + }) + + t.Run("Delete non-existent item", func(t *testing.T) { + _, err := teClient.Get("no-testexecution") + assert.Error(t, err) + + err = teClient.Delete("no-testexecution") + assert.Error(t, err) + }) + }) +} diff --git a/client/testsuiteexecutions/v1/mock_testsuiteexecutions.go b/client/testsuiteexecutions/v1/mock_testsuiteexecutions.go new file mode 100644 index 00000000..bdff6194 --- /dev/null +++ b/client/testsuiteexecutions/v1/mock_testsuiteexecutions.go @@ -0,0 +1,108 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/kubeshop/testkube-operator/client/testsuiteexecutions/v1 (interfaces: Interface) + +// Package testsuiteexecutions is a generated GoMock package. +package testsuiteexecutions + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + v1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" +) + +// MockInterface is a mock of Interface interface. +type MockInterface struct { + ctrl *gomock.Controller + recorder *MockInterfaceMockRecorder +} + +// MockInterfaceMockRecorder is the mock recorder for MockInterface. +type MockInterfaceMockRecorder struct { + mock *MockInterface +} + +// NewMockInterface creates a new mock instance. +func NewMockInterface(ctrl *gomock.Controller) *MockInterface { + mock := &MockInterface{ctrl: ctrl} + mock.recorder = &MockInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder { + return m.recorder +} + +// Create mocks base method. +func (m *MockInterface) Create(arg0 *v1.TestSuiteExecution) (*v1.TestSuiteExecution, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Create", arg0) + ret0, _ := ret[0].(*v1.TestSuiteExecution) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Create indicates an expected call of Create. +func (mr *MockInterfaceMockRecorder) Create(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockInterface)(nil).Create), arg0) +} + +// Delete mocks base method. +func (m *MockInterface) Delete(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockInterfaceMockRecorder) Delete(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockInterface)(nil).Delete), arg0) +} + +// Get mocks base method. +func (m *MockInterface) Get(arg0 string) (*v1.TestSuiteExecution, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", arg0) + ret0, _ := ret[0].(*v1.TestSuiteExecution) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Get indicates an expected call of Get. +func (mr *MockInterfaceMockRecorder) Get(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockInterface)(nil).Get), arg0) +} + +// Update mocks base method. +func (m *MockInterface) Update(arg0 *v1.TestSuiteExecution) (*v1.TestSuiteExecution, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", arg0) + ret0, _ := ret[0].(*v1.TestSuiteExecution) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Update indicates an expected call of Update. +func (mr *MockInterfaceMockRecorder) Update(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockInterface)(nil).Update), arg0) +} + +// UpdateStatus mocks base method. +func (m *MockInterface) UpdateStatus(arg0 *v1.TestSuiteExecution) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateStatus", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// UpdateStatus indicates an expected call of UpdateStatus. +func (mr *MockInterfaceMockRecorder) UpdateStatus(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateStatus", reflect.TypeOf((*MockInterface)(nil).UpdateStatus), arg0) +} diff --git a/client/testsuiteexecutions/v1/testsuiteexecutions.go b/client/testsuiteexecutions/v1/testsuiteexecutions.go new file mode 100644 index 00000000..c8a253d7 --- /dev/null +++ b/client/testsuiteexecutions/v1/testsuiteexecutions.go @@ -0,0 +1,79 @@ +package testsuiteexecutions + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + + testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" +) + +//go:generate mockgen -destination=./mock_testsuiteexecutions.go -package=testsuiteexecutions "github.com/kubeshop/testkube-operator/client/testsuiteexecutions/v1" Interface +type Interface interface { + Get(name string) (*testsuiteexecutionv1.TestSuiteExecution, error) + Create(testSuiteExecution *testsuiteexecutionv1.TestSuiteExecution) (*testsuiteexecutionv1.TestSuiteExecution, error) + Update(testSuiteExecution *testsuiteexecutionv1.TestSuiteExecution) (*testsuiteexecutionv1.TestSuiteExecution, error) + Delete(name string) error + UpdateStatus(testSuiteЕxecution *testsuiteexecutionv1.TestSuiteExecution) error +} + +// NewClient returns new client instance, needs kubernetes client to be passed as dependecy +func NewClient(client client.Client, namespace string) *TestSuiteExecutionsClient { + return &TestSuiteExecutionsClient{ + k8sClient: client, + namespace: namespace, + } +} + +// TestSuiteExecutionsClient client for getting test suite executions CRs +type TestSuiteExecutionsClient struct { + k8sClient client.Client + namespace string +} + +// Get gets test suite execution by name in given namespace +func (s TestSuiteExecutionsClient) Get(name string) (*testsuiteexecutionv1.TestSuiteExecution, error) { + testSuiteExecution := &testsuiteexecutionv1.TestSuiteExecution{} + if err := s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: s.namespace, Name: name}, testSuiteExecution); err != nil { + return nil, err + } + + return testSuiteExecution, nil +} + +// Create creates new test suite execution CRD +func (s TestSuiteExecutionsClient) Create(testSuiteExecution *testsuiteexecutionv1.TestSuiteExecution) (*testsuiteexecutionv1.TestSuiteExecution, error) { + if err := s.k8sClient.Create(context.Background(), testSuiteExecution); err != nil { + return nil, err + } + + return testSuiteExecution, nil +} + +// Update updates test suite execution +func (s TestSuiteExecutionsClient) Update(testSuiteExecution *testsuiteexecutionv1.TestSuiteExecution) (*testsuiteexecutionv1.TestSuiteExecution, error) { + if err := s.k8sClient.Update(context.Background(), testSuiteExecution); err != nil { + return nil, err + } + + return testSuiteExecution, nil +} + +// Delete deletes test suite execution by name +func (s TestSuiteExecutionsClient) Delete(name string) error { + testSuiteExecution := &testsuiteexecutionv1.TestSuiteExecution{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: s.namespace, + }, + } + + err := s.k8sClient.Delete(context.Background(), testSuiteExecution) + return err +} + +// UpdateStatus updates existing test suite execution status +func (s TestSuiteExecutionsClient) UpdateStatus(testSuiteExecution *testsuiteexecutionv1.TestSuiteExecution) error { + return s.k8sClient.Status().Update(context.Background(), testSuiteExecution) +} diff --git a/client/testsuiteexecutions/v1/testsuiteexecutions_test.go b/client/testsuiteexecutions/v1/testsuiteexecutions_test.go new file mode 100644 index 00000000..2bc11958 --- /dev/null +++ b/client/testsuiteexecutions/v1/testsuiteexecutions_test.go @@ -0,0 +1,130 @@ +package testsuiteexecutions + +import ( + "testing" + + testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" + "github.com/stretchr/testify/assert" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +func TestTestSuiteExecutions(t *testing.T) { + var tseClient *TestSuiteExecutionsClient + testTestSuiteExecutions := []*testsuiteexecutionv1.TestSuiteExecution{ + { + ObjectMeta: v1.ObjectMeta{ + Name: "test-testsuiteexecution1", + Namespace: "test-ns", + }, + Spec: testsuiteexecutionv1.TestSuiteExecutionSpec{}, + Status: testsuiteexecutionv1.TestSuiteExecutionStatus{}, + }, + { + ObjectMeta: v1.ObjectMeta{ + Name: "test-testsuiteexecution2", + Namespace: "test-ns", + }, + Spec: testsuiteexecutionv1.TestSuiteExecutionSpec{}, + Status: testsuiteexecutionv1.TestSuiteExecutionStatus{}, + }, + { + ObjectMeta: v1.ObjectMeta{ + Name: "test-testsuiteexecution3", + Namespace: "test-ns", + }, + Spec: testsuiteexecutionv1.TestSuiteExecutionSpec{}, + Status: testsuiteexecutionv1.TestSuiteExecutionStatus{}, + }, + } + + t.Run("NewTestSuiteExecutionsClient", func(t *testing.T) { + clientBuilder := fake.NewClientBuilder() + + groupVersion := schema.GroupVersion{Group: "tests.testkube.io", Version: "v1"} + schemaBuilder := scheme.Builder{GroupVersion: groupVersion} + schemaBuilder.Register(&testsuiteexecutionv1.TestSuiteExecutionList{}) + schemaBuilder.Register(&testsuiteexecutionv1.TestSuiteExecution{}) + + schema, err := schemaBuilder.Build() + assert.NoError(t, err) + assert.NotEmpty(t, schema) + clientBuilder.WithScheme(schema) + + kClient := clientBuilder.Build() + testNamespace := "test-ns" + tseClient = NewClient(kClient, testNamespace) + assert.NotEmpty(t, tseClient) + assert.Equal(t, testNamespace, tseClient.namespace) + }) + t.Run("TestSuiteExecutionCreate", func(t *testing.T) { + t.Run("Create new testsuiteexecutions", func(t *testing.T) { + for _, w := range testTestSuiteExecutions { + created, err := tseClient.Create(w) + assert.NoError(t, err) + assert.Equal(t, w.Name, created.Name) + + res, err := tseClient.Get(w.ObjectMeta.Name) + assert.NoError(t, err) + assert.Equal(t, w.Name, res.Name) + } + }) + }) + t.Run("TestSuiteExecutionUpdate", func(t *testing.T) { + t.Run("Update new testsuiteexecutions", func(t *testing.T) { + for _, w := range testTestSuiteExecutions { + res, err := tseClient.Get(w.ObjectMeta.Name) + assert.NoError(t, err) + assert.Equal(t, w.Name, res.Name) + + updated, err := tseClient.Update(w) + assert.NoError(t, err) + assert.Equal(t, w.Name, updated.Name) + } + }) + }) + t.Run("TestSuiteExecutionGet", func(t *testing.T) { + t.Run("Get testsuiteexecution with empty name", func(t *testing.T) { + t.Parallel() + _, err := tseClient.Get("") + assert.Error(t, err) + }) + + t.Run("Get testsuiteexecution with non existent name", func(t *testing.T) { + t.Parallel() + _, err := tseClient.Get("no-testsuiteexecution") + assert.Error(t, err) + }) + + t.Run("Get existing testsuiteexecution", func(t *testing.T) { + res, err := tseClient.Get(testTestSuiteExecutions[0].Name) + assert.NoError(t, err) + assert.Equal(t, testTestSuiteExecutions[0].Name, res.Name) + }) + }) + t.Run("TestSuiteExecutionDelete", func(t *testing.T) { + t.Run("Delete items", func(t *testing.T) { + for _, testsuiteexecution := range testTestSuiteExecutions { + w, err := tseClient.Get(testsuiteexecution.Name) + assert.NoError(t, err) + assert.Equal(t, w.Name, testsuiteexecution.Name) + + err = tseClient.Delete(testsuiteexecution.Name) + assert.NoError(t, err) + + _, err = tseClient.Get(testsuiteexecution.Name) + assert.Error(t, err) + } + }) + + t.Run("Delete non-existent item", func(t *testing.T) { + _, err := tseClient.Get("no-testsuiteexecution") + assert.Error(t, err) + + err = tseClient.Delete("no-testsuiteexecution") + assert.Error(t, err) + }) + }) +} diff --git a/config/crd/bases/tests.testkube.io_testexecutions.yaml b/config/crd/bases/tests.testkube.io_testexecutions.yaml new file mode 100644 index 00000000..5756afd9 --- /dev/null +++ b/config/crd/bases/tests.testkube.io_testexecutions.yaml @@ -0,0 +1,757 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.8.0 + creationTimestamp: null + name: testexecutions.tests.testkube.io +spec: + group: tests.testkube.io + names: + kind: TestExecution + listKind: TestExecutionList + plural: testexecutions + singular: testexecution + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: TestExecution is the Schema for the testexecutions API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: TestExecutionSpec defines the desired state of TestExecution + properties: + executionRequest: + description: test execution request body + properties: + activeDeadlineSeconds: + description: Optional duration in seconds the pod may be active + on the node relative to StartTime before the system will actively + try to mark it failed and kill associated containers. Value + must be a positive integer. + format: int64 + type: integer + args: + description: additional executor binary arguments + items: + type: string + type: array + argsMode: + description: usage mode for arguments + enum: + - append + - override + type: string + artifactRequest: + description: artifact request body with test artifacts + properties: + dirs: + description: artifact directories for scraping + items: + type: string + type: array + storageClassName: + description: artifact storage class name for container executor + type: string + volumeMountPath: + description: artifact volume mount path for container executor + type: string + required: + - storageClassName + - volumeMountPath + type: object + command: + description: executor binary command + items: + type: string + type: array + cronJobTemplate: + description: cron job template extensions + type: string + envConfigMaps: + description: config map references + items: + description: Reference to env resource + properties: + mapToVariables: + description: whether we shoud map to variables from resource + type: boolean + mount: + description: whether we shoud mount resource + type: boolean + mountPath: + description: where we shoud mount resource + type: string + reference: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same + namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + required: + - reference + type: object + type: array + envSecrets: + description: secret references + items: + description: Reference to env resource + properties: + mapToVariables: + description: whether we shoud map to variables from resource + type: boolean + mount: + description: whether we shoud mount resource + type: boolean + mountPath: + description: where we shoud mount resource + type: string + reference: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same + namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + required: + - reference + type: object + type: array + envs: + additionalProperties: + type: string + description: 'Environment variables passed to executor. Deprecated: + use Basic Variables instead' + type: object + executionLabels: + additionalProperties: + type: string + description: test execution labels + type: object + httpProxy: + description: http proxy for executor containers + type: string + httpsProxy: + description: https proxy for executor containers + type: string + image: + description: container executor image + type: string + imagePullSecrets: + description: container executor image pull secrets + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + isVariablesFileUploaded: + type: boolean + jobTemplate: + description: job template extensions + type: string + name: + description: test execution custom name + type: string + namespace: + description: test kubernetes namespace (\"testkube\" when not + set) + type: string + negativeTest: + description: negative test will fail the execution if it is a + success and it will succeed if it is a failure + type: boolean + number: + description: test execution number + format: int32 + type: integer + postRunScript: + description: script to run after test execution + type: string + preRunScript: + description: script to run before test execution + type: string + runningContext: + description: running context for test or test suite execution + properties: + context: + description: Context value depending from its type + type: string + type: + description: One of possible context types + enum: + - user-cli + - user-ui + - testsuite + - testtrigger + - scheduler + - testexecution + - testsuiteexecution + type: string + required: + - type + type: object + scraperTemplate: + description: scraper template extensions + type: string + secretEnvs: + additionalProperties: + type: string + description: 'Execution variables passed to executor from secrets. + Deprecated: use Secret Variables instead' + type: object + sync: + description: whether to start execution sync or async + type: boolean + testSecretUUID: + description: test secret uuid + type: string + testSuiteName: + description: unique test suite name (CRD Test suite name), if + it's run as a part of test suite + type: string + testSuiteSecretUUID: + description: test suite secret uuid, if it's run as a part of + test suite + type: string + variables: + additionalProperties: + properties: + name: + description: variable name + type: string + type: + description: variable type + type: string + value: + description: variable string value + type: string + valueFrom: + description: or load it from var source + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + type: object + type: object + type: object + variablesFile: + description: variables file content - need to be in format for + particular executor (e.g. postman envs file) + type: string + type: object + test: + properties: + name: + description: object name + type: string + namespace: + description: object kubernetes namespace + type: string + required: + - name + type: object + required: + - test + type: object + status: + description: TestExecutionStatus defines the observed state of TestExecution + properties: + generation: + description: test execution generation + format: int64 + type: integer + latestExecution: + description: 'INSERT ADDITIONAL STATUS FIELD - define observed state + of cluster Important: Run "make" to regenerate code after modifying + this file' + properties: + args: + description: additional arguments/flags passed to executor binary + items: + type: string + type: array + args_mode: + description: usage mode for arguments + enum: + - append + - override + type: string + artifactRequest: + description: artifact request body with test artifacts + properties: + dirs: + description: artifact directories for scraping + items: + type: string + type: array + storageClassName: + description: artifact storage class name for container executor + type: string + volumeMountPath: + description: artifact volume mount path for container executor + type: string + required: + - storageClassName + - volumeMountPath + type: object + bucketName: + description: minio bucket name to get uploads from + type: string + command: + description: executor image command + items: + type: string + type: array + containerShell: + description: shell used in container executor + type: string + content: + description: TestContent defines test content + properties: + data: + description: test content body + type: string + repository: + description: repository of test content + properties: + authType: + description: auth type for git requests + enum: + - basic + - header + type: string + branch: + description: branch/tag name for checkout + type: string + certificateSecret: + description: git auth certificate secret for private repositories + type: string + commit: + description: commit id (sha) for checkout + type: string + path: + description: if needed we can checkout particular path + (dir or file) in case of BIG/mono repositories + type: string + tokenSecret: + description: Testkube internal reference for secret storage + in Kubernetes secrets + properties: + key: + description: object key + type: string + name: + description: object name + type: string + namespace: + description: object kubernetes namespace + type: string + required: + - key + - name + type: object + type: + description: VCS repository type + type: string + uri: + description: uri of content file or git directory + type: string + usernameSecret: + description: Testkube internal reference for secret storage + in Kubernetes secrets + properties: + key: + description: object key + type: string + name: + description: object name + type: string + namespace: + description: object kubernetes namespace + type: string + required: + - key + - name + type: object + workingDir: + description: if provided we checkout the whole repository + and run test from this directory + type: string + type: object + type: + description: test type + enum: + - string + - file-uri + - git-file + - git-dir + - git + type: string + uri: + description: uri of test content + type: string + type: object + duration: + description: test duration + type: string + durationMs: + description: test duration in milliseconds + format: int32 + type: integer + endTime: + description: test end time + format: date-time + type: string + envs: + additionalProperties: + type: string + description: 'Environment variables passed to executor. Deprecated: + use Basic Variables instead' + type: object + executionResult: + description: execution result returned from executor + properties: + errorMessage: + description: error message when status is error, separate + to output as output can be partial in case of error + type: string + reports: + properties: + junit: + type: string + type: object + status: + enum: + - queued + - running + - passed + - failed + - aborted + - timeout + type: string + steps: + description: execution steps (for collection of requests) + items: + description: execution result data + properties: + assertionResults: + items: + description: execution result data + properties: + errorMessage: + type: string + name: + type: string + status: + type: string + type: object + type: array + duration: + type: string + name: + description: step name + type: string + status: + description: execution step status + type: string + required: + - name + - status + type: object + type: array + required: + - status + type: object + id: + description: execution id + type: string + isVariablesFileUploaded: + description: in case the variables file is too big, it will be + uploaded to storage + type: boolean + labels: + additionalProperties: + type: string + description: test and execution labels + type: object + name: + description: execution name + type: string + number: + description: execution number + format: int32 + type: integer + postRunScript: + description: script to run after test execution + type: string + preRunScript: + description: script to run before test execution + type: string + runningContext: + description: running context for test or test suite execution + properties: + context: + description: Context value depending from its type + type: string + type: + description: One of possible context types + enum: + - user-cli + - user-ui + - testsuite + - testtrigger + - scheduler + - testexecution + - testsuiteexecution + type: string + required: + - type + type: object + startTime: + description: test start time + format: date-time + type: string + testName: + description: unique test name (CRD Test name) + type: string + testNamespace: + description: test namespace + type: string + testSecretUUID: + description: test secret uuid + type: string + testSuiteName: + description: unique test suite name (CRD Test suite name), if + it's run as a part of test suite + type: string + testSuiteSecretUUID: + description: test suite secret uuid, if it's run as a part of + test suite + type: string + testType: + description: test type e.g. postman/collection + type: string + uploads: + description: list of file paths that need to be copied into the + test from uploads + items: + type: string + type: array + variables: + additionalProperties: + properties: + name: + description: variable name + type: string + type: + description: variable type + type: string + value: + description: variable string value + type: string + valueFrom: + description: or load it from var source + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + type: object + type: object + type: object + variablesFile: + description: variables file content - need to be in format for + particular executor (e.g. postman envs file) + type: string + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml b/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml new file mode 100644 index 00000000..592b010c --- /dev/null +++ b/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml @@ -0,0 +1,1348 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.8.0 + creationTimestamp: null + name: testsuiteexecutions.tests.testkube.io +spec: + group: tests.testkube.io + names: + kind: TestSuiteExecution + listKind: TestSuiteExecutionList + plural: testsuiteexecutions + singular: testsuiteexecution + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: TestSuiteExecution is the Schema for the testsuiteexecutions + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: TestSuiteExecutionSpec defines the desired state of TestSuiteExecution + properties: + executionRequest: + description: test suite execution request body + properties: + concurrencyLevel: + description: number of tests run in parallel + format: int32 + type: integer + contentRequest: + description: test content request body + properties: + repository: + description: repository parameters for tests in git repositories + properties: + branch: + description: branch/tag name for checkout + type: string + commit: + description: commit id (sha) for checkout + type: string + path: + description: if needed we can checkout particular path + (dir or file) in case of BIG/mono repositories + type: string + workingDir: + description: if provided we checkout the whole repository + and run test from this directory + type: string + type: object + type: object + cronJobTemplate: + description: cron job template extensions + type: string + executionLabels: + additionalProperties: + type: string + description: execution labels + type: object + httpProxy: + description: http proxy for executor containers + type: string + httpsProxy: + description: https proxy for executor containers + type: string + labels: + additionalProperties: + type: string + description: test suite labels + type: object + name: + description: test execution custom name + type: string + namespace: + description: test kubernetes namespace (\"testkube\" when not + set) + type: string + number: + description: test suite execution number + format: int32 + type: integer + runningContext: + description: running context for test or test suite execution + properties: + context: + description: Context value depending from its type + type: string + type: + description: One of possible context types + enum: + - user-cli + - user-ui + - testsuite + - testtrigger + - scheduler + - testexecution + - testsuiteexecution + type: string + required: + - type + type: object + secretUUID: + description: secret uuid + type: string + sync: + description: whether to start execution sync or async + type: boolean + testSuiteExecutionName: + description: test suite execution name started the test suite + execution + type: string + timeout: + description: duration in seconds the test suite may be active, + until its stopped + format: int32 + type: integer + variables: + additionalProperties: + properties: + name: + description: variable name + type: string + type: + description: variable type + type: string + value: + description: variable string value + type: string + valueFrom: + description: or load it from var source + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + type: object + type: object + type: object + type: object + testSuite: + properties: + name: + description: object name + type: string + namespace: + description: object kubernetes namespace + type: string + required: + - name + type: object + required: + - testSuite + type: object + status: + description: TestSuiteExecutionStatus defines the observed state of TestSuiteExecution + properties: + generation: + description: test status execution generation + format: int64 + type: integer + latestExecution: + description: 'INSERT ADDITIONAL STATUS FIELD - define observed state + of cluster Important: Run "make" to regenerate code after modifying + this file' + properties: + duration: + description: test duration + type: string + durationMs: + description: test duration in ms + format: int32 + type: integer + endTime: + description: test end time + format: date-time + type: string + envs: + additionalProperties: + type: string + description: 'Environment variables passed to executor. Deprecated: + use Basic Variables instead' + type: object + executeStepResults: + description: batch steps execution results + items: + description: execution result returned from executor + properties: + execute: + items: + description: execution result returned from executor + properties: + execution: + description: test execution + properties: + args: + description: additional arguments/flags passed + to executor binary + items: + type: string + type: array + args_mode: + description: usage mode for arguments + enum: + - append + - override + type: string + artifactRequest: + description: artifact request body with test artifacts + properties: + dirs: + description: artifact directories for scraping + items: + type: string + type: array + storageClassName: + description: artifact storage class name for + container executor + type: string + volumeMountPath: + description: artifact volume mount path for + container executor + type: string + required: + - storageClassName + - volumeMountPath + type: object + bucketName: + description: minio bucket name to get uploads + from + type: string + command: + description: executor image command + items: + type: string + type: array + containerShell: + description: shell used in container executor + type: string + content: + description: TestContent defines test content + properties: + data: + description: test content body + type: string + repository: + description: repository of test content + properties: + authType: + description: auth type for git requests + enum: + - basic + - header + type: string + branch: + description: branch/tag name for checkout + type: string + certificateSecret: + description: git auth certificate secret + for private repositories + type: string + commit: + description: commit id (sha) for checkout + type: string + path: + description: if needed we can checkout + particular path (dir or file) in case + of BIG/mono repositories + type: string + tokenSecret: + description: Testkube internal reference + for secret storage in Kubernetes secrets + properties: + key: + description: object key + type: string + name: + description: object name + type: string + namespace: + description: object kubernetes namespace + type: string + required: + - key + - name + type: object + type: + description: VCS repository type + type: string + uri: + description: uri of content file or git + directory + type: string + usernameSecret: + description: Testkube internal reference + for secret storage in Kubernetes secrets + properties: + key: + description: object key + type: string + name: + description: object name + type: string + namespace: + description: object kubernetes namespace + type: string + required: + - key + - name + type: object + workingDir: + description: if provided we checkout the + whole repository and run test from this + directory + type: string + type: object + type: + description: test type + enum: + - string + - file-uri + - git-file + - git-dir + - git + type: string + uri: + description: uri of test content + type: string + type: object + duration: + description: test duration + type: string + durationMs: + description: test duration in milliseconds + format: int32 + type: integer + endTime: + description: test end time + format: date-time + type: string + envs: + additionalProperties: + type: string + description: 'Environment variables passed to + executor. Deprecated: use Basic Variables instead' + type: object + executionResult: + description: execution result returned from executor + properties: + errorMessage: + description: error message when status is + error, separate to output as output can + be partial in case of error + type: string + reports: + properties: + junit: + type: string + type: object + status: + enum: + - queued + - running + - passed + - failed + - aborted + - timeout + type: string + steps: + description: execution steps (for collection + of requests) + items: + description: execution result data + properties: + assertionResults: + items: + description: execution result data + properties: + errorMessage: + type: string + name: + type: string + status: + type: string + type: object + type: array + duration: + type: string + name: + description: step name + type: string + status: + description: execution step status + type: string + required: + - name + - status + type: object + type: array + required: + - status + type: object + id: + description: execution id + type: string + isVariablesFileUploaded: + description: in case the variables file is too + big, it will be uploaded to storage + type: boolean + labels: + additionalProperties: + type: string + description: test and execution labels + type: object + name: + description: execution name + type: string + number: + description: execution number + format: int32 + type: integer + postRunScript: + description: script to run after test execution + type: string + preRunScript: + description: script to run before test execution + type: string + runningContext: + description: running context for test or test + suite execution + properties: + context: + description: Context value depending from + its type + type: string + type: + description: One of possible context types + enum: + - user-cli + - user-ui + - testsuite + - testtrigger + - scheduler + - testexecution + - testsuiteexecution + type: string + required: + - type + type: object + startTime: + description: test start time + format: date-time + type: string + testExecutionName: + description: test execution name started the test + execution + type: string + testName: + description: unique test name (CRD Test name) + type: string + testNamespace: + description: test namespace + type: string + testSecretUUID: + description: test secret uuid + type: string + testSuiteName: + description: unique test suite name (CRD Test + suite name), if it's run as a part of test suite + type: string + testSuiteSecretUUID: + description: test suite secret uuid, if it's run + as a part of test suite + type: string + testType: + description: test type e.g. postman/collection + type: string + uploads: + description: list of file paths that need to be + copied into the test from uploads + items: + type: string + type: array + variables: + additionalProperties: + properties: + name: + description: variable name + type: string + type: + description: variable type + type: string + value: + description: variable string value + type: string + valueFrom: + description: or load it from var source + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. + apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the + ConfigMap or its key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the + pod: supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, + status.hostIP, status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of + the container: only resources limits + and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, + requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env + vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + description: 'Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. + apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the + Secret or its key must be defined + type: boolean + required: + - key + type: object + type: object + type: object + type: object + variablesFile: + description: variables file content - need to + be in format for particular executor (e.g. postman + envs file) + type: string + type: object + step: + properties: + delay: + description: delay duration in time units + type: string + test: + description: object name + type: string + type: object + test: + properties: + name: + description: object name + type: string + namespace: + description: object kubernetes namespace + type: string + required: + - name + type: object + type: object + type: array + step: + description: set of steps run in parallel + properties: + execute: + items: + properties: + delay: + description: delay duration in time units + type: string + test: + description: object name + type: string + type: object + type: array + stopOnFailure: + type: boolean + required: + - stopOnFailure + type: object + type: object + type: array + id: + description: execution id + type: string + labels: + additionalProperties: + type: string + description: test suite labels + type: object + name: + description: execution name + type: string + runningContext: + description: running context for test or test suite execution + properties: + context: + description: Context value depending from its type + type: string + type: + description: One of possible context types + enum: + - user-cli + - user-ui + - testsuite + - testtrigger + - scheduler + - testexecution + - testsuiteexecution + type: string + required: + - type + type: object + secretUUID: + description: secret uuid + type: string + startTime: + description: test start time + format: date-time + type: string + status: + enum: + - queued + - running + - passed + - failed + - aborting + - aborted + - timeout + type: string + stepResults: + description: steps execution results + items: + description: execution result returned from executor + properties: + execution: + description: test execution + properties: + args: + description: additional arguments/flags passed to executor + binary + items: + type: string + type: array + args_mode: + description: usage mode for arguments + enum: + - append + - override + type: string + artifactRequest: + description: artifact request body with test artifacts + properties: + dirs: + description: artifact directories for scraping + items: + type: string + type: array + storageClassName: + description: artifact storage class name for container + executor + type: string + volumeMountPath: + description: artifact volume mount path for container + executor + type: string + required: + - storageClassName + - volumeMountPath + type: object + bucketName: + description: minio bucket name to get uploads from + type: string + command: + description: executor image command + items: + type: string + type: array + containerShell: + description: shell used in container executor + type: string + content: + description: TestContent defines test content + properties: + data: + description: test content body + type: string + repository: + description: repository of test content + properties: + authType: + description: auth type for git requests + enum: + - basic + - header + type: string + branch: + description: branch/tag name for checkout + type: string + certificateSecret: + description: git auth certificate secret for + private repositories + type: string + commit: + description: commit id (sha) for checkout + type: string + path: + description: if needed we can checkout particular + path (dir or file) in case of BIG/mono repositories + type: string + tokenSecret: + description: Testkube internal reference for + secret storage in Kubernetes secrets + properties: + key: + description: object key + type: string + name: + description: object name + type: string + namespace: + description: object kubernetes namespace + type: string + required: + - key + - name + type: object + type: + description: VCS repository type + type: string + uri: + description: uri of content file or git directory + type: string + usernameSecret: + description: Testkube internal reference for + secret storage in Kubernetes secrets + properties: + key: + description: object key + type: string + name: + description: object name + type: string + namespace: + description: object kubernetes namespace + type: string + required: + - key + - name + type: object + workingDir: + description: if provided we checkout the whole + repository and run test from this directory + type: string + type: object + type: + description: test type + enum: + - string + - file-uri + - git-file + - git-dir + - git + type: string + uri: + description: uri of test content + type: string + type: object + duration: + description: test duration + type: string + durationMs: + description: test duration in milliseconds + format: int32 + type: integer + endTime: + description: test end time + format: date-time + type: string + envs: + additionalProperties: + type: string + description: 'Environment variables passed to executor. + Deprecated: use Basic Variables instead' + type: object + executionResult: + description: execution result returned from executor + properties: + errorMessage: + description: error message when status is error, + separate to output as output can be partial in + case of error + type: string + reports: + properties: + junit: + type: string + type: object + status: + enum: + - queued + - running + - passed + - failed + - aborted + - timeout + type: string + steps: + description: execution steps (for collection of + requests) + items: + description: execution result data + properties: + assertionResults: + items: + description: execution result data + properties: + errorMessage: + type: string + name: + type: string + status: + type: string + type: object + type: array + duration: + type: string + name: + description: step name + type: string + status: + description: execution step status + type: string + required: + - name + - status + type: object + type: array + required: + - status + type: object + id: + description: execution id + type: string + isVariablesFileUploaded: + description: in case the variables file is too big, + it will be uploaded to storage + type: boolean + labels: + additionalProperties: + type: string + description: test and execution labels + type: object + name: + description: execution name + type: string + number: + description: execution number + format: int32 + type: integer + postRunScript: + description: script to run after test execution + type: string + preRunScript: + description: script to run before test execution + type: string + runningContext: + description: running context for test or test suite + execution + properties: + context: + description: Context value depending from its type + type: string + type: + description: One of possible context types + enum: + - user-cli + - user-ui + - testsuite + - testtrigger + - scheduler + - testexecution + - testsuiteexecution + type: string + required: + - type + type: object + startTime: + description: test start time + format: date-time + type: string + testExecutionName: + description: test execution name started the test execution + type: string + testName: + description: unique test name (CRD Test name) + type: string + testNamespace: + description: test namespace + type: string + testSecretUUID: + description: test secret uuid + type: string + testSuiteName: + description: unique test suite name (CRD Test suite + name), if it's run as a part of test suite + type: string + testSuiteSecretUUID: + description: test suite secret uuid, if it's run as + a part of test suite + type: string + testType: + description: test type e.g. postman/collection + type: string + uploads: + description: list of file paths that need to be copied + into the test from uploads + items: + type: string + type: array + variables: + additionalProperties: + properties: + name: + description: variable name + type: string + type: + description: variable type + type: string + value: + description: variable string value + type: string + valueFrom: + description: or load it from var source + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: + supports metadata.name, metadata.namespace, + `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, + status.hostIP, status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, defaults + to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, limits.ephemeral-storage, + requests.cpu, requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in + the pod's namespace + properties: + key: + description: The key of the secret to + select from. Must be a valid secret + key. + type: string + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + type: object + type: object + type: object + variablesFile: + description: variables file content - need to be in + format for particular executor (e.g. postman envs + file) + type: string + type: object + step: + properties: + delay: + properties: + duration: + description: delay duration in milliseconds + format: int32 + type: integer + required: + - duration + type: object + execute: + properties: + name: + description: object name + type: string + namespace: + description: object kubernetes namespace + type: string + required: + - name + type: object + stopTestOnFailure: + type: boolean + required: + - stopTestOnFailure + type: object + test: + properties: + name: + description: object name + type: string + namespace: + description: object kubernetes namespace + type: string + required: + - name + type: object + type: object + type: array + testSuite: + properties: + name: + description: object name + type: string + namespace: + description: object kubernetes namespace + type: string + required: + - name + type: object + testSuiteExecutionName: + description: test suite execution name started the test suite + execution + type: string + variables: + additionalProperties: + properties: + name: + description: variable name + type: string + type: + description: variable type + type: string + value: + description: variable string value + type: string + valueFrom: + description: or load it from var source + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + type: object + type: object + type: object + required: + - id + - name + - testSuite + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 8ebcab07..6328cc42 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -9,6 +9,8 @@ resources: - bases/executor.testkube.io_webhooks.yaml - bases/tests.testkube.io_testtriggers.yaml - bases/tests.testkube.io_testsources.yaml +- bases/tests.testkube.io_testexecutions.yaml +- bases/tests.testkube.io_testsuiteexecutions.yaml #+kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: @@ -21,6 +23,8 @@ patchesStrategicMerge: #- patches/webhook_in_webhooks.yaml - patches/webhook_in_testtriggers.yaml #- patches/webhook_in_testsources.yaml +#- patches/webhook_in_testexecutions.yaml +#- patches/webhook_in_testsuiteexecutions.yaml #+kubebuilder:scaffold:crdkustomizewebhookpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/crd/patches/webhook_in_testexecutions.yaml b/config/crd/patches/webhook_in_testexecutions.yaml new file mode 100644 index 00000000..a17f767a --- /dev/null +++ b/config/crd/patches/webhook_in_testexecutions.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: testexecutions.tests.testkube.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/config/crd/patches/webhook_in_testsuiteexecutions.yaml b/config/crd/patches/webhook_in_testsuiteexecutions.yaml new file mode 100644 index 00000000..2c847769 --- /dev/null +++ b/config/crd/patches/webhook_in_testsuiteexecutions.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: testsuiteexecutions.tests.testkube.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 9133048a..cf3b87a0 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -1,3 +1,4 @@ + --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -83,6 +84,32 @@ rules: - get - patch - update +- apiGroups: + - tests.testkube.io + resources: + - testexecutions + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - tests.testkube.io + resources: + - testexecutions/finalizers + verbs: + - update +- apiGroups: + - tests.testkube.io + resources: + - testexecutions/status + verbs: + - get + - patch + - update - apiGroups: - tests.testkube.io resources: @@ -135,6 +162,32 @@ rules: - get - patch - update +- apiGroups: + - tests.testkube.io + resources: + - testsuiteexecutions + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - tests.testkube.io + resources: + - testsuiteexecutions/finalizers + verbs: + - update +- apiGroups: + - tests.testkube.io + resources: + - testsuiteexecutions/status + verbs: + - get + - patch + - update - apiGroups: - tests.testkube.io resources: diff --git a/config/rbac/testexecution_editor_role.yaml b/config/rbac/testexecution_editor_role.yaml new file mode 100644 index 00000000..8350b23b --- /dev/null +++ b/config/rbac/testexecution_editor_role.yaml @@ -0,0 +1,24 @@ +# permissions for end users to edit testexecutions. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: testexecution-editor-role +rules: +- apiGroups: + - tests.testkube.io + resources: + - testexecutions + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - tests.testkube.io + resources: + - testexecutions/status + verbs: + - get diff --git a/config/rbac/testexecution_viewer_role.yaml b/config/rbac/testexecution_viewer_role.yaml new file mode 100644 index 00000000..ef53a8fa --- /dev/null +++ b/config/rbac/testexecution_viewer_role.yaml @@ -0,0 +1,20 @@ +# permissions for end users to view testexecutions. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: testexecution-viewer-role +rules: +- apiGroups: + - tests.testkube.io + resources: + - testexecutions + verbs: + - get + - list + - watch +- apiGroups: + - tests.testkube.io + resources: + - testexecutions/status + verbs: + - get diff --git a/config/rbac/testsuiteexecution_editor_role.yaml b/config/rbac/testsuiteexecution_editor_role.yaml new file mode 100644 index 00000000..4208380b --- /dev/null +++ b/config/rbac/testsuiteexecution_editor_role.yaml @@ -0,0 +1,24 @@ +# permissions for end users to edit testsuiteexecutions. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: testsuiteexecution-editor-role +rules: +- apiGroups: + - tests.testkube.io + resources: + - testsuiteexecutions + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - tests.testkube.io + resources: + - testsuiteexecutions/status + verbs: + - get diff --git a/config/rbac/testsuiteexecution_viewer_role.yaml b/config/rbac/testsuiteexecution_viewer_role.yaml new file mode 100644 index 00000000..c494b4b3 --- /dev/null +++ b/config/rbac/testsuiteexecution_viewer_role.yaml @@ -0,0 +1,20 @@ +# permissions for end users to view testsuiteexecutions. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: testsuiteexecution-viewer-role +rules: +- apiGroups: + - tests.testkube.io + resources: + - testsuiteexecutions + verbs: + - get + - list + - watch +- apiGroups: + - tests.testkube.io + resources: + - testsuiteexecutions/status + verbs: + - get diff --git a/config/samples/tests_v1_testexecution.yaml b/config/samples/tests_v1_testexecution.yaml new file mode 100644 index 00000000..5218d822 --- /dev/null +++ b/config/samples/tests_v1_testexecution.yaml @@ -0,0 +1,13 @@ +apiVersion: tests.testkube.io/v1 +kind: TestExecution +metadata: + name: testexecution-sample +spec: + test: + name: test-example + executionRequest: + variables: + VAR_TEST: + name: VAR_TEST + value: "ANY" + type: basic diff --git a/config/samples/tests_v1_testsuiteexecution.yaml b/config/samples/tests_v1_testsuiteexecution.yaml new file mode 100644 index 00000000..12eebce2 --- /dev/null +++ b/config/samples/tests_v1_testsuiteexecution.yaml @@ -0,0 +1,14 @@ +apiVersion: tests.testkube.io/v1 +kind: TestSuiteExecution +metadata: + name: testsuiteexecution-sample +spec: + testSuite: + name: testsuite-example + executionRequest: + variables: + VAR_TEST: + name: VAR_TEST + value: "ANY" + type: basic + diff --git a/controllers/testexecution/suite_test.go b/controllers/testexecution/suite_test.go new file mode 100644 index 00000000..fe6644f1 --- /dev/null +++ b/controllers/testexecution/suite_test.go @@ -0,0 +1,80 @@ +/* +Copyright 2021. + +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 testexecution + +import ( + "path/filepath" + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + testexecutionv1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" + //+kubebuilder:scaffold:imports +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment + +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecs(t, "Controller Suite") +} + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + ErrorIfCRDPathMissing: true, + } + + var err error + // cfg is defined in this file globally. + cfg, err = testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + err = testexecutionv1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient).NotTo(BeNil()) + +}) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) diff --git a/controllers/testexecution/testexecution_controller.go b/controllers/testexecution/testexecution_controller.go new file mode 100644 index 00000000..e51f3682 --- /dev/null +++ b/controllers/testexecution/testexecution_controller.go @@ -0,0 +1,129 @@ +/* +Copyright 2021. + +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 testexecution + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" + + testexecutionv1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" +) + +// TestExecutionReconciler reconciles a TestExecution object +type TestExecutionReconciler struct { + client.Client + Scheme *runtime.Scheme + ServiceName string + ServicePort int +} + +//+kubebuilder:rbac:groups=tests.testkube.io,resources=testexecutions,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=tests.testkube.io,resources=testexecutions/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=tests.testkube.io,resources=testexecutions/finalizers,verbs=update + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the TestExecution object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.4/pkg/reconcile +func (r *TestExecutionReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + _ = log.FromContext(ctx) + + var testExecution testexecutionv1.TestExecution + err := r.Get(ctx, req.NamespacedName, &testExecution) + if err != nil { + if errors.IsNotFound(err) { + return ctrl.Result{}, nil + } + + return ctrl.Result{}, err + } + + if testExecution.Spec.Test == nil { + return ctrl.Result{}, nil + } + + if testExecution.Spec.ExecutionRequest != nil { + testExecution.Spec.ExecutionRequest.RunningContext = &testexecutionv1.RunningContext{ + Type_: testexecutionv1.RunningContextTypeTestSuiteExecution, + Context: testExecution.Name, + } + } + + jsonData, err := json.Marshal(testExecution.Spec.ExecutionRequest) + if err != nil { + return ctrl.Result{}, err + } + + if testExecution.Generation == testExecution.Status.Generation { + return ctrl.Result{}, nil + } + + if _, err = r.executeTest(testExecution.Spec.Test.Name, testExecution.Name, testExecution.Namespace, jsonData); err != nil { + return ctrl.Result{}, err + } + + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *TestExecutionReconciler) SetupWithManager(mgr ctrl.Manager) error { + pred := predicate.GenerationChangedPredicate{} + return ctrl.NewControllerManagedBy(mgr). + For(&testexecutionv1.TestExecution{}). + WithEventFilter(pred). + Complete(r) +} + +func (r *TestExecutionReconciler) executeTest(testName, testExecutionName, namespace string, jsonData []byte) (out string, err error) { + request, err := http.NewRequest(http.MethodPost, + fmt.Sprintf("http://%s.%s.svc.cluster.local:%d/v1/tests/%s/executions?testExecutionName=%s", + r.ServiceName, namespace, r.ServicePort, testName, testExecutionName), + bytes.NewBuffer(jsonData)) + if err != nil { + return out, err + } + + request.Header.Set("Content-Type", "application/json") + resp, err := http.DefaultClient.Do(request) + if err != nil { + return out, err + } + defer resp.Body.Close() + + b, err := io.ReadAll(resp.Body) + if resp.StatusCode > 300 { + return out, fmt.Errorf("could not POST, statusCode: %d", resp.StatusCode) + } + + return fmt.Sprintf("status: %d - %s", resp.StatusCode, b), err +} diff --git a/controllers/tests/test_controller.go b/controllers/tests/test_controller.go index 8bc6368f..3b60fccd 100644 --- a/controllers/tests/test_controller.go +++ b/controllers/tests/test_controller.go @@ -25,6 +25,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" "github.com/kubeshop/testkube-operator/pkg/cronjob" @@ -127,7 +128,9 @@ func (r *TestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl. // SetupWithManager sets up the controller with the Manager. func (r *TestReconciler) SetupWithManager(mgr ctrl.Manager) error { + pred := predicate.GenerationChangedPredicate{} return ctrl.NewControllerManagedBy(mgr). For(&testsv3.Test{}). + WithEventFilter(pred). Complete(r) } diff --git a/controllers/testsuite/testsuite_controller.go b/controllers/testsuite/testsuite_controller.go index e6d90eef..ce5799e4 100644 --- a/controllers/testsuite/testsuite_controller.go +++ b/controllers/testsuite/testsuite_controller.go @@ -25,6 +25,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" "github.com/kubeshop/testkube-operator/pkg/cronjob" @@ -128,7 +129,9 @@ func (r *TestSuiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( // SetupWithManager sets up the controller with the Manager. func (r *TestSuiteReconciler) SetupWithManager(mgr ctrl.Manager) error { + pred := predicate.GenerationChangedPredicate{} return ctrl.NewControllerManagedBy(mgr). For(&testsuitev3.TestSuite{}). + WithEventFilter(pred). Complete(r) } diff --git a/controllers/testsuiteexecution/suite_test.go b/controllers/testsuiteexecution/suite_test.go new file mode 100644 index 00000000..c5561199 --- /dev/null +++ b/controllers/testsuiteexecution/suite_test.go @@ -0,0 +1,80 @@ +/* +Copyright 2021. + +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 testsuiteexecution + +import ( + "path/filepath" + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" + //+kubebuilder:scaffold:imports +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment + +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecs(t, "Controller Suite") +} + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + ErrorIfCRDPathMissing: true, + } + + var err error + // cfg is defined in this file globally. + cfg, err = testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + err = testsuiteexecutionv1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient).NotTo(BeNil()) + +}) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) diff --git a/controllers/testsuiteexecution/testsuiteexecution_controllller.go b/controllers/testsuiteexecution/testsuiteexecution_controllller.go new file mode 100644 index 00000000..079f19b2 --- /dev/null +++ b/controllers/testsuiteexecution/testsuiteexecution_controllller.go @@ -0,0 +1,129 @@ +/* +Copyright 2021. + +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 testsuiteexecution + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" + + testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" +) + +// TestSuiteExecutionReconciler reconciles a TestSuiteExecution object +type TestSuiteExecutionReconciler struct { + client.Client + Scheme *runtime.Scheme + ServiceName string + ServicePort int +} + +//+kubebuilder:rbac:groups=tests.testkube.io,resources=testsuiteexecutions,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=tests.testkube.io,resources=testsuiteexecutions/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=tests.testkube.io,resources=testsuiteexecutions/finalizers,verbs=update + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the TestSuiteExecution object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.4/pkg/reconcile +func (r *TestSuiteExecutionReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + _ = log.FromContext(ctx) + + var testSuiteExecution testsuiteexecutionv1.TestSuiteExecution + err := r.Get(ctx, req.NamespacedName, &testSuiteExecution) + if err != nil { + if errors.IsNotFound(err) { + return ctrl.Result{}, nil + } + + return ctrl.Result{}, err + } + + if testSuiteExecution.Spec.TestSuite == nil { + return ctrl.Result{}, nil + } + + if testSuiteExecution.Spec.ExecutionRequest != nil { + testSuiteExecution.Spec.ExecutionRequest.RunningContext = &testsuiteexecutionv1.RunningContext{ + Type_: testsuiteexecutionv1.RunningContextTypeTestSuiteExecution, + Context: testSuiteExecution.Name, + } + } + + jsonData, err := json.Marshal(testSuiteExecution.Spec.ExecutionRequest) + if err != nil { + return ctrl.Result{}, err + } + + if testSuiteExecution.Generation == testSuiteExecution.Status.Generation { + return ctrl.Result{}, nil + } + + if _, err = r.executeTestSuite(testSuiteExecution.Spec.TestSuite.Name, testSuiteExecution.Name, testSuiteExecution.Namespace, jsonData); err != nil { + return ctrl.Result{}, err + } + + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *TestSuiteExecutionReconciler) SetupWithManager(mgr ctrl.Manager) error { + pred := predicate.GenerationChangedPredicate{} + return ctrl.NewControllerManagedBy(mgr). + For(&testsuiteexecutionv1.TestSuiteExecution{}). + WithEventFilter(pred). + Complete(r) +} + +func (r *TestSuiteExecutionReconciler) executeTestSuite(testSuiteName, testSuiteExecutionName, namespace string, jsonData []byte) (out string, err error) { + request, err := http.NewRequest(http.MethodPost, + fmt.Sprintf("http://%s.%s.svc.cluster.local:%d/v1/test-suites/%s/executions?testSuiteExecutionName=%s", + r.ServiceName, namespace, r.ServicePort, testSuiteName, testSuiteExecutionName), + bytes.NewBuffer(jsonData)) + if err != nil { + return out, err + } + + request.Header.Set("Content-Type", "application/json") + resp, err := http.DefaultClient.Do(request) + if err != nil { + return out, err + } + defer resp.Body.Close() + + b, err := io.ReadAll(resp.Body) + if resp.StatusCode > 300 { + return out, fmt.Errorf("could not POST, statusCode: %d", resp.StatusCode) + } + + return fmt.Sprintf("status: %d - %s", resp.StatusCode, b), err +} diff --git a/go.mod b/go.mod index 4f657db3..8a94d74c 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/google/uuid v1.3.0 github.com/kelseyhightower/envconfig v1.4.0 github.com/onsi/ginkgo v1.16.5 + github.com/onsi/ginkgo/v2 v2.1.4 github.com/onsi/gomega v1.19.0 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.1 diff --git a/go.sum b/go.sum index 508d9710..9c1d68ca 100644 --- a/go.sum +++ b/go.sum @@ -428,6 +428,7 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k 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.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= +github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= diff --git a/main.go b/main.go index a482a2f7..98c1d19e 100644 --- a/main.go +++ b/main.go @@ -41,6 +41,7 @@ import ( executorv1 "github.com/kubeshop/testkube-operator/apis/executor/v1" testkubev1 "github.com/kubeshop/testkube-operator/apis/script/v1" testkubev2 "github.com/kubeshop/testkube-operator/apis/script/v2" + testexecutionv1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" testsv1 "github.com/kubeshop/testkube-operator/apis/tests/v1" testsv2 "github.com/kubeshop/testkube-operator/apis/tests/v2" testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" @@ -48,11 +49,14 @@ import ( testsuitev1 "github.com/kubeshop/testkube-operator/apis/testsuite/v1" testsuitev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" executorcontrollers "github.com/kubeshop/testkube-operator/controllers/executor" scriptcontrollers "github.com/kubeshop/testkube-operator/controllers/script" + testexecutioncontrollers "github.com/kubeshop/testkube-operator/controllers/testexecution" testscontrollers "github.com/kubeshop/testkube-operator/controllers/tests" testsourcecontrollers "github.com/kubeshop/testkube-operator/controllers/testsource" testsuitecontrollers "github.com/kubeshop/testkube-operator/controllers/testsuite" + testsuiteexecutioncontrollers "github.com/kubeshop/testkube-operator/controllers/testsuiteexecution" testtriggerscontrollers "github.com/kubeshop/testkube-operator/controllers/testtriggers" "github.com/kubeshop/testkube-operator/pkg/cronjob" //+kubebuilder:scaffold:imports @@ -85,6 +89,8 @@ func init() { utilruntime.Must(testtriggersv1.AddToScheme(scheme)) utilruntime.Must(testsourcev1.AddToScheme(scheme)) utilruntime.Must(testsuitev3.AddToScheme(scheme)) + utilruntime.Must(testexecutionv1.AddToScheme(scheme)) + utilruntime.Must(testsuiteexecutionv1.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } @@ -183,6 +189,24 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "TestTrigger") os.Exit(1) } + if err = (&testexecutioncontrollers.TestExecutionReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + ServiceName: httpConfig.Fullname, + ServicePort: httpConfig.Port, + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "TestExecution") + os.Exit(1) + } + if err = (&testsuiteexecutioncontrollers.TestSuiteExecutionReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + ServiceName: httpConfig.Fullname, + ServicePort: httpConfig.Port, + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "TestSuiteExecution") + os.Exit(1) + } //+kubebuilder:scaffold:builder if os.Getenv("ENABLE_WEBHOOKS") != "false" { From 9570ed2536cde8240fff51f1e12eba4cd1b9f2e5 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Wed, 16 Aug 2023 18:28:25 +0300 Subject: [PATCH 31/57] fix: use go 1.21 (#169) --- .github/workflows/go.yml | 2 +- go.mod | 2 +- go.sum | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 378193dd..72dc1ebd 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -17,7 +17,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.18 + go-version: 1.21 - name: Build run: go build -v ./... diff --git a/go.mod b/go.mod index 8a94d74c..4162e0e9 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/kubeshop/testkube-operator -go 1.18 +go 1.21 require ( github.com/golang/mock v1.6.0 diff --git a/go.sum b/go.sum index 9c1d68ca..250ab46d 100644 --- a/go.sum +++ b/go.sum @@ -410,6 +410,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 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= @@ -528,6 +529,7 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk= +github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -572,6 +574,7 @@ go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= From 870da6e6365b1fd5dbd2769a16c85aba6f2ace42 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 24 Aug 2023 13:20:36 +0300 Subject: [PATCH 32/57] fix: context typo (#171) --- controllers/testexecution/testexecution_controller.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/testexecution/testexecution_controller.go b/controllers/testexecution/testexecution_controller.go index e51f3682..eb410088 100644 --- a/controllers/testexecution/testexecution_controller.go +++ b/controllers/testexecution/testexecution_controller.go @@ -74,7 +74,7 @@ func (r *TestExecutionReconciler) Reconcile(ctx context.Context, req ctrl.Reques if testExecution.Spec.ExecutionRequest != nil { testExecution.Spec.ExecutionRequest.RunningContext = &testexecutionv1.RunningContext{ - Type_: testexecutionv1.RunningContextTypeTestSuiteExecution, + Type_: testexecutionv1.RunningContextTypeTestExecution, Context: testExecution.Name, } } From 199e57ed51c68f980521d5d299453afce414d104 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 24 Aug 2023 17:41:02 +0300 Subject: [PATCH 33/57] feat: artifact bucket (#170) * feat: artifact bucket * fix: generate * fix: rename field --- apis/testexecution/v1/testexecution_types.go | 4 ++++ apis/tests/v3/test_types.go | 4 ++++ apis/testsuite/v3/zz_generated.deepcopy.go | 6 ++++-- .../v1/testsuiteexecution_types.go | 4 ++++ apis/testtriggers/v1/zz_generated.deepcopy.go | 2 +- .../bases/tests.testkube.io_testexecutions.yaml | 12 ++++++++++++ config/crd/bases/tests.testkube.io_tests.yaml | 6 ++++++ .../tests.testkube.io_testsuiteexecutions.yaml | 14 ++++++++++++++ 8 files changed, 49 insertions(+), 3 deletions(-) diff --git a/apis/testexecution/v1/testexecution_types.go b/apis/testexecution/v1/testexecution_types.go index 54370807..7247ff89 100644 --- a/apis/testexecution/v1/testexecution_types.go +++ b/apis/testexecution/v1/testexecution_types.go @@ -36,6 +36,10 @@ type ArtifactRequest struct { VolumeMountPath string `json:"volumeMountPath"` // artifact directories for scraping Dirs []string `json:"dirs,omitempty"` + // artifact bucket storage + StorageBucket string `json:"storageBucket,omitempty"` + // don't use a separate folder for execution artifacts + OmitFolderPerExecution bool `json:"omitFolderPerExecution,omitempty"` } // running context for test or test suite execution diff --git a/apis/tests/v3/test_types.go b/apis/tests/v3/test_types.go index 6d9c9bca..125fbc08 100644 --- a/apis/tests/v3/test_types.go +++ b/apis/tests/v3/test_types.go @@ -124,6 +124,10 @@ type ArtifactRequest struct { VolumeMountPath string `json:"volumeMountPath"` // artifact directories for scraping Dirs []string `json:"dirs,omitempty"` + // artifact bucket storage + StorageBucket string `json:"storageBucket,omitempty"` + // don't use a separate folder for execution artifacts + OmitFolderPerExecution bool `json:"omitFolderPerExecution,omitempty"` } // running context for test or test suite execution diff --git a/apis/testsuite/v3/zz_generated.deepcopy.go b/apis/testsuite/v3/zz_generated.deepcopy.go index e82521f6..9b82a395 100644 --- a/apis/testsuite/v3/zz_generated.deepcopy.go +++ b/apis/testsuite/v3/zz_generated.deepcopy.go @@ -58,7 +58,9 @@ func (in *TestSuiteBatchStep) DeepCopyInto(out *TestSuiteBatchStep) { if in.Execute != nil { in, out := &in.Execute, &out.Execute *out = make([]TestSuiteStepSpec, len(*in)) - copy(*out, *in) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } } @@ -226,7 +228,7 @@ func (in *TestSuiteStatus) DeepCopy() *TestSuiteStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TestSuiteStepSpec) DeepCopyInto(out *TestSuiteStepSpec) { *out = *in - out.Delay = in.Delay + in.Delay.DeepCopyInto(&out.Delay) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteStepSpec. diff --git a/apis/testsuiteexecution/v1/testsuiteexecution_types.go b/apis/testsuiteexecution/v1/testsuiteexecution_types.go index 7c39d4af..1631bd53 100644 --- a/apis/testsuiteexecution/v1/testsuiteexecution_types.go +++ b/apis/testsuiteexecution/v1/testsuiteexecution_types.go @@ -264,6 +264,10 @@ type ArtifactRequest struct { VolumeMountPath string `json:"volumeMountPath"` // artifact directories for scraping Dirs []string `json:"dirs,omitempty"` + // artifact bucket storage + StorageBucket string `json:"storageBucket,omitempty"` + // don't use a separate folder for execution artifacts + OmitFolderPerExecution bool `json:"omitFolderPerExecution,omitempty"` } // TestContent defines test content diff --git a/apis/testtriggers/v1/zz_generated.deepcopy.go b/apis/testtriggers/v1/zz_generated.deepcopy.go index de6b839b..ac2c588b 100644 --- a/apis/testtriggers/v1/zz_generated.deepcopy.go +++ b/apis/testtriggers/v1/zz_generated.deepcopy.go @@ -209,7 +209,7 @@ func (in *TestTriggerSpec) DeepCopyInto(out *TestTriggerSpec) { if in.Delay != nil { in, out := &in.Delay, &out.Delay *out = new(metav1.Duration) - **out = **in + (*in).DeepCopyInto(*out) } } diff --git a/config/crd/bases/tests.testkube.io_testexecutions.yaml b/config/crd/bases/tests.testkube.io_testexecutions.yaml index 5756afd9..8c87d9ed 100644 --- a/config/crd/bases/tests.testkube.io_testexecutions.yaml +++ b/config/crd/bases/tests.testkube.io_testexecutions.yaml @@ -64,6 +64,12 @@ spec: items: type: string type: array + omitFolderPerExecution: + description: don't use a separate folder for execution artifacts + type: boolean + storageBucket: + description: artifact bucket storage + type: string storageClassName: description: artifact storage class name for container executor type: string @@ -387,6 +393,12 @@ spec: items: type: string type: array + omitFolderPerExecution: + description: don't use a separate folder for execution artifacts + type: boolean + storageBucket: + description: artifact bucket storage + type: string storageClassName: description: artifact storage class name for container executor type: string diff --git a/config/crd/bases/tests.testkube.io_tests.yaml b/config/crd/bases/tests.testkube.io_tests.yaml index f377b380..67b6d8c4 100644 --- a/config/crd/bases/tests.testkube.io_tests.yaml +++ b/config/crd/bases/tests.testkube.io_tests.yaml @@ -459,6 +459,12 @@ spec: items: type: string type: array + omitFolderPerExecution: + description: don't use a separate folder for execution artifacts + type: boolean + storageBucket: + description: artifact bucket storage + type: string storageClassName: description: artifact storage class name for container executor type: string diff --git a/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml b/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml index 592b010c..c000ad11 100644 --- a/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml +++ b/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml @@ -304,6 +304,13 @@ spec: items: type: string type: array + omitFolderPerExecution: + description: don't use a separate folder for execution + artifacts + type: boolean + storageBucket: + description: artifact bucket storage + type: string storageClassName: description: artifact storage class name for container executor @@ -804,6 +811,13 @@ spec: items: type: string type: array + omitFolderPerExecution: + description: don't use a separate folder for execution + artifacts + type: boolean + storageBucket: + description: artifact bucket storage + type: string storageClassName: description: artifact storage class name for container executor From 8fda6043174c9e217b26fe789e7649a00cf85d29 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 24 Aug 2023 17:45:44 +0300 Subject: [PATCH 34/57] feat: test field (#172) * feat: test field * fix: tags --- apis/tests/v3/test_types.go | 2 ++ config/crd/bases/tests.testkube.io_tests.yaml | 3 +++ 2 files changed, 5 insertions(+) diff --git a/apis/tests/v3/test_types.go b/apis/tests/v3/test_types.go index 125fbc08..e864cd4e 100644 --- a/apis/tests/v3/test_types.go +++ b/apis/tests/v3/test_types.go @@ -35,6 +35,8 @@ type TestSpec struct { Type_ string `json:"type,omitempty"` // test name Name string `json:"name,omitempty"` + // test description + Description string `json:"description,omitempty"` // test content object Content *TestContent `json:"content,omitempty"` // reference to test source resource diff --git a/config/crd/bases/tests.testkube.io_tests.yaml b/config/crd/bases/tests.testkube.io_tests.yaml index 67b6d8c4..2f4be569 100644 --- a/config/crd/bases/tests.testkube.io_tests.yaml +++ b/config/crd/bases/tests.testkube.io_tests.yaml @@ -430,6 +430,9 @@ spec: description: uri of test content type: string type: object + description: + description: test description + type: string executionRequest: description: test execution request body properties: From 5c2e3838fed8e29781d249876b4765de437d393c Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Tue, 5 Sep 2023 19:58:43 +0300 Subject: [PATCH 35/57] feat: template crd (#173) * featL template crd * feat: add delete by labels * feat: use cronjob reference * fix: add warnings * fix: error message --- PROJECT | 9 ++ apis/executor/v1/executor_types.go | 2 + apis/executor/v1/webhook_types.go | 2 + apis/template/v1/groupversion_info.go | 36 +++++ apis/template/v1/template_types.go | 78 +++++++++ apis/template/v1/zz_generated.deepcopy.go | 119 ++++++++++++++ apis/tests/v3/test_types.go | 10 ++ apis/testsuite/v3/testsuite_types.go | 14 ++ client/client.go | 2 + client/templates/v1/mock_templates.go | 123 +++++++++++++++ client/templates/v1/templates.go | 108 +++++++++++++ client/templates/v1/templates_test.go | 148 ++++++++++++++++++ .../testexecutions/v1/testexecutions_test.go | 27 ++-- .../v1/testsuiteexecutions_test.go | 27 ++-- .../bases/executor.testkube.io_executors.yaml | 3 + .../bases/executor.testkube.io_webhooks.yaml | 3 + .../bases/tests.testkube.io_templates.yaml | 68 ++++++++ config/crd/bases/tests.testkube.io_tests.yaml | 15 ++ .../bases/tests.testkube.io_testsuites.yaml | 21 +++ config/crd/kustomization.yaml | 2 + config/crd/patches/webhook_in_tempates.yaml | 16 ++ config/rbac/role.yaml | 24 +++ config/rbac/template_editor_role.yaml | 24 +++ config/rbac/template_viewer_role.yaml | 20 +++ config/samples/tests_v1_template.yaml | 7 + controllers/template/suite_test.go | 80 ++++++++++ controllers/template/template_controller.go | 62 ++++++++ controllers/tests/test_controller.go | 25 ++- controllers/testsuite/testsuite_controller.go | 25 ++- main.go | 10 ++ pkg/cronjob/client.go | 15 +- 31 files changed, 1091 insertions(+), 34 deletions(-) create mode 100644 apis/template/v1/groupversion_info.go create mode 100644 apis/template/v1/template_types.go create mode 100644 apis/template/v1/zz_generated.deepcopy.go create mode 100644 client/templates/v1/mock_templates.go create mode 100644 client/templates/v1/templates.go create mode 100644 client/templates/v1/templates_test.go create mode 100644 config/crd/bases/tests.testkube.io_templates.yaml create mode 100644 config/crd/patches/webhook_in_tempates.yaml create mode 100644 config/rbac/template_editor_role.yaml create mode 100644 config/rbac/template_viewer_role.yaml create mode 100644 config/samples/tests_v1_template.yaml create mode 100644 controllers/template/suite_test.go create mode 100644 controllers/template/template_controller.go diff --git a/PROJECT b/PROJECT index 57c4981c..1bb96fd5 100644 --- a/PROJECT +++ b/PROJECT @@ -126,4 +126,13 @@ resources: kind: TestSuiteExecution path: github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1 version: v1 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: testkube.io + group: tests + kind: Template + path: github.com/kubeshop/testkube-operator/apis/template/v1 + version: v1 version: "3" diff --git a/apis/executor/v1/executor_types.go b/apis/executor/v1/executor_types.go index 6d40d09b..71d2753e 100644 --- a/apis/executor/v1/executor_types.go +++ b/apis/executor/v1/executor_types.go @@ -55,6 +55,8 @@ type ExecutorSpec struct { // Job template to launch executor JobTemplate string `json:"job_template,omitempty"` + // name of the template resource + JobTemplateReference string `json:"jobTemplateReference,omitempty"` // Meta data about executor Meta *ExecutorMeta `json:"meta,omitempty"` diff --git a/apis/executor/v1/webhook_types.go b/apis/executor/v1/webhook_types.go index 1f5bd29d..aca94f8d 100644 --- a/apis/executor/v1/webhook_types.go +++ b/apis/executor/v1/webhook_types.go @@ -38,6 +38,8 @@ type WebhookSpec struct { PayloadObjectField string `json:"payloadObjectField,omitempty"` // golang based template for notification payload PayloadTemplate string `json:"payloadTemplate,omitempty"` + // name of the template resource + PayloadTemplateReference string `json:"payloadTemplateReference,omitempty"` // webhook headers Headers map[string]string `json:"headers,omitempty"` } diff --git a/apis/template/v1/groupversion_info.go b/apis/template/v1/groupversion_info.go new file mode 100644 index 00000000..fc8561e7 --- /dev/null +++ b/apis/template/v1/groupversion_info.go @@ -0,0 +1,36 @@ +/* +Copyright 2021. + +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 v1 contains API Schema definitions for the templates v1 API group +// +kubebuilder:object:generate=true +// +groupName=tests.testkube.io +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "tests.testkube.io", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/apis/template/v1/template_types.go b/apis/template/v1/template_types.go new file mode 100644 index 00000000..2b41d864 --- /dev/null +++ b/apis/template/v1/template_types.go @@ -0,0 +1,78 @@ +/* +Copyright 2021. + +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 v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// TemplateType defines template type by purpose +// +kubebuilder:validation:Enum=job;container;cronjob;scraper;pvc;webhook +type TemplateType string + +const ( + JOB_TemplateType TemplateType = "job" + CONTAINER_TemplateType TemplateType = "container" + CRONJOB_TemplateType TemplateType = "cronjob" + SCRAPER_TemplateType TemplateType = "scraper" + PVC_TemplateType TemplateType = "pvc" + WEBHOOK_TemplateType TemplateType = "webhook" +) + +// TemplateSpec defines the desired state of Template +type TemplateSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + Type_ *TemplateType `json:"type"` + // template body to use + Body string `json:"body"` +} + +// TemplateStatus defines the observed state of Template +type TemplateStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status + +// Template is the Schema for the Templates API +type Template struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec TemplateSpec `json:"spec,omitempty"` + Status TemplateStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// TemplateList contains a list of Template +type TemplateList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Template `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Template{}, &TemplateList{}) +} diff --git a/apis/template/v1/zz_generated.deepcopy.go b/apis/template/v1/zz_generated.deepcopy.go new file mode 100644 index 00000000..e7434b2d --- /dev/null +++ b/apis/template/v1/zz_generated.deepcopy.go @@ -0,0 +1,119 @@ +// +build !ignore_autogenerated + +/* +Copyright 2021. + +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Template) DeepCopyInto(out *Template) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Template. +func (in *Template) DeepCopy() *Template { + if in == nil { + return nil + } + out := new(Template) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Template) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TemplateList) DeepCopyInto(out *TemplateList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Template, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TemplateList. +func (in *TemplateList) DeepCopy() *TemplateList { + if in == nil { + return nil + } + out := new(TemplateList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TemplateList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TemplateSpec) DeepCopyInto(out *TemplateSpec) { + *out = *in + if in.Type_ != nil { + in, out := &in.Type_, &out.Type_ + *out = new(TemplateType) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TemplateSpec. +func (in *TemplateSpec) DeepCopy() *TemplateSpec { + if in == nil { + return nil + } + out := new(TemplateSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TemplateStatus) DeepCopyInto(out *TemplateStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TemplateStatus. +func (in *TemplateStatus) DeepCopy() *TemplateStatus { + if in == nil { + return nil + } + out := new(TemplateStatus) + in.DeepCopyInto(out) + return out +} diff --git a/apis/tests/v3/test_types.go b/apis/tests/v3/test_types.go index e864cd4e..5004a9a8 100644 --- a/apis/tests/v3/test_types.go +++ b/apis/tests/v3/test_types.go @@ -202,14 +202,24 @@ type ExecutionRequest struct { ArtifactRequest *ArtifactRequest `json:"artifactRequest,omitempty"` // job template extensions JobTemplate string `json:"jobTemplate,omitempty"` + // name of the template resource + JobTemplateReference string `json:"jobTemplateReference,omitempty"` // cron job template extensions CronJobTemplate string `json:"cronJobTemplate,omitempty"` + // name of the template resource + CronJobTemplateReference string `json:"cronJobTemplateReference,omitempty"` // script to run before test execution PreRunScript string `json:"preRunScript,omitempty"` // script to run after test execution PostRunScript string `json:"postRunScript,omitempty"` // scraper template extensions ScraperTemplate string `json:"scraperTemplate,omitempty"` + // name of the template resource + ScraperTemplateReference string `json:"scraperTemplateReference,omitempty"` + // pvc template extensions + PvcTemplate string `json:"pvcTemplate,omitempty"` + // name of the template resource + PvcTemplateReference string `json:"pvcTemplateReference,omitempty"` // config map references EnvConfigMaps []EnvReference `json:"envConfigMaps,omitempty"` // secret references diff --git a/apis/testsuite/v3/testsuite_types.go b/apis/testsuite/v3/testsuite_types.go index c3dcc379..f4d6fd62 100644 --- a/apis/testsuite/v3/testsuite_types.go +++ b/apis/testsuite/v3/testsuite_types.go @@ -102,8 +102,22 @@ type TestSuiteExecutionRequest struct { // timeout for test suite execution Timeout int32 `json:"timeout,omitempty"` RunningContext *RunningContext `json:"runningContext,omitempty"` + // job template extensions + JobTemplate string `json:"jobTemplate,omitempty"` + // name of the template resource + JobTemplateReference string `json:"jobTemplateReference,omitempty"` // cron job template extensions CronJobTemplate string `json:"cronJobTemplate,omitempty"` + // name of the template resource + CronJobTemplateReference string `json:"cronJobTemplateReference,omitempty"` + // scraper template extensions + ScraperTemplate string `json:"scraperTemplate,omitempty"` + // name of the template resource + ScraperTemplateReference string `json:"scraperTemplateReference,omitempty"` + // pvc template extensions + PvcTemplate string `json:"pvcTemplate,omitempty"` + // name of the template resource + PvcTemplateReference string `json:"pvcTemplateReference,omitempty"` } type TestSuiteExecutionStatus string diff --git a/client/client.go b/client/client.go index 435e8550..7ec665ec 100644 --- a/client/client.go +++ b/client/client.go @@ -10,6 +10,7 @@ import ( executorv1 "github.com/kubeshop/testkube-operator/apis/executor/v1" scriptv1 "github.com/kubeshop/testkube-operator/apis/script/v1" scriptv2 "github.com/kubeshop/testkube-operator/apis/script/v2" + templatev1 "github.com/kubeshop/testkube-operator/apis/template/v1" testexecutionv1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" testsv1 "github.com/kubeshop/testkube-operator/apis/tests/v1" testsv2 "github.com/kubeshop/testkube-operator/apis/tests/v2" @@ -38,6 +39,7 @@ func GetClient() (client.Client, error) { testsourcev1.AddToScheme(scheme) testexecutionv1.AddToScheme(scheme) testsuiteexecutionv1.AddToScheme(scheme) + templatev1.AddToScheme(scheme) kubeconfig, err := ctrl.GetConfig() if err != nil { diff --git a/client/templates/v1/mock_templates.go b/client/templates/v1/mock_templates.go new file mode 100644 index 00000000..29268e1e --- /dev/null +++ b/client/templates/v1/mock_templates.go @@ -0,0 +1,123 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/kubeshop/testkube-operator/client/templates/v1 (interfaces: Interface) + +// Package templates is a generated GoMock package. +package templates + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + v1 "github.com/kubeshop/testkube-operator/apis/template/v1" +) + +// MockInterface is a mock of Interface interface. +type MockInterface struct { + ctrl *gomock.Controller + recorder *MockInterfaceMockRecorder +} + +// MockInterfaceMockRecorder is the mock recorder for MockInterface. +type MockInterfaceMockRecorder struct { + mock *MockInterface +} + +// NewMockInterface creates a new mock instance. +func NewMockInterface(ctrl *gomock.Controller) *MockInterface { + mock := &MockInterface{ctrl: ctrl} + mock.recorder = &MockInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder { + return m.recorder +} + +// Create mocks base method. +func (m *MockInterface) Create(arg0 *v1.Template) (*v1.Template, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Create", arg0) + ret0, _ := ret[0].(*v1.Template) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Create indicates an expected call of Create. +func (mr *MockInterfaceMockRecorder) Create(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockInterface)(nil).Create), arg0) +} + +// Delete mocks base method. +func (m *MockInterface) Delete(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockInterfaceMockRecorder) Delete(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockInterface)(nil).Delete), arg0) +} + +// DeleteByLabels mocks base method. +func (m *MockInterface) DeleteByLabels(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteByLabels", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteByLabels indicates an expected call of DeleteByLabels. +func (mr *MockInterfaceMockRecorder) DeleteByLabels(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteByLabels", reflect.TypeOf((*MockInterface)(nil).DeleteByLabels), arg0) +} + +// Get mocks base method. +func (m *MockInterface) Get(arg0 string) (*v1.Template, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", arg0) + ret0, _ := ret[0].(*v1.Template) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Get indicates an expected call of Get. +func (mr *MockInterfaceMockRecorder) Get(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockInterface)(nil).Get), arg0) +} + +// List mocks base method. +func (m *MockInterface) List(arg0 string) (*v1.TemplateList, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "List", arg0) + ret0, _ := ret[0].(*v1.TemplateList) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// List indicates an expected call of List. +func (mr *MockInterfaceMockRecorder) List(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockInterface)(nil).List), arg0) +} + +// Update mocks base method. +func (m *MockInterface) Update(arg0 *v1.Template) (*v1.Template, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Update", arg0) + ret0, _ := ret[0].(*v1.Template) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Update indicates an expected call of Update. +func (mr *MockInterfaceMockRecorder) Update(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockInterface)(nil).Update), arg0) +} diff --git a/client/templates/v1/templates.go b/client/templates/v1/templates.go new file mode 100644 index 00000000..5fa33c41 --- /dev/null +++ b/client/templates/v1/templates.go @@ -0,0 +1,108 @@ +package templates + +import ( + "context" + + templatev1 "github.com/kubeshop/testkube-operator/apis/template/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/labels" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +//go:generate mockgen -destination=./mock_templates.go -package=templates "github.com/kubeshop/testkube-operator/client/templates/v1" Interface +type Interface interface { + List(selector string) (*templatev1.TemplateList, error) + Get(name string) (*templatev1.Template, error) + Create(template *templatev1.Template) (*templatev1.Template, error) + Update(template *templatev1.Template) (*templatev1.Template, error) + Delete(name string) error + DeleteByLabels(selector string) error +} + +// NewClient returns new client instance, needs kubernetes client to be passed as dependecy +func NewClient(client client.Client, namespace string) *TemplatesClient { + return &TemplatesClient{ + k8sClient: client, + namespace: namespace, + } +} + +// TemplatesClient client for getting templates CRs +type TemplatesClient struct { + k8sClient client.Client + namespace string +} + +// List shows list of available executors +func (s TemplatesClient) List(selector string) (*templatev1.TemplateList, error) { + list := &templatev1.TemplateList{} + reqs, err := labels.ParseToRequirements(selector) + if err != nil { + return list, err + } + + options := &client.ListOptions{ + Namespace: s.namespace, + LabelSelector: labels.NewSelector().Add(reqs...), + } + + err = s.k8sClient.List(context.Background(), list, options) + return list, err +} + +// Get gets template by name in given namespace +func (s TemplatesClient) Get(name string) (*templatev1.Template, error) { + template := &templatev1.Template{} + if err := s.k8sClient.Get(context.Background(), client.ObjectKey{Namespace: s.namespace, Name: name}, template); err != nil { + return nil, err + } + + return template, nil +} + +// Create creates new template CRD +func (s TemplatesClient) Create(template *templatev1.Template) (*templatev1.Template, error) { + if err := s.k8sClient.Create(context.Background(), template); err != nil { + return nil, err + } + + return template, nil +} + +// Update updates template +func (s TemplatesClient) Update(template *templatev1.Template) (*templatev1.Template, error) { + if err := s.k8sClient.Update(context.Background(), template); err != nil { + return nil, err + } + + return template, nil +} + +// Delete deletes template by name +func (s TemplatesClient) Delete(name string) error { + template := &templatev1.Template{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: s.namespace, + }, + } + + err := s.k8sClient.Delete(context.Background(), template) + return err +} + +// DeleteByLabels deletes templates by labels +func (s TemplatesClient) DeleteByLabels(selector string) error { + reqs, err := labels.ParseToRequirements(selector) + if err != nil { + return err + } + + u := &unstructured.Unstructured{} + u.SetKind("Template") + u.SetAPIVersion("tests.testkube.io/v1") + err = s.k8sClient.DeleteAllOf(context.Background(), u, client.InNamespace(s.namespace), + client.MatchingLabelsSelector{Selector: labels.NewSelector().Add(reqs...)}) + return err +} diff --git a/client/templates/v1/templates_test.go b/client/templates/v1/templates_test.go new file mode 100644 index 00000000..70c2814c --- /dev/null +++ b/client/templates/v1/templates_test.go @@ -0,0 +1,148 @@ +package templates + +import ( + "testing" + + "github.com/stretchr/testify/assert" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/scheme" + + templatesv1 "github.com/kubeshop/testkube-operator/apis/template/v1" +) + +func TestTemplates(t *testing.T) { + var tClient *TemplatesClient + tType := templatesv1.CONTAINER_TemplateType + testTemplates := []*templatesv1.Template{ + { + ObjectMeta: v1.ObjectMeta{ + Name: "test-template1", + Namespace: "test-ns", + }, + Spec: templatesv1.TemplateSpec{ + Type_: &tType, + Body: "body1", + }, + Status: templatesv1.TemplateStatus{}, + }, + { + ObjectMeta: v1.ObjectMeta{ + Name: "test-template2", + Namespace: "test-ns", + }, + Spec: templatesv1.TemplateSpec{ + Type_: &tType, + Body: "body2", + }, + Status: templatesv1.TemplateStatus{}, + }, + { + ObjectMeta: v1.ObjectMeta{ + Name: "test-template3", + Namespace: "test-ns", + }, + Spec: templatesv1.TemplateSpec{ + Type_: &tType, + Body: "body3", + }, + Status: templatesv1.TemplateStatus{}, + }, + } + + t.Run("NewTemplatesClient", func(t *testing.T) { + clientBuilder := fake.NewClientBuilder() + + groupVersion := schema.GroupVersion{Group: "template.testkube.io", Version: "v1"} + schemaBuilder := scheme.Builder{GroupVersion: groupVersion} + schemaBuilder.Register(&templatesv1.TemplateList{}) + schemaBuilder.Register(&templatesv1.Template{}) + + schema, err := schemaBuilder.Build() + assert.NoError(t, err) + assert.NotEmpty(t, schema) + clientBuilder.WithScheme(schema) + + kClient := clientBuilder.Build() + testNamespace := "test-ns" + tClient = NewClient(kClient, testNamespace) + assert.NotEmpty(t, tClient) + assert.Equal(t, testNamespace, tClient.namespace) + }) + t.Run("TemplateCreate", func(t *testing.T) { + t.Run("Create new templates", func(t *testing.T) { + for _, tp := range testTemplates { + created, err := tClient.Create(tp) + assert.NoError(t, err) + assert.Equal(t, tp.Name, created.Name) + + res, err := tClient.Get(tp.ObjectMeta.Name) + assert.NoError(t, err) + assert.Equal(t, tp.Name, res.Name) + } + }) + }) + t.Run("TemplateUpdate", func(t *testing.T) { + t.Run("Update new templates", func(t *testing.T) { + for _, tp := range testTemplates { + res, err := tClient.Get(tp.ObjectMeta.Name) + assert.NoError(t, err) + assert.Equal(t, tp.Name, res.Name) + + updated, err := tClient.Update(tp) + assert.NoError(t, err) + assert.Equal(t, tp.Name, updated.Name) + } + }) + }) + t.Run("TemplateList", func(t *testing.T) { + t.Run("List without selector", func(t *testing.T) { + l, err := tClient.List("") + assert.NoError(t, err) + assert.Equal(t, len(testTemplates), len(l.Items)) + }) + }) + t.Run("TemplateGet", func(t *testing.T) { + t.Run("Get template with empty name", func(t *testing.T) { + t.Parallel() + _, err := tClient.Get("") + assert.Error(t, err) + }) + + t.Run("Get template with non existent name", func(t *testing.T) { + t.Parallel() + _, err := tClient.Get("no-template") + assert.Error(t, err) + }) + + t.Run("Get existing template", func(t *testing.T) { + res, err := tClient.Get(testTemplates[0].Name) + assert.NoError(t, err) + assert.Equal(t, testTemplates[0].Name, res.Name) + }) + }) + t.Run("TemplateDelete", func(t *testing.T) { + t.Run("Delete items", func(t *testing.T) { + for _, template := range testTemplates { + tp, err := tClient.Get(template.Name) + assert.NoError(t, err) + assert.Equal(t, tp.Name, template.Name) + + err = tClient.Delete(template.Name) + assert.NoError(t, err) + + _, err = tClient.Get(template.Name) + assert.Error(t, err) + } + }) + + t.Run("Delete non-existent item", func(t *testing.T) { + _, err := tClient.Get("no-template") + assert.Error(t, err) + + err = tClient.Delete("no-template") + assert.Error(t, err) + }) + }) +} diff --git a/client/testexecutions/v1/testexecutions_test.go b/client/testexecutions/v1/testexecutions_test.go index f3a92f27..ede73e3b 100644 --- a/client/testexecutions/v1/testexecutions_test.go +++ b/client/testexecutions/v1/testexecutions_test.go @@ -3,12 +3,13 @@ package testexecutions import ( "testing" - testexecutionv1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" "github.com/stretchr/testify/assert" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/scheme" + + testexecutionv1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" ) func TestTestExecutions(t *testing.T) { @@ -61,27 +62,27 @@ func TestTestExecutions(t *testing.T) { }) t.Run("TestExecutionCreate", func(t *testing.T) { t.Run("Create new testexecutions", func(t *testing.T) { - for _, w := range testTestExecutions { - created, err := teClient.Create(w) + for _, te := range testTestExecutions { + created, err := teClient.Create(te) assert.NoError(t, err) - assert.Equal(t, w.Name, created.Name) + assert.Equal(t, te.Name, created.Name) - res, err := teClient.Get(w.ObjectMeta.Name) + res, err := teClient.Get(te.ObjectMeta.Name) assert.NoError(t, err) - assert.Equal(t, w.Name, res.Name) + assert.Equal(t, te.Name, res.Name) } }) }) t.Run("TestExecutionUpdate", func(t *testing.T) { t.Run("Update new testexecutions", func(t *testing.T) { - for _, w := range testTestExecutions { - res, err := teClient.Get(w.ObjectMeta.Name) + for _, te := range testTestExecutions { + res, err := teClient.Get(te.ObjectMeta.Name) assert.NoError(t, err) - assert.Equal(t, w.Name, res.Name) + assert.Equal(t, te.Name, res.Name) - updated, err := teClient.Update(w) + updated, err := teClient.Update(te) assert.NoError(t, err) - assert.Equal(t, w.Name, updated.Name) + assert.Equal(t, te.Name, updated.Name) } }) }) @@ -107,9 +108,9 @@ func TestTestExecutions(t *testing.T) { t.Run("TestExecutionDelete", func(t *testing.T) { t.Run("Delete items", func(t *testing.T) { for _, testexecution := range testTestExecutions { - w, err := teClient.Get(testexecution.Name) + te, err := teClient.Get(testexecution.Name) assert.NoError(t, err) - assert.Equal(t, w.Name, testexecution.Name) + assert.Equal(t, te.Name, testexecution.Name) err = teClient.Delete(testexecution.Name) assert.NoError(t, err) diff --git a/client/testsuiteexecutions/v1/testsuiteexecutions_test.go b/client/testsuiteexecutions/v1/testsuiteexecutions_test.go index 2bc11958..1493c34d 100644 --- a/client/testsuiteexecutions/v1/testsuiteexecutions_test.go +++ b/client/testsuiteexecutions/v1/testsuiteexecutions_test.go @@ -3,12 +3,13 @@ package testsuiteexecutions import ( "testing" - testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" "github.com/stretchr/testify/assert" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/scheme" + + testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" ) func TestTestSuiteExecutions(t *testing.T) { @@ -61,27 +62,27 @@ func TestTestSuiteExecutions(t *testing.T) { }) t.Run("TestSuiteExecutionCreate", func(t *testing.T) { t.Run("Create new testsuiteexecutions", func(t *testing.T) { - for _, w := range testTestSuiteExecutions { - created, err := tseClient.Create(w) + for _, te := range testTestSuiteExecutions { + created, err := tseClient.Create(te) assert.NoError(t, err) - assert.Equal(t, w.Name, created.Name) + assert.Equal(t, te.Name, created.Name) - res, err := tseClient.Get(w.ObjectMeta.Name) + res, err := tseClient.Get(te.ObjectMeta.Name) assert.NoError(t, err) - assert.Equal(t, w.Name, res.Name) + assert.Equal(t, te.Name, res.Name) } }) }) t.Run("TestSuiteExecutionUpdate", func(t *testing.T) { t.Run("Update new testsuiteexecutions", func(t *testing.T) { - for _, w := range testTestSuiteExecutions { - res, err := tseClient.Get(w.ObjectMeta.Name) + for _, te := range testTestSuiteExecutions { + res, err := tseClient.Get(te.ObjectMeta.Name) assert.NoError(t, err) - assert.Equal(t, w.Name, res.Name) + assert.Equal(t, te.Name, res.Name) - updated, err := tseClient.Update(w) + updated, err := tseClient.Update(te) assert.NoError(t, err) - assert.Equal(t, w.Name, updated.Name) + assert.Equal(t, te.Name, updated.Name) } }) }) @@ -107,9 +108,9 @@ func TestTestSuiteExecutions(t *testing.T) { t.Run("TestSuiteExecutionDelete", func(t *testing.T) { t.Run("Delete items", func(t *testing.T) { for _, testsuiteexecution := range testTestSuiteExecutions { - w, err := tseClient.Get(testsuiteexecution.Name) + te, err := tseClient.Get(testsuiteexecution.Name) assert.NoError(t, err) - assert.Equal(t, w.Name, testsuiteexecution.Name) + assert.Equal(t, te.Name, testsuiteexecution.Name) err = tseClient.Delete(testsuiteexecution.Name) assert.NoError(t, err) diff --git a/config/crd/bases/executor.testkube.io_executors.yaml b/config/crd/bases/executor.testkube.io_executors.yaml index 6e5848e4..f17debf8 100644 --- a/config/crd/bases/executor.testkube.io_executors.yaml +++ b/config/crd/bases/executor.testkube.io_executors.yaml @@ -92,6 +92,9 @@ spec: job_template: description: Job template to launch executor type: string + jobTemplateReference: + description: name of the template resource + type: string meta: description: Meta data about executor properties: diff --git a/config/crd/bases/executor.testkube.io_webhooks.yaml b/config/crd/bases/executor.testkube.io_webhooks.yaml index fe69e09e..c8fd07dc 100644 --- a/config/crd/bases/executor.testkube.io_webhooks.yaml +++ b/config/crd/bases/executor.testkube.io_webhooks.yaml @@ -64,6 +64,9 @@ spec: payloadTemplate: description: golang based template for notification payload type: string + payloadTemplateReference: + description: name of the template resource + type: string selector: description: Labels to filter for tests and test suites type: string diff --git a/config/crd/bases/tests.testkube.io_templates.yaml b/config/crd/bases/tests.testkube.io_templates.yaml new file mode 100644 index 00000000..e951fd4b --- /dev/null +++ b/config/crd/bases/tests.testkube.io_templates.yaml @@ -0,0 +1,68 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.8.0 + creationTimestamp: null + name: templates.tests.testkube.io +spec: + group: tests.testkube.io + names: + kind: Template + listKind: TemplateList + plural: templates + singular: template + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Template is the Schema for the Templates API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: TemplateSpec defines the desired state of Template + properties: + body: + description: template body to use + type: string + type: + description: TemplateType defines template type by purpose + enum: + - job + - container + - cronjob + - scraper + - pvc + - webhook + type: string + required: + - body + - type + type: object + status: + description: TemplateStatus defines the observed state of Template + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd/bases/tests.testkube.io_tests.yaml b/config/crd/bases/tests.testkube.io_tests.yaml index 2f4be569..aa2d0f80 100644 --- a/config/crd/bases/tests.testkube.io_tests.yaml +++ b/config/crd/bases/tests.testkube.io_tests.yaml @@ -486,6 +486,9 @@ spec: cronJobTemplate: description: cron job template extensions type: string + cronJobTemplateReference: + description: name of the template resource + type: string envConfigMaps: description: config map references items: @@ -579,6 +582,9 @@ spec: jobTemplate: description: job template extensions type: string + jobTemplateReference: + description: name of the template resource + type: string name: description: test execution custom name type: string @@ -600,9 +606,18 @@ spec: preRunScript: description: script to run before test execution type: string + pvcTemplate: + description: pvc template extensions + type: string + pvcTemplateReference: + description: name of the template resource + type: string scraperTemplate: description: scraper template extensions type: string + scraperTemplateReference: + description: name of the template resource + type: string secretEnvs: additionalProperties: type: string diff --git a/config/crd/bases/tests.testkube.io_testsuites.yaml b/config/crd/bases/tests.testkube.io_testsuites.yaml index 4420562e..3672c668 100644 --- a/config/crd/bases/tests.testkube.io_testsuites.yaml +++ b/config/crd/bases/tests.testkube.io_testsuites.yaml @@ -618,6 +618,9 @@ spec: cronJobTemplate: description: cron job template extensions type: string + cronJobTemplateReference: + description: name of the template resource + type: string executionLabels: additionalProperties: type: string @@ -629,6 +632,12 @@ spec: httpsProxy: description: https proxy for executor containers type: string + jobTemplate: + description: job template extensions + type: string + jobTemplateReference: + description: name of the template resource + type: string labels: additionalProperties: type: string @@ -641,6 +650,18 @@ spec: description: test kubernetes namespace (\"testkube\" when not set) type: string + pvcTemplate: + description: pvc template extensions + type: string + pvcTemplateReference: + description: name of the template resource + type: string + scraperTemplate: + description: scraper template extensions + type: string + scraperTemplateReference: + description: name of the template resource + type: string secretUUID: description: secret uuid type: string diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 6328cc42..a606317e 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -11,6 +11,7 @@ resources: - bases/tests.testkube.io_testsources.yaml - bases/tests.testkube.io_testexecutions.yaml - bases/tests.testkube.io_testsuiteexecutions.yaml +- bases/tests.testkube.io_templates.yaml #+kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: @@ -25,6 +26,7 @@ patchesStrategicMerge: #- patches/webhook_in_testsources.yaml #- patches/webhook_in_testexecutions.yaml #- patches/webhook_in_testsuiteexecutions.yaml +#- patches/webhook_in_templates.yaml #+kubebuilder:scaffold:crdkustomizewebhookpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/crd/patches/webhook_in_tempates.yaml b/config/crd/patches/webhook_in_tempates.yaml new file mode 100644 index 00000000..ca9297a0 --- /dev/null +++ b/config/crd/patches/webhook_in_tempates.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: templates.tests.testkube.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index cf3b87a0..ff39e4ef 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -84,6 +84,30 @@ rules: - get - patch - update +- apiGroups: + - tests.testkube.io + resources: + - templates + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - tests.testkube.io + resources: + - templates/finalizers + verbs: + - update +- apiGroups: + - tests.testkube.io + resources: + - templates/status + verbs: + - get - apiGroups: - tests.testkube.io resources: diff --git a/config/rbac/template_editor_role.yaml b/config/rbac/template_editor_role.yaml new file mode 100644 index 00000000..b8c45b34 --- /dev/null +++ b/config/rbac/template_editor_role.yaml @@ -0,0 +1,24 @@ +# permissions for end users to edit templates. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: templaate-editor-role +rules: +- apiGroups: + - tests.testkube.io + resources: + - templates + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - tests.testkube.io + resources: + - templates/status + verbs: + - get diff --git a/config/rbac/template_viewer_role.yaml b/config/rbac/template_viewer_role.yaml new file mode 100644 index 00000000..32e06ec4 --- /dev/null +++ b/config/rbac/template_viewer_role.yaml @@ -0,0 +1,20 @@ +# permissions for end users to view templates. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: template-viewer-role +rules: +- apiGroups: + - tests.testkube.io + resources: + - templates + verbs: + - get + - list + - watch +- apiGroups: + - tests.testkube.io + resources: + - templates/status + verbs: + - get diff --git a/config/samples/tests_v1_template.yaml b/config/samples/tests_v1_template.yaml new file mode 100644 index 00000000..f7aa9aaf --- /dev/null +++ b/config/samples/tests_v1_template.yaml @@ -0,0 +1,7 @@ +apiVersion: tests.testkube.io/v1 +kind: Template +metadata: + name: template-sample +spec: + type: webhook + body: "{{ .Id }}" diff --git a/controllers/template/suite_test.go b/controllers/template/suite_test.go new file mode 100644 index 00000000..1f23242a --- /dev/null +++ b/controllers/template/suite_test.go @@ -0,0 +1,80 @@ +/* +Copyright 2021. + +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 template + +import ( + "path/filepath" + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + templatev1 "github.com/kubeshop/testkube-operator/apis/template/v1" + //+kubebuilder:scaffold:imports +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment + +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecs(t, "Controller Suite") +} + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + ErrorIfCRDPathMissing: true, + } + + var err error + // cfg is defined in this file globally. + cfg, err = testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + err = templatev1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient).NotTo(BeNil()) + +}) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) diff --git a/controllers/template/template_controller.go b/controllers/template/template_controller.go new file mode 100644 index 00000000..ca27d462 --- /dev/null +++ b/controllers/template/template_controller.go @@ -0,0 +1,62 @@ +/* +Copyright 2021. + +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 template + +import ( + "context" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + templatev1 "github.com/kubeshop/testkube-operator/apis/template/v1" +) + +// TemplateReconciler reconciles a Template object +type TemplateReconciler struct { + client.Client + Scheme *runtime.Scheme +} + +//+kubebuilder:rbac:groups=tests.testkube.io,resources=templates,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=tests.testkube.io,resources=templates/status,verbs=get +//+kubebuilder:rbac:groups=tests.testkube.io,resources=templates/finalizers,verbs=update + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the Template object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.4/pkg/reconcile +func (r *TemplateReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + _ = log.FromContext(ctx) + + // TODO(user): your logic here + + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *TemplateReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&templatev1.Template{}). + Complete(r) +} diff --git a/controllers/tests/test_controller.go b/controllers/tests/test_controller.go index 3b60fccd..cb3e1b3f 100644 --- a/controllers/tests/test_controller.go +++ b/controllers/tests/test_controller.go @@ -22,11 +22,13 @@ import ( "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/predicate" + templatesv1 "github.com/kubeshop/testkube-operator/apis/template/v1" testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" "github.com/kubeshop/testkube-operator/pkg/cronjob" ) @@ -90,9 +92,25 @@ func (r *TestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl. return ctrl.Result{}, err } - jobTemplate := "" + var jobTemplate, jobTemplateExt string if test.Spec.ExecutionRequest != nil { - jobTemplate = test.Spec.ExecutionRequest.CronJobTemplate + jobTemplateExt = test.Spec.ExecutionRequest.CronJobTemplate + if test.Spec.ExecutionRequest.CronJobTemplateReference != "" { + var template templatesv1.Template + object := types.NamespacedName{ + Namespace: req.Namespace, + Name: test.Spec.ExecutionRequest.CronJobTemplateReference, + } + if err = r.Get(ctx, object, &template); err != nil { + return ctrl.Result{}, err + } + + if template.Spec.Type_ != nil && *template.Spec.Type_ == templatesv1.CRONJOB_TemplateType { + jobTemplate = template.Spec.Body + } else { + ctrl.Log.Info("not matched template type", "template", test.Spec.ExecutionRequest.CronJobTemplateReference) + } + } } options := cronjob.CronJobOptions{ @@ -100,7 +118,8 @@ func (r *TestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl. Resource: cronjob.TestResourceURI, Data: string(data), Labels: test.Labels, - CronJobTemplateExtensions: jobTemplate, + CronJobTemplate: jobTemplate, + CronJobTemplateExtensions: jobTemplateExt, } // Create CronJob if it was not created before for provided Test schedule diff --git a/controllers/testsuite/testsuite_controller.go b/controllers/testsuite/testsuite_controller.go index ce5799e4..72fd4f68 100644 --- a/controllers/testsuite/testsuite_controller.go +++ b/controllers/testsuite/testsuite_controller.go @@ -22,11 +22,13 @@ import ( "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/predicate" + templatesv1 "github.com/kubeshop/testkube-operator/apis/template/v1" testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" "github.com/kubeshop/testkube-operator/pkg/cronjob" ) @@ -91,9 +93,25 @@ func (r *TestSuiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( return ctrl.Result{}, err } - jobTemplate := "" + var jobTemplate, jobTemplateExt string if testSuite.Spec.ExecutionRequest != nil { - jobTemplate = testSuite.Spec.ExecutionRequest.CronJobTemplate + jobTemplateExt = testSuite.Spec.ExecutionRequest.CronJobTemplate + if testSuite.Spec.ExecutionRequest.CronJobTemplateReference != "" { + var template templatesv1.Template + object := types.NamespacedName{ + Namespace: req.Namespace, + Name: testSuite.Spec.ExecutionRequest.CronJobTemplateReference, + } + if err = r.Get(ctx, object, &template); err != nil { + return ctrl.Result{}, err + } + + if template.Spec.Type_ != nil && *template.Spec.Type_ == templatesv1.CRONJOB_TemplateType { + jobTemplate = template.Spec.Body + } else { + ctrl.Log.Info("not matched template type", "template", testSuite.Spec.ExecutionRequest.CronJobTemplateReference) + } + } } options := cronjob.CronJobOptions{ @@ -101,7 +119,8 @@ func (r *TestSuiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( Resource: cronjob.TestSuiteResourceURI, Data: string(data), Labels: testSuite.Labels, - CronJobTemplateExtensions: jobTemplate, + CronJobTemplate: jobTemplate, + CronJobTemplateExtensions: jobTemplateExt, } // Create CronJob if it was not created before for provided TestSuite schedule diff --git a/main.go b/main.go index 98c1d19e..ac5f70ee 100644 --- a/main.go +++ b/main.go @@ -41,6 +41,7 @@ import ( executorv1 "github.com/kubeshop/testkube-operator/apis/executor/v1" testkubev1 "github.com/kubeshop/testkube-operator/apis/script/v1" testkubev2 "github.com/kubeshop/testkube-operator/apis/script/v2" + templatev1 "github.com/kubeshop/testkube-operator/apis/template/v1" testexecutionv1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" testsv1 "github.com/kubeshop/testkube-operator/apis/tests/v1" testsv2 "github.com/kubeshop/testkube-operator/apis/tests/v2" @@ -52,6 +53,7 @@ import ( testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" executorcontrollers "github.com/kubeshop/testkube-operator/controllers/executor" scriptcontrollers "github.com/kubeshop/testkube-operator/controllers/script" + templatecontrollers "github.com/kubeshop/testkube-operator/controllers/template" testexecutioncontrollers "github.com/kubeshop/testkube-operator/controllers/testexecution" testscontrollers "github.com/kubeshop/testkube-operator/controllers/tests" testsourcecontrollers "github.com/kubeshop/testkube-operator/controllers/testsource" @@ -91,6 +93,7 @@ func init() { utilruntime.Must(testsuitev3.AddToScheme(scheme)) utilruntime.Must(testexecutionv1.AddToScheme(scheme)) utilruntime.Must(testsuiteexecutionv1.AddToScheme(scheme)) + utilruntime.Must(templatev1.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } @@ -207,6 +210,13 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "TestSuiteExecution") os.Exit(1) } + if err = (&templatecontrollers.TemplateReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "Template") + os.Exit(1) + } //+kubebuilder:scaffold:builder if os.Getenv("ENABLE_WEBHOOKS") != "false" { diff --git a/pkg/cronjob/client.go b/pkg/cronjob/client.go index 21dc2191..3c5ec856 100644 --- a/pkg/cronjob/client.go +++ b/pkg/cronjob/client.go @@ -37,6 +37,7 @@ type CronJobOptions struct { Resource string Data string Labels map[string]string + CronJobTemplate string CronJobTemplateExtensions string } @@ -78,6 +79,11 @@ func (c *Client) Get(ctx context.Context, name, namespace string) (*batchv1.Cron // Create is a method to create a cron job func (c *Client) Create(ctx context.Context, id, name, namespace string, options CronJobOptions) error { + template := c.cronJobTemplate + if options.CronJobTemplate != "" { + template = options.CronJobTemplate + } + parameters := templateParameters{ Id: id, Name: name, @@ -86,7 +92,7 @@ func (c *Client) Create(ctx context.Context, id, name, namespace string, options ServicePort: c.servicePort, Schedule: options.Schedule, Resource: options.Resource, - CronJobTemplate: c.cronJobTemplate, + CronJobTemplate: template, CronJobTemplateExtensions: options.CronJobTemplateExtensions, Data: options.Data, Labels: options.Labels, @@ -107,6 +113,11 @@ func (c *Client) Create(ctx context.Context, id, name, namespace string, options // Update is a method to update an existing cron job func (c *Client) Update(ctx context.Context, cronJob *batchv1.CronJob, id, name, namespace string, options CronJobOptions) error { + template := c.cronJobTemplate + if options.CronJobTemplate != "" { + template = options.CronJobTemplate + } + parameters := templateParameters{ Id: id, Name: name, @@ -115,7 +126,7 @@ func (c *Client) Update(ctx context.Context, cronJob *batchv1.CronJob, id, name, ServicePort: c.servicePort, Schedule: options.Schedule, Resource: options.Resource, - CronJobTemplate: c.cronJobTemplate, + CronJobTemplate: template, CronJobTemplateExtensions: options.CronJobTemplateExtensions, Data: options.Data, Labels: options.Labels, From e93d866779a372ac448b00bad48775cd092b7809 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 7 Sep 2023 17:26:50 +0300 Subject: [PATCH 36/57] feat: adjust uri descrription (#174) * feat: adjust uri descrription * fix: adjust header description --- apis/executor/v1/webhook_types.go | 4 ++-- config/crd/bases/executor.testkube.io_webhooks.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apis/executor/v1/webhook_types.go b/apis/executor/v1/webhook_types.go index aca94f8d..5c05f123 100644 --- a/apis/executor/v1/webhook_types.go +++ b/apis/executor/v1/webhook_types.go @@ -28,7 +28,7 @@ type WebhookSpec struct { // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster // Important: Run "make" to regenerate code after modifying this file - // Uri is address where webhook should be made + // Uri is address where webhook should be made (golang template supported) Uri string `json:"uri,omitempty"` // Events declare list if events on which webhook should be called Events []EventType `json:"events,omitempty"` @@ -40,7 +40,7 @@ type WebhookSpec struct { PayloadTemplate string `json:"payloadTemplate,omitempty"` // name of the template resource PayloadTemplateReference string `json:"payloadTemplateReference,omitempty"` - // webhook headers + // webhook headers (golang template supported) Headers map[string]string `json:"headers,omitempty"` } diff --git a/config/crd/bases/executor.testkube.io_webhooks.yaml b/config/crd/bases/executor.testkube.io_webhooks.yaml index c8fd07dc..58ee254e 100644 --- a/config/crd/bases/executor.testkube.io_webhooks.yaml +++ b/config/crd/bases/executor.testkube.io_webhooks.yaml @@ -55,7 +55,7 @@ spec: headers: additionalProperties: type: string - description: webhook headers + description: webhook headers (golang template supported) type: object payloadObjectField: description: will load the generated payload for notification inside @@ -71,7 +71,7 @@ spec: description: Labels to filter for tests and test suites type: string uri: - description: Uri is address where webhook should be made + description: Uri is address where webhook should be made (golang template supported) type: string type: object status: From 4d087b24667c97eab86d8f4bf763bfb5c95457c2 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 18 Sep 2023 17:15:50 +0300 Subject: [PATCH 37/57] feat: trigger concurrency policy (#175) * feat: trigger concurrency policy * fix: make policy optional * fix: policy validation --- apis/testtriggers/v1/testtrigger_types.go | 13 ++++++++++++ .../bases/tests.testkube.io_testtriggers.yaml | 8 ++++++++ .../testtriggers/testtrigger_validator.go | 16 +++++++++++++++ .../testtrigger_validator_test.go | 20 +++++++++++++++++++ pkg/validation/tests/v1/testtrigger/types.go | 3 +++ pkg/validation/tests/v1/testtrigger/util.go | 4 ++++ 6 files changed, 64 insertions(+) diff --git a/apis/testtriggers/v1/testtrigger_types.go b/apis/testtriggers/v1/testtrigger_types.go index 89fd2f78..a35c8400 100644 --- a/apis/testtriggers/v1/testtrigger_types.go +++ b/apis/testtriggers/v1/testtrigger_types.go @@ -57,6 +57,8 @@ type TestTriggerSpec struct { Execution TestTriggerExecution `json:"execution"` // TestSelector identifies on which Testkube Kubernetes Objects an Action should be taken TestSelector TestTriggerSelector `json:"testSelector"` + // ConcurrencyPolicy defines concurrency policy for selected Execution + ConcurrencyPolicy TestTriggerConcurrencyPolicy `json:"concurrencyPolicy, omitEmpty"` // Delay is a duration string which specifies how long should the test be delayed after a trigger is matched // +kubebuilder:validation:Type:=string // +kubebuilder:validation:Format:=duration @@ -113,6 +115,17 @@ const ( TestTriggerExecutionTestsuite TestTriggerExecution = "testsuite" ) +// TestTriggerConcurrencyPolicy defines concurrency policy for test triggers +// +kubebuilder:validation:Enum=allow;forbid;replace +type TestTriggerConcurrencyPolicy string + +// List of TestTriggerConcurrencyPolicy +const ( + TestTriggerConcurrencyPolicyAllow TestTriggerConcurrencyPolicy = "allow" + TestTriggerConcurrencyPolicyForbid TestTriggerConcurrencyPolicy = "forbid" + TestTriggerConcurrencyPolicyReplace TestTriggerConcurrencyPolicy = "replace" +) + // TestTriggerSelector is used for selecting Kubernetes Objects type TestTriggerSelector struct { // Name selector is used to identify a Kubernetes Object based on the metadata name diff --git a/config/crd/bases/tests.testkube.io_testtriggers.yaml b/config/crd/bases/tests.testkube.io_testtriggers.yaml index 0bd9b881..7334b0a6 100644 --- a/config/crd/bases/tests.testkube.io_testtriggers.yaml +++ b/config/crd/bases/tests.testkube.io_testtriggers.yaml @@ -54,6 +54,14 @@ spec: enum: - run type: string + concurrencyPolicy: + description: ConcurrencyPolicy defines concurrency policy for selected + Execution + enum: + - allow + - forbid + - replace + type: string conditionSpec: description: What resource conditions should be matched properties: diff --git a/controllers/testtriggers/testtrigger_validator.go b/controllers/testtriggers/testtrigger_validator.go index 6ac53494..00d178d5 100644 --- a/controllers/testtriggers/testtrigger_validator.go +++ b/controllers/testtriggers/testtrigger_validator.go @@ -61,6 +61,10 @@ func (v *Validator) ValidateCreate(ctx context.Context, t *testtriggerv1.TestTri allErrs = append(allErrs, err) } + if err := v.validateConcurrencyPolicy(t.Spec.ConcurrencyPolicy); err != nil { + allErrs = append(allErrs, err) + } + if err := v.validateResourceSelector(t.Spec.ResourceSelector); err != nil { allErrs = append(allErrs, err...) } @@ -106,6 +110,10 @@ func (v *Validator) ValidateUpdate(ctx context.Context, old runtime.Object, new allErrs = append(allErrs, err) } + if err := v.validateConcurrencyPolicy(new.Spec.ConcurrencyPolicy); err != nil { + allErrs = append(allErrs, err) + } + if errs := v.validateResourceSelector(new.Spec.ResourceSelector); errs != nil { allErrs = append(allErrs, errs...) } @@ -208,6 +216,14 @@ func (v *Validator) validateExecution(execution testtriggerv1.TestTriggerExecuti return nil } +func (v *Validator) validateConcurrencyPolicy(concurrencyPolicy testtriggerv1.TestTriggerConcurrencyPolicy) *field.Error { + if concurrencyPolicy != "" && !utils.In(string(concurrencyPolicy), testtrigger.GetSupportedConcurrencyPolicies()) { + fld := field.NewPath("spec").Child("concurrencyPolicy") + return field.NotSupported(fld, concurrencyPolicy, testtrigger.GetSupportedConcurrencyPolicies()) + } + return nil +} + func (v *Validator) validateConditions(conditionSpec *testtriggerv1.TestTriggerConditionSpec) field.ErrorList { var allErrs field.ErrorList if conditionSpec == nil { diff --git a/controllers/testtriggers/testtrigger_validator_test.go b/controllers/testtriggers/testtrigger_validator_test.go index f2b1d446..bb525881 100644 --- a/controllers/testtriggers/testtrigger_validator_test.go +++ b/controllers/testtriggers/testtrigger_validator_test.go @@ -69,6 +69,26 @@ func TestValidator_validateExecution(t *testing.T) { }) } +func TestValidator_validateConcurrencyPlocy(t *testing.T) { + t.Parallel() + + v := NewValidator(buildFakeK8sClient(t)) + + t.Run("no error for valid concurrency policy", func(t *testing.T) { + t.Parallel() + + err := v.validateConcurrencyPolicy("allow") + assert.Nil(t, err) + }) + + t.Run("error for invalid concurrency policy", func(t *testing.T) { + t.Parallel() + + err := v.validateConcurrencyPolicy("skip") + assert.ErrorContains(t, err, "spec.concurrencyPolicy: Unsupported value: \"skip\"") + }) +} + func TestValidator_validateResource(t *testing.T) { t.Parallel() diff --git a/pkg/validation/tests/v1/testtrigger/types.go b/pkg/validation/tests/v1/testtrigger/types.go index 9ee96156..caaddb0d 100644 --- a/pkg/validation/tests/v1/testtrigger/types.go +++ b/pkg/validation/tests/v1/testtrigger/types.go @@ -8,6 +8,9 @@ const ( ExecutionTest = "test" ExecutionTestsuite = "testsuite" ActionRun = "run" + ConcurrencyPolicyAllow = "allow" + ConcurrencyPolicyForbid = "forbid" + ConcurrencyPolicyReplace = "replace" ResourcePod = "pod" ResourceDeployment = "deployment" ResourceStatefulSet = "statefulset" diff --git a/pkg/validation/tests/v1/testtrigger/util.go b/pkg/validation/tests/v1/testtrigger/util.go index f32a4d42..ca397da6 100644 --- a/pkg/validation/tests/v1/testtrigger/util.go +++ b/pkg/validation/tests/v1/testtrigger/util.go @@ -25,6 +25,10 @@ func GetSupportedExecutions() []string { return []string{ExecutionTest, ExecutionTestsuite} } +func GetSupportedConcurrencyPolicies() []string { + return []string{ConcurrencyPolicyAllow, ConcurrencyPolicyForbid, ConcurrencyPolicyReplace} +} + func GetSupportedConditionStatuses() []string { return []string{ string(testtriggerv1.TRUE_TestTriggerConditionStatuses), From fe2d1f93a3938bb351494111ed92b161d0f8eda4 Mon Sep 17 00:00:00 2001 From: hiteshwani <110378441+hiteshwani@users.noreply.github.com> Date: Tue, 26 Sep 2023 15:08:55 +0530 Subject: [PATCH 38/57] Added slaves field in executor CRD to add slaves configuration (#177) * Added slaves field in executor CRD to add slaves configuration Signed-off-by: hiteshwani * Discard changes Signed-off-by: hiteshwani * Fixed trivial review comments Signed-off-by: Aman Parauliya --------- Signed-off-by: hiteshwani Signed-off-by: Aman Parauliya Co-authored-by: Aman Parauliya --- apis/executor/v1/executor_types.go | 7 +++++ apis/executor/v1/zz_generated.deepcopy.go | 21 +++++++++++++++ apis/template/v1/zz_generated.deepcopy.go | 1 + apis/tests/v3/zz_generated.deepcopy.go | 20 ++++++++++++++ apis/testsuite/v2/zz_generated.deepcopy.go | 20 ++++++++++++++ apis/testsuite/v3/zz_generated.deepcopy.go | 26 ++++++++++++++++--- apis/testtriggers/v1/testtrigger_types.go | 2 +- apis/testtriggers/v1/zz_generated.deepcopy.go | 2 +- .../bases/executor.testkube.io_executors.yaml | 8 ++++++ ...tests.testkube.io_testsuiteexecutions.yaml | 3 +-- config/rbac/role.yaml | 1 - 11 files changed, 102 insertions(+), 9 deletions(-) diff --git a/apis/executor/v1/executor_types.go b/apis/executor/v1/executor_types.go index 71d2753e..8b2991c4 100644 --- a/apis/executor/v1/executor_types.go +++ b/apis/executor/v1/executor_types.go @@ -60,6 +60,13 @@ type ExecutorSpec struct { // Meta data about executor Meta *ExecutorMeta `json:"meta,omitempty"` + + // Slaves data to run test in distributed environment + Slaves *SlavesMeta `json:"slaves,omitempty"` +} + +type SlavesMeta struct { + Image string `json:"image"` } // +kubebuilder:validation:Enum=artifacts;junit-report diff --git a/apis/executor/v1/zz_generated.deepcopy.go b/apis/executor/v1/zz_generated.deepcopy.go index b04aca4e..89fa978e 100644 --- a/apis/executor/v1/zz_generated.deepcopy.go +++ b/apis/executor/v1/zz_generated.deepcopy.go @@ -1,3 +1,4 @@ +//go:build !ignore_autogenerated // +build !ignore_autogenerated /* @@ -144,6 +145,11 @@ func (in *ExecutorSpec) DeepCopyInto(out *ExecutorSpec) { *out = new(ExecutorMeta) (*in).DeepCopyInto(*out) } + if in.Slaves != nil { + in, out := &in.Slaves, &out.Slaves + *out = new(SlavesMeta) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecutorSpec. @@ -186,6 +192,21 @@ func (in *Runner) DeepCopy() *Runner { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SlavesMeta) DeepCopyInto(out *SlavesMeta) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SlavesMeta. +func (in *SlavesMeta) DeepCopy() *SlavesMeta { + if in == nil { + return nil + } + out := new(SlavesMeta) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Webhook) DeepCopyInto(out *Webhook) { *out = *in diff --git a/apis/template/v1/zz_generated.deepcopy.go b/apis/template/v1/zz_generated.deepcopy.go index e7434b2d..cc3514ab 100644 --- a/apis/template/v1/zz_generated.deepcopy.go +++ b/apis/template/v1/zz_generated.deepcopy.go @@ -1,3 +1,4 @@ +//go:build !ignore_autogenerated // +build !ignore_autogenerated /* diff --git a/apis/tests/v3/zz_generated.deepcopy.go b/apis/tests/v3/zz_generated.deepcopy.go index ea191dae..744838aa 100644 --- a/apis/tests/v3/zz_generated.deepcopy.go +++ b/apis/tests/v3/zz_generated.deepcopy.go @@ -145,6 +145,11 @@ func (in *ExecutionRequest) DeepCopyInto(out *ExecutionRequest) { *out = make([]EnvReference, len(*in)) copy(*out, *in) } + if in.RunningContext != nil { + in, out := &in.RunningContext, &out.RunningContext + *out = new(RunningContext) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecutionRequest. @@ -182,6 +187,21 @@ func (in *Repository) DeepCopy() *Repository { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RunningContext) DeepCopyInto(out *RunningContext) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunningContext. +func (in *RunningContext) DeepCopy() *RunningContext { + if in == nil { + return nil + } + out := new(RunningContext) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecretRef) DeepCopyInto(out *SecretRef) { *out = *in diff --git a/apis/testsuite/v2/zz_generated.deepcopy.go b/apis/testsuite/v2/zz_generated.deepcopy.go index 027d3d72..3280c564 100644 --- a/apis/testsuite/v2/zz_generated.deepcopy.go +++ b/apis/testsuite/v2/zz_generated.deepcopy.go @@ -25,6 +25,21 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RunningContext) DeepCopyInto(out *RunningContext) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunningContext. +func (in *RunningContext) DeepCopy() *RunningContext { + if in == nil { + return nil + } + out := new(RunningContext) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TestSuite) DeepCopyInto(out *TestSuite) { *out = *in @@ -98,6 +113,11 @@ func (in *TestSuiteExecutionRequest) DeepCopyInto(out *TestSuiteExecutionRequest (*out)[key] = val } } + if in.RunningContext != nil { + in, out := &in.RunningContext, &out.RunningContext + *out = new(RunningContext) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteExecutionRequest. diff --git a/apis/testsuite/v3/zz_generated.deepcopy.go b/apis/testsuite/v3/zz_generated.deepcopy.go index 9b82a395..da7595fc 100644 --- a/apis/testsuite/v3/zz_generated.deepcopy.go +++ b/apis/testsuite/v3/zz_generated.deepcopy.go @@ -25,6 +25,21 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RunningContext) DeepCopyInto(out *RunningContext) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunningContext. +func (in *RunningContext) DeepCopy() *RunningContext { + if in == nil { + return nil + } + out := new(RunningContext) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TestSuite) DeepCopyInto(out *TestSuite) { *out = *in @@ -58,9 +73,7 @@ func (in *TestSuiteBatchStep) DeepCopyInto(out *TestSuiteBatchStep) { if in.Execute != nil { in, out := &in.Execute, &out.Execute *out = make([]TestSuiteStepSpec, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } + copy(*out, *in) } } @@ -120,6 +133,11 @@ func (in *TestSuiteExecutionRequest) DeepCopyInto(out *TestSuiteExecutionRequest (*out)[key] = val } } + if in.RunningContext != nil { + in, out := &in.RunningContext, &out.RunningContext + *out = new(RunningContext) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteExecutionRequest. @@ -228,7 +246,7 @@ func (in *TestSuiteStatus) DeepCopy() *TestSuiteStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TestSuiteStepSpec) DeepCopyInto(out *TestSuiteStepSpec) { *out = *in - in.Delay.DeepCopyInto(&out.Delay) + out.Delay = in.Delay } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteStepSpec. diff --git a/apis/testtriggers/v1/testtrigger_types.go b/apis/testtriggers/v1/testtrigger_types.go index a35c8400..cf998f71 100644 --- a/apis/testtriggers/v1/testtrigger_types.go +++ b/apis/testtriggers/v1/testtrigger_types.go @@ -58,7 +58,7 @@ type TestTriggerSpec struct { // TestSelector identifies on which Testkube Kubernetes Objects an Action should be taken TestSelector TestTriggerSelector `json:"testSelector"` // ConcurrencyPolicy defines concurrency policy for selected Execution - ConcurrencyPolicy TestTriggerConcurrencyPolicy `json:"concurrencyPolicy, omitEmpty"` + ConcurrencyPolicy TestTriggerConcurrencyPolicy `json:"concurrencyPolicy,omitempty"` // Delay is a duration string which specifies how long should the test be delayed after a trigger is matched // +kubebuilder:validation:Type:=string // +kubebuilder:validation:Format:=duration diff --git a/apis/testtriggers/v1/zz_generated.deepcopy.go b/apis/testtriggers/v1/zz_generated.deepcopy.go index ac2c588b..de6b839b 100644 --- a/apis/testtriggers/v1/zz_generated.deepcopy.go +++ b/apis/testtriggers/v1/zz_generated.deepcopy.go @@ -209,7 +209,7 @@ func (in *TestTriggerSpec) DeepCopyInto(out *TestTriggerSpec) { if in.Delay != nil { in, out := &in.Delay, &out.Delay *out = new(metav1.Duration) - (*in).DeepCopyInto(*out) + **out = **in } } diff --git a/config/crd/bases/executor.testkube.io_executors.yaml b/config/crd/bases/executor.testkube.io_executors.yaml index f17debf8..645b02e6 100644 --- a/config/crd/bases/executor.testkube.io_executors.yaml +++ b/config/crd/bases/executor.testkube.io_executors.yaml @@ -110,6 +110,14 @@ spec: description: executor tooltips type: object type: object + slaves: + description: Slaves data to run test in distributed environment + properties: + image: + type: string + required: + - image + type: object types: description: Types defines what types can be handled by executor e.g. "postman/collection", ":curl/command" etc diff --git a/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml b/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml index c000ad11..b6af21ed 100644 --- a/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml +++ b/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml @@ -305,8 +305,7 @@ spec: type: string type: array omitFolderPerExecution: - description: don't use a separate folder for execution - artifacts + description: don't use a separate folder for execution artifacts type: boolean storageBucket: description: artifact bucket storage diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index ff39e4ef..b139c78c 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -1,4 +1,3 @@ - --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole From 785d10665337cebdf5672a26e2d8cc64aa8323f9 Mon Sep 17 00:00:00 2001 From: Dejan Zele Pejchev Date: Wed, 27 Sep 2023 07:53:40 +0200 Subject: [PATCH 39/57] feat: update operator to use latest kubebuilder layout (#178) * update operator to use latest kubebuilder layout * update dependencies * update dependencies * remove some unused fields from CRDs * fix failing test --- .github/workflows/docker-build-beta-tag.yaml | 19 +- .github/workflows/docker-build-develop.yaml | 23 +- .github/workflows/docker-build-release.yaml | 23 +- .github/workflows/docker-build-tag.yaml | 19 +- .gitignore | 4 +- Dockerfile | 5 +- Makefile | 16 +- PROJECT | 32 +- {apis => api}/common/v1/variables.go | 0 {apis => api}/executor/v1/executor_types.go | 0 .../executor/v1/groupversion_info.go | 0 {apis => api}/executor/v1/webhook_types.go | 0 .../executor/v1/zz_generated.deepcopy.go | 0 {apis => api}/script/v1/groupversion_info.go | 0 {apis => api}/script/v1/script_conversion.go | 0 {apis => api}/script/v1/script_types.go | 0 {apis => api}/script/v1/script_webhook.go | 0 .../script/v1/zz_generated.deepcopy.go | 0 {apis => api}/script/v2/groupversion_info.go | 0 {apis => api}/script/v2/script_conversion.go | 4 +- {apis => api}/script/v2/script_types.go | 0 {apis => api}/script/v2/script_webhook.go | 0 .../script/v2/zz_generated.deepcopy.go | 0 .../template/v1/groupversion_info.go | 0 {apis => api}/template/v1/template_types.go | 0 .../template/v1/zz_generated.deepcopy.go | 0 .../testexecution/v1/groupversion_info.go | 0 .../testexecution/v1/testexecution_types.go | 2 +- .../testexecution/v1/zz_generated.deepcopy.go | 0 {apis => api}/tests/v1/groupversion_info.go | 0 {apis => api}/tests/v1/test_conversion.go | 2 +- {apis => api}/tests/v1/test_types.go | 0 {apis => api}/tests/v1/test_webhook.go | 0 .../tests/v1/zz_generated.deepcopy.go | 0 {apis => api}/tests/v2/groupversion_info.go | 0 {apis => api}/tests/v2/test_conversion.go | 0 {apis => api}/tests/v2/test_types.go | 2 +- {apis => api}/tests/v2/test_webhook.go | 0 .../tests/v2/zz_generated.deepcopy.go | 0 {apis => api}/tests/v3/groupversion_info.go | 0 {apis => api}/tests/v3/test_conversion.go | 12 +- {apis => api}/tests/v3/test_types.go | 10 +- {apis => api}/tests/v3/test_webhook.go | 0 .../tests/v3/zz_generated.deepcopy.go | 0 .../testsource/v1/groupversion_info.go | 0 .../testsource/v1/testsource_types.go | 6 +- .../testsource/v1/zz_generated.deepcopy.go | 0 .../testsuite/v1/groupversion_info.go | 0 .../testsuite/v1/testsuite_conversion.go | 4 +- {apis => api}/testsuite/v1/testsuite_types.go | 2 +- .../testsuite/v1/testsuite_webhook.go | 0 .../testsuite/v1/zz_generated.deepcopy.go | 0 .../testsuite/v2/groupversion_info.go | 0 .../testsuite/v2/testsuite_conversion.go | 0 {apis => api}/testsuite/v2/testsuite_types.go | 8 +- .../testsuite/v2/testsuite_webhook.go | 0 .../testsuite/v2/zz_generated.deepcopy.go | 0 .../testsuite/v3/groupversion_info.go | 0 .../testsuite/v3/testsuite_conversion.go | 2 +- {apis => api}/testsuite/v3/testsuite_types.go | 12 +- .../testsuite/v3/testsuite_webhook.go | 0 .../testsuite/v3/zz_generated.deepcopy.go | 0 .../v1/groupversion_info.go | 0 .../v1/testsuiteexecution_types.go | 2 +- .../v1/zz_generated.deepcopy.go | 0 .../testtriggers/v1/groupversion_info.go | 0 .../testtriggers/v1/testtrigger_suite_test.go | 24 +- .../testtriggers/v1/testtrigger_types.go | 0 .../testtriggers/v1/testtrigger_webhook.go | 13 +- .../testtriggers/v1/zz_generated.deepcopy.go | 0 client/client.go | 50 - main.go => cmd/main.go | 56 +- config/certmanager/certificate.yaml | 39 + config/certmanager/kustomization.yaml | 5 + config/certmanager/kustomizeconfig.yaml | 8 + .../bases/executor.testkube.io_executors.yaml | 2 - .../bases/executor.testkube.io_webhooks.yaml | 3 +- config/crd/bases/tests.testkube.io_tests.yaml | 8 +- .../bases/tests.testkube.io_testsources.yaml | 12 +- ...tests.testkube.io_testsuiteexecutions.yaml | 3 +- .../bases/tests.testkube.io_testsuites.yaml | 9 +- .../patches/cainjection_in_testtriggers.yaml | 7 + config/default/kustomization.yaml | 130 +- config/default/manager_auth_proxy_patch.yaml | 45 +- config/default/manager_config_patch.yaml | 12 +- config/default/webhookcainjection_patch.yaml | 22 + config/manager/controller_manager_config.yaml | 11 - config/manager/kustomization.yaml | 8 - config/manager/manager.yaml | 7 +- config/webhook/kustomizeconfig.yaml | 33 +- config/webhook/manifests.yaml | 2 - demo/curl.yaml | 16 + demo/trigger.yaml | 17 + go.mod | 105 +- go.sum | 1079 ++--------------- goreleaser/.goreleaser-snapshot.yaml | 1 + goreleaser/.goreleaser.yml | 1 + hack/cert.sh | 46 + .../executor/executor_controller.go | 2 +- .../controller}/executor/suite_test.go | 7 +- .../executor/webhook_controller.go | 2 +- .../controller}/script/script_controller.go | 2 +- .../controller}/script/suite_test.go | 7 +- .../controller}/template/suite_test.go | 4 +- .../template/template_controller.go | 2 +- .../controller}/testexecution/suite_test.go | 4 +- .../testexecution/testexecution_controller.go | 2 +- .../controller}/tests/test_controller.go | 4 +- .../controller}/testsource/suite_test.go | 7 +- .../testsource/testsource_controller.go | 2 +- .../controller}/testsuite/suite_test.go | 7 +- .../testsuite/testsuite_controller.go | 4 +- .../testsuiteexecution/suite_test.go | 4 +- .../testsuiteexecution_controllller.go | 2 +- .../controller}/testtriggers/suite_test.go | 7 +- .../testtriggers/testtrigger_controller.go | 2 +- .../testtriggers/testtrigger_validator.go | 4 +- .../testtrigger_validator_test.go | 4 +- {utils => internal/utils}/utils.go | 0 local.Dockerfile | 6 + pkg/client/client.go | 51 + {client => pkg/client}/executors/executors.go | 2 +- .../client}/executors/v1/executors.go | 2 +- .../client}/executors/v1/mock_executors.go | 2 +- .../client}/executors/v1/webhooks.go | 2 +- .../client}/executors/v1/webhooks_test.go | 2 +- {client => pkg/client}/scripts/scripts.go | 4 +- {client => pkg/client}/scripts/v2/scripts.go | 4 +- .../client}/templates/v1/mock_templates.go | 2 +- .../client}/templates/v1/templates.go | 2 +- .../client}/templates/v1/templates_test.go | 2 +- .../testexecutions/v1/mock_testexecutions.go | 2 +- .../testexecutions/v1/testexecutions.go | 2 +- .../testexecutions/v1/testexecutions_test.go | 2 +- {client => pkg/client}/tests/tests.go | 4 +- {client => pkg/client}/tests/v2/tests.go | 4 +- {client => pkg/client}/tests/v2/tests_test.go | 4 +- {client => pkg/client}/tests/v3/mock_tests.go | 2 +- {client => pkg/client}/tests/v3/test.go | 6 +- {client => pkg/client}/tests/v3/test_test.go | 4 +- .../testsources/v1/mock_testsources.go | 2 +- .../client}/testsources/v1/testsources.go | 4 +- .../testsources/v1/testsources_test.go | 2 +- .../v1/mock_testsuiteexecutions.go | 2 +- .../v1/testsuiteexecutions.go | 2 +- .../v1/testsuiteexecutions_test.go | 2 +- .../client}/testsuites/v1/testsuites.go | 4 +- .../client}/testsuites/v1/testsuites_test.go | 4 +- .../client}/testsuites/v2/mock_testsuites.go | 2 +- .../client}/testsuites/v2/testsuites.go | 4 +- .../client}/testsuites/v2/testsuites_test.go | 4 +- .../client}/testsuites/v3/mock_testsuites.go | 2 +- .../client}/testsuites/v3/testsuites.go | 4 +- .../client}/testsuites/v3/testsuites_test.go | 4 +- pkg/clientset/versioned/fake/register.go | 6 +- pkg/clientset/versioned/scheme/register.go | 6 +- .../typed/tests/v1/fake/fake_testtrigger.go | 2 +- .../versioned/typed/tests/v1/tests_client.go | 2 +- .../versioned/typed/tests/v1/testtrigger.go | 2 +- .../typed/tests/v2/fake/fake_testsuite.go | 2 +- .../versioned/typed/tests/v2/tests_client.go | 2 +- .../versioned/typed/tests/v2/testsuite.go | 2 +- .../typed/tests/v3/fake/fake_tests.go | 2 +- .../typed/tests/v3/fake/fake_testsuite.go | 2 +- .../versioned/typed/tests/v3/test.go | 2 +- .../versioned/typed/tests/v3/tests_client.go | 2 +- .../versioned/typed/tests/v3/testsuite.go | 2 +- pkg/informers/externalversions/generic.go | 6 +- .../externalversions/tests/v1/testtrigger.go | 2 +- .../externalversions/tests/v2/testsuite.go | 2 +- .../externalversions/tests/v3/test.go | 2 +- .../externalversions/tests/v3/testsuite.go | 2 +- pkg/listers/tests/v1/testtriggers.go | 2 +- pkg/listers/tests/v2/testsuites.go | 2 +- pkg/listers/tests/v3/tests.go | 2 +- pkg/listers/tests/v3/testsuites.go | 2 +- pkg/validation/tests/v1/testtrigger/util.go | 2 +- 177 files changed, 826 insertions(+), 1447 deletions(-) rename {apis => api}/common/v1/variables.go (100%) rename {apis => api}/executor/v1/executor_types.go (100%) rename {apis => api}/executor/v1/groupversion_info.go (100%) rename {apis => api}/executor/v1/webhook_types.go (100%) rename {apis => api}/executor/v1/zz_generated.deepcopy.go (100%) rename {apis => api}/script/v1/groupversion_info.go (100%) rename {apis => api}/script/v1/script_conversion.go (100%) rename {apis => api}/script/v1/script_types.go (100%) rename {apis => api}/script/v1/script_webhook.go (100%) rename {apis => api}/script/v1/zz_generated.deepcopy.go (100%) rename {apis => api}/script/v2/groupversion_info.go (100%) rename {apis => api}/script/v2/script_conversion.go (94%) rename {apis => api}/script/v2/script_types.go (100%) rename {apis => api}/script/v2/script_webhook.go (100%) rename {apis => api}/script/v2/zz_generated.deepcopy.go (100%) rename {apis => api}/template/v1/groupversion_info.go (100%) rename {apis => api}/template/v1/template_types.go (100%) rename {apis => api}/template/v1/zz_generated.deepcopy.go (100%) rename {apis => api}/testexecution/v1/groupversion_info.go (100%) rename {apis => api}/testexecution/v1/testexecution_types.go (99%) rename {apis => api}/testexecution/v1/zz_generated.deepcopy.go (100%) rename {apis => api}/tests/v1/groupversion_info.go (100%) rename {apis => api}/tests/v1/test_conversion.go (94%) rename {apis => api}/tests/v1/test_types.go (100%) rename {apis => api}/tests/v1/test_webhook.go (100%) rename {apis => api}/tests/v1/zz_generated.deepcopy.go (100%) rename {apis => api}/tests/v2/groupversion_info.go (100%) rename {apis => api}/tests/v2/test_conversion.go (100%) rename {apis => api}/tests/v2/test_types.go (98%) rename {apis => api}/tests/v2/test_webhook.go (100%) rename {apis => api}/tests/v2/zz_generated.deepcopy.go (100%) rename {apis => api}/tests/v3/groupversion_info.go (100%) rename {apis => api}/tests/v3/test_conversion.go (92%) rename {apis => api}/tests/v3/test_types.go (97%) rename {apis => api}/tests/v3/test_webhook.go (100%) rename {apis => api}/tests/v3/zz_generated.deepcopy.go (100%) rename {apis => api}/testsource/v1/groupversion_info.go (100%) rename {apis => api}/testsource/v1/testsource_types.go (94%) rename {apis => api}/testsource/v1/zz_generated.deepcopy.go (100%) rename {apis => api}/testsuite/v1/groupversion_info.go (100%) rename {apis => api}/testsuite/v1/testsuite_conversion.go (97%) rename {apis => api}/testsuite/v1/testsuite_types.go (98%) rename {apis => api}/testsuite/v1/testsuite_webhook.go (100%) rename {apis => api}/testsuite/v1/zz_generated.deepcopy.go (100%) rename {apis => api}/testsuite/v2/groupversion_info.go (100%) rename {apis => api}/testsuite/v2/testsuite_conversion.go (100%) rename {apis => api}/testsuite/v2/testsuite_types.go (96%) rename {apis => api}/testsuite/v2/testsuite_webhook.go (100%) rename {apis => api}/testsuite/v2/zz_generated.deepcopy.go (100%) rename {apis => api}/testsuite/v3/groupversion_info.go (100%) rename {apis => api}/testsuite/v3/testsuite_conversion.go (98%) rename {apis => api}/testsuite/v3/testsuite_types.go (95%) rename {apis => api}/testsuite/v3/testsuite_webhook.go (100%) rename {apis => api}/testsuite/v3/zz_generated.deepcopy.go (100%) rename {apis => api}/testsuiteexecution/v1/groupversion_info.go (100%) rename {apis => api}/testsuiteexecution/v1/testsuiteexecution_types.go (99%) rename {apis => api}/testsuiteexecution/v1/zz_generated.deepcopy.go (100%) rename {apis => api}/testtriggers/v1/groupversion_info.go (100%) rename {apis => api}/testtriggers/v1/testtrigger_suite_test.go (87%) rename {apis => api}/testtriggers/v1/testtrigger_types.go (100%) rename {apis => api}/testtriggers/v1/testtrigger_webhook.go (75%) rename {apis => api}/testtriggers/v1/zz_generated.deepcopy.go (100%) delete mode 100644 client/client.go rename main.go => cmd/main.go (84%) create mode 100644 config/certmanager/certificate.yaml create mode 100644 config/certmanager/kustomization.yaml create mode 100644 config/certmanager/kustomizeconfig.yaml create mode 100644 config/crd/patches/cainjection_in_testtriggers.yaml create mode 100644 config/default/webhookcainjection_patch.yaml delete mode 100644 config/manager/controller_manager_config.yaml create mode 100644 demo/curl.yaml create mode 100644 demo/trigger.yaml create mode 100755 hack/cert.sh rename {controllers => internal/controller}/executor/executor_controller.go (96%) rename {controllers => internal/controller}/executor/suite_test.go (89%) rename {controllers => internal/controller}/executor/webhook_controller.go (96%) rename {controllers => internal/controller}/script/script_controller.go (96%) rename {controllers => internal/controller}/script/suite_test.go (89%) rename {controllers => internal/controller}/template/suite_test.go (92%) rename {controllers => internal/controller}/template/template_controller.go (96%) rename {controllers => internal/controller}/testexecution/suite_test.go (92%) rename {controllers => internal/controller}/testexecution/testexecution_controller.go (98%) rename {controllers => internal/controller}/tests/test_controller.go (97%) rename {controllers => internal/controller}/testsource/suite_test.go (88%) rename {controllers => internal/controller}/testsource/testsource_controller.go (96%) rename {controllers => internal/controller}/testsuite/suite_test.go (88%) rename {controllers => internal/controller}/testsuite/testsuite_controller.go (97%) rename {controllers => internal/controller}/testsuiteexecution/suite_test.go (94%) rename {controllers => internal/controller}/testsuiteexecution/testsuiteexecution_controllller.go (99%) rename {controllers => internal/controller}/testtriggers/suite_test.go (88%) rename {controllers => internal/controller}/testtriggers/testtrigger_controller.go (96%) rename {controllers => internal/controller}/testtriggers/testtrigger_validator.go (98%) rename {controllers => internal/controller}/testtriggers/testtrigger_validator_test.go (98%) rename {utils => internal/utils}/utils.go (100%) create mode 100644 local.Dockerfile create mode 100644 pkg/client/client.go rename {client => pkg/client}/executors/executors.go (97%) rename {client => pkg/client}/executors/v1/executors.go (98%) rename {client => pkg/client}/executors/v1/mock_executors.go (98%) rename {client => pkg/client}/executors/v1/webhooks.go (98%) rename {client => pkg/client}/executors/v1/webhooks_test.go (98%) rename {client => pkg/client}/scripts/scripts.go (95%) rename {client => pkg/client}/scripts/v2/scripts.go (95%) rename {client => pkg/client}/templates/v1/mock_templates.go (98%) rename {client => pkg/client}/templates/v1/templates.go (97%) rename {client => pkg/client}/templates/v1/templates_test.go (98%) rename {client => pkg/client}/testexecutions/v1/mock_testexecutions.go (98%) rename {client => pkg/client}/testexecutions/v1/testexecutions.go (97%) rename {client => pkg/client}/testexecutions/v1/testexecutions_test.go (97%) rename {client => pkg/client}/tests/tests.go (94%) rename {client => pkg/client}/tests/v2/tests.go (98%) rename {client => pkg/client}/tests/v2/tests_test.go (96%) rename {client => pkg/client}/tests/v3/mock_tests.go (99%) rename {client => pkg/client}/tests/v3/test.go (99%) rename {client => pkg/client}/tests/v3/test_test.go (96%) rename {client => pkg/client}/testsources/v1/mock_testsources.go (98%) rename {client => pkg/client}/testsources/v1/testsources.go (98%) rename {client => pkg/client}/testsources/v1/testsources_test.go (98%) rename {client => pkg/client}/testsuiteexecutions/v1/mock_testsuiteexecutions.go (98%) rename {client => pkg/client}/testsuiteexecutions/v1/testsuiteexecutions.go (99%) rename {client => pkg/client}/testsuiteexecutions/v1/testsuiteexecutions_test.go (99%) rename {client => pkg/client}/testsuites/v1/testsuites.go (98%) rename {client => pkg/client}/testsuites/v1/testsuites_test.go (95%) rename {client => pkg/client}/testsuites/v2/mock_testsuites.go (99%) rename {client => pkg/client}/testsuites/v2/testsuites.go (98%) rename {client => pkg/client}/testsuites/v2/testsuites_test.go (96%) rename {client => pkg/client}/testsuites/v3/mock_testsuites.go (99%) rename {client => pkg/client}/testsuites/v3/testsuites.go (98%) rename {client => pkg/client}/testsuites/v3/testsuites_test.go (96%) diff --git a/.github/workflows/docker-build-beta-tag.yaml b/.github/workflows/docker-build-beta-tag.yaml index be74c693..df830867 100644 --- a/.github/workflows/docker-build-beta-tag.yaml +++ b/.github/workflows/docker-build-beta-tag.yaml @@ -5,33 +5,26 @@ on: - "v[0-9]+.[0-9]+.[0-9]+-*" env: - ALPINE_IMAGE: alpine:3.18.0 + ALPINE_IMAGE: alpine:3.18.3 jobs: docker: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Docker Buildx id: buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v3 - - name: Go Cache - uses: actions/cache@v2 - with: - path: | - ~/go/pkg/mod - ~/.cache/go-build - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- + - name: Set up Go + uses: actions/setup-go@v4 - name: Login to DockerHub uses: docker/login-action@v2 diff --git a/.github/workflows/docker-build-develop.yaml b/.github/workflows/docker-build-develop.yaml index 5be850d4..acc5fb89 100644 --- a/.github/workflows/docker-build-develop.yaml +++ b/.github/workflows/docker-build-develop.yaml @@ -5,34 +5,29 @@ on: - develop env: - ALPINE_IMAGE: alpine:3.18.0 + ALPINE_IMAGE: alpine:3.18.3 jobs: docker: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up Docker Buildx id: buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v3 - - name: Go Cache - uses: actions/cache@v2 - with: - path: | - ~/go/pkg/mod - ~/.cache/go-build - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- + - name: Set up Go + uses: actions/setup-go@v4 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} diff --git a/.github/workflows/docker-build-release.yaml b/.github/workflows/docker-build-release.yaml index cc63fa03..8a5f3057 100644 --- a/.github/workflows/docker-build-release.yaml +++ b/.github/workflows/docker-build-release.yaml @@ -6,34 +6,29 @@ on: - release/** env: - ALPINE_IMAGE: alpine:3.18.0 + ALPINE_IMAGE: alpine:3.18.3 jobs: docker: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up Docker Buildx id: buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v3 - - name: Go Cache - uses: actions/cache@v2 - with: - path: | - ~/go/pkg/mod - ~/.cache/go-build - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- + - name: Set up Go + uses: actions/setup-go@v4 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} diff --git a/.github/workflows/docker-build-tag.yaml b/.github/workflows/docker-build-tag.yaml index bd2beb89..3911acec 100644 --- a/.github/workflows/docker-build-tag.yaml +++ b/.github/workflows/docker-build-tag.yaml @@ -5,33 +5,26 @@ on: - "v[0-9]+.[0-9]+.[0-9]+" env: - ALPINE_IMAGE: alpine:3.18.0 + ALPINE_IMAGE: alpine:3.18.3 jobs: docker: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Docker Buildx id: buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v3 - - name: Go Cache - uses: actions/cache@v2 - with: - path: | - ~/go/pkg/mod - ~/.cache/go-build - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- + - name: Set up Go + uses: actions/setup-go@v4 - name: Login to DockerHub uses: docker/login-action@v2 diff --git a/.gitignore b/.gitignore index 5f2beae3..6e60b9db 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ - # Binaries for programs and plugins *.exe *.exe~ @@ -8,6 +7,9 @@ bin controllers/testbin/* +# GoReleaser +dist/ + # Test binary, build with `go test -c` *.test diff --git a/Dockerfile b/Dockerfile index aa17b0fb..43075cf8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,6 @@ -ARG ALPINE_IMAGE -FROM ${ALPINE_IMAGE} +FROM gcr.io/distroless/static:nonroot + +WORKDIR / COPY testkube-operator /manager ENTRYPOINT ["/manager"] diff --git a/Makefile b/Makefile index ffb8b566..cec18960 100644 --- a/Makefile +++ b/Makefile @@ -58,10 +58,22 @@ test: manifests generate fmt vet ## Run tests. ##@ Build build: generate fmt vet ## Build manager binary. - go build -o bin/manager main.go + go build -o bin/manager cmd/main.go + +.PHONY: build-local-linux +build-local-linux: + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o dist/manager cmd/main.go + +.PHONY: docker-build-local +docker-build-local: build-local-linux + docker build -t controller:latest -f local.Dockerfile . + +.PHONY: kind-load-local +kind-load-local: docker-build-local + kind load docker-image controller:latest --name testkube run: manifests generate fmt vet ## Run a controller from your host. - go run ./main.go + go run ./cmd/main.go docker-build: test ## Build docker image with the manager. docker build -t ${IMG} . diff --git a/PROJECT b/PROJECT index 1bb96fd5..3a859925 100644 --- a/PROJECT +++ b/PROJECT @@ -4,7 +4,7 @@ # More info: https://book.kubebuilder.io/reference/project-config.html domain: testkube.io layout: -- go.kubebuilder.io/v3 +- go.kubebuilder.io/v4 multigroup: true projectName: testkube repo: github.com/kubeshop/testkube-operator @@ -16,7 +16,7 @@ resources: domain: testkube.io group: tests kind: Script - path: github.com/kubeshop/testkube-operator/apis/script/v1 + path: github.com/kubeshop/testkube-operator/api/script/v1 version: v1 - api: crdVersion: v1 @@ -25,7 +25,7 @@ resources: domain: testkube.io group: executor kind: Executor - path: github.com/kubeshop/testkube-operator/apis/executor/v1 + path: github.com/kubeshop/testkube-operator/api/executor/v1 version: v1 - api: crdVersion: v1 @@ -34,7 +34,7 @@ resources: domain: testkube.io group: tests kind: Test - path: github.com/kubeshop/testkube-operator/apis/tests/v1 + path: github.com/kubeshop/testkube-operator/api/tests/v1 version: v1 - api: crdVersion: v1 @@ -43,7 +43,7 @@ resources: domain: testkube.io group: tests kind: TestSuite - path: github.com/kubeshop/testkube-operator/apis/testsuite/v1 + path: github.com/kubeshop/testkube-operator/api/testsuite/v1 version: v1 - api: crdVersion: v1 @@ -52,7 +52,7 @@ resources: domain: testkube.io group: executor kind: Webhook - path: github.com/kubeshop/testkube-operator/apis/executor/v1 + path: github.com/kubeshop/testkube-operator/api/executor/v1 version: v1 - api: crdVersion: v1 @@ -60,7 +60,7 @@ resources: domain: testkube.io group: tests kind: Test - path: github.com/kubeshop/testkube-operator/apis/tests/v3 + path: github.com/kubeshop/testkube-operator/api/tests/v3 version: v3 - api: crdVersion: v1 @@ -68,7 +68,7 @@ resources: domain: testkube.io group: tests kind: TestSuite - path: github.com/kubeshop/testkube-operator/apis/testsuite/v2 + path: github.com/kubeshop/testkube-operator/api/testsuite/v2 version: v2 - api: crdVersion: v1 @@ -77,7 +77,7 @@ resources: domain: testkube.io group: tests kind: TestTrigger - path: github.com/kubeshop/testkube-operator/apis/testtriggers/v1 + path: github.com/kubeshop/testkube-operator/api/testtriggers/v1 version: v1 webhooks: validation: true @@ -89,7 +89,7 @@ resources: domain: testkube.io group: tests kind: TestSource - path: github.com/kubeshop/testkube-operator/apis/testsource/v1 + path: github.com/kubeshop/testkube-operator/api/testsource/v1 version: v1 - api: crdVersion: v1 @@ -97,7 +97,7 @@ resources: domain: testkube.io group: tests kind: Test - path: github.com/kubeshop/testkube-operator/apis/tests/v2 + path: github.com/kubeshop/testkube-operator/api/tests/v2 version: v2 - api: crdVersion: v1 @@ -106,7 +106,7 @@ resources: domain: testkube.io group: tests kind: TestSuite - path: github.com/kubeshop/testkube-operator/apis/testsuite/v3 + path: github.com/kubeshop/testkube-operator/api/testsuite/v3 version: v3 - api: crdVersion: v1 @@ -115,7 +115,7 @@ resources: domain: testkube.io group: tests kind: TestExecution - path: github.com/kubeshop/testkube-operator/apis/testexecution/v1 + path: github.com/kubeshop/testkube-operator/api/testexecution/v1 version: v1 - api: crdVersion: v1 @@ -124,7 +124,7 @@ resources: domain: testkube.io group: tests kind: TestSuiteExecution - path: github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1 + path: github.com/kubeshop/testkube-operator/api/testsuiteexecution/v1 version: v1 - api: crdVersion: v1 @@ -133,6 +133,6 @@ resources: domain: testkube.io group: tests kind: Template - path: github.com/kubeshop/testkube-operator/apis/template/v1 - version: v1 + path: github.com/kubeshop/testkube-operator/api/template/v1 + version: v1 version: "3" diff --git a/apis/common/v1/variables.go b/api/common/v1/variables.go similarity index 100% rename from apis/common/v1/variables.go rename to api/common/v1/variables.go diff --git a/apis/executor/v1/executor_types.go b/api/executor/v1/executor_types.go similarity index 100% rename from apis/executor/v1/executor_types.go rename to api/executor/v1/executor_types.go diff --git a/apis/executor/v1/groupversion_info.go b/api/executor/v1/groupversion_info.go similarity index 100% rename from apis/executor/v1/groupversion_info.go rename to api/executor/v1/groupversion_info.go diff --git a/apis/executor/v1/webhook_types.go b/api/executor/v1/webhook_types.go similarity index 100% rename from apis/executor/v1/webhook_types.go rename to api/executor/v1/webhook_types.go diff --git a/apis/executor/v1/zz_generated.deepcopy.go b/api/executor/v1/zz_generated.deepcopy.go similarity index 100% rename from apis/executor/v1/zz_generated.deepcopy.go rename to api/executor/v1/zz_generated.deepcopy.go diff --git a/apis/script/v1/groupversion_info.go b/api/script/v1/groupversion_info.go similarity index 100% rename from apis/script/v1/groupversion_info.go rename to api/script/v1/groupversion_info.go diff --git a/apis/script/v1/script_conversion.go b/api/script/v1/script_conversion.go similarity index 100% rename from apis/script/v1/script_conversion.go rename to api/script/v1/script_conversion.go diff --git a/apis/script/v1/script_types.go b/api/script/v1/script_types.go similarity index 100% rename from apis/script/v1/script_types.go rename to api/script/v1/script_types.go diff --git a/apis/script/v1/script_webhook.go b/api/script/v1/script_webhook.go similarity index 100% rename from apis/script/v1/script_webhook.go rename to api/script/v1/script_webhook.go diff --git a/apis/script/v1/zz_generated.deepcopy.go b/api/script/v1/zz_generated.deepcopy.go similarity index 100% rename from apis/script/v1/zz_generated.deepcopy.go rename to api/script/v1/zz_generated.deepcopy.go diff --git a/apis/script/v2/groupversion_info.go b/api/script/v2/groupversion_info.go similarity index 100% rename from apis/script/v2/groupversion_info.go rename to api/script/v2/groupversion_info.go diff --git a/apis/script/v2/script_conversion.go b/api/script/v2/script_conversion.go similarity index 94% rename from apis/script/v2/script_conversion.go rename to api/script/v2/script_conversion.go index 188dbce4..cd1f96e5 100644 --- a/apis/script/v2/script_conversion.go +++ b/api/script/v2/script_conversion.go @@ -16,8 +16,8 @@ package v2 import ( "sigs.k8s.io/controller-runtime/pkg/conversion" - executorv1 "github.com/kubeshop/testkube-operator/apis/executor/v1" - testkubev1 "github.com/kubeshop/testkube-operator/apis/script/v1" + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" + testkubev1 "github.com/kubeshop/testkube-operator/api/script/v1" ) // ConvertTo converts this Script to the Hub version (v1). diff --git a/apis/script/v2/script_types.go b/api/script/v2/script_types.go similarity index 100% rename from apis/script/v2/script_types.go rename to api/script/v2/script_types.go diff --git a/apis/script/v2/script_webhook.go b/api/script/v2/script_webhook.go similarity index 100% rename from apis/script/v2/script_webhook.go rename to api/script/v2/script_webhook.go diff --git a/apis/script/v2/zz_generated.deepcopy.go b/api/script/v2/zz_generated.deepcopy.go similarity index 100% rename from apis/script/v2/zz_generated.deepcopy.go rename to api/script/v2/zz_generated.deepcopy.go diff --git a/apis/template/v1/groupversion_info.go b/api/template/v1/groupversion_info.go similarity index 100% rename from apis/template/v1/groupversion_info.go rename to api/template/v1/groupversion_info.go diff --git a/apis/template/v1/template_types.go b/api/template/v1/template_types.go similarity index 100% rename from apis/template/v1/template_types.go rename to api/template/v1/template_types.go diff --git a/apis/template/v1/zz_generated.deepcopy.go b/api/template/v1/zz_generated.deepcopy.go similarity index 100% rename from apis/template/v1/zz_generated.deepcopy.go rename to api/template/v1/zz_generated.deepcopy.go diff --git a/apis/testexecution/v1/groupversion_info.go b/api/testexecution/v1/groupversion_info.go similarity index 100% rename from apis/testexecution/v1/groupversion_info.go rename to api/testexecution/v1/groupversion_info.go diff --git a/apis/testexecution/v1/testexecution_types.go b/api/testexecution/v1/testexecution_types.go similarity index 99% rename from apis/testexecution/v1/testexecution_types.go rename to api/testexecution/v1/testexecution_types.go index 7247ff89..9a5755c5 100644 --- a/apis/testexecution/v1/testexecution_types.go +++ b/api/testexecution/v1/testexecution_types.go @@ -20,7 +20,7 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" ) // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! diff --git a/apis/testexecution/v1/zz_generated.deepcopy.go b/api/testexecution/v1/zz_generated.deepcopy.go similarity index 100% rename from apis/testexecution/v1/zz_generated.deepcopy.go rename to api/testexecution/v1/zz_generated.deepcopy.go diff --git a/apis/tests/v1/groupversion_info.go b/api/tests/v1/groupversion_info.go similarity index 100% rename from apis/tests/v1/groupversion_info.go rename to api/tests/v1/groupversion_info.go diff --git a/apis/tests/v1/test_conversion.go b/api/tests/v1/test_conversion.go similarity index 94% rename from apis/tests/v1/test_conversion.go rename to api/tests/v1/test_conversion.go index ee50995d..6566eed1 100644 --- a/apis/tests/v1/test_conversion.go +++ b/api/tests/v1/test_conversion.go @@ -16,7 +16,7 @@ package v1 import ( "sigs.k8s.io/controller-runtime/pkg/conversion" - testkubev2 "github.com/kubeshop/testkube-operator/apis/tests/v2" + testkubev2 "github.com/kubeshop/testkube-operator/api/tests/v2" ) // ConvertTo converts this Script to the Hub version (v1). diff --git a/apis/tests/v1/test_types.go b/api/tests/v1/test_types.go similarity index 100% rename from apis/tests/v1/test_types.go rename to api/tests/v1/test_types.go diff --git a/apis/tests/v1/test_webhook.go b/api/tests/v1/test_webhook.go similarity index 100% rename from apis/tests/v1/test_webhook.go rename to api/tests/v1/test_webhook.go diff --git a/apis/tests/v1/zz_generated.deepcopy.go b/api/tests/v1/zz_generated.deepcopy.go similarity index 100% rename from apis/tests/v1/zz_generated.deepcopy.go rename to api/tests/v1/zz_generated.deepcopy.go diff --git a/apis/tests/v2/groupversion_info.go b/api/tests/v2/groupversion_info.go similarity index 100% rename from apis/tests/v2/groupversion_info.go rename to api/tests/v2/groupversion_info.go diff --git a/apis/tests/v2/test_conversion.go b/api/tests/v2/test_conversion.go similarity index 100% rename from apis/tests/v2/test_conversion.go rename to api/tests/v2/test_conversion.go diff --git a/apis/tests/v2/test_types.go b/api/tests/v2/test_types.go similarity index 98% rename from apis/tests/v2/test_types.go rename to api/tests/v2/test_types.go index 3e7f27b8..8d8e034f 100644 --- a/apis/tests/v2/test_types.go +++ b/api/tests/v2/test_types.go @@ -17,7 +17,7 @@ limitations under the License. package v2 import ( - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/apis/tests/v2/test_webhook.go b/api/tests/v2/test_webhook.go similarity index 100% rename from apis/tests/v2/test_webhook.go rename to api/tests/v2/test_webhook.go diff --git a/apis/tests/v2/zz_generated.deepcopy.go b/api/tests/v2/zz_generated.deepcopy.go similarity index 100% rename from apis/tests/v2/zz_generated.deepcopy.go rename to api/tests/v2/zz_generated.deepcopy.go diff --git a/apis/tests/v3/groupversion_info.go b/api/tests/v3/groupversion_info.go similarity index 100% rename from apis/tests/v3/groupversion_info.go rename to api/tests/v3/groupversion_info.go diff --git a/apis/tests/v3/test_conversion.go b/api/tests/v3/test_conversion.go similarity index 92% rename from apis/tests/v3/test_conversion.go rename to api/tests/v3/test_conversion.go index 76ccfa91..ec9c085b 100644 --- a/apis/tests/v3/test_conversion.go +++ b/api/tests/v3/test_conversion.go @@ -16,8 +16,8 @@ package v3 import ( "sigs.k8s.io/controller-runtime/pkg/conversion" - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" - testkubev2 "github.com/kubeshop/testkube-operator/apis/tests/v2" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" + testkubev2 "github.com/kubeshop/testkube-operator/api/tests/v2" ) // ConvertTo converts this Script to the Hub version (v1). @@ -44,9 +44,7 @@ func (src *Test) ConvertTo(dstRaw conversion.Hub) error { } dst.Spec.ExecutorArgs = make([]string, len(src.Spec.ExecutionRequest.Args)) - for i, arg := range src.Spec.ExecutionRequest.Args { - dst.Spec.ExecutorArgs[i] = arg - } + copy(dst.Spec.ExecutorArgs, src.Spec.ExecutionRequest.Args) } if src.Spec.Content != nil { @@ -103,9 +101,7 @@ func (dst *Test) ConvertFrom(srcRaw conversion.Hub) error { } dst.Spec.ExecutionRequest.Args = make([]string, len(src.Spec.ExecutorArgs)) - for i, arg := range src.Spec.ExecutorArgs { - dst.Spec.ExecutionRequest.Args[i] = arg - } + copy(dst.Spec.ExecutionRequest.Args, src.Spec.ExecutorArgs) } if src.Spec.Content != nil { diff --git a/apis/tests/v3/test_types.go b/api/tests/v3/test_types.go similarity index 97% rename from apis/tests/v3/test_types.go rename to api/tests/v3/test_types.go index 5004a9a8..babcbff4 100644 --- a/apis/tests/v3/test_types.go +++ b/api/tests/v3/test_types.go @@ -20,7 +20,7 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" ) // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! @@ -75,10 +75,10 @@ const ( TestContentTypeGit TestContentType = "git" ) -// Testkube internal reference for secret storage in Kubernetes secrets +// SecretRef is the Testkube internal reference for secret storage in Kubernetes secrets type SecretRef struct { // object kubernetes namespace - Namespace string `json:"namespace,omitempty"` + Namespace string `json:"-"` // object name Name string `json:"name"` // object key @@ -132,7 +132,7 @@ type ArtifactRequest struct { OmitFolderPerExecution bool `json:"omitFolderPerExecution,omitempty"` } -// running context for test or test suite execution +// RunningContext for test or test suite execution type RunningContext struct { // One of possible context types Type_ RunningContextType `json:"type"` @@ -224,7 +224,7 @@ type ExecutionRequest struct { EnvConfigMaps []EnvReference `json:"envConfigMaps,omitempty"` // secret references EnvSecrets []EnvReference `json:"envSecrets,omitempty"` - RunningContext *RunningContext `json:"runningContext,omitempty"` + RunningContext *RunningContext `json:"-"` } // ArgsModeType defines args mode type diff --git a/apis/tests/v3/test_webhook.go b/api/tests/v3/test_webhook.go similarity index 100% rename from apis/tests/v3/test_webhook.go rename to api/tests/v3/test_webhook.go diff --git a/apis/tests/v3/zz_generated.deepcopy.go b/api/tests/v3/zz_generated.deepcopy.go similarity index 100% rename from apis/tests/v3/zz_generated.deepcopy.go rename to api/tests/v3/zz_generated.deepcopy.go diff --git a/apis/testsource/v1/groupversion_info.go b/api/testsource/v1/groupversion_info.go similarity index 100% rename from apis/testsource/v1/groupversion_info.go rename to api/testsource/v1/groupversion_info.go diff --git a/apis/testsource/v1/testsource_types.go b/api/testsource/v1/testsource_types.go similarity index 94% rename from apis/testsource/v1/testsource_types.go rename to api/testsource/v1/testsource_types.go index a59ea30e..22e8ff77 100644 --- a/apis/testsource/v1/testsource_types.go +++ b/api/testsource/v1/testsource_types.go @@ -50,10 +50,10 @@ const ( TestSourceTypeGit TestSourceType = "git" ) -// Testkube internal reference for secret storage in Kubernetes secrets +// SecretRef is the Testkube internal reference for secret storage in Kubernetes secrets type SecretRef struct { // object kubernetes namespace - Namespace string `json:"namespace,omitempty"` + Namespace string `json:"-"` // object name Name string `json:"name"` // object key @@ -70,7 +70,7 @@ type Repository struct { Branch string `json:"branch,omitempty"` // commit id (sha) for checkout Commit string `json:"commit,omitempty"` - // if needed we can checkout particular path (dir or file) in case of BIG/mono repositories + // If specified, does a sparse checkout of the repository at the given path Path string `json:"path,omitempty"` UsernameSecret *SecretRef `json:"usernameSecret,omitempty"` TokenSecret *SecretRef `json:"tokenSecret,omitempty"` diff --git a/apis/testsource/v1/zz_generated.deepcopy.go b/api/testsource/v1/zz_generated.deepcopy.go similarity index 100% rename from apis/testsource/v1/zz_generated.deepcopy.go rename to api/testsource/v1/zz_generated.deepcopy.go diff --git a/apis/testsuite/v1/groupversion_info.go b/api/testsuite/v1/groupversion_info.go similarity index 100% rename from apis/testsuite/v1/groupversion_info.go rename to api/testsuite/v1/groupversion_info.go diff --git a/apis/testsuite/v1/testsuite_conversion.go b/api/testsuite/v1/testsuite_conversion.go similarity index 97% rename from apis/testsuite/v1/testsuite_conversion.go rename to api/testsuite/v1/testsuite_conversion.go index 1c147532..464ab200 100644 --- a/apis/testsuite/v1/testsuite_conversion.go +++ b/api/testsuite/v1/testsuite_conversion.go @@ -16,8 +16,8 @@ package v1 import ( "sigs.k8s.io/controller-runtime/pkg/conversion" - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" - testkubev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" + testkubev2 "github.com/kubeshop/testkube-operator/api/testsuite/v2" ) // ConvertTo converts this Script to the Hub version (v2). diff --git a/apis/testsuite/v1/testsuite_types.go b/api/testsuite/v1/testsuite_types.go similarity index 98% rename from apis/testsuite/v1/testsuite_types.go rename to api/testsuite/v1/testsuite_types.go index e68b7b58..4e3bcb30 100644 --- a/apis/testsuite/v1/testsuite_types.go +++ b/api/testsuite/v1/testsuite_types.go @@ -17,7 +17,7 @@ limitations under the License. package v1 import ( - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/apis/testsuite/v1/testsuite_webhook.go b/api/testsuite/v1/testsuite_webhook.go similarity index 100% rename from apis/testsuite/v1/testsuite_webhook.go rename to api/testsuite/v1/testsuite_webhook.go diff --git a/apis/testsuite/v1/zz_generated.deepcopy.go b/api/testsuite/v1/zz_generated.deepcopy.go similarity index 100% rename from apis/testsuite/v1/zz_generated.deepcopy.go rename to api/testsuite/v1/zz_generated.deepcopy.go diff --git a/apis/testsuite/v2/groupversion_info.go b/api/testsuite/v2/groupversion_info.go similarity index 100% rename from apis/testsuite/v2/groupversion_info.go rename to api/testsuite/v2/groupversion_info.go diff --git a/apis/testsuite/v2/testsuite_conversion.go b/api/testsuite/v2/testsuite_conversion.go similarity index 100% rename from apis/testsuite/v2/testsuite_conversion.go rename to api/testsuite/v2/testsuite_conversion.go diff --git a/apis/testsuite/v2/testsuite_types.go b/api/testsuite/v2/testsuite_types.go similarity index 96% rename from apis/testsuite/v2/testsuite_types.go rename to api/testsuite/v2/testsuite_types.go index bd65b0ba..df97adc3 100644 --- a/apis/testsuite/v2/testsuite_types.go +++ b/api/testsuite/v2/testsuite_types.go @@ -17,7 +17,7 @@ limitations under the License. package v2 import ( - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -74,7 +74,7 @@ type TestSuiteStepDelay struct { Duration int32 `json:"duration,omitempty"` } -// running context for test or test suite execution +// RunningContext for test or test suite execution type RunningContext struct { // One of possible context types Type_ RunningContextType `json:"type"` @@ -93,7 +93,7 @@ const ( RunningContextTypeEmpty RunningContextType = "" ) -// test suite execution request body +// TestSuiteExecutionRequest defines the execution request body type TestSuiteExecutionRequest struct { // test execution custom name Name string `json:"name,omitempty"` @@ -114,7 +114,7 @@ type TestSuiteExecutionRequest struct { HttpsProxy string `json:"httpsProxy,omitempty"` // timeout for test suite execution Timeout int32 `json:"timeout,omitempty"` - RunningContext *RunningContext `json:"runningContext,omitempty"` + RunningContext *RunningContext `json:"-"` // cron job template extensions CronJobTemplate string `json:"cronJobTemplate,omitempty"` } diff --git a/apis/testsuite/v2/testsuite_webhook.go b/api/testsuite/v2/testsuite_webhook.go similarity index 100% rename from apis/testsuite/v2/testsuite_webhook.go rename to api/testsuite/v2/testsuite_webhook.go diff --git a/apis/testsuite/v2/zz_generated.deepcopy.go b/api/testsuite/v2/zz_generated.deepcopy.go similarity index 100% rename from apis/testsuite/v2/zz_generated.deepcopy.go rename to api/testsuite/v2/zz_generated.deepcopy.go diff --git a/apis/testsuite/v3/groupversion_info.go b/api/testsuite/v3/groupversion_info.go similarity index 100% rename from apis/testsuite/v3/groupversion_info.go rename to api/testsuite/v3/groupversion_info.go diff --git a/apis/testsuite/v3/testsuite_conversion.go b/api/testsuite/v3/testsuite_conversion.go similarity index 98% rename from apis/testsuite/v3/testsuite_conversion.go rename to api/testsuite/v3/testsuite_conversion.go index fbb8be5f..f10e55c8 100644 --- a/apis/testsuite/v3/testsuite_conversion.go +++ b/api/testsuite/v3/testsuite_conversion.go @@ -18,7 +18,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/conversion" - testkubev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" + testkubev2 "github.com/kubeshop/testkube-operator/api/testsuite/v2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/apis/testsuite/v3/testsuite_types.go b/api/testsuite/v3/testsuite_types.go similarity index 95% rename from apis/testsuite/v3/testsuite_types.go rename to api/testsuite/v3/testsuite_types.go index f4d6fd62..54b2ffb6 100644 --- a/apis/testsuite/v3/testsuite_types.go +++ b/api/testsuite/v3/testsuite_types.go @@ -17,7 +17,7 @@ limitations under the License. package v3 import ( - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -55,17 +55,17 @@ type TestSuiteStepSpec struct { Delay metav1.Duration `json:"delay,omitempty"` } -// set of steps run in parallel +// TestSuiteBatchStep is set of steps run in parallel type TestSuiteBatchStep struct { StopOnFailure bool `json:"stopOnFailure"` Execute []TestSuiteStepSpec `json:"execute,omitempty"` } -// running context for test or test suite execution +// RunningContext for test or test suite execution type RunningContext struct { // One of possible context types Type_ RunningContextType `json:"type"` - // Context value depending from its type + // Context value which depends from its type Context string `json:"context,omitempty"` } @@ -101,7 +101,7 @@ type TestSuiteExecutionRequest struct { HttpsProxy string `json:"httpsProxy,omitempty"` // timeout for test suite execution Timeout int32 `json:"timeout,omitempty"` - RunningContext *RunningContext `json:"runningContext,omitempty"` + RunningContext *RunningContext `json:"-"` // job template extensions JobTemplate string `json:"jobTemplate,omitempty"` // name of the template resource @@ -133,7 +133,7 @@ const ( TIMEOUT_TestSuiteExecutionStatus TestSuiteExecutionStatus = "timeout" ) -// test suite execution core +// TestSuiteExecutionCore defines the observed state of TestSuiteExecution type TestSuiteExecutionCore struct { // execution id Id string `json:"id,omitempty"` diff --git a/apis/testsuite/v3/testsuite_webhook.go b/api/testsuite/v3/testsuite_webhook.go similarity index 100% rename from apis/testsuite/v3/testsuite_webhook.go rename to api/testsuite/v3/testsuite_webhook.go diff --git a/apis/testsuite/v3/zz_generated.deepcopy.go b/api/testsuite/v3/zz_generated.deepcopy.go similarity index 100% rename from apis/testsuite/v3/zz_generated.deepcopy.go rename to api/testsuite/v3/zz_generated.deepcopy.go diff --git a/apis/testsuiteexecution/v1/groupversion_info.go b/api/testsuiteexecution/v1/groupversion_info.go similarity index 100% rename from apis/testsuiteexecution/v1/groupversion_info.go rename to api/testsuiteexecution/v1/groupversion_info.go diff --git a/apis/testsuiteexecution/v1/testsuiteexecution_types.go b/api/testsuiteexecution/v1/testsuiteexecution_types.go similarity index 99% rename from apis/testsuiteexecution/v1/testsuiteexecution_types.go rename to api/testsuiteexecution/v1/testsuiteexecution_types.go index 1631bd53..e0d689a2 100644 --- a/apis/testsuiteexecution/v1/testsuiteexecution_types.go +++ b/api/testsuiteexecution/v1/testsuiteexecution_types.go @@ -19,7 +19,7 @@ package v1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" ) // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! diff --git a/apis/testsuiteexecution/v1/zz_generated.deepcopy.go b/api/testsuiteexecution/v1/zz_generated.deepcopy.go similarity index 100% rename from apis/testsuiteexecution/v1/zz_generated.deepcopy.go rename to api/testsuiteexecution/v1/zz_generated.deepcopy.go diff --git a/apis/testtriggers/v1/groupversion_info.go b/api/testtriggers/v1/groupversion_info.go similarity index 100% rename from apis/testtriggers/v1/groupversion_info.go rename to api/testtriggers/v1/groupversion_info.go diff --git a/apis/testtriggers/v1/testtrigger_suite_test.go b/api/testtriggers/v1/testtrigger_suite_test.go similarity index 87% rename from apis/testtriggers/v1/testtrigger_suite_test.go rename to api/testtriggers/v1/testtrigger_suite_test.go index fd882603..7843a7e4 100644 --- a/apis/testtriggers/v1/testtrigger_suite_test.go +++ b/api/testtriggers/v1/testtrigger_suite_test.go @@ -22,20 +22,20 @@ import ( "fmt" "net" "path/filepath" + "sigs.k8s.io/controller-runtime/pkg/webhook" "testing" "time" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - admissionv1beta1 "k8s.io/api/admission/v1beta1" + admissionv1 "k8s.io/api/admission/v1" //+kubebuilder:scaffold:imports "k8s.io/apimachinery/pkg/runtime" "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/printer" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" ) @@ -55,7 +55,7 @@ func TestAPIs(t *testing.T) { RunSpecsWithDefaultAndCustomReporters(t, "Webhook Suite", - []Reporter{printer.NewlineReporter{}}) + nil) } var _ = BeforeSuite(func() { @@ -80,7 +80,7 @@ var _ = BeforeSuite(func() { err = AddToScheme(scheme) Expect(err).NotTo(HaveOccurred()) - err = admissionv1beta1.AddToScheme(scheme) + err = admissionv1.AddToScheme(scheme) Expect(err).NotTo(HaveOccurred()) //+kubebuilder:scaffold:scheme @@ -91,13 +91,17 @@ var _ = BeforeSuite(func() { // start webhook server using Manager webhookInstallOptions := &testEnv.WebhookInstallOptions + webhookOptions := webhook.Options{ + Host: webhookInstallOptions.LocalServingHost, + Port: webhookInstallOptions.LocalServingPort, + CertDir: webhookInstallOptions.LocalServingCertDir, + } + webhookServer := webhook.NewServer(webhookOptions) + mgr, err := ctrl.NewManager(cfg, ctrl.Options{ - Scheme: scheme, - Host: webhookInstallOptions.LocalServingHost, - Port: webhookInstallOptions.LocalServingPort, - CertDir: webhookInstallOptions.LocalServingCertDir, - LeaderElection: false, - MetricsBindAddress: "0", + WebhookServer: webhookServer, + Scheme: scheme, + LeaderElection: false, }) Expect(err).NotTo(HaveOccurred()) diff --git a/apis/testtriggers/v1/testtrigger_types.go b/api/testtriggers/v1/testtrigger_types.go similarity index 100% rename from apis/testtriggers/v1/testtrigger_types.go rename to api/testtriggers/v1/testtrigger_types.go diff --git a/apis/testtriggers/v1/testtrigger_webhook.go b/api/testtriggers/v1/testtrigger_webhook.go similarity index 75% rename from apis/testtriggers/v1/testtrigger_webhook.go rename to api/testtriggers/v1/testtrigger_webhook.go index 51981fa9..8b500d02 100644 --- a/apis/testtriggers/v1/testtrigger_webhook.go +++ b/api/testtriggers/v1/testtrigger_webhook.go @@ -21,6 +21,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) // +k8s:deepcopy-gen=false @@ -33,16 +34,16 @@ type TestTriggerValidator interface { var ctx = context.Background() var vldtr TestTriggerValidator -func (in *TestTrigger) ValidateCreate() error { - return vldtr.ValidateCreate(ctx, in) +func (in *TestTrigger) ValidateCreate() (admission.Warnings, error) { + return nil, vldtr.ValidateCreate(ctx, in) } -func (in *TestTrigger) ValidateUpdate(old runtime.Object) error { - return vldtr.ValidateUpdate(ctx, old, in) +func (in *TestTrigger) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + return nil, vldtr.ValidateUpdate(ctx, old, in) } -func (in *TestTrigger) ValidateDelete() error { - return vldtr.ValidateDelete(ctx, in) +func (in *TestTrigger) ValidateDelete() (admission.Warnings, error) { + return nil, vldtr.ValidateDelete(ctx, in) } var _ webhook.Validator = &TestTrigger{} diff --git a/apis/testtriggers/v1/zz_generated.deepcopy.go b/api/testtriggers/v1/zz_generated.deepcopy.go similarity index 100% rename from apis/testtriggers/v1/zz_generated.deepcopy.go rename to api/testtriggers/v1/zz_generated.deepcopy.go diff --git a/client/client.go b/client/client.go deleted file mode 100644 index 7ec665ec..00000000 --- a/client/client.go +++ /dev/null @@ -1,50 +0,0 @@ -package client - -import ( - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" - _ "k8s.io/client-go/plugin/pkg/client/auth" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - executorv1 "github.com/kubeshop/testkube-operator/apis/executor/v1" - scriptv1 "github.com/kubeshop/testkube-operator/apis/script/v1" - scriptv2 "github.com/kubeshop/testkube-operator/apis/script/v2" - templatev1 "github.com/kubeshop/testkube-operator/apis/template/v1" - testexecutionv1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" - testsv1 "github.com/kubeshop/testkube-operator/apis/tests/v1" - testsv2 "github.com/kubeshop/testkube-operator/apis/tests/v2" - testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" - testsourcev1 "github.com/kubeshop/testkube-operator/apis/testsource/v1" - testsuitev1 "github.com/kubeshop/testkube-operator/apis/testsuite/v1" - testsuitev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" - testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" - testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" -) - -// GetClient returns kubernetes CRD client with registered schemes -func GetClient() (client.Client, error) { - scheme := runtime.NewScheme() - - scriptv1.AddToScheme(scheme) - scriptv2.AddToScheme(scheme) - executorv1.AddToScheme(scheme) - testsv1.AddToScheme(scheme) - testsv2.AddToScheme(scheme) - testsv3.AddToScheme(scheme) - testsuitev1.AddToScheme(scheme) - corev1.AddToScheme(scheme) - testsuitev2.AddToScheme(scheme) - testsuitev3.AddToScheme(scheme) - testsourcev1.AddToScheme(scheme) - testexecutionv1.AddToScheme(scheme) - testsuiteexecutionv1.AddToScheme(scheme) - templatev1.AddToScheme(scheme) - - kubeconfig, err := ctrl.GetConfig() - if err != nil { - return nil, err - } - - return client.New(kubeconfig, client.Options{Scheme: scheme}) -} diff --git a/main.go b/cmd/main.go similarity index 84% rename from main.go rename to cmd/main.go index ac5f70ee..2d860526 100644 --- a/main.go +++ b/cmd/main.go @@ -19,9 +19,9 @@ package main import ( "encoding/base64" "flag" + testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" "os" - - testtriggersv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) // to ensure that exec-entrypoint and run can make use of them. @@ -38,28 +38,28 @@ import ( "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" - executorv1 "github.com/kubeshop/testkube-operator/apis/executor/v1" - testkubev1 "github.com/kubeshop/testkube-operator/apis/script/v1" - testkubev2 "github.com/kubeshop/testkube-operator/apis/script/v2" - templatev1 "github.com/kubeshop/testkube-operator/apis/template/v1" - testexecutionv1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" - testsv1 "github.com/kubeshop/testkube-operator/apis/tests/v1" - testsv2 "github.com/kubeshop/testkube-operator/apis/tests/v2" - testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" - testsourcev1 "github.com/kubeshop/testkube-operator/apis/testsource/v1" - testsuitev1 "github.com/kubeshop/testkube-operator/apis/testsuite/v1" - testsuitev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" - testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" - testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" - executorcontrollers "github.com/kubeshop/testkube-operator/controllers/executor" - scriptcontrollers "github.com/kubeshop/testkube-operator/controllers/script" - templatecontrollers "github.com/kubeshop/testkube-operator/controllers/template" - testexecutioncontrollers "github.com/kubeshop/testkube-operator/controllers/testexecution" - testscontrollers "github.com/kubeshop/testkube-operator/controllers/tests" - testsourcecontrollers "github.com/kubeshop/testkube-operator/controllers/testsource" - testsuitecontrollers "github.com/kubeshop/testkube-operator/controllers/testsuite" - testsuiteexecutioncontrollers "github.com/kubeshop/testkube-operator/controllers/testsuiteexecution" - testtriggerscontrollers "github.com/kubeshop/testkube-operator/controllers/testtriggers" + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" + testkubev1 "github.com/kubeshop/testkube-operator/api/script/v1" + testkubev2 "github.com/kubeshop/testkube-operator/api/script/v2" + templatev1 "github.com/kubeshop/testkube-operator/api/template/v1" + testexecutionv1 "github.com/kubeshop/testkube-operator/api/testexecution/v1" + testsv1 "github.com/kubeshop/testkube-operator/api/tests/v1" + testsv2 "github.com/kubeshop/testkube-operator/api/tests/v2" + testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" + testsourcev1 "github.com/kubeshop/testkube-operator/api/testsource/v1" + testsuitev1 "github.com/kubeshop/testkube-operator/api/testsuite/v1" + testsuitev2 "github.com/kubeshop/testkube-operator/api/testsuite/v2" + testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" + testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/api/testsuiteexecution/v1" + executorcontrollers "github.com/kubeshop/testkube-operator/internal/controller/executor" + scriptcontrollers "github.com/kubeshop/testkube-operator/internal/controller/script" + templatecontrollers "github.com/kubeshop/testkube-operator/internal/controller/template" + testexecutioncontrollers "github.com/kubeshop/testkube-operator/internal/controller/testexecution" + testscontrollers "github.com/kubeshop/testkube-operator/internal/controller/tests" + testsourcecontrollers "github.com/kubeshop/testkube-operator/internal/controller/testsource" + testsuitecontrollers "github.com/kubeshop/testkube-operator/internal/controller/testsuite" + testsuiteexecutioncontrollers "github.com/kubeshop/testkube-operator/internal/controller/testsuiteexecution" + testtriggerscontrollers "github.com/kubeshop/testkube-operator/internal/controller/testtriggers" "github.com/kubeshop/testkube-operator/pkg/cronjob" //+kubebuilder:scaffold:imports ) @@ -112,7 +112,7 @@ func main() { var httpConfig config err := envconfig.Process("APISERVER", &httpConfig) - // Do we want to panic here or just ignore the err + // TODO: Do we want to panic here or just ignore the error? if err != nil { panic(err) } @@ -128,9 +128,9 @@ func main() { } mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ + Scheme: scheme, - MetricsBindAddress: metricsAddr, - Port: 9443, + Metrics: metricsserver.Options{BindAddress: metricsAddr}, HealthProbeBindAddress: probeAddr, LeaderElection: enableLeaderElection, LeaderElectionID: "47f0dfc1.testkube.io", @@ -257,6 +257,8 @@ func main() { setupLog.Error(err, "unable to create webhook", "webhook", "TestTrigger") os.Exit(1) } + } else { + setupLog.Info("Webhooks are disabled") } if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/config/certmanager/certificate.yaml b/config/certmanager/certificate.yaml new file mode 100644 index 00000000..fe2fc617 --- /dev/null +++ b/config/certmanager/certificate.yaml @@ -0,0 +1,39 @@ +# The following manifests contain a self-signed issuer CR and a certificate CR. +# More document can be found at https://docs.cert-manager.io +# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes. +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + app.kubernetes.io/name: certificate + app.kubernetes.io/instance: serving-cert + app.kubernetes.io/component: certificate + app.kubernetes.io/created-by: project-v4 + app.kubernetes.io/part-of: project-v4 + app.kubernetes.io/managed-by: kustomize + name: selfsigned-issuer + namespace: system +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + app.kubernetes.io/name: certificate + app.kubernetes.io/instance: serving-cert + app.kubernetes.io/component: certificate + app.kubernetes.io/created-by: project-v4 + app.kubernetes.io/part-of: project-v4 + app.kubernetes.io/managed-by: kustomize + name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml + namespace: system +spec: + # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize + dnsNames: + - SERVICE_NAME.SERVICE_NAMESPACE.svc + - SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local + issuerRef: + kind: Issuer + name: selfsigned-issuer + secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize \ No newline at end of file diff --git a/config/certmanager/kustomization.yaml b/config/certmanager/kustomization.yaml new file mode 100644 index 00000000..bbaca30d --- /dev/null +++ b/config/certmanager/kustomization.yaml @@ -0,0 +1,5 @@ +resources: + - certificate.yaml + +configurations: + - kustomizeconfig.yaml \ No newline at end of file diff --git a/config/certmanager/kustomizeconfig.yaml b/config/certmanager/kustomizeconfig.yaml new file mode 100644 index 00000000..004284be --- /dev/null +++ b/config/certmanager/kustomizeconfig.yaml @@ -0,0 +1,8 @@ +# This configuration is for teaching kustomize how to update name ref substitution +nameReference: + - kind: Issuer + group: cert-manager.io + fieldSpecs: + - kind: Certificate + group: cert-manager.io + path: spec/issuerRef/name \ No newline at end of file diff --git a/config/crd/bases/executor.testkube.io_executors.yaml b/config/crd/bases/executor.testkube.io_executors.yaml index 645b02e6..ffdc3781 100644 --- a/config/crd/bases/executor.testkube.io_executors.yaml +++ b/config/crd/bases/executor.testkube.io_executors.yaml @@ -51,9 +51,7 @@ spec: enum: - string - file-uri - # Deprecated: use git instead - git-file - # Deprecated: use git instead - git-dir - git type: string diff --git a/config/crd/bases/executor.testkube.io_webhooks.yaml b/config/crd/bases/executor.testkube.io_webhooks.yaml index 58ee254e..840d7507 100644 --- a/config/crd/bases/executor.testkube.io_webhooks.yaml +++ b/config/crd/bases/executor.testkube.io_webhooks.yaml @@ -71,7 +71,8 @@ spec: description: Labels to filter for tests and test suites type: string uri: - description: Uri is address where webhook should be made (golang template supported) + description: Uri is address where webhook should be made (golang template + supported) type: string type: object status: diff --git a/config/crd/bases/tests.testkube.io_tests.yaml b/config/crd/bases/tests.testkube.io_tests.yaml index aa2d0f80..9f61d60f 100644 --- a/config/crd/bases/tests.testkube.io_tests.yaml +++ b/config/crd/bases/tests.testkube.io_tests.yaml @@ -379,8 +379,8 @@ spec: or file) in case of BIG/mono repositories type: string tokenSecret: - description: Testkube internal reference for secret storage - in Kubernetes secrets + description: SecretRef is the Testkube internal reference + for secret storage in Kubernetes secrets properties: key: description: object key @@ -399,8 +399,8 @@ spec: description: uri of content file or git directory type: string usernameSecret: - description: Testkube internal reference for secret storage - in Kubernetes secrets + description: SecretRef is the Testkube internal reference + for secret storage in Kubernetes secrets properties: key: description: object key diff --git a/config/crd/bases/tests.testkube.io_testsources.yaml b/config/crd/bases/tests.testkube.io_testsources.yaml index f801d513..3c417d5a 100644 --- a/config/crd/bases/tests.testkube.io_testsources.yaml +++ b/config/crd/bases/tests.testkube.io_testsources.yaml @@ -57,12 +57,12 @@ spec: description: commit id (sha) for checkout type: string path: - description: if needed we can checkout particular path (dir or - file) in case of BIG/mono repositories + description: If specified, does a sparse checkout of the repository + at the given path type: string tokenSecret: - description: Testkube internal reference for secret storage in - Kubernetes secrets + description: SecretRef is the Testkube internal reference for + secret storage in Kubernetes secrets properties: key: description: object key @@ -81,8 +81,8 @@ spec: description: uri of content file or git directory type: string usernameSecret: - description: Testkube internal reference for secret storage in - Kubernetes secrets + description: SecretRef is the Testkube internal reference for + secret storage in Kubernetes secrets properties: key: description: object key diff --git a/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml b/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml index b6af21ed..d346777b 100644 --- a/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml +++ b/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml @@ -305,7 +305,8 @@ spec: type: string type: array omitFolderPerExecution: - description: don't use a separate folder for execution artifacts + description: don't use a separate folder for + execution artifacts type: boolean storageBucket: description: artifact bucket storage diff --git a/config/crd/bases/tests.testkube.io_testsuites.yaml b/config/crd/bases/tests.testkube.io_testsuites.yaml index 3672c668..db8af5e0 100644 --- a/config/crd/bases/tests.testkube.io_testsuites.yaml +++ b/config/crd/bases/tests.testkube.io_testsuites.yaml @@ -328,7 +328,8 @@ spec: description: type: string executionRequest: - description: test suite execution request body + description: TestSuiteExecutionRequest defines the execution request + body properties: cronJobTemplate: description: cron job template extensions @@ -562,7 +563,7 @@ spec: description: After batch steps is list of batch tests which will be sequentially orchestrated for parallel tests in each batch items: - description: set of steps run in parallel + description: TestSuiteBatchStep is set of steps run in parallel properties: execute: items: @@ -588,7 +589,7 @@ spec: description: Before batch steps is list of batch tests which will be sequentially orchestrated for parallel tests in each batch items: - description: set of steps run in parallel + description: TestSuiteBatchStep is set of steps run in parallel properties: execute: items: @@ -780,7 +781,7 @@ spec: description: Batch steps is list of batch tests which will be sequentially orchestrated for parallel tests in each batch items: - description: set of steps run in parallel + description: TestSuiteBatchStep is set of steps run in parallel properties: execute: items: diff --git a/config/crd/patches/cainjection_in_testtriggers.yaml b/config/crd/patches/cainjection_in_testtriggers.yaml new file mode 100644 index 00000000..5ec5a098 --- /dev/null +++ b/config/crd/patches/cainjection_in_testtriggers.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME + name: testtriggers.tests.testkube.io \ No newline at end of file diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index a8400c5b..0f6565ac 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -19,34 +19,122 @@ resources: # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml - ../webhook +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. +- ../certmanager # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. #- ../prometheus patchesStrategicMerge: -# Protect the /metrics endpoint by putting it behind auth. -# If you want your controller-manager to expose the /metrics -# endpoint w/o any authn/z, please comment the following line. + # Protect the /metrics endpoint by putting it behind auth. + # If you want your controller-manager to expose the /metrics + # endpoint w/o any authn/z, please comment the following line. - manager_auth_proxy_patch.yaml -# Mount the controller config file for loading manager configurations -# through a ComponentConfig type -#- manager_config_patch.yaml - # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml - manager_webhook_patch.yaml -# the following config is for teaching kustomize how to do var substitution -vars: -- name: SERVICE_NAMESPACE # namespace of the service - objref: - kind: Service - version: v1 - name: webhook-service - fieldref: - fieldpath: metadata.namespace -- name: SERVICE_NAME - objref: - kind: Service - version: v1 - name: webhook-service +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. +# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. +# 'CERTMANAGER' needs to be enabled to use ca injection +- webhookcainjection_patch.yaml + +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. +# Uncomment the following replacements to add the cert-manager CA injection annotations +replacements: + - source: # Add cert-manager annotation to ValidatingWebhookConfiguration, MutatingWebhookConfiguration and CRDs + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # this name should match the one in certificate.yaml + fieldPath: .metadata.namespace # namespace of the certificate CR + targets: + - select: + kind: ValidatingWebhookConfiguration + fieldPaths: + - .metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 0 + create: true + - select: + kind: MutatingWebhookConfiguration + fieldPaths: + - .metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 0 + create: true + - select: + kind: CustomResourceDefinition + fieldPaths: + - .metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 0 + create: true + - source: + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # this name should match the one in certificate.yaml + fieldPath: .metadata.name + targets: + - select: + kind: ValidatingWebhookConfiguration + fieldPaths: + - .metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 1 + create: true + - select: + kind: MutatingWebhookConfiguration + fieldPaths: + - .metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 1 + create: true + - select: + kind: CustomResourceDefinition + fieldPaths: + - .metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 1 + create: true + - source: # Add cert-manager annotation to the webhook Service + kind: Service + version: v1 + name: webhook-service + fieldPath: .metadata.name # namespace of the service + targets: + - select: + kind: Certificate + group: cert-manager.io + version: v1 + fieldPaths: + - .spec.dnsNames.0 + - .spec.dnsNames.1 + options: + delimiter: '.' + index: 0 + create: true + - source: + kind: Service + version: v1 + name: webhook-service + fieldPath: .metadata.namespace # namespace of the service + targets: + - select: + kind: Certificate + group: cert-manager.io + version: v1 + fieldPaths: + - .spec.dnsNames.0 + - .spec.dnsNames.1 + options: + delimiter: '.' + index: 1 + create: true diff --git a/config/default/manager_auth_proxy_patch.yaml b/config/default/manager_auth_proxy_patch.yaml index a224be19..5addbb4b 100644 --- a/config/default/manager_auth_proxy_patch.yaml +++ b/config/default/manager_auth_proxy_patch.yaml @@ -1,5 +1,3 @@ -# This patch inject a sidecar container which is a HTTP proxy for the -# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. apiVersion: apps/v1 kind: Deployment metadata: @@ -9,18 +7,31 @@ spec: template: spec: containers: - - name: kube-rbac-proxy - image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0 - args: - - "--secure-listen-address=0.0.0.0:8443" - - "--upstream=http://127.0.0.1:8080/" - - "--logtostderr=true" - - "--v=10" - ports: - - containerPort: 8443 - name: https - - name: manager - args: - - "--health-probe-bind-address=:8081" - - "--metrics-bind-address=127.0.0.1:8080" - - "--leader-elect" + - name: kube-rbac-proxy + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - "ALL" + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.14.1 + args: + - "--secure-listen-address=0.0.0.0:8443" + - "--upstream=http://127.0.0.1:8080/" + - "--logtostderr=true" + - "--v=0" + ports: + - containerPort: 8443 + protocol: TCP + name: https + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 5m + memory: 64Mi + - name: manager + args: + - "--health-probe-bind-address=:8081" + - "--metrics-bind-address=127.0.0.1:8080" + - "--leader-elect" \ No newline at end of file diff --git a/config/default/manager_config_patch.yaml b/config/default/manager_config_patch.yaml index 6c400155..370b50b0 100644 --- a/config/default/manager_config_patch.yaml +++ b/config/default/manager_config_patch.yaml @@ -7,14 +7,4 @@ spec: template: spec: containers: - - name: manager - args: - - "--config=controller_manager_config.yaml" - volumeMounts: - - name: manager-config - mountPath: /controller_manager_config.yaml - subPath: controller_manager_config.yaml - volumes: - - name: manager-config - configMap: - name: manager-config + - name: manager \ No newline at end of file diff --git a/config/default/webhookcainjection_patch.yaml b/config/default/webhookcainjection_patch.yaml new file mode 100644 index 00000000..87942809 --- /dev/null +++ b/config/default/webhookcainjection_patch.yaml @@ -0,0 +1,22 @@ +# This patch add annotation to admission webhook config and +# CERTIFICATE_NAMESPACE and CERTIFICATE_NAME will be substituted by kustomize +#apiVersion: admissionregistration.k8s.io/v1 +#kind: MutatingWebhookConfiguration +#metadata: +# labels: +# app.kubernetes.io/name: mutatingwebhookconfiguration +# app.kubernetes.io/instance: mutating-webhook-configuration +# app.kubernetes.io/component: webhook +# app.kubernetes.io/created-by: project-v4 +# app.kubernetes.io/part-of: project-v4 +# app.kubernetes.io/managed-by: kustomize +# name: mutating-webhook-configuration +# annotations: +# cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: webhook-admission + annotations: + cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME \ No newline at end of file diff --git a/config/manager/controller_manager_config.yaml b/config/manager/controller_manager_config.yaml deleted file mode 100644 index f4ec6f68..00000000 --- a/config/manager/controller_manager_config.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 -kind: ControllerManagerConfig -health: - healthProbeBindAddress: :8081 -metrics: - bindAddress: 127.0.0.1:8080 -webhook: - port: 9443 -leaderElection: - leaderElect: true - resourceName: 47f0dfc1.testkube.io diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 5e793dd1..ad13e96b 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -1,13 +1,5 @@ resources: - manager.yaml - -generatorOptions: - disableNameSuffixHash: true - -configMapGenerator: -- files: - - controller_manager_config.yaml - name: manager-config apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization images: diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 79adfe72..fab118df 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -31,6 +31,7 @@ spec: - --leader-elect image: controller:latest name: manager + imagePullPolicy: IfNotPresent securityContext: allowPrivilegeEscalation: false livenessProbe: @@ -47,10 +48,10 @@ spec: periodSeconds: 10 resources: limits: - cpu: 100m - memory: 30Mi + cpu: 250m + memory: 150Mi requests: cpu: 100m - memory: 20Mi + memory: 60Mi serviceAccountName: controller-manager terminationGracePeriodSeconds: 10 diff --git a/config/webhook/kustomizeconfig.yaml b/config/webhook/kustomizeconfig.yaml index 25e21e3c..bd200494 100644 --- a/config/webhook/kustomizeconfig.yaml +++ b/config/webhook/kustomizeconfig.yaml @@ -1,25 +1,22 @@ # the following config is for teaching kustomize where to look at when substituting vars. # It requires kustomize v2.1.0 or newer to work properly. nameReference: -- kind: Service - version: v1 - fieldSpecs: + - kind: Service + version: v1 + fieldSpecs: + - kind: MutatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/name + - kind: ValidatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/name + +namespace: - kind: MutatingWebhookConfiguration group: admissionregistration.k8s.io - path: webhooks/clientConfig/service/name + path: webhooks/clientConfig/service/namespace + create: true - kind: ValidatingWebhookConfiguration group: admissionregistration.k8s.io - path: webhooks/clientConfig/service/name - -namespace: -- kind: MutatingWebhookConfiguration - group: admissionregistration.k8s.io - path: webhooks/clientConfig/service/namespace - create: true -- kind: ValidatingWebhookConfiguration - group: admissionregistration.k8s.io - path: webhooks/clientConfig/service/namespace - create: true - -varReference: -- path: metadata/annotations + path: webhooks/clientConfig/service/namespace + create: true \ No newline at end of file diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index 13df368b..7813a7e8 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -1,12 +1,10 @@ apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: - creationTimestamp: null name: webhook-admission webhooks: - admissionReviewVersions: - v1 - - v1beta1 clientConfig: service: name: webhook-service diff --git a/demo/curl.yaml b/demo/curl.yaml new file mode 100644 index 00000000..7b44b0cb --- /dev/null +++ b/demo/curl.yaml @@ -0,0 +1,16 @@ +apiVersion: tests.testkube.io/v3 +kind: Test +metadata: + name: curl-executor-smoke + namespace: testkube + labels: + core-tests: executors +spec: + type: curl/test + content: + type: git-file + repository: + type: git-file + uri: https://github.com/kubeshop/testkube.git + branch: main + path: test/curl/executor-tests/curl-smoke-test.json \ No newline at end of file diff --git a/demo/trigger.yaml b/demo/trigger.yaml new file mode 100644 index 00000000..8dfd5eb3 --- /dev/null +++ b/demo/trigger.yaml @@ -0,0 +1,17 @@ +apiVersion: tests.testkube.io/v1 +kind: TestTrigger +metadata: + name: configmap-modified-trigger + namespace: testkube +spec: + resource: configmap + resourceSelector: + name: testkube-triggers-example-config + namespace: testkube + event: modified + action: run + execution: test + delay: 30s + testSelector: + name: healthcheck-test + namespace: testkube \ No newline at end of file diff --git a/go.mod b/go.mod index 4162e0e9..8cc2d928 100644 --- a/go.mod +++ b/go.mod @@ -4,85 +4,80 @@ go 1.21 require ( github.com/golang/mock v1.6.0 - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.3.1 github.com/kelseyhightower/envconfig v1.4.0 github.com/onsi/ginkgo v1.16.5 - github.com/onsi/ginkgo/v2 v2.1.4 - github.com/onsi/gomega v1.19.0 + github.com/onsi/ginkgo/v2 v2.12.0 + github.com/onsi/gomega v1.27.10 github.com/pkg/errors v0.9.1 - github.com/stretchr/testify v1.8.1 - go.uber.org/zap v1.21.0 - k8s.io/api v0.24.1 - k8s.io/apimachinery v0.24.1 - k8s.io/client-go v0.24.1 - sigs.k8s.io/controller-runtime v0.12.1 - sigs.k8s.io/kustomize/kyaml v0.14.1 + github.com/stretchr/testify v1.8.4 + go.uber.org/zap v1.25.0 + k8s.io/api v0.28.2 + k8s.io/apimachinery v0.28.2 + k8s.io/client-go v0.28.2 + sigs.k8s.io/controller-runtime v0.16.2 + sigs.k8s.io/kustomize/kyaml v0.14.3 ) require ( - cloud.google.com/go/compute v1.6.1 // indirect - github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.27 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect - github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect - github.com/Azure/go-autorest/logger v0.2.1 // indirect - github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/emicklei/go-restful/v3 v3.8.0 // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect - github.com/go-errors/errors v1.4.2 // indirect - github.com/go-logr/logr v1.2.3 // indirect - github.com/go-logr/zapr v1.2.3 // indirect - github.com/go-openapi/jsonpointer v0.19.6 // indirect - github.com/go-openapi/jsonreference v0.20.1 // indirect - github.com/go-openapi/swag v0.22.3 // indirect + github.com/evanphx/json-patch/v5 v5.7.0 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-errors/errors v1.5.1 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/zapr v1.2.4 // indirect + github.com/go-openapi/jsonpointer v0.20.0 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.4 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.4.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/google/gnostic v0.6.9 // indirect - github.com/google/go-cmp v0.5.8 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/imdario/mergo v0.3.13 // indirect + github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect + github.com/imdario/mergo v0.3.16 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.12.2 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.34.0 // indirect - github.com/prometheus/procfs v0.7.3 // indirect + github.com/prometheus/client_golang v1.16.0 // indirect + github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - go.uber.org/atomic v1.9.0 // indirect - go.uber.org/multierr v1.8.0 // indirect - golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect - golang.org/x/net v0.4.0 // indirect - golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401 // indirect - golang.org/x/sys v0.3.0 // indirect - golang.org/x/term v0.3.0 // indirect - golang.org/x/text v0.5.0 // indirect - golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect - gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.28.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/net v0.15.0 // indirect + golang.org/x/oauth2 v0.12.0 // indirect + golang.org/x/sys v0.12.0 // indirect + golang.org/x/term v0.12.0 // indirect + golang.org/x/text v0.13.0 // indirect + golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.13.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.24.1 // indirect - k8s.io/component-base v0.24.1 // indirect - k8s.io/klog/v2 v2.60.1 // indirect - k8s.io/kube-openapi v0.0.0-20230109183929-3758b55a6596 // indirect - k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect - sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + k8s.io/apiextensions-apiserver v0.28.2 // indirect + k8s.io/component-base v0.28.2 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/kube-openapi v0.0.0-20230918164632-68afd615200d // indirect + k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 250ab46d..fbe0b46c 100644 --- a/go.sum +++ b/go.sum @@ -1,1140 +1,303 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1 h1:2sMmt8prCn7DPaG4Pmh0N3Inmc8cT8ae5k1M6VJ9Wqc= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A= -github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg= -github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= -github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 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/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc= +github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= -github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +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-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= -github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= -github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8= -github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= +github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ= -github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/cel-go v0.10.1/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w= -github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= -github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= -github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.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/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 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/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 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/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/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= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 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/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= -github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI= +github.com/onsi/ginkgo/v2 v2.12.0/go.mod h1:ZNEzXISYlqpb8S36iN71ifqLi3vVD1rVJGvWRCJOUpQ= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.34.0 h1:RBmGO9d/FVjqHT0yUGQwBJhkwKV+wPCn7KGpvfab0uE= -github.com/prometheus/common v0.34.0/go.mod h1:gB3sOl7P0TvJabZpLY5uQMpUqRCPPCyRLCZYc7JZTNE= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= +github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk= -github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= +github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= -go.etcd.io/etcd/client/v3 v3.5.1/go.mod h1:OnjH4M8OnAotwaB2l9bVgZzRFKru7/ZMoS46OtKyd3Q= -go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= -go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= -go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= -go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= -go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= -go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= +go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -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= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.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.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -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/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/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-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -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= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401 h1:zwrSfklXn0gxyLRX/aR+q6cgHbV/ItVyzbPlbA+dkAw= -golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -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-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-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/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= -golang.org/x/sys v0.3.0/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-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w= -golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -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.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= -gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201102152239-715cce707fb0/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/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= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.24.1 h1:BjCMRDcyEYz03joa3K1+rbshwh1Ay6oB53+iUx2H8UY= -k8s.io/api v0.24.1/go.mod h1:JhoOvNiLXKTPQ60zh2g0ewpA+bnEYf5q44Flhquh4vQ= -k8s.io/apiextensions-apiserver v0.24.1 h1:5yBh9+ueTq/kfnHQZa0MAo6uNcPrtxPMpNQgorBaKS0= -k8s.io/apiextensions-apiserver v0.24.1/go.mod h1:A6MHfaLDGfjOc/We2nM7uewD5Oa/FnEbZ6cD7g2ca4Q= -k8s.io/apimachinery v0.24.1 h1:ShD4aDxTQKN5zNf8K1RQ2u98ELLdIW7jEnlO9uAMX/I= -k8s.io/apimachinery v0.24.1/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= -k8s.io/apiserver v0.24.1/go.mod h1:dQWNMx15S8NqJMp0gpYfssyvhYnkilc1LpExd/dkLh0= -k8s.io/client-go v0.24.1 h1:w1hNdI9PFrzu3OlovVeTnf4oHDt+FJLd9Ndluvnb42E= -k8s.io/client-go v0.24.1/go.mod h1:f1kIDqcEYmwXS/vTbbhopMUbhKp2JhOeVTfxgaCIlF8= -k8s.io/code-generator v0.24.1/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= -k8s.io/component-base v0.24.1 h1:APv6W/YmfOWZfo+XJ1mZwep/f7g7Tpwvdbo9CQLDuts= -k8s.io/component-base v0.24.1/go.mod h1:DW5vQGYVCog8WYpNob3PMmmsY8A3L9QZNg4j/dV3s38= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc= -k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kube-openapi v0.0.0-20230109183929-3758b55a6596 h1:8cNCQs+WqqnSpZ7y0LMQPKD+RZUHU17VqLPMW3qxnxc= -k8s.io/kube-openapi v0.0.0-20230109183929-3758b55a6596/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc= -k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw= -sigs.k8s.io/controller-runtime v0.12.1 h1:4BJY01xe9zKQti8oRjj/NeHKRXthf1YkYJAgLONFFoI= -sigs.k8s.io/controller-runtime v0.12.1/go.mod h1:BKhxlA4l7FPK4AQcsuL4X6vZeWnKDXez/vp1Y8dxTU0= -sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= -sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124 h1:2sgAQQcY0dEW2SsQwTXhQV4vO6+rSslYx8K3XmM5hqQ= -sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= -sigs.k8s.io/kustomize/kyaml v0.14.1 h1:c8iibius7l24G2wVAGZn/Va2wNys03GXLjYVIcFVxKA= -sigs.k8s.io/kustomize/kyaml v0.14.1/go.mod h1:AN1/IpawKilWD7V+YvQwRGUvuUOOWpjsHu6uHwonSF4= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw= +k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg= +k8s.io/apiextensions-apiserver v0.28.2 h1:J6/QRWIKV2/HwBhHRVITMLYoypCoPY1ftigDM0Kn+QU= +k8s.io/apiextensions-apiserver v0.28.2/go.mod h1:5tnkxLGa9nefefYzWuAlWZ7RZYuN/765Au8cWLA6SRg= +k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ= +k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU= +k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY= +k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY= +k8s.io/component-base v0.28.2 h1:Yc1yU+6AQSlpJZyvehm/NkJBII72rzlEsd6MkBQ+G0E= +k8s.io/component-base v0.28.2/go.mod h1:4IuQPQviQCg3du4si8GpMrhAIegxpsgPngPRR/zWpzc= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20230918164632-68afd615200d h1:/CFeJBjBrZvHX09rObS2+2iEEDevMWYc1v3aIYAjIYI= +k8s.io/kube-openapi v0.0.0-20230918164632-68afd615200d/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= +sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/kustomize/kyaml v0.14.3 h1:WpabVAKZe2YEp/irTSHwD6bfjwZnTtSDewd2BVJGMZs= +sigs.k8s.io/kustomize/kyaml v0.14.3/go.mod h1:npvh9epWysfQ689Rtt/U+dpOJDTBn8kUnF1O6VzvmZA= +sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk= +sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/goreleaser/.goreleaser-snapshot.yaml b/goreleaser/.goreleaser-snapshot.yaml index a3a8e618..4930ea6a 100644 --- a/goreleaser/.goreleaser-snapshot.yaml +++ b/goreleaser/.goreleaser-snapshot.yaml @@ -14,6 +14,7 @@ project_name: testkube-operator builds: - id: "linux" env: [CGO_ENABLED=0] + main: cmd/main.go goos: - linux goarch: diff --git a/goreleaser/.goreleaser.yml b/goreleaser/.goreleaser.yml index aac8375e..008e96a9 100644 --- a/goreleaser/.goreleaser.yml +++ b/goreleaser/.goreleaser.yml @@ -14,6 +14,7 @@ project_name: testkube-operator builds: - id: "linux" env: [CGO_ENABLED=0] + main: cmd/main.go goos: - linux goarch: diff --git a/hack/cert.sh b/hack/cert.sh new file mode 100755 index 00000000..d3e242b3 --- /dev/null +++ b/hack/cert.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# Define the namespace where the operator is running. +NAMESPACE="testkube" + +# Define the names of your certificate and key files. +OUTPUT_DIR="/tmp/serving-certs" +mkdir -p ${OUTPUT_DIR} +CA_KEY="$OUTPUT_DIR/ca.key" +CA_CERT="$OUTPUT_DIR/ca.crt" +CSR_FILE="$OUTPUT_DIR/server.csr" +CERT_FILE="$OUTPUT_DIR/cert.crt" +KEY_FILE="$OUTPUT_DIR/key.key" + +## Clean existing keys +#rm -f ${CERT_FILE} ${KEY_FILE} ${CA_KEY} ${CA_CERT} +# +## Create the CA cert and private key +#openssl genrsa -out ${CA_KEY} 2048 +#openssl req -new -x509 -days 365 -key ${CA_KEY} -subj "/C=CN/ST=GD/L=SZ/O=Acme, Inc./CN=Acme Root CA" -out ${CA_CERT} +# +## Create the private key, certificate signing request (CSR), and certificate +#openssl req -newkey rsa:2048 -nodes -keyout ${KEY_FILE} -subj "/C=CN/ST=GD/L=SZ/O=Acme, Inc./CN=testkube-operator-webhook-service.${NAMESPACE}.svc" -out ${CSR_FILE} +#openssl x509 -req -extfile <(printf "subjectAltName=DNS:testkube-operator-webhook-service.%s.svc" $NAMESPACE) -days 365 -in ${CSR_FILE} -CA ${CA_CERT} -CAkey ${CA_KEY} -CAcreateserial -out ${CERT_FILE} +# +## Check if the certificate and key were generated successfully. +#if [[ $? -ne 0 ]]; then +# echo "Failed to generate the certificate and key." +# exit 1 +#fi + +certs=$(self-signed-cert --namespace testkube --service-name testkube-operator-webhook-service) + +# Re-create the Kubernetes secret for the webhook server cert. +kubectl delete secret webhook-server-cert -n ${NAMESPACE} --ignore-not-found=true +kubectl create secret tls webhook-server-cert \ + --cert="$certs/server.crt" \ + --key="$certs/server.key" \ + -n ${NAMESPACE} + +# Check if the secret was created successfully. +if [[ $? -eq 0 ]]; then + echo "Secret 'webhook-server-cert' created successfully." +else + echo "Failed to create secret 'webhook-server-cert'." +fi \ No newline at end of file diff --git a/controllers/executor/executor_controller.go b/internal/controller/executor/executor_controller.go similarity index 96% rename from controllers/executor/executor_controller.go rename to internal/controller/executor/executor_controller.go index 8bd776f3..c1e00a19 100644 --- a/controllers/executor/executor_controller.go +++ b/internal/controller/executor/executor_controller.go @@ -24,7 +24,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" - executorv1 "github.com/kubeshop/testkube-operator/apis/executor/v1" + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" ) // ExecutorReconciler reconciles a Executor object diff --git a/controllers/executor/suite_test.go b/internal/controller/executor/suite_test.go similarity index 89% rename from controllers/executor/suite_test.go rename to internal/controller/executor/suite_test.go index 14b274b7..f4658c75 100644 --- a/controllers/executor/suite_test.go +++ b/internal/controller/executor/suite_test.go @@ -26,11 +26,10 @@ import ( "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" - "sigs.k8s.io/controller-runtime/pkg/envtest/printer" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - executorv1 "github.com/kubeshop/testkube-operator/apis/executor/v1" + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" //+kubebuilder:scaffold:imports ) @@ -47,7 +46,7 @@ func TestAPIs(t *testing.T) { RunSpecsWithDefaultAndCustomReporters(t, "Controller Suite", - []Reporter{printer.NewlineReporter{}}) + nil) } var _ = BeforeSuite(func() { @@ -55,7 +54,7 @@ var _ = BeforeSuite(func() { By("bootstrapping test environment") testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")}, ErrorIfCRDPathMissing: true, } diff --git a/controllers/executor/webhook_controller.go b/internal/controller/executor/webhook_controller.go similarity index 96% rename from controllers/executor/webhook_controller.go rename to internal/controller/executor/webhook_controller.go index 4353ec65..72ee37c7 100644 --- a/controllers/executor/webhook_controller.go +++ b/internal/controller/executor/webhook_controller.go @@ -24,7 +24,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" - executorv1 "github.com/kubeshop/testkube-operator/apis/executor/v1" + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" ) // WebhookReconciler reconciles a Webhook object diff --git a/controllers/script/script_controller.go b/internal/controller/script/script_controller.go similarity index 96% rename from controllers/script/script_controller.go rename to internal/controller/script/script_controller.go index 0ffc04bf..ed545b35 100644 --- a/controllers/script/script_controller.go +++ b/internal/controller/script/script_controller.go @@ -24,7 +24,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" - testkubev1 "github.com/kubeshop/testkube-operator/apis/script/v1" + testkubev1 "github.com/kubeshop/testkube-operator/api/script/v1" ) // ScriptReconciler reconciles a Script object diff --git a/controllers/script/suite_test.go b/internal/controller/script/suite_test.go similarity index 89% rename from controllers/script/suite_test.go rename to internal/controller/script/suite_test.go index 6b91bc30..6dd778d7 100644 --- a/controllers/script/suite_test.go +++ b/internal/controller/script/suite_test.go @@ -26,11 +26,10 @@ import ( "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" - "sigs.k8s.io/controller-runtime/pkg/envtest/printer" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - testkubev1 "github.com/kubeshop/testkube-operator/apis/script/v1" + testkubev1 "github.com/kubeshop/testkube-operator/api/script/v1" //+kubebuilder:scaffold:imports ) @@ -47,7 +46,7 @@ func TestAPIs(t *testing.T) { RunSpecsWithDefaultAndCustomReporters(t, "Controller Suite", - []Reporter{printer.NewlineReporter{}}) + nil) } var _ = BeforeSuite(func() { @@ -55,7 +54,7 @@ var _ = BeforeSuite(func() { By("bootstrapping test environment") testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")}, + CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")}, ErrorIfCRDPathMissing: true, } diff --git a/controllers/template/suite_test.go b/internal/controller/template/suite_test.go similarity index 92% rename from controllers/template/suite_test.go rename to internal/controller/template/suite_test.go index 1f23242a..80f8aee1 100644 --- a/controllers/template/suite_test.go +++ b/internal/controller/template/suite_test.go @@ -30,7 +30,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - templatev1 "github.com/kubeshop/testkube-operator/apis/template/v1" + templatev1 "github.com/kubeshop/testkube-operator/api/template/v1" //+kubebuilder:scaffold:imports ) @@ -52,7 +52,7 @@ var _ = BeforeSuite(func() { By("bootstrapping test environment") testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")}, ErrorIfCRDPathMissing: true, } diff --git a/controllers/template/template_controller.go b/internal/controller/template/template_controller.go similarity index 96% rename from controllers/template/template_controller.go rename to internal/controller/template/template_controller.go index ca27d462..ba736e9c 100644 --- a/controllers/template/template_controller.go +++ b/internal/controller/template/template_controller.go @@ -24,7 +24,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" - templatev1 "github.com/kubeshop/testkube-operator/apis/template/v1" + templatev1 "github.com/kubeshop/testkube-operator/api/template/v1" ) // TemplateReconciler reconciles a Template object diff --git a/controllers/testexecution/suite_test.go b/internal/controller/testexecution/suite_test.go similarity index 92% rename from controllers/testexecution/suite_test.go rename to internal/controller/testexecution/suite_test.go index fe6644f1..983d45c5 100644 --- a/controllers/testexecution/suite_test.go +++ b/internal/controller/testexecution/suite_test.go @@ -30,7 +30,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - testexecutionv1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" + testexecutionv1 "github.com/kubeshop/testkube-operator/api/testexecution/v1" //+kubebuilder:scaffold:imports ) @@ -52,7 +52,7 @@ var _ = BeforeSuite(func() { By("bootstrapping test environment") testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")}, ErrorIfCRDPathMissing: true, } diff --git a/controllers/testexecution/testexecution_controller.go b/internal/controller/testexecution/testexecution_controller.go similarity index 98% rename from controllers/testexecution/testexecution_controller.go rename to internal/controller/testexecution/testexecution_controller.go index eb410088..a93fe890 100644 --- a/controllers/testexecution/testexecution_controller.go +++ b/internal/controller/testexecution/testexecution_controller.go @@ -31,7 +31,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/predicate" - testexecutionv1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" + testexecutionv1 "github.com/kubeshop/testkube-operator/api/testexecution/v1" ) // TestExecutionReconciler reconciles a TestExecution object diff --git a/controllers/tests/test_controller.go b/internal/controller/tests/test_controller.go similarity index 97% rename from controllers/tests/test_controller.go rename to internal/controller/tests/test_controller.go index cb3e1b3f..9d3090b7 100644 --- a/controllers/tests/test_controller.go +++ b/internal/controller/tests/test_controller.go @@ -28,8 +28,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/predicate" - templatesv1 "github.com/kubeshop/testkube-operator/apis/template/v1" - testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" + templatesv1 "github.com/kubeshop/testkube-operator/api/template/v1" + testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" "github.com/kubeshop/testkube-operator/pkg/cronjob" ) diff --git a/controllers/testsource/suite_test.go b/internal/controller/testsource/suite_test.go similarity index 88% rename from controllers/testsource/suite_test.go rename to internal/controller/testsource/suite_test.go index 21d5066f..d45ff782 100644 --- a/controllers/testsource/suite_test.go +++ b/internal/controller/testsource/suite_test.go @@ -26,11 +26,10 @@ import ( "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" - "sigs.k8s.io/controller-runtime/pkg/envtest/printer" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - testsourcev1 "github.com/kubeshop/testkube-operator/apis/testsource/v1" + testsourcev1 "github.com/kubeshop/testkube-operator/api/testsource/v1" //+kubebuilder:scaffold:imports ) @@ -47,7 +46,7 @@ func TestAPIs(t *testing.T) { RunSpecsWithDefaultAndCustomReporters(t, "Controller Suite", - []Reporter{printer.NewlineReporter{}}) + nil) } var _ = BeforeSuite(func() { @@ -55,7 +54,7 @@ var _ = BeforeSuite(func() { By("bootstrapping test environment") testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")}, ErrorIfCRDPathMissing: true, } diff --git a/controllers/testsource/testsource_controller.go b/internal/controller/testsource/testsource_controller.go similarity index 96% rename from controllers/testsource/testsource_controller.go rename to internal/controller/testsource/testsource_controller.go index 3660362c..610ce9b3 100644 --- a/controllers/testsource/testsource_controller.go +++ b/internal/controller/testsource/testsource_controller.go @@ -24,7 +24,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" - testsourcev1 "github.com/kubeshop/testkube-operator/apis/testsource/v1" + testsourcev1 "github.com/kubeshop/testkube-operator/api/testsource/v1" ) // TestSourceReconciler reconciles a TestSource object diff --git a/controllers/testsuite/suite_test.go b/internal/controller/testsuite/suite_test.go similarity index 88% rename from controllers/testsuite/suite_test.go rename to internal/controller/testsuite/suite_test.go index 61b50fb0..a46e0577 100644 --- a/controllers/testsuite/suite_test.go +++ b/internal/controller/testsuite/suite_test.go @@ -26,11 +26,10 @@ import ( "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" - "sigs.k8s.io/controller-runtime/pkg/envtest/printer" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" //+kubebuilder:scaffold:imports ) @@ -47,7 +46,7 @@ func TestAPIs(t *testing.T) { RunSpecsWithDefaultAndCustomReporters(t, "Controller Suite", - []Reporter{printer.NewlineReporter{}}) + nil) } var _ = BeforeSuite(func() { @@ -55,7 +54,7 @@ var _ = BeforeSuite(func() { By("bootstrapping test environment") testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")}, ErrorIfCRDPathMissing: true, } diff --git a/controllers/testsuite/testsuite_controller.go b/internal/controller/testsuite/testsuite_controller.go similarity index 97% rename from controllers/testsuite/testsuite_controller.go rename to internal/controller/testsuite/testsuite_controller.go index 72fd4f68..92892df4 100644 --- a/controllers/testsuite/testsuite_controller.go +++ b/internal/controller/testsuite/testsuite_controller.go @@ -28,8 +28,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/predicate" - templatesv1 "github.com/kubeshop/testkube-operator/apis/template/v1" - testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + templatesv1 "github.com/kubeshop/testkube-operator/api/template/v1" + testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" "github.com/kubeshop/testkube-operator/pkg/cronjob" ) diff --git a/controllers/testsuiteexecution/suite_test.go b/internal/controller/testsuiteexecution/suite_test.go similarity index 94% rename from controllers/testsuiteexecution/suite_test.go rename to internal/controller/testsuiteexecution/suite_test.go index c5561199..5b64cb5d 100644 --- a/controllers/testsuiteexecution/suite_test.go +++ b/internal/controller/testsuiteexecution/suite_test.go @@ -30,7 +30,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" + testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/api/testsuiteexecution/v1" //+kubebuilder:scaffold:imports ) @@ -52,7 +52,7 @@ var _ = BeforeSuite(func() { By("bootstrapping test environment") testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")}, ErrorIfCRDPathMissing: true, } diff --git a/controllers/testsuiteexecution/testsuiteexecution_controllller.go b/internal/controller/testsuiteexecution/testsuiteexecution_controllller.go similarity index 99% rename from controllers/testsuiteexecution/testsuiteexecution_controllller.go rename to internal/controller/testsuiteexecution/testsuiteexecution_controllller.go index 079f19b2..fcc00a75 100644 --- a/controllers/testsuiteexecution/testsuiteexecution_controllller.go +++ b/internal/controller/testsuiteexecution/testsuiteexecution_controllller.go @@ -31,7 +31,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/predicate" - testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" + testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/api/testsuiteexecution/v1" ) // TestSuiteExecutionReconciler reconciles a TestSuiteExecution object diff --git a/controllers/testtriggers/suite_test.go b/internal/controller/testtriggers/suite_test.go similarity index 88% rename from controllers/testtriggers/suite_test.go rename to internal/controller/testtriggers/suite_test.go index f9c404e9..5411d46d 100644 --- a/controllers/testtriggers/suite_test.go +++ b/internal/controller/testtriggers/suite_test.go @@ -17,7 +17,7 @@ limitations under the License. package testtriggers import ( - testtriggersv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" + testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" "path/filepath" "testing" @@ -27,7 +27,6 @@ import ( "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" - "sigs.k8s.io/controller-runtime/pkg/envtest/printer" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" //+kubebuilder:scaffold:imports @@ -46,7 +45,7 @@ func TestAPIs(t *testing.T) { RunSpecsWithDefaultAndCustomReporters(t, "Controller Suite", - []Reporter{printer.NewlineReporter{}}) + nil) } var _ = BeforeSuite(func() { @@ -54,7 +53,7 @@ var _ = BeforeSuite(func() { By("bootstrapping test environment") testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")}, ErrorIfCRDPathMissing: true, } diff --git a/controllers/testtriggers/testtrigger_controller.go b/internal/controller/testtriggers/testtrigger_controller.go similarity index 96% rename from controllers/testtriggers/testtrigger_controller.go rename to internal/controller/testtriggers/testtrigger_controller.go index e6ef089d..b4cf38bd 100644 --- a/controllers/testtriggers/testtrigger_controller.go +++ b/internal/controller/testtriggers/testtrigger_controller.go @@ -18,7 +18,7 @@ package testtriggers import ( "context" - testtriggersv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" + testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" diff --git a/controllers/testtriggers/testtrigger_validator.go b/internal/controller/testtriggers/testtrigger_validator.go similarity index 98% rename from controllers/testtriggers/testtrigger_validator.go rename to internal/controller/testtriggers/testtrigger_validator.go index 00d178d5..81d23cad 100644 --- a/controllers/testtriggers/testtrigger_validator.go +++ b/internal/controller/testtriggers/testtrigger_validator.go @@ -19,9 +19,9 @@ package testtriggers import ( "context" - testtriggerv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" + testtriggerv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" + "github.com/kubeshop/testkube-operator/internal/utils" "github.com/kubeshop/testkube-operator/pkg/validation/tests/v1/testtrigger" - "github.com/kubeshop/testkube-operator/utils" k8serrors "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" diff --git a/controllers/testtriggers/testtrigger_validator_test.go b/internal/controller/testtriggers/testtrigger_validator_test.go similarity index 98% rename from controllers/testtriggers/testtrigger_validator_test.go rename to internal/controller/testtriggers/testtrigger_validator_test.go index bb525881..efe228b5 100644 --- a/controllers/testtriggers/testtrigger_validator_test.go +++ b/internal/controller/testtriggers/testtrigger_validator_test.go @@ -19,7 +19,7 @@ package testtriggers import ( "testing" - testtriggerv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" + testtriggerv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -181,7 +181,7 @@ func TestValidator_validateSelector(t *testing.T) { } verrs := v.validateSelector(fld, selector) assert.Len(t, verrs, 1) - assert.ErrorContains(t, verrs[0], "\"invalid\" is not a valid pod selector operator") + assert.ErrorContains(t, verrs[0], "\"invalid\" is not a valid label selector operator") }) } diff --git a/utils/utils.go b/internal/utils/utils.go similarity index 100% rename from utils/utils.go rename to internal/utils/utils.go diff --git a/local.Dockerfile b/local.Dockerfile new file mode 100644 index 00000000..b478950c --- /dev/null +++ b/local.Dockerfile @@ -0,0 +1,6 @@ +FROM gcr.io/distroless/static:nonroot + +WORKDIR / + +COPY dist/manager /manager +ENTRYPOINT ["/manager"] diff --git a/pkg/client/client.go b/pkg/client/client.go new file mode 100644 index 00000000..a5defbf9 --- /dev/null +++ b/pkg/client/client.go @@ -0,0 +1,51 @@ +package client + +import ( + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + _ "k8s.io/client-go/plugin/pkg/client/auth" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" + scriptv1 "github.com/kubeshop/testkube-operator/api/script/v1" + scriptv2 "github.com/kubeshop/testkube-operator/api/script/v2" + templatev1 "github.com/kubeshop/testkube-operator/api/template/v1" + testexecutionv1 "github.com/kubeshop/testkube-operator/api/testexecution/v1" + testsv1 "github.com/kubeshop/testkube-operator/api/tests/v1" + testsv2 "github.com/kubeshop/testkube-operator/api/tests/v2" + testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" + testsourcev1 "github.com/kubeshop/testkube-operator/api/testsource/v1" + testsuitev1 "github.com/kubeshop/testkube-operator/api/testsuite/v1" + testsuitev2 "github.com/kubeshop/testkube-operator/api/testsuite/v2" + testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" + testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/api/testsuiteexecution/v1" +) + +// GetClient returns kubernetes CRD client with registered schemes +func GetClient() (client.Client, error) { + scheme := runtime.NewScheme() + + utilruntime.Must(scriptv1.AddToScheme(scheme)) + utilruntime.Must(scriptv2.AddToScheme(scheme)) + utilruntime.Must(executorv1.AddToScheme(scheme)) + utilruntime.Must(testsv1.AddToScheme(scheme)) + utilruntime.Must(testsv2.AddToScheme(scheme)) + utilruntime.Must(testsv3.AddToScheme(scheme)) + utilruntime.Must(testsuitev1.AddToScheme(scheme)) + utilruntime.Must(corev1.AddToScheme(scheme)) + utilruntime.Must(testsuitev2.AddToScheme(scheme)) + utilruntime.Must(testsuitev3.AddToScheme(scheme)) + utilruntime.Must(testsourcev1.AddToScheme(scheme)) + utilruntime.Must(testexecutionv1.AddToScheme(scheme)) + utilruntime.Must(testsuiteexecutionv1.AddToScheme(scheme)) + utilruntime.Must(templatev1.AddToScheme(scheme)) + + kubeconfig, err := ctrl.GetConfig() + if err != nil { + return nil, err + } + + return client.New(kubeconfig, client.Options{Scheme: scheme}) +} diff --git a/client/executors/executors.go b/pkg/client/executors/executors.go similarity index 97% rename from client/executors/executors.go rename to pkg/client/executors/executors.go index 1202f2c6..693de68d 100644 --- a/client/executors/executors.go +++ b/pkg/client/executors/executors.go @@ -5,7 +5,7 @@ import ( "context" "fmt" - executorv1 "github.com/kubeshop/testkube-operator/apis/executor/v1" + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" ) diff --git a/client/executors/v1/executors.go b/pkg/client/executors/v1/executors.go similarity index 98% rename from client/executors/v1/executors.go rename to pkg/client/executors/v1/executors.go index 57dac1cf..1d0ddf84 100644 --- a/client/executors/v1/executors.go +++ b/pkg/client/executors/v1/executors.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - executorv1 "github.com/kubeshop/testkube-operator/apis/executor/v1" + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" diff --git a/client/executors/v1/mock_executors.go b/pkg/client/executors/v1/mock_executors.go similarity index 98% rename from client/executors/v1/mock_executors.go rename to pkg/client/executors/v1/mock_executors.go index 5563af0e..d53ee530 100644 --- a/client/executors/v1/mock_executors.go +++ b/pkg/client/executors/v1/mock_executors.go @@ -8,7 +8,7 @@ import ( reflect "reflect" gomock "github.com/golang/mock/gomock" - v1 "github.com/kubeshop/testkube-operator/apis/executor/v1" + v1 "github.com/kubeshop/testkube-operator/api/executor/v1" ) // MockInterface is a mock of Interface interface. diff --git a/client/executors/v1/webhooks.go b/pkg/client/executors/v1/webhooks.go similarity index 98% rename from client/executors/v1/webhooks.go rename to pkg/client/executors/v1/webhooks.go index 60237fef..17173395 100644 --- a/client/executors/v1/webhooks.go +++ b/pkg/client/executors/v1/webhooks.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - executorsv1 "github.com/kubeshop/testkube-operator/apis/executor/v1" + executorsv1 "github.com/kubeshop/testkube-operator/api/executor/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" diff --git a/client/executors/v1/webhooks_test.go b/pkg/client/executors/v1/webhooks_test.go similarity index 98% rename from client/executors/v1/webhooks_test.go rename to pkg/client/executors/v1/webhooks_test.go index 6686c37f..84e9aa1a 100644 --- a/client/executors/v1/webhooks_test.go +++ b/pkg/client/executors/v1/webhooks_test.go @@ -3,7 +3,7 @@ package executors import ( "testing" - executorsv1 "github.com/kubeshop/testkube-operator/apis/executor/v1" + executorsv1 "github.com/kubeshop/testkube-operator/api/executor/v1" "github.com/stretchr/testify/assert" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/client/scripts/scripts.go b/pkg/client/scripts/scripts.go similarity index 95% rename from client/scripts/scripts.go rename to pkg/client/scripts/scripts.go index 5550c275..d3c9abc3 100644 --- a/client/scripts/scripts.go +++ b/pkg/client/scripts/scripts.go @@ -3,12 +3,12 @@ package scripts import ( "context" - "github.com/kubeshop/testkube-operator/utils" + "github.com/kubeshop/testkube-operator/internal/utils" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/controller-runtime/pkg/client" - scriptv1 "github.com/kubeshop/testkube-operator/apis/script/v1" + scriptv1 "github.com/kubeshop/testkube-operator/api/script/v1" ) func NewClient(client client.Client, namespace string) *ScriptsClient { diff --git a/client/scripts/v2/scripts.go b/pkg/client/scripts/v2/scripts.go similarity index 95% rename from client/scripts/v2/scripts.go rename to pkg/client/scripts/v2/scripts.go index 580bc39a..c756dd20 100644 --- a/client/scripts/v2/scripts.go +++ b/pkg/client/scripts/v2/scripts.go @@ -2,12 +2,12 @@ package scripts import ( "context" - "github.com/kubeshop/testkube-operator/utils" + "github.com/kubeshop/testkube-operator/internal/utils" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/controller-runtime/pkg/client" - scriptv2 "github.com/kubeshop/testkube-operator/apis/script/v2" + scriptv2 "github.com/kubeshop/testkube-operator/api/script/v2" ) func NewClient(client client.Client, namespace string) *ScriptsClient { diff --git a/client/templates/v1/mock_templates.go b/pkg/client/templates/v1/mock_templates.go similarity index 98% rename from client/templates/v1/mock_templates.go rename to pkg/client/templates/v1/mock_templates.go index 29268e1e..cb483b4a 100644 --- a/client/templates/v1/mock_templates.go +++ b/pkg/client/templates/v1/mock_templates.go @@ -8,7 +8,7 @@ import ( reflect "reflect" gomock "github.com/golang/mock/gomock" - v1 "github.com/kubeshop/testkube-operator/apis/template/v1" + v1 "github.com/kubeshop/testkube-operator/api/template/v1" ) // MockInterface is a mock of Interface interface. diff --git a/client/templates/v1/templates.go b/pkg/client/templates/v1/templates.go similarity index 97% rename from client/templates/v1/templates.go rename to pkg/client/templates/v1/templates.go index 5fa33c41..6f231803 100644 --- a/client/templates/v1/templates.go +++ b/pkg/client/templates/v1/templates.go @@ -3,7 +3,7 @@ package templates import ( "context" - templatev1 "github.com/kubeshop/testkube-operator/apis/template/v1" + templatev1 "github.com/kubeshop/testkube-operator/api/template/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" diff --git a/client/templates/v1/templates_test.go b/pkg/client/templates/v1/templates_test.go similarity index 98% rename from client/templates/v1/templates_test.go rename to pkg/client/templates/v1/templates_test.go index 70c2814c..20592797 100644 --- a/client/templates/v1/templates_test.go +++ b/pkg/client/templates/v1/templates_test.go @@ -9,7 +9,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/scheme" - templatesv1 "github.com/kubeshop/testkube-operator/apis/template/v1" + templatesv1 "github.com/kubeshop/testkube-operator/api/template/v1" ) func TestTemplates(t *testing.T) { diff --git a/client/testexecutions/v1/mock_testexecutions.go b/pkg/client/testexecutions/v1/mock_testexecutions.go similarity index 98% rename from client/testexecutions/v1/mock_testexecutions.go rename to pkg/client/testexecutions/v1/mock_testexecutions.go index 7da7bafc..addeba34 100644 --- a/client/testexecutions/v1/mock_testexecutions.go +++ b/pkg/client/testexecutions/v1/mock_testexecutions.go @@ -8,7 +8,7 @@ import ( reflect "reflect" gomock "github.com/golang/mock/gomock" - v1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" + v1 "github.com/kubeshop/testkube-operator/api/testexecution/v1" ) // MockInterface is a mock of Interface interface. diff --git a/client/testexecutions/v1/testexecutions.go b/pkg/client/testexecutions/v1/testexecutions.go similarity index 97% rename from client/testexecutions/v1/testexecutions.go rename to pkg/client/testexecutions/v1/testexecutions.go index d6938a33..162a368d 100644 --- a/client/testexecutions/v1/testexecutions.go +++ b/pkg/client/testexecutions/v1/testexecutions.go @@ -3,7 +3,7 @@ package testexecutions import ( "context" - testexecutionv1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" + testexecutionv1 "github.com/kubeshop/testkube-operator/api/testexecution/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" ) diff --git a/client/testexecutions/v1/testexecutions_test.go b/pkg/client/testexecutions/v1/testexecutions_test.go similarity index 97% rename from client/testexecutions/v1/testexecutions_test.go rename to pkg/client/testexecutions/v1/testexecutions_test.go index ede73e3b..8132a8d0 100644 --- a/client/testexecutions/v1/testexecutions_test.go +++ b/pkg/client/testexecutions/v1/testexecutions_test.go @@ -9,7 +9,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/scheme" - testexecutionv1 "github.com/kubeshop/testkube-operator/apis/testexecution/v1" + testexecutionv1 "github.com/kubeshop/testkube-operator/api/testexecution/v1" ) func TestTestExecutions(t *testing.T) { diff --git a/client/tests/tests.go b/pkg/client/tests/tests.go similarity index 94% rename from client/tests/tests.go rename to pkg/client/tests/tests.go index 01f20a21..f8dbcfaa 100644 --- a/client/tests/tests.go +++ b/pkg/client/tests/tests.go @@ -2,12 +2,12 @@ package tests import ( "context" - "github.com/kubeshop/testkube-operator/utils" + "github.com/kubeshop/testkube-operator/internal/utils" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/controller-runtime/pkg/client" - testsv1 "github.com/kubeshop/testkube-operator/apis/tests/v1" + testsv1 "github.com/kubeshop/testkube-operator/api/tests/v1" ) func NewClient(client client.Client, namespace string) *TestsClient { diff --git a/client/tests/v2/tests.go b/pkg/client/tests/v2/tests.go similarity index 98% rename from client/tests/v2/tests.go rename to pkg/client/tests/v2/tests.go index 1bf45211..13b4138a 100644 --- a/client/tests/v2/tests.go +++ b/pkg/client/tests/v2/tests.go @@ -12,8 +12,8 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/controller-runtime/pkg/client" - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" - testsv2 "github.com/kubeshop/testkube-operator/apis/tests/v2" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" + testsv2 "github.com/kubeshop/testkube-operator/api/tests/v2" "k8s.io/apimachinery/pkg/labels" ) diff --git a/client/tests/v2/tests_test.go b/pkg/client/tests/v2/tests_test.go similarity index 96% rename from client/tests/v2/tests_test.go rename to pkg/client/tests/v2/tests_test.go index c699363d..390253c3 100644 --- a/client/tests/v2/tests_test.go +++ b/pkg/client/tests/v2/tests_test.go @@ -8,8 +8,8 @@ import ( "fmt" "testing" - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" - testsv2 "github.com/kubeshop/testkube-operator/apis/tests/v2" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" + testsv2 "github.com/kubeshop/testkube-operator/api/tests/v2" kubeclient "github.com/kubeshop/testkube-operator/client" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/client/tests/v3/mock_tests.go b/pkg/client/tests/v3/mock_tests.go similarity index 99% rename from client/tests/v3/mock_tests.go rename to pkg/client/tests/v3/mock_tests.go index 89f23d38..e1285df8 100644 --- a/client/tests/v3/mock_tests.go +++ b/pkg/client/tests/v3/mock_tests.go @@ -8,7 +8,7 @@ import ( reflect "reflect" gomock "github.com/golang/mock/gomock" - v3 "github.com/kubeshop/testkube-operator/apis/tests/v3" + v3 "github.com/kubeshop/testkube-operator/api/tests/v3" v1 "k8s.io/api/core/v1" ) diff --git a/client/tests/v3/test.go b/pkg/client/tests/v3/test.go similarity index 99% rename from client/tests/v3/test.go rename to pkg/client/tests/v3/test.go index e8858672..53d8e2cb 100644 --- a/client/tests/v3/test.go +++ b/pkg/client/tests/v3/test.go @@ -12,8 +12,8 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/controller-runtime/pkg/client" - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" - testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" + testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" "github.com/kubeshop/testkube-operator/pkg/secret" "k8s.io/apimachinery/pkg/labels" ) @@ -610,6 +610,4 @@ func clearTestSecrets(test *testsv3.Test, secretName string) { test.Spec.Content.Repository.TokenSecret.Name == secretName { test.Spec.Content.Repository.TokenSecret = nil } - - return } diff --git a/client/tests/v3/test_test.go b/pkg/client/tests/v3/test_test.go similarity index 96% rename from client/tests/v3/test_test.go rename to pkg/client/tests/v3/test_test.go index a78ea524..32a97888 100644 --- a/client/tests/v3/test_test.go +++ b/pkg/client/tests/v3/test_test.go @@ -8,8 +8,8 @@ import ( "fmt" "testing" - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" - testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" + testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" kubeclient "github.com/kubeshop/testkube-operator/client" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/client/testsources/v1/mock_testsources.go b/pkg/client/testsources/v1/mock_testsources.go similarity index 98% rename from client/testsources/v1/mock_testsources.go rename to pkg/client/testsources/v1/mock_testsources.go index 2c12df5f..1f8e9eaa 100644 --- a/client/testsources/v1/mock_testsources.go +++ b/pkg/client/testsources/v1/mock_testsources.go @@ -8,7 +8,7 @@ import ( reflect "reflect" gomock "github.com/golang/mock/gomock" - v1 "github.com/kubeshop/testkube-operator/apis/testsource/v1" + v1 "github.com/kubeshop/testkube-operator/api/testsource/v1" ) // MockInterface is a mock of Interface interface. diff --git a/client/testsources/v1/testsources.go b/pkg/client/testsources/v1/testsources.go similarity index 98% rename from client/testsources/v1/testsources.go rename to pkg/client/testsources/v1/testsources.go index 0e48c194..883ddbf2 100644 --- a/client/testsources/v1/testsources.go +++ b/pkg/client/testsources/v1/testsources.go @@ -3,7 +3,7 @@ package testsources import ( "context" - testsourcev1 "github.com/kubeshop/testkube-operator/apis/testsource/v1" + testsourcev1 "github.com/kubeshop/testkube-operator/api/testsource/v1" "github.com/kubeshop/testkube-operator/pkg/secret" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -213,6 +213,4 @@ func clearTestSourceSecrets(testSource *testsourcev1.TestSource, secretName stri testSource.Spec.Repository.TokenSecret.Name == secretName { testSource.Spec.Repository.TokenSecret = nil } - - return } diff --git a/client/testsources/v1/testsources_test.go b/pkg/client/testsources/v1/testsources_test.go similarity index 98% rename from client/testsources/v1/testsources_test.go rename to pkg/client/testsources/v1/testsources_test.go index d28ce6b2..f4243425 100644 --- a/client/testsources/v1/testsources_test.go +++ b/pkg/client/testsources/v1/testsources_test.go @@ -3,7 +3,7 @@ package testsources import ( "testing" - testsourcev1 "github.com/kubeshop/testkube-operator/apis/testsource/v1" + testsourcev1 "github.com/kubeshop/testkube-operator/api/testsource/v1" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/client/testsuiteexecutions/v1/mock_testsuiteexecutions.go b/pkg/client/testsuiteexecutions/v1/mock_testsuiteexecutions.go similarity index 98% rename from client/testsuiteexecutions/v1/mock_testsuiteexecutions.go rename to pkg/client/testsuiteexecutions/v1/mock_testsuiteexecutions.go index bdff6194..728f8446 100644 --- a/client/testsuiteexecutions/v1/mock_testsuiteexecutions.go +++ b/pkg/client/testsuiteexecutions/v1/mock_testsuiteexecutions.go @@ -8,7 +8,7 @@ import ( reflect "reflect" gomock "github.com/golang/mock/gomock" - v1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" + v1 "github.com/kubeshop/testkube-operator/api/testsuiteexecution/v1" ) // MockInterface is a mock of Interface interface. diff --git a/client/testsuiteexecutions/v1/testsuiteexecutions.go b/pkg/client/testsuiteexecutions/v1/testsuiteexecutions.go similarity index 99% rename from client/testsuiteexecutions/v1/testsuiteexecutions.go rename to pkg/client/testsuiteexecutions/v1/testsuiteexecutions.go index c8a253d7..d39196dd 100644 --- a/client/testsuiteexecutions/v1/testsuiteexecutions.go +++ b/pkg/client/testsuiteexecutions/v1/testsuiteexecutions.go @@ -6,7 +6,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" - testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" + testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/api/testsuiteexecution/v1" ) //go:generate mockgen -destination=./mock_testsuiteexecutions.go -package=testsuiteexecutions "github.com/kubeshop/testkube-operator/client/testsuiteexecutions/v1" Interface diff --git a/client/testsuiteexecutions/v1/testsuiteexecutions_test.go b/pkg/client/testsuiteexecutions/v1/testsuiteexecutions_test.go similarity index 99% rename from client/testsuiteexecutions/v1/testsuiteexecutions_test.go rename to pkg/client/testsuiteexecutions/v1/testsuiteexecutions_test.go index 1493c34d..706c7918 100644 --- a/client/testsuiteexecutions/v1/testsuiteexecutions_test.go +++ b/pkg/client/testsuiteexecutions/v1/testsuiteexecutions_test.go @@ -9,7 +9,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/scheme" - testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/apis/testsuiteexecution/v1" + testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/api/testsuiteexecution/v1" ) func TestTestSuiteExecutions(t *testing.T) { diff --git a/client/testsuites/v1/testsuites.go b/pkg/client/testsuites/v1/testsuites.go similarity index 98% rename from client/testsuites/v1/testsuites.go rename to pkg/client/testsuites/v1/testsuites.go index 92f27d31..1c5d14ab 100644 --- a/client/testsuites/v1/testsuites.go +++ b/pkg/client/testsuites/v1/testsuites.go @@ -13,8 +13,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/google/uuid" - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" - testsuitev1 "github.com/kubeshop/testkube-operator/apis/testsuite/v1" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" + testsuitev1 "github.com/kubeshop/testkube-operator/api/testsuite/v1" ) const ( diff --git a/client/testsuites/v1/testsuites_test.go b/pkg/client/testsuites/v1/testsuites_test.go similarity index 95% rename from client/testsuites/v1/testsuites_test.go rename to pkg/client/testsuites/v1/testsuites_test.go index 9cfc8e7b..6a89b097 100644 --- a/client/testsuites/v1/testsuites_test.go +++ b/pkg/client/testsuites/v1/testsuites_test.go @@ -7,8 +7,8 @@ package v1 import ( "testing" - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" - testsuitev1 "github.com/kubeshop/testkube-operator/apis/testsuite/v1" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" + testsuitev1 "github.com/kubeshop/testkube-operator/api/testsuite/v1" kubeclient "github.com/kubeshop/testkube-operator/client" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/client/testsuites/v2/mock_testsuites.go b/pkg/client/testsuites/v2/mock_testsuites.go similarity index 99% rename from client/testsuites/v2/mock_testsuites.go rename to pkg/client/testsuites/v2/mock_testsuites.go index f249ab5c..e7fd0346 100644 --- a/client/testsuites/v2/mock_testsuites.go +++ b/pkg/client/testsuites/v2/mock_testsuites.go @@ -8,7 +8,7 @@ import ( reflect "reflect" gomock "github.com/golang/mock/gomock" - v2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" + v2 "github.com/kubeshop/testkube-operator/api/testsuite/v2" v1 "k8s.io/api/core/v1" ) diff --git a/client/testsuites/v2/testsuites.go b/pkg/client/testsuites/v2/testsuites.go similarity index 98% rename from client/testsuites/v2/testsuites.go rename to pkg/client/testsuites/v2/testsuites.go index 1741080c..33e80ddb 100644 --- a/client/testsuites/v2/testsuites.go +++ b/pkg/client/testsuites/v2/testsuites.go @@ -13,8 +13,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/google/uuid" - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" - testsuitev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" + testsuitev2 "github.com/kubeshop/testkube-operator/api/testsuite/v2" ) const ( diff --git a/client/testsuites/v2/testsuites_test.go b/pkg/client/testsuites/v2/testsuites_test.go similarity index 96% rename from client/testsuites/v2/testsuites_test.go rename to pkg/client/testsuites/v2/testsuites_test.go index 1e9d3d87..b1e2be02 100644 --- a/client/testsuites/v2/testsuites_test.go +++ b/pkg/client/testsuites/v2/testsuites_test.go @@ -7,8 +7,8 @@ package v2 import ( "testing" - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" - testsuitev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" + testsuitev2 "github.com/kubeshop/testkube-operator/api/testsuite/v2" kubeclient "github.com/kubeshop/testkube-operator/client" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/client/testsuites/v3/mock_testsuites.go b/pkg/client/testsuites/v3/mock_testsuites.go similarity index 99% rename from client/testsuites/v3/mock_testsuites.go rename to pkg/client/testsuites/v3/mock_testsuites.go index e5ce0d63..acd0fce3 100644 --- a/client/testsuites/v3/mock_testsuites.go +++ b/pkg/client/testsuites/v3/mock_testsuites.go @@ -8,7 +8,7 @@ import ( reflect "reflect" gomock "github.com/golang/mock/gomock" - v3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + v3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" v1 "k8s.io/api/core/v1" ) diff --git a/client/testsuites/v3/testsuites.go b/pkg/client/testsuites/v3/testsuites.go similarity index 98% rename from client/testsuites/v3/testsuites.go rename to pkg/client/testsuites/v3/testsuites.go index 5ca405fa..050fb977 100644 --- a/client/testsuites/v3/testsuites.go +++ b/pkg/client/testsuites/v3/testsuites.go @@ -13,8 +13,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/google/uuid" - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" - testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" + testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" ) const ( diff --git a/client/testsuites/v3/testsuites_test.go b/pkg/client/testsuites/v3/testsuites_test.go similarity index 96% rename from client/testsuites/v3/testsuites_test.go rename to pkg/client/testsuites/v3/testsuites_test.go index b975f389..7ca06ab4 100644 --- a/client/testsuites/v3/testsuites_test.go +++ b/pkg/client/testsuites/v3/testsuites_test.go @@ -7,8 +7,8 @@ package v3 import ( "testing" - commonv1 "github.com/kubeshop/testkube-operator/apis/common/v1" - testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" + testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" kubeclient "github.com/kubeshop/testkube-operator/client" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/clientset/versioned/fake/register.go b/pkg/clientset/versioned/fake/register.go index 8cbb55a3..59f07697 100644 --- a/pkg/clientset/versioned/fake/register.go +++ b/pkg/clientset/versioned/fake/register.go @@ -17,9 +17,9 @@ limitations under the License. package fake import ( - testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" - testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" - testtriggersv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" + testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" + testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" + testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/clientset/versioned/scheme/register.go b/pkg/clientset/versioned/scheme/register.go index 4b006c21..440f31bc 100644 --- a/pkg/clientset/versioned/scheme/register.go +++ b/pkg/clientset/versioned/scheme/register.go @@ -17,9 +17,9 @@ limitations under the License. package scheme import ( - testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" - testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" - testtriggersv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" + testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" + testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" + testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/clientset/versioned/typed/tests/v1/fake/fake_testtrigger.go b/pkg/clientset/versioned/typed/tests/v1/fake/fake_testtrigger.go index d64a5ce0..ecb43338 100644 --- a/pkg/clientset/versioned/typed/tests/v1/fake/fake_testtrigger.go +++ b/pkg/clientset/versioned/typed/tests/v1/fake/fake_testtrigger.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - testtriggersv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" + testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" diff --git a/pkg/clientset/versioned/typed/tests/v1/tests_client.go b/pkg/clientset/versioned/typed/tests/v1/tests_client.go index b08c8f92..291f43ae 100644 --- a/pkg/clientset/versioned/typed/tests/v1/tests_client.go +++ b/pkg/clientset/versioned/typed/tests/v1/tests_client.go @@ -20,7 +20,7 @@ import ( "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/scheme" "net/http" - testtriggersv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" + testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" "k8s.io/client-go/rest" ) diff --git a/pkg/clientset/versioned/typed/tests/v1/testtrigger.go b/pkg/clientset/versioned/typed/tests/v1/testtrigger.go index 6a3a9c53..ef3bff94 100644 --- a/pkg/clientset/versioned/typed/tests/v1/testtrigger.go +++ b/pkg/clientset/versioned/typed/tests/v1/testtrigger.go @@ -18,7 +18,7 @@ package v1 import ( "context" - testtriggersv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" + testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/scheme" "time" diff --git a/pkg/clientset/versioned/typed/tests/v2/fake/fake_testsuite.go b/pkg/clientset/versioned/typed/tests/v2/fake/fake_testsuite.go index 447e14cb..b8f02365 100644 --- a/pkg/clientset/versioned/typed/tests/v2/fake/fake_testsuite.go +++ b/pkg/clientset/versioned/typed/tests/v2/fake/fake_testsuite.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - testsuitev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" + testsuitev2 "github.com/kubeshop/testkube-operator/api/testsuite/v2" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" diff --git a/pkg/clientset/versioned/typed/tests/v2/tests_client.go b/pkg/clientset/versioned/typed/tests/v2/tests_client.go index 7a67b26f..899c0a76 100644 --- a/pkg/clientset/versioned/typed/tests/v2/tests_client.go +++ b/pkg/clientset/versioned/typed/tests/v2/tests_client.go @@ -21,7 +21,7 @@ import ( "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/scheme" - testsuitev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" + testsuitev2 "github.com/kubeshop/testkube-operator/api/testsuite/v2" "k8s.io/client-go/rest" ) diff --git a/pkg/clientset/versioned/typed/tests/v2/testsuite.go b/pkg/clientset/versioned/typed/tests/v2/testsuite.go index 72d16511..277d17c2 100644 --- a/pkg/clientset/versioned/typed/tests/v2/testsuite.go +++ b/pkg/clientset/versioned/typed/tests/v2/testsuite.go @@ -20,7 +20,7 @@ import ( "context" "time" - testsuitev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" + testsuitev2 "github.com/kubeshop/testkube-operator/api/testsuite/v2" "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/scheme" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/clientset/versioned/typed/tests/v3/fake/fake_tests.go b/pkg/clientset/versioned/typed/tests/v3/fake/fake_tests.go index 14b25608..f01b13c8 100644 --- a/pkg/clientset/versioned/typed/tests/v3/fake/fake_tests.go +++ b/pkg/clientset/versioned/typed/tests/v3/fake/fake_tests.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" + testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" diff --git a/pkg/clientset/versioned/typed/tests/v3/fake/fake_testsuite.go b/pkg/clientset/versioned/typed/tests/v3/fake/fake_testsuite.go index ac2ce3d0..5b1a9b05 100644 --- a/pkg/clientset/versioned/typed/tests/v3/fake/fake_testsuite.go +++ b/pkg/clientset/versioned/typed/tests/v3/fake/fake_testsuite.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" diff --git a/pkg/clientset/versioned/typed/tests/v3/test.go b/pkg/clientset/versioned/typed/tests/v3/test.go index 5367b3e1..5e78b439 100644 --- a/pkg/clientset/versioned/typed/tests/v3/test.go +++ b/pkg/clientset/versioned/typed/tests/v3/test.go @@ -20,7 +20,7 @@ import ( "context" "time" - testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" + testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/scheme" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/clientset/versioned/typed/tests/v3/tests_client.go b/pkg/clientset/versioned/typed/tests/v3/tests_client.go index e2b817ab..df4cdd7f 100644 --- a/pkg/clientset/versioned/typed/tests/v3/tests_client.go +++ b/pkg/clientset/versioned/typed/tests/v3/tests_client.go @@ -21,7 +21,7 @@ import ( "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/scheme" - testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" + testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" "k8s.io/client-go/rest" ) diff --git a/pkg/clientset/versioned/typed/tests/v3/testsuite.go b/pkg/clientset/versioned/typed/tests/v3/testsuite.go index 9d3bbfa6..4b8b5a8a 100644 --- a/pkg/clientset/versioned/typed/tests/v3/testsuite.go +++ b/pkg/clientset/versioned/typed/tests/v3/testsuite.go @@ -20,7 +20,7 @@ import ( "context" "time" - testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/scheme" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/informers/externalversions/generic.go b/pkg/informers/externalversions/generic.go index 0ce0e452..4f39a45f 100644 --- a/pkg/informers/externalversions/generic.go +++ b/pkg/informers/externalversions/generic.go @@ -17,9 +17,9 @@ limitations under the License. package externalversions import ( - testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" - testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" - testtriggersv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" + testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" + testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" + testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" "github.com/pkg/errors" schema "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/informers/externalversions/tests/v1/testtrigger.go b/pkg/informers/externalversions/tests/v1/testtrigger.go index 2f6ce4b6..c6873590 100644 --- a/pkg/informers/externalversions/tests/v1/testtrigger.go +++ b/pkg/informers/externalversions/tests/v1/testtrigger.go @@ -18,7 +18,7 @@ package v1 import ( "context" - testtriggersv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" + testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" "github.com/kubeshop/testkube-operator/pkg/clientset/versioned" "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/internalinterfaces" testtriggerslisterv1 "github.com/kubeshop/testkube-operator/pkg/listers/tests/v1" diff --git a/pkg/informers/externalversions/tests/v2/testsuite.go b/pkg/informers/externalversions/tests/v2/testsuite.go index 2ecb5d82..fdd51484 100644 --- a/pkg/informers/externalversions/tests/v2/testsuite.go +++ b/pkg/informers/externalversions/tests/v2/testsuite.go @@ -20,7 +20,7 @@ import ( "context" "time" - testsuitev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" + testsuitev2 "github.com/kubeshop/testkube-operator/api/testsuite/v2" "github.com/kubeshop/testkube-operator/pkg/clientset/versioned" "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/internalinterfaces" testsuiteslisterv2 "github.com/kubeshop/testkube-operator/pkg/listers/tests/v2" diff --git a/pkg/informers/externalversions/tests/v3/test.go b/pkg/informers/externalversions/tests/v3/test.go index a08f3246..044aec8f 100644 --- a/pkg/informers/externalversions/tests/v3/test.go +++ b/pkg/informers/externalversions/tests/v3/test.go @@ -20,7 +20,7 @@ import ( "context" "time" - testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" + testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" "github.com/kubeshop/testkube-operator/pkg/clientset/versioned" "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/internalinterfaces" testslisterv3 "github.com/kubeshop/testkube-operator/pkg/listers/tests/v3" diff --git a/pkg/informers/externalversions/tests/v3/testsuite.go b/pkg/informers/externalversions/tests/v3/testsuite.go index b62bb70a..c795f732 100644 --- a/pkg/informers/externalversions/tests/v3/testsuite.go +++ b/pkg/informers/externalversions/tests/v3/testsuite.go @@ -20,7 +20,7 @@ import ( "context" "time" - testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" "github.com/kubeshop/testkube-operator/pkg/clientset/versioned" "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/internalinterfaces" testsuiteslisterv3 "github.com/kubeshop/testkube-operator/pkg/listers/tests/v3" diff --git a/pkg/listers/tests/v1/testtriggers.go b/pkg/listers/tests/v1/testtriggers.go index 89593396..da8df72c 100644 --- a/pkg/listers/tests/v1/testtriggers.go +++ b/pkg/listers/tests/v1/testtriggers.go @@ -17,7 +17,7 @@ limitations under the License. package v1 import ( - testtriggersv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" + testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/listers/tests/v2/testsuites.go b/pkg/listers/tests/v2/testsuites.go index 5275020d..e290706a 100644 --- a/pkg/listers/tests/v2/testsuites.go +++ b/pkg/listers/tests/v2/testsuites.go @@ -17,7 +17,7 @@ limitations under the License. package v2 import ( - testsuitev2 "github.com/kubeshop/testkube-operator/apis/testsuite/v2" + testsuitev2 "github.com/kubeshop/testkube-operator/api/testsuite/v2" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/listers/tests/v3/tests.go b/pkg/listers/tests/v3/tests.go index 54ecd155..422f7039 100644 --- a/pkg/listers/tests/v3/tests.go +++ b/pkg/listers/tests/v3/tests.go @@ -17,7 +17,7 @@ limitations under the License. package v3 import ( - testsv3 "github.com/kubeshop/testkube-operator/apis/tests/v3" + testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/listers/tests/v3/testsuites.go b/pkg/listers/tests/v3/testsuites.go index 68913d65..65b8b535 100644 --- a/pkg/listers/tests/v3/testsuites.go +++ b/pkg/listers/tests/v3/testsuites.go @@ -17,7 +17,7 @@ limitations under the License. package v3 import ( - testsuitev3 "github.com/kubeshop/testkube-operator/apis/testsuite/v3" + testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/validation/tests/v1/testtrigger/util.go b/pkg/validation/tests/v1/testtrigger/util.go index ca397da6..e472e3e2 100644 --- a/pkg/validation/tests/v1/testtrigger/util.go +++ b/pkg/validation/tests/v1/testtrigger/util.go @@ -1,7 +1,7 @@ package testtrigger import ( - testtriggerv1 "github.com/kubeshop/testkube-operator/apis/testtriggers/v1" + testtriggerv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" ) func GetSupportedResources() []string { From 688b0e147b5de90234c498c3ecf032b7dc4e0a74 Mon Sep 17 00:00:00 2001 From: Dejan Zele Pejchev Date: Wed, 27 Sep 2023 08:21:08 +0200 Subject: [PATCH 40/57] fix invalid reference (#179) --- pkg/client/tests/v3/test_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/client/tests/v3/test_test.go b/pkg/client/tests/v3/test_test.go index 32a97888..f24c09e5 100644 --- a/pkg/client/tests/v3/test_test.go +++ b/pkg/client/tests/v3/test_test.go @@ -10,7 +10,7 @@ import ( commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" - kubeclient "github.com/kubeshop/testkube-operator/client" + kubeclient "github.com/kubeshop/testkube-operator/pkg/client" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) From 5fc20213a65a05f7218ce23b99e715c72e9baa8b Mon Sep 17 00:00:00 2001 From: Dejan Zele Pejchev Date: Wed, 27 Sep 2023 08:37:15 +0200 Subject: [PATCH 41/57] fix mocks (#180) --- Makefile | 3 + pkg/client/executors/v1/executors.go | 2 +- pkg/client/executors/v1/mock_executors.go | 2 +- pkg/client/templates/v1/mock_templates.go | 2 +- pkg/client/templates/v1/templates.go | 2 +- .../testexecutions/v1/mock_testexecutions.go | 2 +- .../testexecutions/v1/testexecutions.go | 2 +- pkg/client/tests/v2/tests_test.go | 2 +- pkg/client/tests/v3/mock_tests.go | 102 +++++++++--------- pkg/client/tests/v3/test.go | 2 +- pkg/client/testsources/v1/mock_testsources.go | 54 +++++----- pkg/client/testsources/v1/testsources.go | 2 +- .../v1/mock_testsuiteexecutions.go | 2 +- .../v1/testsuiteexecutions.go | 2 +- pkg/client/testsuites/v1/testsuites_test.go | 2 +- pkg/client/testsuites/v2/mock_testsuites.go | 10 +- pkg/client/testsuites/v2/testsuites.go | 2 +- pkg/client/testsuites/v2/testsuites_test.go | 2 +- pkg/client/testsuites/v3/mock_testsuites.go | 2 +- pkg/client/testsuites/v3/testsuites.go | 2 +- pkg/client/testsuites/v3/testsuites_test.go | 2 +- 21 files changed, 103 insertions(+), 100 deletions(-) diff --git a/Makefile b/Makefile index cec18960..190d5662 100644 --- a/Makefile +++ b/Makefile @@ -75,6 +75,9 @@ kind-load-local: docker-build-local run: manifests generate fmt vet ## Run a controller from your host. go run ./cmd/main.go +run-no-webhook: manifests generate fmt vet ## Run a controller from your host. + ENABLE_WEBHOOKS=false go run ./cmd/main.go + docker-build: test ## Build docker image with the manager. docker build -t ${IMG} . diff --git a/pkg/client/executors/v1/executors.go b/pkg/client/executors/v1/executors.go index 1d0ddf84..33f03017 100644 --- a/pkg/client/executors/v1/executors.go +++ b/pkg/client/executors/v1/executors.go @@ -19,7 +19,7 @@ func NewClient(client client.Client, namespace string) *ExecutorsClient { } } -//go:generate mockgen -destination=./mock_executors.go -package=executors "github.com/kubeshop/testkube-operator/client/executors/v1" Interface +//go:generate mockgen -destination=./mock_executors.go -package=executors "github.com/kubeshop/testkube-operator/pkg/client/executors/v1" Interface type Interface interface { List(selector string) (*executorv1.ExecutorList, error) Get(name string) (*executorv1.Executor, error) diff --git a/pkg/client/executors/v1/mock_executors.go b/pkg/client/executors/v1/mock_executors.go index d53ee530..249afade 100644 --- a/pkg/client/executors/v1/mock_executors.go +++ b/pkg/client/executors/v1/mock_executors.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/kubeshop/testkube-operator/client/executors/v1 (interfaces: Interface) +// Source: github.com/kubeshop/testkube-operator/pkg/client/executors/v1 (interfaces: Interface) // Package executors is a generated GoMock package. package executors diff --git a/pkg/client/templates/v1/mock_templates.go b/pkg/client/templates/v1/mock_templates.go index cb483b4a..6d6c2cd1 100644 --- a/pkg/client/templates/v1/mock_templates.go +++ b/pkg/client/templates/v1/mock_templates.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/kubeshop/testkube-operator/client/templates/v1 (interfaces: Interface) +// Source: github.com/kubeshop/testkube-operator/pkg/client/templates/v1 (interfaces: Interface) // Package templates is a generated GoMock package. package templates diff --git a/pkg/client/templates/v1/templates.go b/pkg/client/templates/v1/templates.go index 6f231803..9b529763 100644 --- a/pkg/client/templates/v1/templates.go +++ b/pkg/client/templates/v1/templates.go @@ -10,7 +10,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -//go:generate mockgen -destination=./mock_templates.go -package=templates "github.com/kubeshop/testkube-operator/client/templates/v1" Interface +//go:generate mockgen -destination=./mock_templates.go -package=templates "github.com/kubeshop/testkube-operator/pkg/client/templates/v1" Interface type Interface interface { List(selector string) (*templatev1.TemplateList, error) Get(name string) (*templatev1.Template, error) diff --git a/pkg/client/testexecutions/v1/mock_testexecutions.go b/pkg/client/testexecutions/v1/mock_testexecutions.go index addeba34..2553047e 100644 --- a/pkg/client/testexecutions/v1/mock_testexecutions.go +++ b/pkg/client/testexecutions/v1/mock_testexecutions.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/kubeshop/testkube-operator/client/testexecutions/v1 (interfaces: Interface) +// Source: github.com/kubeshop/testkube-operator/pkg/client/testexecutions/v1 (interfaces: Interface) // Package testexecutions is a generated GoMock package. package testexecutions diff --git a/pkg/client/testexecutions/v1/testexecutions.go b/pkg/client/testexecutions/v1/testexecutions.go index 162a368d..677b71b7 100644 --- a/pkg/client/testexecutions/v1/testexecutions.go +++ b/pkg/client/testexecutions/v1/testexecutions.go @@ -8,7 +8,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -//go:generate mockgen -destination=./mock_testexecutions.go -package=testexecutions "github.com/kubeshop/testkube-operator/client/testexecutions/v1" Interface +//go:generate mockgen -destination=./mock_testexecutions.go -package=testexecutions "github.com/kubeshop/testkube-operator/pkg/client/testexecutions/v1" Interface type Interface interface { Get(name string) (*testexecutionv1.TestExecution, error) Create(testExecution *testexecutionv1.TestExecution) (*testexecutionv1.TestExecution, error) diff --git a/pkg/client/tests/v2/tests_test.go b/pkg/client/tests/v2/tests_test.go index 390253c3..56c61f95 100644 --- a/pkg/client/tests/v2/tests_test.go +++ b/pkg/client/tests/v2/tests_test.go @@ -10,7 +10,7 @@ import ( commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" testsv2 "github.com/kubeshop/testkube-operator/api/tests/v2" - kubeclient "github.com/kubeshop/testkube-operator/client" + kubeclient "github.com/kubeshop/testkube-operator/pkg/client" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/client/tests/v3/mock_tests.go b/pkg/client/tests/v3/mock_tests.go index e1285df8..63649783 100644 --- a/pkg/client/tests/v3/mock_tests.go +++ b/pkg/client/tests/v3/mock_tests.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/kubeshop/testkube-operator/client/tests/v3 (interfaces: Interface) +// Source: ./test.go // Package tests is a generated GoMock package. package tests @@ -36,10 +36,10 @@ func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder { } // Create mocks base method. -func (m *MockInterface) Create(arg0 *v3.Test, arg1 ...Option) (*v3.Test, error) { +func (m *MockInterface) Create(test *v3.Test, options ...Option) (*v3.Test, error) { m.ctrl.T.Helper() - varargs := []interface{}{arg0} - for _, a := range arg1 { + varargs := []interface{}{test} + for _, a := range options { varargs = append(varargs, a) } ret := m.ctrl.Call(m, "Create", varargs...) @@ -49,38 +49,38 @@ func (m *MockInterface) Create(arg0 *v3.Test, arg1 ...Option) (*v3.Test, error) } // Create indicates an expected call of Create. -func (mr *MockInterfaceMockRecorder) Create(arg0 interface{}, arg1 ...interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) Create(test interface{}, options ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{arg0}, arg1...) + varargs := append([]interface{}{test}, options...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockInterface)(nil).Create), varargs...) } // CreateTestSecrets mocks base method. -func (m *MockInterface) CreateTestSecrets(arg0 *v3.Test) error { +func (m *MockInterface) CreateTestSecrets(test *v3.Test) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateTestSecrets", arg0) + ret := m.ctrl.Call(m, "CreateTestSecrets", test) ret0, _ := ret[0].(error) return ret0 } // CreateTestSecrets indicates an expected call of CreateTestSecrets. -func (mr *MockInterfaceMockRecorder) CreateTestSecrets(arg0 interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) CreateTestSecrets(test interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateTestSecrets", reflect.TypeOf((*MockInterface)(nil).CreateTestSecrets), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateTestSecrets", reflect.TypeOf((*MockInterface)(nil).CreateTestSecrets), test) } // Delete mocks base method. -func (m *MockInterface) Delete(arg0 string) error { +func (m *MockInterface) Delete(name string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Delete", arg0) + ret := m.ctrl.Call(m, "Delete", name) ret0, _ := ret[0].(error) return ret0 } // Delete indicates an expected call of Delete. -func (mr *MockInterfaceMockRecorder) Delete(arg0 interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) Delete(name interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockInterface)(nil).Delete), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockInterface)(nil).Delete), name) } // DeleteAll mocks base method. @@ -98,92 +98,92 @@ func (mr *MockInterfaceMockRecorder) DeleteAll() *gomock.Call { } // DeleteByLabels mocks base method. -func (m *MockInterface) DeleteByLabels(arg0 string) error { +func (m *MockInterface) DeleteByLabels(selector string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteByLabels", arg0) + ret := m.ctrl.Call(m, "DeleteByLabels", selector) ret0, _ := ret[0].(error) return ret0 } // DeleteByLabels indicates an expected call of DeleteByLabels. -func (mr *MockInterfaceMockRecorder) DeleteByLabels(arg0 interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) DeleteByLabels(selector interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteByLabels", reflect.TypeOf((*MockInterface)(nil).DeleteByLabels), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteByLabels", reflect.TypeOf((*MockInterface)(nil).DeleteByLabels), selector) } // Get mocks base method. -func (m *MockInterface) Get(arg0 string) (*v3.Test, error) { +func (m *MockInterface) Get(name string) (*v3.Test, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", arg0) + ret := m.ctrl.Call(m, "Get", name) ret0, _ := ret[0].(*v3.Test) ret1, _ := ret[1].(error) return ret0, ret1 } // Get indicates an expected call of Get. -func (mr *MockInterfaceMockRecorder) Get(arg0 interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) Get(name interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockInterface)(nil).Get), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockInterface)(nil).Get), name) } // GetCurrentSecretUUID mocks base method. -func (m *MockInterface) GetCurrentSecretUUID(arg0 string) (string, error) { +func (m *MockInterface) GetCurrentSecretUUID(testName string) (string, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCurrentSecretUUID", arg0) + ret := m.ctrl.Call(m, "GetCurrentSecretUUID", testName) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } // GetCurrentSecretUUID indicates an expected call of GetCurrentSecretUUID. -func (mr *MockInterfaceMockRecorder) GetCurrentSecretUUID(arg0 interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) GetCurrentSecretUUID(testName interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentSecretUUID", reflect.TypeOf((*MockInterface)(nil).GetCurrentSecretUUID), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentSecretUUID", reflect.TypeOf((*MockInterface)(nil).GetCurrentSecretUUID), testName) } // GetSecretTestVars mocks base method. -func (m *MockInterface) GetSecretTestVars(arg0, arg1 string) (map[string]string, error) { +func (m *MockInterface) GetSecretTestVars(testName, secretUUID string) (map[string]string, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSecretTestVars", arg0, arg1) + ret := m.ctrl.Call(m, "GetSecretTestVars", testName, secretUUID) ret0, _ := ret[0].(map[string]string) ret1, _ := ret[1].(error) return ret0, ret1 } // GetSecretTestVars indicates an expected call of GetSecretTestVars. -func (mr *MockInterfaceMockRecorder) GetSecretTestVars(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) GetSecretTestVars(testName, secretUUID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSecretTestVars", reflect.TypeOf((*MockInterface)(nil).GetSecretTestVars), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSecretTestVars", reflect.TypeOf((*MockInterface)(nil).GetSecretTestVars), testName, secretUUID) } // List mocks base method. -func (m *MockInterface) List(arg0 string) (*v3.TestList, error) { +func (m *MockInterface) List(selector string) (*v3.TestList, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "List", arg0) + ret := m.ctrl.Call(m, "List", selector) ret0, _ := ret[0].(*v3.TestList) ret1, _ := ret[1].(error) return ret0, ret1 } // List indicates an expected call of List. -func (mr *MockInterfaceMockRecorder) List(arg0 interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) List(selector interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockInterface)(nil).List), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockInterface)(nil).List), selector) } // ListByNames mocks base method. -func (m *MockInterface) ListByNames(arg0 []string) ([]v3.Test, error) { +func (m *MockInterface) ListByNames(names []string) ([]v3.Test, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ListByNames", arg0) + ret := m.ctrl.Call(m, "ListByNames", names) ret0, _ := ret[0].([]v3.Test) ret1, _ := ret[1].(error) return ret0, ret1 } // ListByNames indicates an expected call of ListByNames. -func (mr *MockInterfaceMockRecorder) ListByNames(arg0 interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) ListByNames(names interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListByNames", reflect.TypeOf((*MockInterface)(nil).ListByNames), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListByNames", reflect.TypeOf((*MockInterface)(nil).ListByNames), names) } // ListLabels mocks base method. @@ -202,25 +202,25 @@ func (mr *MockInterfaceMockRecorder) ListLabels() *gomock.Call { } // LoadTestVariablesSecret mocks base method. -func (m *MockInterface) LoadTestVariablesSecret(arg0 *v3.Test) (*v1.Secret, error) { +func (m *MockInterface) LoadTestVariablesSecret(test *v3.Test) (*v1.Secret, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LoadTestVariablesSecret", arg0) + ret := m.ctrl.Call(m, "LoadTestVariablesSecret", test) ret0, _ := ret[0].(*v1.Secret) ret1, _ := ret[1].(error) return ret0, ret1 } // LoadTestVariablesSecret indicates an expected call of LoadTestVariablesSecret. -func (mr *MockInterfaceMockRecorder) LoadTestVariablesSecret(arg0 interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) LoadTestVariablesSecret(test interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadTestVariablesSecret", reflect.TypeOf((*MockInterface)(nil).LoadTestVariablesSecret), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadTestVariablesSecret", reflect.TypeOf((*MockInterface)(nil).LoadTestVariablesSecret), test) } // Update mocks base method. -func (m *MockInterface) Update(arg0 *v3.Test, arg1 ...Option) (*v3.Test, error) { +func (m *MockInterface) Update(test *v3.Test, options ...Option) (*v3.Test, error) { m.ctrl.T.Helper() - varargs := []interface{}{arg0} - for _, a := range arg1 { + varargs := []interface{}{test} + for _, a := range options { varargs = append(varargs, a) } ret := m.ctrl.Call(m, "Update", varargs...) @@ -230,9 +230,9 @@ func (m *MockInterface) Update(arg0 *v3.Test, arg1 ...Option) (*v3.Test, error) } // Update indicates an expected call of Update. -func (mr *MockInterfaceMockRecorder) Update(arg0 interface{}, arg1 ...interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) Update(test interface{}, options ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{arg0}, arg1...) + varargs := append([]interface{}{test}, options...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockInterface)(nil).Update), varargs...) } @@ -251,15 +251,15 @@ func (mr *MockInterfaceMockRecorder) UpdateStatus(test interface{}) *gomock.Call } // UpdateTestSecrets mocks base method. -func (m *MockInterface) UpdateTestSecrets(arg0 *v3.Test) error { +func (m *MockInterface) UpdateTestSecrets(test *v3.Test) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateTestSecrets", arg0) + ret := m.ctrl.Call(m, "UpdateTestSecrets", test) ret0, _ := ret[0].(error) return ret0 } // UpdateTestSecrets indicates an expected call of UpdateTestSecrets. -func (mr *MockInterfaceMockRecorder) UpdateTestSecrets(arg0 interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) UpdateTestSecrets(test interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTestSecrets", reflect.TypeOf((*MockInterface)(nil).UpdateTestSecrets), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTestSecrets", reflect.TypeOf((*MockInterface)(nil).UpdateTestSecrets), test) } diff --git a/pkg/client/tests/v3/test.go b/pkg/client/tests/v3/test.go index 53d8e2cb..f6fc2ac2 100644 --- a/pkg/client/tests/v3/test.go +++ b/pkg/client/tests/v3/test.go @@ -34,7 +34,7 @@ var testSecretDefaultLabels = map[string]string{ "testkubeSecretType": "variables", } -//go:generate mockgen -destination=./mock_tests.go -package=tests "github.com/kubeshop/testkube-operator/client/tests/v3" Interface +//go:generate mockgen -source=./test.go -destination=./mock_tests.go -package=tests "github.com/kubeshop/testkube-operator/pkg/client/tests/v3" Interface type Interface interface { List(selector string) (*testsv3.TestList, error) ListLabels() (map[string][]string, error) diff --git a/pkg/client/testsources/v1/mock_testsources.go b/pkg/client/testsources/v1/mock_testsources.go index 1f8e9eaa..703eb8cc 100644 --- a/pkg/client/testsources/v1/mock_testsources.go +++ b/pkg/client/testsources/v1/mock_testsources.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/kubeshop/testkube-operator/client/testsources/v1 (interfaces: Interface) +// Source: ./testsources.go // Package testsources is a generated GoMock package. package testsources @@ -35,10 +35,10 @@ func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder { } // Create mocks base method. -func (m *MockInterface) Create(arg0 *v1.TestSource, arg1 ...Option) (*v1.TestSource, error) { +func (m *MockInterface) Create(testSource *v1.TestSource, options ...Option) (*v1.TestSource, error) { m.ctrl.T.Helper() - varargs := []interface{}{arg0} - for _, a := range arg1 { + varargs := []interface{}{testSource} + for _, a := range options { varargs = append(varargs, a) } ret := m.ctrl.Call(m, "Create", varargs...) @@ -48,75 +48,75 @@ func (m *MockInterface) Create(arg0 *v1.TestSource, arg1 ...Option) (*v1.TestSou } // Create indicates an expected call of Create. -func (mr *MockInterfaceMockRecorder) Create(arg0 interface{}, arg1 ...interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) Create(testSource interface{}, options ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{arg0}, arg1...) + varargs := append([]interface{}{testSource}, options...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockInterface)(nil).Create), varargs...) } // Delete mocks base method. -func (m *MockInterface) Delete(arg0 string) error { +func (m *MockInterface) Delete(name string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Delete", arg0) + ret := m.ctrl.Call(m, "Delete", name) ret0, _ := ret[0].(error) return ret0 } // Delete indicates an expected call of Delete. -func (mr *MockInterfaceMockRecorder) Delete(arg0 interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) Delete(name interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockInterface)(nil).Delete), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockInterface)(nil).Delete), name) } // DeleteByLabels mocks base method. -func (m *MockInterface) DeleteByLabels(arg0 string) error { +func (m *MockInterface) DeleteByLabels(selector string) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteByLabels", arg0) + ret := m.ctrl.Call(m, "DeleteByLabels", selector) ret0, _ := ret[0].(error) return ret0 } // DeleteByLabels indicates an expected call of DeleteByLabels. -func (mr *MockInterfaceMockRecorder) DeleteByLabels(arg0 interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) DeleteByLabels(selector interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteByLabels", reflect.TypeOf((*MockInterface)(nil).DeleteByLabels), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteByLabels", reflect.TypeOf((*MockInterface)(nil).DeleteByLabels), selector) } // Get mocks base method. -func (m *MockInterface) Get(arg0 string) (*v1.TestSource, error) { +func (m *MockInterface) Get(name string) (*v1.TestSource, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", arg0) + ret := m.ctrl.Call(m, "Get", name) ret0, _ := ret[0].(*v1.TestSource) ret1, _ := ret[1].(error) return ret0, ret1 } // Get indicates an expected call of Get. -func (mr *MockInterfaceMockRecorder) Get(arg0 interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) Get(name interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockInterface)(nil).Get), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockInterface)(nil).Get), name) } // List mocks base method. -func (m *MockInterface) List(arg0 string) (*v1.TestSourceList, error) { +func (m *MockInterface) List(selector string) (*v1.TestSourceList, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "List", arg0) + ret := m.ctrl.Call(m, "List", selector) ret0, _ := ret[0].(*v1.TestSourceList) ret1, _ := ret[1].(error) return ret0, ret1 } // List indicates an expected call of List. -func (mr *MockInterfaceMockRecorder) List(arg0 interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) List(selector interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockInterface)(nil).List), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockInterface)(nil).List), selector) } // Update mocks base method. -func (m *MockInterface) Update(arg0 *v1.TestSource, arg1 ...Option) (*v1.TestSource, error) { +func (m *MockInterface) Update(testSource *v1.TestSource, options ...Option) (*v1.TestSource, error) { m.ctrl.T.Helper() - varargs := []interface{}{arg0} - for _, a := range arg1 { + varargs := []interface{}{testSource} + for _, a := range options { varargs = append(varargs, a) } ret := m.ctrl.Call(m, "Update", varargs...) @@ -126,8 +126,8 @@ func (m *MockInterface) Update(arg0 *v1.TestSource, arg1 ...Option) (*v1.TestSou } // Update indicates an expected call of Update. -func (mr *MockInterfaceMockRecorder) Update(arg0 interface{}, arg1 ...interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) Update(testSource interface{}, options ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{arg0}, arg1...) + varargs := append([]interface{}{testSource}, options...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockInterface)(nil).Update), varargs...) } diff --git a/pkg/client/testsources/v1/testsources.go b/pkg/client/testsources/v1/testsources.go index 883ddbf2..078cd12f 100644 --- a/pkg/client/testsources/v1/testsources.go +++ b/pkg/client/testsources/v1/testsources.go @@ -21,7 +21,7 @@ const ( gitTokenSecretName = "git-token" ) -//go:generate mockgen -destination=./mock_testsources.go -package=testsources "github.com/kubeshop/testkube-operator/client/testsources/v1" Interface +//go:generate mockgen -source=./testsources.go -destination=./mock_testsources.go -package=testsources "github.com/kubeshop/testkube-operator/pkg/client/testsources/v1" Interface type Interface interface { List(selector string) (*testsourcev1.TestSourceList, error) Get(name string) (*testsourcev1.TestSource, error) diff --git a/pkg/client/testsuiteexecutions/v1/mock_testsuiteexecutions.go b/pkg/client/testsuiteexecutions/v1/mock_testsuiteexecutions.go index 728f8446..3a495bed 100644 --- a/pkg/client/testsuiteexecutions/v1/mock_testsuiteexecutions.go +++ b/pkg/client/testsuiteexecutions/v1/mock_testsuiteexecutions.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/kubeshop/testkube-operator/client/testsuiteexecutions/v1 (interfaces: Interface) +// Source: github.com/kubeshop/testkube-operator/pkg/client/testsuiteexecutions/v1 (interfaces: Interface) // Package testsuiteexecutions is a generated GoMock package. package testsuiteexecutions diff --git a/pkg/client/testsuiteexecutions/v1/testsuiteexecutions.go b/pkg/client/testsuiteexecutions/v1/testsuiteexecutions.go index d39196dd..73725e1c 100644 --- a/pkg/client/testsuiteexecutions/v1/testsuiteexecutions.go +++ b/pkg/client/testsuiteexecutions/v1/testsuiteexecutions.go @@ -9,7 +9,7 @@ import ( testsuiteexecutionv1 "github.com/kubeshop/testkube-operator/api/testsuiteexecution/v1" ) -//go:generate mockgen -destination=./mock_testsuiteexecutions.go -package=testsuiteexecutions "github.com/kubeshop/testkube-operator/client/testsuiteexecutions/v1" Interface +//go:generate mockgen -destination=./mock_testsuiteexecutions.go -package=testsuiteexecutions "github.com/kubeshop/testkube-operator/pkg/client/testsuiteexecutions/v1" Interface type Interface interface { Get(name string) (*testsuiteexecutionv1.TestSuiteExecution, error) Create(testSuiteExecution *testsuiteexecutionv1.TestSuiteExecution) (*testsuiteexecutionv1.TestSuiteExecution, error) diff --git a/pkg/client/testsuites/v1/testsuites_test.go b/pkg/client/testsuites/v1/testsuites_test.go index 6a89b097..1335bb35 100644 --- a/pkg/client/testsuites/v1/testsuites_test.go +++ b/pkg/client/testsuites/v1/testsuites_test.go @@ -9,7 +9,7 @@ import ( commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" testsuitev1 "github.com/kubeshop/testkube-operator/api/testsuite/v1" - kubeclient "github.com/kubeshop/testkube-operator/client" + kubeclient "github.com/kubeshop/testkube-operator/pkg/client" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/client/testsuites/v2/mock_testsuites.go b/pkg/client/testsuites/v2/mock_testsuites.go index e7fd0346..1ae85946 100644 --- a/pkg/client/testsuites/v2/mock_testsuites.go +++ b/pkg/client/testsuites/v2/mock_testsuites.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/kubeshop/testkube-operator/client/testsuites/v2 (interfaces: Interface) +// Source: github.com/kubeshop/testkube-operator/pkg/client/testsuites/v2 (interfaces: Interface) // Package v2 is a generated GoMock package. package v2 @@ -212,17 +212,17 @@ func (mr *MockInterfaceMockRecorder) Update(arg0 interface{}) *gomock.Call { } // UpdateStatus mocks base method. -func (m *MockInterface) UpdateStatus(testSuite *v2.TestSuite) error { +func (m *MockInterface) UpdateStatus(arg0 *v2.TestSuite) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateStatus", testSuite) + ret := m.ctrl.Call(m, "UpdateStatus", arg0) ret0, _ := ret[0].(error) return ret0 } // UpdateStatus indicates an expected call of UpdateStatus. -func (mr *MockInterfaceMockRecorder) UpdateStatus(testSuite interface{}) *gomock.Call { +func (mr *MockInterfaceMockRecorder) UpdateStatus(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateStatus", reflect.TypeOf((*MockInterface)(nil).UpdateStatus), testSuite) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateStatus", reflect.TypeOf((*MockInterface)(nil).UpdateStatus), arg0) } // UpdateTestsuiteSecrets mocks base method. diff --git a/pkg/client/testsuites/v2/testsuites.go b/pkg/client/testsuites/v2/testsuites.go index 33e80ddb..849cbd6d 100644 --- a/pkg/client/testsuites/v2/testsuites.go +++ b/pkg/client/testsuites/v2/testsuites.go @@ -27,7 +27,7 @@ var testsuiteSecretDefaultLabels = map[string]string{ "testkubeSecretType": "variables", } -//go:generate mockgen -destination=./mock_testsuites.go -package=v2 "github.com/kubeshop/testkube-operator/client/testsuites/v2" Interface +//go:generate mockgen -destination=./mock_testsuites.go -package=v2 "github.com/kubeshop/testkube-operator/pkg/client/testsuites/v2" Interface type Interface interface { List(selector string) (*testsuitev2.TestSuiteList, error) ListLabels() (map[string][]string, error) diff --git a/pkg/client/testsuites/v2/testsuites_test.go b/pkg/client/testsuites/v2/testsuites_test.go index b1e2be02..d89ce3cd 100644 --- a/pkg/client/testsuites/v2/testsuites_test.go +++ b/pkg/client/testsuites/v2/testsuites_test.go @@ -9,7 +9,7 @@ import ( commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" testsuitev2 "github.com/kubeshop/testkube-operator/api/testsuite/v2" - kubeclient "github.com/kubeshop/testkube-operator/client" + kubeclient "github.com/kubeshop/testkube-operator/pkg/client" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/client/testsuites/v3/mock_testsuites.go b/pkg/client/testsuites/v3/mock_testsuites.go index acd0fce3..fcc0d73f 100644 --- a/pkg/client/testsuites/v3/mock_testsuites.go +++ b/pkg/client/testsuites/v3/mock_testsuites.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/kubeshop/testkube-operator/client/testsuites/v3 (interfaces: Interface) +// Source: github.com/kubeshop/testkube-operator/pkg/client/testsuites/v3 (interfaces: Interface) // Package v3 is a generated GoMock package. package v3 diff --git a/pkg/client/testsuites/v3/testsuites.go b/pkg/client/testsuites/v3/testsuites.go index 050fb977..edac46a7 100644 --- a/pkg/client/testsuites/v3/testsuites.go +++ b/pkg/client/testsuites/v3/testsuites.go @@ -27,7 +27,7 @@ var testsuiteSecretDefaultLabels = map[string]string{ "testkubeSecretType": "variables", } -//go:generate mockgen -destination=./mock_testsuites.go -package=v3 "github.com/kubeshop/testkube-operator/client/testsuites/v3" Interface +//go:generate mockgen -destination=./mock_testsuites.go -package=v3 "github.com/kubeshop/testkube-operator/pkg/client/testsuites/v3" Interface type Interface interface { List(selector string) (*testsuitev3.TestSuiteList, error) ListLabels() (map[string][]string, error) diff --git a/pkg/client/testsuites/v3/testsuites_test.go b/pkg/client/testsuites/v3/testsuites_test.go index 7ca06ab4..3de59b13 100644 --- a/pkg/client/testsuites/v3/testsuites_test.go +++ b/pkg/client/testsuites/v3/testsuites_test.go @@ -9,7 +9,7 @@ import ( commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" - kubeclient "github.com/kubeshop/testkube-operator/client" + kubeclient "github.com/kubeshop/testkube-operator/pkg/client" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) From 457bf713e6c86b0444bec39c81df8bb377cc5323 Mon Sep 17 00:00:00 2001 From: Dejan Zele Pejchev Date: Wed, 27 Sep 2023 11:00:00 +0200 Subject: [PATCH 42/57] fix: make test fields optional (#181) --- api/tests/v3/test_types.go | 4 ++-- config/crd/bases/tests.testkube.io_tests.yaml | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/api/tests/v3/test_types.go b/api/tests/v3/test_types.go index babcbff4..5f5d9e01 100644 --- a/api/tests/v3/test_types.go +++ b/api/tests/v3/test_types.go @@ -121,9 +121,9 @@ const ( // artifact request body with test artifacts type ArtifactRequest struct { // artifact storage class name for container executor - StorageClassName string `json:"storageClassName"` + StorageClassName string `json:"storageClassName,omitempty"` // artifact volume mount path for container executor - VolumeMountPath string `json:"volumeMountPath"` + VolumeMountPath string `json:"volumeMountPath,omitempty"` // artifact directories for scraping Dirs []string `json:"dirs,omitempty"` // artifact bucket storage diff --git a/config/crd/bases/tests.testkube.io_tests.yaml b/config/crd/bases/tests.testkube.io_tests.yaml index 9f61d60f..82252b0b 100644 --- a/config/crd/bases/tests.testkube.io_tests.yaml +++ b/config/crd/bases/tests.testkube.io_tests.yaml @@ -474,9 +474,6 @@ spec: volumeMountPath: description: artifact volume mount path for container executor type: string - required: - - storageClassName - - volumeMountPath type: object command: description: executor binary command From aa5afde3a8f8f8ef00526fba2a8041f571f9e11d Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 5 Oct 2023 15:42:34 +0300 Subject: [PATCH 43/57] feat: execute post run script before scraping field (#183) * feat: execute post run script before scraping field * fix: pragma --- api/testexecution/v1/testexecution_types.go | 8 ++++++-- api/tests/v3/test_types.go | 2 ++ api/testsuite/v3/zz_generated.deepcopy.go | 6 ++++-- api/testsuiteexecution/v1/testsuiteexecution_types.go | 6 ++++-- api/testtriggers/v1/zz_generated.deepcopy.go | 2 +- config/crd/bases/tests.testkube.io_testexecutions.yaml | 8 ++++++++ config/crd/bases/tests.testkube.io_tests.yaml | 4 ++++ .../crd/bases/tests.testkube.io_testsuiteexecutions.yaml | 8 ++++++++ 8 files changed, 37 insertions(+), 7 deletions(-) diff --git a/api/testexecution/v1/testexecution_types.go b/api/testexecution/v1/testexecution_types.go index 9a5755c5..cc16b6ca 100644 --- a/api/testexecution/v1/testexecution_types.go +++ b/api/testexecution/v1/testexecution_types.go @@ -122,6 +122,8 @@ type ExecutionRequest struct { PreRunScript string `json:"preRunScript,omitempty"` // script to run after test execution PostRunScript string `json:"postRunScript,omitempty"` + // execute post run script before scraping (prebuilt executor only) + ExecutePostRunScriptBeforeScraping bool `json:"executePostRunScriptBeforeScraping,omitempty"` // scraper template extensions ScraperTemplate string `json:"scraperTemplate,omitempty"` // config map references @@ -223,8 +225,10 @@ type Execution struct { // script to run before test execution PreRunScript string `json:"preRunScript,omitempty"` // script to run after test execution - PostRunScript string `json:"postRunScript,omitempty"` - RunningContext *RunningContext `json:"runningContext,omitempty"` + PostRunScript string `json:"postRunScript,omitempty"` + // execute post run script before scraping (prebuilt executor only) + ExecutePostRunScriptBeforeScraping bool `json:"executePostRunScriptBeforeScraping,omitempty"` + RunningContext *RunningContext `json:"runningContext,omitempty"` // shell used in container executor ContainerShell string `json:"containerShell,omitempty"` } diff --git a/api/tests/v3/test_types.go b/api/tests/v3/test_types.go index 5f5d9e01..632debfc 100644 --- a/api/tests/v3/test_types.go +++ b/api/tests/v3/test_types.go @@ -212,6 +212,8 @@ type ExecutionRequest struct { PreRunScript string `json:"preRunScript,omitempty"` // script to run after test execution PostRunScript string `json:"postRunScript,omitempty"` + // execute post run script before scraping (prebuilt executor only) + ExecutePostRunScriptBeforeScraping bool `json:"executePostRunScriptBeforeScraping,omitempty"` // scraper template extensions ScraperTemplate string `json:"scraperTemplate,omitempty"` // name of the template resource diff --git a/api/testsuite/v3/zz_generated.deepcopy.go b/api/testsuite/v3/zz_generated.deepcopy.go index da7595fc..464f2e08 100644 --- a/api/testsuite/v3/zz_generated.deepcopy.go +++ b/api/testsuite/v3/zz_generated.deepcopy.go @@ -73,7 +73,9 @@ func (in *TestSuiteBatchStep) DeepCopyInto(out *TestSuiteBatchStep) { if in.Execute != nil { in, out := &in.Execute, &out.Execute *out = make([]TestSuiteStepSpec, len(*in)) - copy(*out, *in) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } } @@ -246,7 +248,7 @@ func (in *TestSuiteStatus) DeepCopy() *TestSuiteStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TestSuiteStepSpec) DeepCopyInto(out *TestSuiteStepSpec) { *out = *in - out.Delay = in.Delay + in.Delay.DeepCopyInto(&out.Delay) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteStepSpec. diff --git a/api/testsuiteexecution/v1/testsuiteexecution_types.go b/api/testsuiteexecution/v1/testsuiteexecution_types.go index e0d689a2..72dcf148 100644 --- a/api/testsuiteexecution/v1/testsuiteexecution_types.go +++ b/api/testsuiteexecution/v1/testsuiteexecution_types.go @@ -248,8 +248,10 @@ type Execution struct { // script to run before test execution PreRunScript string `json:"preRunScript,omitempty"` // script to run after test execution - PostRunScript string `json:"postRunScript,omitempty"` - RunningContext *RunningContext `json:"runningContext,omitempty"` + PostRunScript string `json:"postRunScript,omitempty"` + // execute post run script before scraping (prebuilt executor only) + ExecutePostRunScriptBeforeScraping bool `json:"executePostRunScriptBeforeScraping,omitempty"` + RunningContext *RunningContext `json:"runningContext,omitempty"` // shell used in container executor ContainerShell string `json:"containerShell,omitempty"` // test execution name started the test execution diff --git a/api/testtriggers/v1/zz_generated.deepcopy.go b/api/testtriggers/v1/zz_generated.deepcopy.go index de6b839b..ac2c588b 100644 --- a/api/testtriggers/v1/zz_generated.deepcopy.go +++ b/api/testtriggers/v1/zz_generated.deepcopy.go @@ -209,7 +209,7 @@ func (in *TestTriggerSpec) DeepCopyInto(out *TestTriggerSpec) { if in.Delay != nil { in, out := &in.Delay, &out.Delay *out = new(metav1.Duration) - **out = **in + (*in).DeepCopyInto(*out) } } diff --git a/config/crd/bases/tests.testkube.io_testexecutions.yaml b/config/crd/bases/tests.testkube.io_testexecutions.yaml index 8c87d9ed..80082323 100644 --- a/config/crd/bases/tests.testkube.io_testexecutions.yaml +++ b/config/crd/bases/tests.testkube.io_testexecutions.yaml @@ -150,6 +150,10 @@ spec: description: 'Environment variables passed to executor. Deprecated: use Basic Variables instead' type: object + executePostRunScriptBeforeScraping: + description: execute post run script before scraping (prebuilt + executor only) + type: boolean executionLabels: additionalProperties: type: string @@ -523,6 +527,10 @@ spec: description: 'Environment variables passed to executor. Deprecated: use Basic Variables instead' type: object + executePostRunScriptBeforeScraping: + description: execute post run script before scraping (prebuilt + executor only) + type: boolean executionResult: description: execution result returned from executor properties: diff --git a/config/crd/bases/tests.testkube.io_tests.yaml b/config/crd/bases/tests.testkube.io_tests.yaml index 82252b0b..62a47d6d 100644 --- a/config/crd/bases/tests.testkube.io_tests.yaml +++ b/config/crd/bases/tests.testkube.io_tests.yaml @@ -548,6 +548,10 @@ spec: description: 'Environment variables passed to executor. Deprecated: use Basic Variables instead' type: object + executePostRunScriptBeforeScraping: + description: execute post run script before scraping (prebuilt + executor only) + type: boolean executionLabels: additionalProperties: type: string diff --git a/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml b/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml index d346777b..1017e0f2 100644 --- a/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml +++ b/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml @@ -442,6 +442,10 @@ spec: description: 'Environment variables passed to executor. Deprecated: use Basic Variables instead' type: object + executePostRunScriptBeforeScraping: + description: execute post run script before scraping + (prebuilt executor only) + type: boolean executionResult: description: execution result returned from executor properties: @@ -945,6 +949,10 @@ spec: description: 'Environment variables passed to executor. Deprecated: use Basic Variables instead' type: object + executePostRunScriptBeforeScraping: + description: execute post run script before scraping + (prebuilt executor only) + type: boolean executionResult: description: execution result returned from executor properties: From 3ec11798a62fb90fddf6f6bbc79a15b80d23d58a Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Fri, 20 Oct 2023 15:27:30 +0300 Subject: [PATCH 44/57] feat: regex field (#186) * feat: regex field * fix: validate regex --- api/testtriggers/v1/testtrigger_types.go | 2 ++ config/crd/bases/tests.testkube.io_testtriggers.yaml | 6 ++++++ .../controller/testtriggers/testtrigger_validator.go | 9 +++++---- .../testtriggers/testtrigger_validator_test.go | 4 ++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/api/testtriggers/v1/testtrigger_types.go b/api/testtriggers/v1/testtrigger_types.go index cf998f71..8d48d9db 100644 --- a/api/testtriggers/v1/testtrigger_types.go +++ b/api/testtriggers/v1/testtrigger_types.go @@ -130,6 +130,8 @@ const ( type TestTriggerSelector struct { // Name selector is used to identify a Kubernetes Object based on the metadata name Name string `json:"name,omitempty"` + // kubernetes resource name regex + NameRegex string `json:"nameRegex,omitempty"` // Namespace of the Kubernetes object Namespace string `json:"namespace,omitempty"` // LabelSelector is used to identify a group of Kubernetes Objects based on their metadata labels diff --git a/config/crd/bases/tests.testkube.io_testtriggers.yaml b/config/crd/bases/tests.testkube.io_testtriggers.yaml index 7334b0a6..4f89b3ff 100644 --- a/config/crd/bases/tests.testkube.io_testtriggers.yaml +++ b/config/crd/bases/tests.testkube.io_testtriggers.yaml @@ -238,6 +238,9 @@ spec: description: Name selector is used to identify a Kubernetes Object based on the metadata name type: string + nameRegex: + description: kubernetes resource name regex + type: string namespace: description: Namespace of the Kubernetes object type: string @@ -295,6 +298,9 @@ spec: description: Name selector is used to identify a Kubernetes Object based on the metadata name type: string + nameRegex: + description: kubernetes resource name regex + type: string namespace: description: Namespace of the Kubernetes object type: string diff --git a/internal/controller/testtriggers/testtrigger_validator.go b/internal/controller/testtriggers/testtrigger_validator.go index 81d23cad..a7197107 100644 --- a/internal/controller/testtriggers/testtrigger_validator.go +++ b/internal/controller/testtriggers/testtrigger_validator.go @@ -169,13 +169,14 @@ func (v *Validator) validateSelector(fld *field.Path, selector testtriggerv1.Tes isLabelSelectorEmpty = isEmpty } - if selector.Name != "" && selector.LabelSelector != nil { - verr := field.Duplicate(fld, "either name or label selector can be used") + if (selector.Name != "" && selector.LabelSelector != nil) || (selector.NameRegex != "" && selector.LabelSelector != nil) || + (selector.Name != "" && selector.NameRegex != "") { + verr := field.Duplicate(fld, "either name, name regex or label selector can be used") allErrs = append(allErrs, verr) } - if selector.Name == "" && isLabelSelectorEmpty { - verr := field.Invalid(fld, selector, "neither name nor label selector is specified") + if selector.Name == "" && selector.NameRegex == "" && isLabelSelectorEmpty { + verr := field.Invalid(fld, selector, "neither name, name regex nor label selector is specified") allErrs = append(allErrs, verr) } diff --git a/internal/controller/testtriggers/testtrigger_validator_test.go b/internal/controller/testtriggers/testtrigger_validator_test.go index efe228b5..420a5874 100644 --- a/internal/controller/testtriggers/testtrigger_validator_test.go +++ b/internal/controller/testtriggers/testtrigger_validator_test.go @@ -142,14 +142,14 @@ func TestValidator_validateSelector(t *testing.T) { assert.Empty(t, verrs) }) - t.Run("error when neither name nor label selector are specified", func(t *testing.T) { + t.Run("error when neither name, name regex nor label selector are specified", func(t *testing.T) { t.Parallel() fld := field.NewPath("spec").Child("testSelector") selector := testtriggerv1.TestTriggerSelector{LabelSelector: &metav1.LabelSelector{}} verrs := v.validateSelector(fld, selector) assert.Len(t, verrs, 1) - assert.ErrorContains(t, verrs[0], "neither name nor label selector is specified") + assert.ErrorContains(t, verrs[0], "neither name, name regex nor label selector is specified") }) t.Run("error when invalid labels are specified", func(t *testing.T) { From 62a79514fcf5efae3364d87d395c8ab7d330d1df Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Fri, 20 Oct 2023 18:40:56 +0300 Subject: [PATCH 45/57] fix: visibility for secrets (#187) --- pkg/client/tests/v3/test.go | 1 + pkg/client/testsuites/v3/testsuites.go | 1 + pkg/secret/client.go | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/client/tests/v3/test.go b/pkg/client/tests/v3/test.go index f6fc2ac2..30dad9a9 100644 --- a/pkg/client/tests/v3/test.go +++ b/pkg/client/tests/v3/test.go @@ -32,6 +32,7 @@ const ( var testSecretDefaultLabels = map[string]string{ "testkube": testkubeTestSecretLabel, "testkubeSecretType": "variables", + "visibility": "testkube", } //go:generate mockgen -source=./test.go -destination=./mock_tests.go -package=tests "github.com/kubeshop/testkube-operator/pkg/client/tests/v3" Interface diff --git a/pkg/client/testsuites/v3/testsuites.go b/pkg/client/testsuites/v3/testsuites.go index edac46a7..54a3bec4 100644 --- a/pkg/client/testsuites/v3/testsuites.go +++ b/pkg/client/testsuites/v3/testsuites.go @@ -25,6 +25,7 @@ const ( var testsuiteSecretDefaultLabels = map[string]string{ "testkube": testkubeTestsuiteSecretLabel, "testkubeSecretType": "variables", + "visibility": "testkube", } //go:generate mockgen -destination=./mock_testsuites.go -package=v3 "github.com/kubeshop/testkube-operator/pkg/client/testsuites/v3" Interface diff --git a/pkg/secret/client.go b/pkg/secret/client.go index aa0bb802..9e52a829 100644 --- a/pkg/secret/client.go +++ b/pkg/secret/client.go @@ -138,7 +138,7 @@ func NewSpec(id, namespace, label string, labels, stringData map[string]string) ObjectMeta: metav1.ObjectMeta{ Name: id, Namespace: namespace, - Labels: map[string]string{"testkube": label}, + Labels: map[string]string{"testkube": label, "visibility": "testkube"}, }, Type: v1.SecretTypeOpaque, StringData: stringData, From 11468a1f04f18834f784c00a1e14452b2ae29ede Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Wed, 25 Oct 2023 20:44:15 +0300 Subject: [PATCH 46/57] fix: back merge (#191) * feat: cron job template field (#132) * feat: cron job template field * fix: dep update * Revert "feat: cron job template field (#132)" (#134) This reverts commit 48422d59cb0873f16a7c0cfca3caa8332b783b17. * add check for release branch (#138) * commented automatic merge of release branch for now * fix release branch naming * fix typo * fix: upload variables file (#135) (#140) * fix path in goreleaser * ci: rename release branch (#141) ci: rename release branch * ci: parametrize alpine (#144) * parametrize alpine image * ci: rename gh token var (#145) * rename gh token var * fix: add missing var for alpine image for arm64 arch * ci: add docker registry description (#146) * ci: add GH action to update readme for Docker registry * ci: add workflow dispatch (#149) * Release/v1.12.0 (#150) * feat: cron job template field (#132) (#133) * feat: cron job template field * fix: dep update * feat: deprecate args (#130) * feat: add args mode * fix: add args mode type * fix: change artifact support * fix: upload variables file (#135) * add tests for develop branch (#136) * add check fir release branch (#137) * comment out the automatic merge of release branch for now * fix release branch naming * fix typo * fix path for goreleaser file * rename release branch (#142) * ci: parametrize alpine (#144) * parametrize alpine image * fix: ttl for trigger condition (#143) * ci: rename gh token var (#145) * rename gh token var * fix: add missing var for alpine image for arm64 arch * fix: remove empty username and token (#147) * ci: add docker registry description (#146) * ci: add GH action to update readme for Docker registry * ci: add workflow dispatch (#149) --------- Co-authored-by: Lilla Vass Co-authored-by: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Co-authored-by: ypoplavs * fix: support external secrets (#151) * fix: secret check (#153) (#154) * fix: secret check * fix: remove wrong condition * ci: remove release branch creation in helm-charts repo (#157) * Release/v1.13.0 (#161) * feat: cron job template field (#132) (#133) * feat: cron job template field * fix: dep update * feat: deprecate args (#130) * feat: add args mode * fix: add args mode type * fix: change artifact support * fix: upload variables file (#135) * add tests for develop branch (#136) * add check fir release branch (#137) * comment out the automatic merge of release branch for now * fix release branch naming * fix typo * fix path for goreleaser file * rename release branch (#142) * ci: parametrize alpine (#144) * parametrize alpine image * fix: ttl for trigger condition (#143) * ci: rename gh token var (#145) * rename gh token var * fix: add missing var for alpine image for arm64 arch * fix: remove empty username and token (#147) * ci: add docker registry description (#146) * ci: add GH action to update readme for Docker registry * ci: add workflow dispatch (#149) * fix: support external secrets for tests (#148) * fix: support external secrets for tests * fix: support external secrets for test suite * fix: rename interface method * fix: test mock * feat: webhook templlate and headers (#152) * feat: webhook templlate and headers * fix: description typo * fix: secret check (#153) * fix: secret check * fix: remove wrong condition * feat: provide known condition types (#155) * feat: provide known condition types * fix: rename util method * feat: parallel testsuite (#109) * feat: test suite v3 * feat: test suite v3 client and watcher * fix: dep update * Update config/crd/bases/tests.testkube.io_tests.yaml Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> * fix: conversion typo * fix: test suite v3 sample * fix: use proper informer version * fix: v3 informer * fix: typo func name * add a separate workflow to test parallel testsuite images * add a separate workflow to test parallel testsuite images * fix: typo test suite version * fix: make steps optional * fix: sync recent changes * fix: solve merge errors * fix: rename fields * fix: tune crd fields * fix: rename vars and methods * fix: refresh mock * fix: rename vars * fix: duration format * fix: change test suite step object * fix: secret var check * fix: modify test suite example v3 * fix: update delay type --------- Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> Co-authored-by: ypoplavs * fix: remove run secrets as well (#139) debug fix: on deletion do not quit if something related to test could not be deleted, put in a single error fix: remove logging and improve errors fix: delete dependency error and delete test first * feat: postrun script (#156) * fix: post run scipt model * fix: add postrun script to crd * ci: remove release branch creation in helm-charts repo (#157) * fix: don't remove non Testkube secrets (#160) --------- Co-authored-by: Lilla Vass Co-authored-by: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Co-authored-by: ypoplavs Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> * fix: image registry (#166) (#167) * feat: Release/v1.14.0 (#168) * feat: cron job template field (#132) (#133) * feat: cron job template field * fix: dep update * feat: deprecate args (#130) * feat: add args mode * fix: add args mode type * fix: change artifact support * fix: upload variables file (#135) * add tests for develop branch (#136) * add check fir release branch (#137) * comment out the automatic merge of release branch for now * fix release branch naming * fix typo * fix path for goreleaser file * rename release branch (#142) * ci: parametrize alpine (#144) * parametrize alpine image * fix: ttl for trigger condition (#143) * ci: rename gh token var (#145) * rename gh token var * fix: add missing var for alpine image for arm64 arch * fix: remove empty username and token (#147) * ci: add docker registry description (#146) * ci: add GH action to update readme for Docker registry * ci: add workflow dispatch (#149) * fix: support external secrets for tests (#148) * fix: support external secrets for tests * fix: support external secrets for test suite * fix: rename interface method * fix: test mock * feat: webhook templlate and headers (#152) * feat: webhook templlate and headers * fix: description typo * fix: secret check (#153) * fix: secret check * fix: remove wrong condition * feat: provide known condition types (#155) * feat: provide known condition types * fix: rename util method * feat: parallel testsuite (#109) * feat: test suite v3 * feat: test suite v3 client and watcher * fix: dep update * Update config/crd/bases/tests.testkube.io_tests.yaml Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> * fix: conversion typo * fix: test suite v3 sample * fix: use proper informer version * fix: v3 informer * fix: typo func name * add a separate workflow to test parallel testsuite images * add a separate workflow to test parallel testsuite images * fix: typo test suite version * fix: make steps optional * fix: sync recent changes * fix: solve merge errors * fix: rename fields * fix: tune crd fields * fix: rename vars and methods * fix: refresh mock * fix: rename vars * fix: duration format * fix: change test suite step object * fix: secret var check * fix: modify test suite example v3 * fix: update delay type --------- Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> Co-authored-by: ypoplavs * fix: remove run secrets as well (#139) debug fix: on deletion do not quit if something related to test could not be deleted, put in a single error fix: remove logging and improve errors fix: delete dependency error and delete test first * feat: postrun script (#156) * fix: post run scipt model * fix: add postrun script to crd * ci: remove release branch creation in helm-charts repo (#157) * feat: probe conditions (#158) * feat: probe spec model * feat: test trigger crd with probes * fix: refactor probe definition * fix: unit tests * fix: don't remove non Testkube secrets (#160) * feat: remove outdated description (#164) * fix: image registry (#166) * feat: basic test execution crd (#165) * feat: basic test execution crd * feat: test execution CRD spec * fix: test execution client * fix: remove output * fix: update status method * fix: update get method * feat: test execution reconciler * fix: url port * fix: test name * fix: ignore status update * feat: test suite execution core * feat: test suite execution crd * feat: add unit tests * fix: test status * fix: remove not used structure * fix: api url typo * fix: running context * fix: generation field * fix: remove unused fields * fix: examples * fix: use go 1.21 (#169) * fix: context typo (#171) --------- Co-authored-by: Lilla Vass Co-authored-by: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Co-authored-by: ypoplavs Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> * feat: Release/v1.15.0 (#184) * feat: cron job template field (#132) (#133) * feat: cron job template field * fix: dep update * feat: deprecate args (#130) * feat: add args mode * fix: add args mode type * fix: change artifact support * fix: upload variables file (#135) * add tests for develop branch (#136) * add check fir release branch (#137) * comment out the automatic merge of release branch for now * fix release branch naming * fix typo * fix path for goreleaser file * rename release branch (#142) * ci: parametrize alpine (#144) * parametrize alpine image * fix: ttl for trigger condition (#143) * ci: rename gh token var (#145) * rename gh token var * fix: add missing var for alpine image for arm64 arch * fix: remove empty username and token (#147) * ci: add docker registry description (#146) * ci: add GH action to update readme for Docker registry * ci: add workflow dispatch (#149) * fix: support external secrets for tests (#148) * fix: support external secrets for tests * fix: support external secrets for test suite * fix: rename interface method * fix: test mock * feat: webhook templlate and headers (#152) * feat: webhook templlate and headers * fix: description typo * fix: secret check (#153) * fix: secret check * fix: remove wrong condition * feat: provide known condition types (#155) * feat: provide known condition types * fix: rename util method * feat: parallel testsuite (#109) * feat: test suite v3 * feat: test suite v3 client and watcher * fix: dep update * Update config/crd/bases/tests.testkube.io_tests.yaml Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> * fix: conversion typo * fix: test suite v3 sample * fix: use proper informer version * fix: v3 informer * fix: typo func name * add a separate workflow to test parallel testsuite images * add a separate workflow to test parallel testsuite images * fix: typo test suite version * fix: make steps optional * fix: sync recent changes * fix: solve merge errors * fix: rename fields * fix: tune crd fields * fix: rename vars and methods * fix: refresh mock * fix: rename vars * fix: duration format * fix: change test suite step object * fix: secret var check * fix: modify test suite example v3 * fix: update delay type --------- Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> Co-authored-by: ypoplavs * fix: remove run secrets as well (#139) debug fix: on deletion do not quit if something related to test could not be deleted, put in a single error fix: remove logging and improve errors fix: delete dependency error and delete test first * feat: postrun script (#156) * fix: post run scipt model * fix: add postrun script to crd * ci: remove release branch creation in helm-charts repo (#157) * feat: probe conditions (#158) * feat: probe spec model * feat: test trigger crd with probes * fix: refactor probe definition * fix: unit tests * fix: don't remove non Testkube secrets (#160) * feat: remove outdated description (#164) * fix: image registry (#166) * feat: basic test execution crd (#165) * feat: basic test execution crd * feat: test execution CRD spec * fix: test execution client * fix: remove output * fix: update status method * fix: update get method * feat: test execution reconciler * fix: url port * fix: test name * fix: ignore status update * feat: test suite execution core * feat: test suite execution crd * feat: add unit tests * fix: test status * fix: remove not used structure * fix: api url typo * fix: running context * fix: generation field * fix: remove unused fields * fix: examples * fix: use go 1.21 (#169) * fix: context typo (#171) * feat: artifact bucket (#170) * feat: artifact bucket * fix: generate * fix: rename field * feat: test field (#172) * feat: test field * fix: tags * feat: template crd (#173) * featL template crd * feat: add delete by labels * feat: use cronjob reference * fix: add warnings * fix: error message * feat: adjust uri descrription (#174) * feat: adjust uri descrription * fix: adjust header description * feat: trigger concurrency policy (#175) * feat: trigger concurrency policy * fix: make policy optional * fix: policy validation * Added slaves field in executor CRD to add slaves configuration (#177) * Added slaves field in executor CRD to add slaves configuration Signed-off-by: hiteshwani * Discard changes Signed-off-by: hiteshwani * Fixed trivial review comments Signed-off-by: Aman Parauliya --------- Signed-off-by: hiteshwani Signed-off-by: Aman Parauliya Co-authored-by: Aman Parauliya * feat: update operator to use latest kubebuilder layout (#178) * update operator to use latest kubebuilder layout * update dependencies * update dependencies * remove some unused fields from CRDs * fix failing test * fix invalid reference (#179) * fix mocks (#180) * fix: make test fields optional (#181) * feat: execute post run script before scraping field (#183) * feat: execute post run script before scraping field * fix: pragma * fix: resolve conflicts with main (#185) * feat: cron job template field (#132) * feat: cron job template field * fix: dep update * Revert "feat: cron job template field (#132)" (#134) This reverts commit 48422d59cb0873f16a7c0cfca3caa8332b783b17. * add check for release branch (#138) * commented automatic merge of release branch for now * fix release branch naming * fix typo * fix: upload variables file (#135) (#140) * fix path in goreleaser * ci: rename release branch (#141) ci: rename release branch * ci: parametrize alpine (#144) * parametrize alpine image * ci: rename gh token var (#145) * rename gh token var * fix: add missing var for alpine image for arm64 arch * ci: add docker registry description (#146) * ci: add GH action to update readme for Docker registry * ci: add workflow dispatch (#149) * Release/v1.12.0 (#150) * feat: cron job template field (#132) (#133) * feat: cron job template field * fix: dep update * feat: deprecate args (#130) * feat: add args mode * fix: add args mode type * fix: change artifact support * fix: upload variables file (#135) * add tests for develop branch (#136) * add check fir release branch (#137) * comment out the automatic merge of release branch for now * fix release branch naming * fix typo * fix path for goreleaser file * rename release branch (#142) * ci: parametrize alpine (#144) * parametrize alpine image * fix: ttl for trigger condition (#143) * ci: rename gh token var (#145) * rename gh token var * fix: add missing var for alpine image for arm64 arch * fix: remove empty username and token (#147) * ci: add docker registry description (#146) * ci: add GH action to update readme for Docker registry * ci: add workflow dispatch (#149) --------- Co-authored-by: Lilla Vass Co-authored-by: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Co-authored-by: ypoplavs * fix: support external secrets (#151) * fix: secret check (#153) (#154) * fix: secret check * fix: remove wrong condition * ci: remove release branch creation in helm-charts repo (#157) * Release/v1.13.0 (#161) * feat: cron job template field (#132) (#133) * feat: cron job template field * fix: dep update * feat: deprecate args (#130) * feat: add args mode * fix: add args mode type * fix: change artifact support * fix: upload variables file (#135) * add tests for develop branch (#136) * add check fir release branch (#137) * comment out the automatic merge of release branch for now * fix release branch naming * fix typo * fix path for goreleaser file * rename release branch (#142) * ci: parametrize alpine (#144) * parametrize alpine image * fix: ttl for trigger condition (#143) * ci: rename gh token var (#145) * rename gh token var * fix: add missing var for alpine image for arm64 arch * fix: remove empty username and token (#147) * ci: add docker registry description (#146) * ci: add GH action to update readme for Docker registry * ci: add workflow dispatch (#149) * fix: support external secrets for tests (#148) * fix: support external secrets for tests * fix: support external secrets for test suite * fix: rename interface method * fix: test mock * feat: webhook templlate and headers (#152) * feat: webhook templlate and headers * fix: description typo * fix: secret check (#153) * fix: secret check * fix: remove wrong condition * feat: provide known condition types (#155) * feat: provide known condition types * fix: rename util method * feat: parallel testsuite (#109) * feat: test suite v3 * feat: test suite v3 client and watcher * fix: dep update * Update config/crd/bases/tests.testkube.io_tests.yaml Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> * fix: conversion typo * fix: test suite v3 sample * fix: use proper informer version * fix: v3 informer * fix: typo func name * add a separate workflow to test parallel testsuite images * add a separate workflow to test parallel testsuite images * fix: typo test suite version * fix: make steps optional * fix: sync recent changes * fix: solve merge errors * fix: rename fields * fix: tune crd fields * fix: rename vars and methods * fix: refresh mock * fix: rename vars * fix: duration format * fix: change test suite step object * fix: secret var check * fix: modify test suite example v3 * fix: update delay type --------- Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> Co-authored-by: ypoplavs * fix: remove run secrets as well (#139) debug fix: on deletion do not quit if something related to test could not be deleted, put in a single error fix: remove logging and improve errors fix: delete dependency error and delete test first * feat: postrun script (#156) * fix: post run scipt model * fix: add postrun script to crd * ci: remove release branch creation in helm-charts repo (#157) * fix: don't remove non Testkube secrets (#160) --------- Co-authored-by: Lilla Vass Co-authored-by: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Co-authored-by: ypoplavs Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> * fix: image registry (#166) (#167) * feat: Release/v1.14.0 (#168) * feat: cron job template field (#132) (#133) * feat: cron job template field * fix: dep update * feat: deprecate args (#130) * feat: add args mode * fix: add args mode type * fix: change artifact support * fix: upload variables file (#135) * add tests for develop branch (#136) * add check fir release branch (#137) * comment out the automatic merge of release branch for now * fix release branch naming * fix typo * fix path for goreleaser file * rename release branch (#142) * ci: parametrize alpine (#144) * parametrize alpine image * fix: ttl for trigger condition (#143) * ci: rename gh token var (#145) * rename gh token var * fix: add missing var for alpine image for arm64 arch * fix: remove empty username and token (#147) * ci: add docker registry description (#146) * ci: add GH action to update readme for Docker registry * ci: add workflow dispatch (#149) * fix: support external secrets for tests (#148) * fix: support external secrets for tests * fix: support external secrets for test suite * fix: rename interface method * fix: test mock * feat: webhook templlate and headers (#152) * feat: webhook templlate and headers * fix: description typo * fix: secret check (#153) * fix: secret check * fix: remove wrong condition * feat: provide known condition types (#155) * feat: provide known condition types * fix: rename util method * feat: parallel testsuite (#109) * feat: test suite v3 * feat: test suite v3 client and watcher * fix: dep update * Update config/crd/bases/tests.testkube.io_tests.yaml Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> * fix: conversion typo * fix: test suite v3 sample * fix: use proper informer version * fix: v3 informer * fix: typo func name * add a separate workflow to test parallel testsuite images * add a separate workflow to test parallel testsuite images * fix: typo test suite version * fix: make steps optional * fix: sync recent changes * fix: solve merge errors * fix: rename fields * fix: tune crd fields * fix: rename vars and methods * fix: refresh mock * fix: rename vars * fix: duration format * fix: change test suite step object * fix: secret var check * fix: modify test suite example v3 * fix: update delay type --------- Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> Co-authored-by: ypoplavs * fix: remove run secrets as well (#139) debug fix: on deletion do not quit if something related to test could not be deleted, put in a single error fix: remove logging and improve errors fix: delete dependency error and delete test first * feat: postrun script (#156) * fix: post run scipt model * fix: add postrun script to crd * ci: remove release branch creation in helm-charts repo (#157) * feat: probe conditions (#158) * feat: probe spec model * feat: test trigger crd with probes * fix: refactor probe definition * fix: unit tests * fix: don't remove non Testkube secrets (#160) * feat: remove outdated description (#164) * fix: image registry (#166) * feat: basic test execution crd (#165) * feat: basic test execution crd * feat: test execution CRD spec * fix: test execution client * fix: remove output * fix: update status method * fix: update get method * feat: test execution reconciler * fix: url port * fix: test name * fix: ignore status update * feat: test suite execution core * feat: test suite execution crd * feat: add unit tests * fix: test status * fix: remove not used structure * fix: api url typo * fix: running context * fix: generation field * fix: remove unused fields * fix: examples * fix: use go 1.21 (#169) * fix: context typo (#171) --------- Co-authored-by: Lilla Vass Co-authored-by: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Co-authored-by: ypoplavs Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> * resolve conflicts with main --------- Co-authored-by: Vladislav Sukhin Co-authored-by: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Co-authored-by: ypoplavs Co-authored-by: Lilla Vass Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> --------- Signed-off-by: hiteshwani Signed-off-by: Aman Parauliya Co-authored-by: Lilla Vass Co-authored-by: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Co-authored-by: ypoplavs Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> Co-authored-by: hiteshwani <110378441+hiteshwani@users.noreply.github.com> Co-authored-by: Aman Parauliya Co-authored-by: Dejan Zele Pejchev * fix: 1.15.3 (#190) * feat: cron job template field (#132) (#133) * feat: cron job template field * fix: dep update * feat: deprecate args (#130) * feat: add args mode * fix: add args mode type * fix: change artifact support * fix: upload variables file (#135) * add tests for develop branch (#136) * add check fir release branch (#137) * comment out the automatic merge of release branch for now * fix release branch naming * fix typo * fix path for goreleaser file * rename release branch (#142) * ci: parametrize alpine (#144) * parametrize alpine image * fix: ttl for trigger condition (#143) * ci: rename gh token var (#145) * rename gh token var * fix: add missing var for alpine image for arm64 arch * fix: remove empty username and token (#147) * ci: add docker registry description (#146) * ci: add GH action to update readme for Docker registry * ci: add workflow dispatch (#149) * fix: support external secrets for tests (#148) * fix: support external secrets for tests * fix: support external secrets for test suite * fix: rename interface method * fix: test mock * feat: webhook templlate and headers (#152) * feat: webhook templlate and headers * fix: description typo * fix: secret check (#153) * fix: secret check * fix: remove wrong condition * feat: provide known condition types (#155) * feat: provide known condition types * fix: rename util method * feat: parallel testsuite (#109) * feat: test suite v3 * feat: test suite v3 client and watcher * fix: dep update * Update config/crd/bases/tests.testkube.io_tests.yaml Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> * fix: conversion typo * fix: test suite v3 sample * fix: use proper informer version * fix: v3 informer * fix: typo func name * add a separate workflow to test parallel testsuite images * add a separate workflow to test parallel testsuite images * fix: typo test suite version * fix: make steps optional * fix: sync recent changes * fix: solve merge errors * fix: rename fields * fix: tune crd fields * fix: rename vars and methods * fix: refresh mock * fix: rename vars * fix: duration format * fix: change test suite step object * fix: secret var check * fix: modify test suite example v3 * fix: update delay type --------- Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> Co-authored-by: ypoplavs * fix: remove run secrets as well (#139) debug fix: on deletion do not quit if something related to test could not be deleted, put in a single error fix: remove logging and improve errors fix: delete dependency error and delete test first * feat: postrun script (#156) * fix: post run scipt model * fix: add postrun script to crd * ci: remove release branch creation in helm-charts repo (#157) * feat: probe conditions (#158) * feat: probe spec model * feat: test trigger crd with probes * fix: refactor probe definition * fix: unit tests * fix: don't remove non Testkube secrets (#160) * feat: remove outdated description (#164) * fix: image registry (#166) * feat: basic test execution crd (#165) * feat: basic test execution crd * feat: test execution CRD spec * fix: test execution client * fix: remove output * fix: update status method * fix: update get method * feat: test execution reconciler * fix: url port * fix: test name * fix: ignore status update * feat: test suite execution core * feat: test suite execution crd * feat: add unit tests * fix: test status * fix: remove not used structure * fix: api url typo * fix: running context * fix: generation field * fix: remove unused fields * fix: examples * fix: use go 1.21 (#169) * fix: context typo (#171) * feat: artifact bucket (#170) * feat: artifact bucket * fix: generate * fix: rename field * feat: test field (#172) * feat: test field * fix: tags * feat: template crd (#173) * featL template crd * feat: add delete by labels * feat: use cronjob reference * fix: add warnings * fix: error message * feat: adjust uri descrription (#174) * feat: adjust uri descrription * fix: adjust header description * feat: trigger concurrency policy (#175) * feat: trigger concurrency policy * fix: make policy optional * fix: policy validation * Added slaves field in executor CRD to add slaves configuration (#177) * Added slaves field in executor CRD to add slaves configuration Signed-off-by: hiteshwani * Discard changes Signed-off-by: hiteshwani * Fixed trivial review comments Signed-off-by: Aman Parauliya --------- Signed-off-by: hiteshwani Signed-off-by: Aman Parauliya Co-authored-by: Aman Parauliya * feat: update operator to use latest kubebuilder layout (#178) * update operator to use latest kubebuilder layout * update dependencies * update dependencies * remove some unused fields from CRDs * fix failing test * fix invalid reference (#179) * fix mocks (#180) * fix: make test fields optional (#181) * feat: execute post run script before scraping field (#183) * feat: execute post run script before scraping field * fix: pragma * feat: regex field (#186) * feat: regex field * fix: validate regex * fix: visibility for secrets (#187) --------- Signed-off-by: hiteshwani Signed-off-by: Aman Parauliya Co-authored-by: Lilla Vass Co-authored-by: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Co-authored-by: ypoplavs Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> Co-authored-by: hiteshwani <110378441+hiteshwani@users.noreply.github.com> Co-authored-by: Aman Parauliya Co-authored-by: Dejan Zele Pejchev * fix: comment * fix: pragma --------- Signed-off-by: hiteshwani Signed-off-by: Aman Parauliya Co-authored-by: ypoplavs <45286051+ypoplavs@users.noreply.github.com> Co-authored-by: ypoplavs Co-authored-by: Lilla Vass Co-authored-by: nicufk <89570185+nicufk@users.noreply.github.com> Co-authored-by: hiteshwani <110378441+hiteshwani@users.noreply.github.com> Co-authored-by: Aman Parauliya Co-authored-by: Dejan Zele Pejchev --- api/testsuite/v1/groupversion_info.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/testsuite/v1/groupversion_info.go b/api/testsuite/v1/groupversion_info.go index 948ec14a..1c954788 100644 --- a/api/testsuite/v1/groupversion_info.go +++ b/api/testsuite/v1/groupversion_info.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Package v1 contains API Schema definitions for the tests v1 API group +// Package v1 contains API Schema definitions for the test suites v1 API group // +kubebuilder:object:generate=true // +groupName=tests.testkube.io package v1 From f61e073d68b33d199c943defd2ac80a626d4abe7 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 2 Nov 2023 17:10:19 +0300 Subject: [PATCH 47/57] feat: data dir as working dir (#192) --- api/executor/v1/executor_types.go | 3 +++ config/crd/bases/executor.testkube.io_executors.yaml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/api/executor/v1/executor_types.go b/api/executor/v1/executor_types.go index 8b2991c4..5cc0c064 100644 --- a/api/executor/v1/executor_types.go +++ b/api/executor/v1/executor_types.go @@ -63,6 +63,9 @@ type ExecutorSpec struct { // Slaves data to run test in distributed environment Slaves *SlavesMeta `json:"slaves,omitempty"` + + // use data dir as working dir for executor + UseDataDirAsWorkingDir bool `json:"useDataDirAsWorkingDir,omitempty"` } type SlavesMeta struct { diff --git a/config/crd/bases/executor.testkube.io_executors.yaml b/config/crd/bases/executor.testkube.io_executors.yaml index ffdc3781..5fad9b78 100644 --- a/config/crd/bases/executor.testkube.io_executors.yaml +++ b/config/crd/bases/executor.testkube.io_executors.yaml @@ -125,6 +125,9 @@ spec: uri: description: URI for rest based executors type: string + useDataDirAsWorkingDir: + description: use data dir as working dir for executor + type: boolean type: object status: description: ExecutorStatus defines the observed state of Executor From c66d03db189f47cb2ed04ac9d013e90b0109ffa3 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Wed, 8 Nov 2023 13:02:43 +0300 Subject: [PATCH 48/57] feat: pass artifacts testsuite (#193) * feat: download artifacts model * fix: add comments --- api/testsuite/v3/testsuite_types.go | 12 +++++-- api/testsuite/v3/zz_generated.deepcopy.go | 25 +++++++++++++ .../bases/tests.testkube.io_testsuites.yaml | 36 +++++++++++++++++++ 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/api/testsuite/v3/testsuite_types.go b/api/testsuite/v3/testsuite_types.go index 54b2ffb6..ef51f212 100644 --- a/api/testsuite/v3/testsuite_types.go +++ b/api/testsuite/v3/testsuite_types.go @@ -55,10 +55,18 @@ type TestSuiteStepSpec struct { Delay metav1.Duration `json:"delay,omitempty"` } +// options to download artifacts from previous steps +type DownloadArtifactOptions struct { + AllPreviousSteps bool `json:"allPreviousSteps,omitempty"` + // previous step numbers starting from 1 + PreviousStepNumbers []int32 `json:"previousStepNumbers,omitempty"` +} + // TestSuiteBatchStep is set of steps run in parallel type TestSuiteBatchStep struct { - StopOnFailure bool `json:"stopOnFailure"` - Execute []TestSuiteStepSpec `json:"execute,omitempty"` + StopOnFailure bool `json:"stopOnFailure"` + DownloadArtifacts *DownloadArtifactOptions `json:"downloadArtifacts,omitempty"` + Execute []TestSuiteStepSpec `json:"execute,omitempty"` } // RunningContext for test or test suite execution diff --git a/api/testsuite/v3/zz_generated.deepcopy.go b/api/testsuite/v3/zz_generated.deepcopy.go index 464f2e08..6b5bdd83 100644 --- a/api/testsuite/v3/zz_generated.deepcopy.go +++ b/api/testsuite/v3/zz_generated.deepcopy.go @@ -25,6 +25,26 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DownloadArtifactOptions) DeepCopyInto(out *DownloadArtifactOptions) { + *out = *in + if in.PreviousStepNumbers != nil { + in, out := &in.PreviousStepNumbers, &out.PreviousStepNumbers + *out = make([]int32, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DownloadArtifactOptions. +func (in *DownloadArtifactOptions) DeepCopy() *DownloadArtifactOptions { + if in == nil { + return nil + } + out := new(DownloadArtifactOptions) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RunningContext) DeepCopyInto(out *RunningContext) { *out = *in @@ -70,6 +90,11 @@ func (in *TestSuite) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TestSuiteBatchStep) DeepCopyInto(out *TestSuiteBatchStep) { *out = *in + if in.DownloadArtifacts != nil { + in, out := &in.DownloadArtifacts, &out.DownloadArtifacts + *out = new(DownloadArtifactOptions) + (*in).DeepCopyInto(*out) + } if in.Execute != nil { in, out := &in.Execute, &out.Execute *out = make([]TestSuiteStepSpec, len(*in)) diff --git a/config/crd/bases/tests.testkube.io_testsuites.yaml b/config/crd/bases/tests.testkube.io_testsuites.yaml index db8af5e0..f39bafaa 100644 --- a/config/crd/bases/tests.testkube.io_testsuites.yaml +++ b/config/crd/bases/tests.testkube.io_testsuites.yaml @@ -565,6 +565,18 @@ spec: items: description: TestSuiteBatchStep is set of steps run in parallel properties: + downloadArtifacts: + description: options to download artifacts from previous steps + properties: + allPreviousSteps: + type: boolean + previousStepNumbers: + description: previous step numbers starting from 1 + items: + format: int32 + type: integer + type: array + type: object execute: items: description: TestSuiteStepSpec for particular type will have @@ -591,6 +603,18 @@ spec: items: description: TestSuiteBatchStep is set of steps run in parallel properties: + downloadArtifacts: + description: options to download artifacts from previous steps + properties: + allPreviousSteps: + type: boolean + previousStepNumbers: + description: previous step numbers starting from 1 + items: + format: int32 + type: integer + type: array + type: object execute: items: description: TestSuiteStepSpec for particular type will have @@ -783,6 +807,18 @@ spec: items: description: TestSuiteBatchStep is set of steps run in parallel properties: + downloadArtifacts: + description: options to download artifacts from previous steps + properties: + allPreviousSteps: + type: boolean + previousStepNumbers: + description: previous step numbers starting from 1 + items: + format: int32 + type: integer + type: array + type: object execute: items: description: TestSuiteStepSpec for particular type will have From 1f48caf736f45841f4db2a8adaa63c3af011bd15 Mon Sep 17 00:00:00 2001 From: Dawid Rusnak Date: Fri, 10 Nov 2023 13:33:04 +0100 Subject: [PATCH 49/57] fix: correct downloading tools with Go 1.16+ (#195) --- Makefile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 190d5662..88b3cd2d 100644 --- a/Makefile +++ b/Makefile @@ -114,10 +114,9 @@ define go-get-tool @[ -f $(1) ] || { \ set -e ;\ TMP_DIR=$$(mktemp -d) ;\ -cd $$TMP_DIR ;\ -go mod init tmp ;\ echo "Downloading $(2)" ;\ -GOBIN=$(PROJECT_DIR)/bin go get $(2) ;\ -rm -rf $$TMP_DIR ;\ +GOPATH="$$TMP_DIR" GOBIN="$$TMP_DIR/bin" go install $(2) ;\ +cp -r "$$TMP_DIR/bin" "$(PROJECT_DIR)" ;\ +chmod -R 777 "$$TMP_DIR" ; rm -rf "$$TMP_DIR" ;\ } endef From 0a5b5efaabec56822a7c8bec5a2cc23a5857515d Mon Sep 17 00:00:00 2001 From: fivenp Date: Tue, 14 Nov 2023 11:02:26 +0100 Subject: [PATCH 50/57] chore: rename default secret label (#196) --- pkg/client/tests/v3/test.go | 2 +- pkg/client/testsuites/v3/testsuites.go | 2 +- pkg/secret/client.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/client/tests/v3/test.go b/pkg/client/tests/v3/test.go index 30dad9a9..9a6092e8 100644 --- a/pkg/client/tests/v3/test.go +++ b/pkg/client/tests/v3/test.go @@ -32,7 +32,7 @@ const ( var testSecretDefaultLabels = map[string]string{ "testkube": testkubeTestSecretLabel, "testkubeSecretType": "variables", - "visibility": "testkube", + "createdBy": "testkube", } //go:generate mockgen -source=./test.go -destination=./mock_tests.go -package=tests "github.com/kubeshop/testkube-operator/pkg/client/tests/v3" Interface diff --git a/pkg/client/testsuites/v3/testsuites.go b/pkg/client/testsuites/v3/testsuites.go index 54a3bec4..4d1b070f 100644 --- a/pkg/client/testsuites/v3/testsuites.go +++ b/pkg/client/testsuites/v3/testsuites.go @@ -25,7 +25,7 @@ const ( var testsuiteSecretDefaultLabels = map[string]string{ "testkube": testkubeTestsuiteSecretLabel, "testkubeSecretType": "variables", - "visibility": "testkube", + "createdBy": "testkube", } //go:generate mockgen -destination=./mock_testsuites.go -package=v3 "github.com/kubeshop/testkube-operator/pkg/client/testsuites/v3" Interface diff --git a/pkg/secret/client.go b/pkg/secret/client.go index 9e52a829..a8ef2eec 100644 --- a/pkg/secret/client.go +++ b/pkg/secret/client.go @@ -138,7 +138,7 @@ func NewSpec(id, namespace, label string, labels, stringData map[string]string) ObjectMeta: metav1.ObjectMeta{ Name: id, Namespace: namespace, - Labels: map[string]string{"testkube": label, "visibility": "testkube"}, + Labels: map[string]string{"testkube": label, "createdBy": "testkube"}, }, Type: v1.SecretTypeOpaque, StringData: stringData, From 803ccbc584ff76dd6ecc79ca45d155999340221a Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Wed, 15 Nov 2023 13:52:21 +0300 Subject: [PATCH 51/57] feat: support argo cd sync (#197) * feat: support argo cd sync * fix: rename config var * fix: rename field * fix: add vesion * fix: rename field --- cmd/main.go | 19 ++++++++------- internal/controller/tests/test_controller.go | 8 ++++--- .../testsuite/testsuite_controller.go | 8 ++++--- pkg/cronjob/client.go | 23 ++++++++++++++++--- 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 2d860526..b6f24b97 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -19,8 +19,9 @@ package main import ( "encoding/base64" "flag" - testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" "os" + + testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) @@ -75,6 +76,7 @@ type config struct { Fullname string TemplateCronjob string `split_words:"true"` Registry string + UseArgocdSync bool `split_words:"true"` } func init() { @@ -128,7 +130,6 @@ func main() { } mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ - Scheme: scheme, Metrics: metricsserver.Options{BindAddress: metricsAddr}, HealthProbeBindAddress: probeAddr, @@ -155,17 +156,19 @@ func main() { os.Exit(1) } if err = (&testscontrollers.TestReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - CronJobClient: cronjob.NewClient(mgr.GetClient(), httpConfig.Fullname, httpConfig.Port, templateCronjob, httpConfig.Registry), + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + CronJobClient: cronjob.NewClient(mgr.GetClient(), httpConfig.Fullname, httpConfig.Port, + templateCronjob, httpConfig.Registry, httpConfig.UseArgocdSync), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Test") os.Exit(1) } if err = (&testsuitecontrollers.TestSuiteReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - CronJobClient: cronjob.NewClient(mgr.GetClient(), httpConfig.Fullname, httpConfig.Port, templateCronjob, httpConfig.Registry), + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + CronJobClient: cronjob.NewClient(mgr.GetClient(), httpConfig.Fullname, httpConfig.Port, + templateCronjob, httpConfig.Registry, httpConfig.UseArgocdSync), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "TestSuite") os.Exit(1) diff --git a/internal/controller/tests/test_controller.go b/internal/controller/tests/test_controller.go index 9d3090b7..d3f7b461 100644 --- a/internal/controller/tests/test_controller.go +++ b/internal/controller/tests/test_controller.go @@ -115,7 +115,9 @@ func (r *TestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl. options := cronjob.CronJobOptions{ Schedule: test.Spec.Schedule, - Resource: cronjob.TestResourceURI, + Resource: testsv3.Resource, + Version: testsv3.Version, + ResourceURI: cronjob.TestResourceURI, Data: string(data), Labels: test.Labels, CronJobTemplate: jobTemplate, @@ -128,7 +130,7 @@ func (r *TestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl. if err != nil { if errors.IsNotFound(err) { if err = r.CronJobClient.Create(ctx, test.Name, - cronjob.GetMetadataName(test.Name, cronjob.TestResourceURI), req.NamespacedName.Namespace, options); err != nil { + cronjob.GetMetadataName(test.Name, cronjob.TestResourceURI), req.NamespacedName.Namespace, string(test.UID), options); err != nil { return ctrl.Result{}, err } } @@ -138,7 +140,7 @@ func (r *TestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl. // Update CronJob if it was created before provided Test schedule if err = r.CronJobClient.Update(ctx, cronJob, test.Name, - cronjob.GetMetadataName(test.Name, cronjob.TestResourceURI), req.NamespacedName.Namespace, options); err != nil { + cronjob.GetMetadataName(test.Name, cronjob.TestResourceURI), req.NamespacedName.Namespace, string(test.UID), options); err != nil { return ctrl.Result{}, err } diff --git a/internal/controller/testsuite/testsuite_controller.go b/internal/controller/testsuite/testsuite_controller.go index 92892df4..7d31db00 100644 --- a/internal/controller/testsuite/testsuite_controller.go +++ b/internal/controller/testsuite/testsuite_controller.go @@ -116,7 +116,9 @@ func (r *TestSuiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( options := cronjob.CronJobOptions{ Schedule: testSuite.Spec.Schedule, - Resource: cronjob.TestSuiteResourceURI, + Resource: testsuitev3.Resource, + Version: testsuitev3.Version, + ResourceURI: cronjob.TestSuiteResourceURI, Data: string(data), Labels: testSuite.Labels, CronJobTemplate: jobTemplate, @@ -129,7 +131,7 @@ func (r *TestSuiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( if err != nil { if errors.IsNotFound(err) { if err = r.CronJobClient.Create(ctx, testSuite.Name, - cronjob.GetMetadataName(testSuite.Name, cronjob.TestSuiteResourceURI), req.NamespacedName.Namespace, options); err != nil { + cronjob.GetMetadataName(testSuite.Name, cronjob.TestSuiteResourceURI), req.NamespacedName.Namespace, string(testSuite.UID), options); err != nil { return ctrl.Result{}, err } } @@ -139,7 +141,7 @@ func (r *TestSuiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( // Update CronJob if it was created before provided Test schedule if err = r.CronJobClient.Update(ctx, cronJob, testSuite.Name, - cronjob.GetMetadataName(testSuite.Name, cronjob.TestSuiteResourceURI), req.NamespacedName.Namespace, options); err != nil { + cronjob.GetMetadataName(testSuite.Name, cronjob.TestSuiteResourceURI), req.NamespacedName.Namespace, string(testSuite.UID), options); err != nil { return ctrl.Result{}, err } diff --git a/pkg/cronjob/client.go b/pkg/cronjob/client.go index 3c5ec856..b1171a80 100644 --- a/pkg/cronjob/client.go +++ b/pkg/cronjob/client.go @@ -30,11 +30,14 @@ type Client struct { servicePort int cronJobTemplate string registry string + argoCDSync bool } type CronJobOptions struct { Schedule string Resource string + Version string + ResourceURI string Data string Labels map[string]string CronJobTemplate string @@ -49,21 +52,27 @@ type templateParameters struct { ServicePort int Schedule string Resource string + Version string + ResourceURI string CronJobTemplate string CronJobTemplateExtensions string Data string Labels map[string]string Registry string + ArgoCDSync bool + UID string } // NewClient is a method to create new cron job client -func NewClient(cli client.Client, serviceName string, servicePort int, cronJobTemplate, registry string) *Client { +func NewClient(cli client.Client, serviceName string, servicePort int, cronJobTemplate, registry string, + argoCDSync bool) *Client { return &Client{ Client: cli, serviceName: serviceName, servicePort: servicePort, cronJobTemplate: cronJobTemplate, registry: registry, + argoCDSync: argoCDSync, } } @@ -78,7 +87,7 @@ func (c *Client) Get(ctx context.Context, name, namespace string) (*batchv1.Cron } // Create is a method to create a cron job -func (c *Client) Create(ctx context.Context, id, name, namespace string, options CronJobOptions) error { +func (c *Client) Create(ctx context.Context, id, name, namespace, uid string, options CronJobOptions) error { template := c.cronJobTemplate if options.CronJobTemplate != "" { template = options.CronJobTemplate @@ -92,11 +101,15 @@ func (c *Client) Create(ctx context.Context, id, name, namespace string, options ServicePort: c.servicePort, Schedule: options.Schedule, Resource: options.Resource, + Version: options.Version, + ResourceURI: options.ResourceURI, CronJobTemplate: template, CronJobTemplateExtensions: options.CronJobTemplateExtensions, Data: options.Data, Labels: options.Labels, Registry: c.registry, + ArgoCDSync: c.argoCDSync, + UID: uid, } cronJobSpec, err := NewCronJobSpec(parameters) @@ -112,7 +125,7 @@ func (c *Client) Create(ctx context.Context, id, name, namespace string, options } // Update is a method to update an existing cron job -func (c *Client) Update(ctx context.Context, cronJob *batchv1.CronJob, id, name, namespace string, options CronJobOptions) error { +func (c *Client) Update(ctx context.Context, cronJob *batchv1.CronJob, id, name, namespace, uid string, options CronJobOptions) error { template := c.cronJobTemplate if options.CronJobTemplate != "" { template = options.CronJobTemplate @@ -126,11 +139,15 @@ func (c *Client) Update(ctx context.Context, cronJob *batchv1.CronJob, id, name, ServicePort: c.servicePort, Schedule: options.Schedule, Resource: options.Resource, + Version: options.Version, + ResourceURI: options.ResourceURI, CronJobTemplate: template, CronJobTemplateExtensions: options.CronJobTemplateExtensions, Data: options.Data, Labels: options.Labels, Registry: c.registry, + ArgoCDSync: c.argoCDSync, + UID: uid, } cronJobSpec, err := NewCronJobSpec(parameters) From ab055e3fece8ecd737254daa484ba78d4f452897 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 27 Nov 2023 13:39:46 +0300 Subject: [PATCH 52/57] feat: slave pod spec (#199) * feat: add pod slave model * feat: pod config crds * feat: template enum --- api/template/v1/template_types.go | 1 + api/testexecution/v1/testexecution_types.go | 31 +++++++- api/testexecution/v1/zz_generated.deepcopy.go | 70 +++++++++++++++++++ api/tests/v3/test_types.go | 28 +++++++- api/tests/v3/zz_generated.deepcopy.go | 65 +++++++++++++++++ .../v1/testsuiteexecution_types.go | 26 ++++++- .../v1/zz_generated.deepcopy.go | 65 +++++++++++++++++ .../bases/tests.testkube.io_templates.yaml | 1 + .../tests.testkube.io_testexecutions.yaml | 68 ++++++++++++++++++ config/crd/bases/tests.testkube.io_tests.yaml | 34 +++++++++ ...tests.testkube.io_testsuiteexecutions.yaml | 68 ++++++++++++++++++ 11 files changed, 451 insertions(+), 6 deletions(-) diff --git a/api/template/v1/template_types.go b/api/template/v1/template_types.go index 2b41d864..01827cb4 100644 --- a/api/template/v1/template_types.go +++ b/api/template/v1/template_types.go @@ -34,6 +34,7 @@ const ( SCRAPER_TemplateType TemplateType = "scraper" PVC_TemplateType TemplateType = "pvc" WEBHOOK_TemplateType TemplateType = "webhook" + POD_TemplateType TemplateType = "pod" ) // TemplateSpec defines the desired state of Template diff --git a/api/testexecution/v1/testexecution_types.go b/api/testexecution/v1/testexecution_types.go index cc16b6ca..0a7df57b 100644 --- a/api/testexecution/v1/testexecution_types.go +++ b/api/testexecution/v1/testexecution_types.go @@ -129,8 +129,9 @@ type ExecutionRequest struct { // config map references EnvConfigMaps []EnvReference `json:"envConfigMaps,omitempty"` // secret references - EnvSecrets []EnvReference `json:"envSecrets,omitempty"` - RunningContext *RunningContext `json:"runningContext,omitempty"` + EnvSecrets []EnvReference `json:"envSecrets,omitempty"` + RunningContext *RunningContext `json:"runningContext,omitempty"` + SlavePodRequest *PodRequest `json:"slavePodRequest,omitempty"` } // ArgsModeType defines args mode type @@ -171,6 +172,29 @@ type TestExecutionSpec struct { ExecutionRequest *ExecutionRequest `json:"executionRequest,omitempty"` } +// pod request body +type PodRequest struct { + Resources *PodResourcesRequest `json:"resources,omitempty"` + // pod template extensions + PodTemplate string `json:"podTemplate,omitempty"` + // name of the template resource + PodTemplateReference string `json:"podTemplateReference,omitempty"` +} + +// pod resources request specification +type PodResourcesRequest struct { + Requests *ResourceRequest `json:"requests,omitempty"` + Limits *ResourceRequest `json:"limits,omitempty"` +} + +// resource request specification +type ResourceRequest struct { + // requested cpu units + Cpu string `json:"cpu,omitempty"` + // requested memory units + Memory string `json:"memory,omitempty"` +} + // test execution type Execution struct { // execution id @@ -230,7 +254,8 @@ type Execution struct { ExecutePostRunScriptBeforeScraping bool `json:"executePostRunScriptBeforeScraping,omitempty"` RunningContext *RunningContext `json:"runningContext,omitempty"` // shell used in container executor - ContainerShell string `json:"containerShell,omitempty"` + ContainerShell string `json:"containerShell,omitempty"` + SlavePodRequest *PodRequest `json:"slavePodRequest,omitempty"` } // TestContent defines test content diff --git a/api/testexecution/v1/zz_generated.deepcopy.go b/api/testexecution/v1/zz_generated.deepcopy.go index 91370918..737425e0 100644 --- a/api/testexecution/v1/zz_generated.deepcopy.go +++ b/api/testexecution/v1/zz_generated.deepcopy.go @@ -138,6 +138,11 @@ func (in *Execution) DeepCopyInto(out *Execution) { *out = new(RunningContext) **out = **in } + if in.SlavePodRequest != nil { + in, out := &in.SlavePodRequest, &out.SlavePodRequest + *out = new(PodRequest) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Execution. @@ -216,6 +221,11 @@ func (in *ExecutionRequest) DeepCopyInto(out *ExecutionRequest) { *out = new(RunningContext) **out = **in } + if in.SlavePodRequest != nil { + in, out := &in.SlavePodRequest, &out.SlavePodRequest + *out = new(PodRequest) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecutionRequest. @@ -310,6 +320,51 @@ func (in *ObjectRef) DeepCopy() *ObjectRef { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodRequest) DeepCopyInto(out *PodRequest) { + *out = *in + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = new(PodResourcesRequest) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodRequest. +func (in *PodRequest) DeepCopy() *PodRequest { + if in == nil { + return nil + } + out := new(PodRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodResourcesRequest) DeepCopyInto(out *PodResourcesRequest) { + *out = *in + if in.Requests != nil { + in, out := &in.Requests, &out.Requests + *out = new(ResourceRequest) + **out = **in + } + if in.Limits != nil { + in, out := &in.Limits, &out.Limits + *out = new(ResourceRequest) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodResourcesRequest. +func (in *PodResourcesRequest) DeepCopy() *PodResourcesRequest { + if in == nil { + return nil + } + out := new(PodResourcesRequest) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Repository) DeepCopyInto(out *Repository) { *out = *in @@ -335,6 +390,21 @@ func (in *Repository) DeepCopy() *Repository { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceRequest) DeepCopyInto(out *ResourceRequest) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceRequest. +func (in *ResourceRequest) DeepCopy() *ResourceRequest { + if in == nil { + return nil + } + out := new(ResourceRequest) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RunningContext) DeepCopyInto(out *RunningContext) { *out = *in diff --git a/api/tests/v3/test_types.go b/api/tests/v3/test_types.go index 632debfc..3cca982b 100644 --- a/api/tests/v3/test_types.go +++ b/api/tests/v3/test_types.go @@ -151,6 +151,29 @@ const ( RunningContextTypeEmpty RunningContextType = "" ) +// pod request body +type PodRequest struct { + Resources *PodResourcesRequest `json:"resources,omitempty"` + // pod template extensions + PodTemplate string `json:"podTemplate,omitempty"` + // name of the template resource + PodTemplateReference string `json:"podTemplateReference,omitempty"` +} + +// pod resources request specification +type PodResourcesRequest struct { + Requests *ResourceRequest `json:"requests,omitempty"` + Limits *ResourceRequest `json:"limits,omitempty"` +} + +// resource request specification +type ResourceRequest struct { + // requested cpu units + Cpu string `json:"cpu,omitempty"` + // requested memory units + Memory string `json:"memory,omitempty"` +} + // test execution request body type ExecutionRequest struct { // test execution custom name @@ -225,8 +248,9 @@ type ExecutionRequest struct { // config map references EnvConfigMaps []EnvReference `json:"envConfigMaps,omitempty"` // secret references - EnvSecrets []EnvReference `json:"envSecrets,omitempty"` - RunningContext *RunningContext `json:"-"` + EnvSecrets []EnvReference `json:"envSecrets,omitempty"` + RunningContext *RunningContext `json:"-"` + SlavePodRequest *PodRequest `json:"slavePodRequest,omitempty"` } // ArgsModeType defines args mode type diff --git a/api/tests/v3/zz_generated.deepcopy.go b/api/tests/v3/zz_generated.deepcopy.go index 744838aa..bf9950b0 100644 --- a/api/tests/v3/zz_generated.deepcopy.go +++ b/api/tests/v3/zz_generated.deepcopy.go @@ -150,6 +150,11 @@ func (in *ExecutionRequest) DeepCopyInto(out *ExecutionRequest) { *out = new(RunningContext) **out = **in } + if in.SlavePodRequest != nil { + in, out := &in.SlavePodRequest, &out.SlavePodRequest + *out = new(PodRequest) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecutionRequest. @@ -162,6 +167,51 @@ func (in *ExecutionRequest) DeepCopy() *ExecutionRequest { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodRequest) DeepCopyInto(out *PodRequest) { + *out = *in + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = new(PodResourcesRequest) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodRequest. +func (in *PodRequest) DeepCopy() *PodRequest { + if in == nil { + return nil + } + out := new(PodRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodResourcesRequest) DeepCopyInto(out *PodResourcesRequest) { + *out = *in + if in.Requests != nil { + in, out := &in.Requests, &out.Requests + *out = new(ResourceRequest) + **out = **in + } + if in.Limits != nil { + in, out := &in.Limits, &out.Limits + *out = new(ResourceRequest) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodResourcesRequest. +func (in *PodResourcesRequest) DeepCopy() *PodResourcesRequest { + if in == nil { + return nil + } + out := new(PodResourcesRequest) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Repository) DeepCopyInto(out *Repository) { *out = *in @@ -187,6 +237,21 @@ func (in *Repository) DeepCopy() *Repository { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceRequest) DeepCopyInto(out *ResourceRequest) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceRequest. +func (in *ResourceRequest) DeepCopy() *ResourceRequest { + if in == nil { + return nil + } + out := new(ResourceRequest) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RunningContext) DeepCopyInto(out *RunningContext) { *out = *in diff --git a/api/testsuiteexecution/v1/testsuiteexecution_types.go b/api/testsuiteexecution/v1/testsuiteexecution_types.go index 72dcf148..f8d623ff 100644 --- a/api/testsuiteexecution/v1/testsuiteexecution_types.go +++ b/api/testsuiteexecution/v1/testsuiteexecution_types.go @@ -194,6 +194,29 @@ const ( ArgsModeTypeOverride ArgsModeType = "override" ) +// pod request body +type PodRequest struct { + Resources *PodResourcesRequest `json:"resources,omitempty"` + // pod template extensions + PodTemplate string `json:"podTemplate,omitempty"` + // name of the template resource + PodTemplateReference string `json:"podTemplateReference,omitempty"` +} + +// pod resources request specification +type PodResourcesRequest struct { + Requests *ResourceRequest `json:"requests,omitempty"` + Limits *ResourceRequest `json:"limits,omitempty"` +} + +// resource request specification +type ResourceRequest struct { + // requested cpu units + Cpu string `json:"cpu,omitempty"` + // requested memory units + Memory string `json:"memory,omitempty"` +} + // test execution type Execution struct { // execution id @@ -255,7 +278,8 @@ type Execution struct { // shell used in container executor ContainerShell string `json:"containerShell,omitempty"` // test execution name started the test execution - TestExecutionName string `json:"testExecutionName,omitempty"` + TestExecutionName string `json:"testExecutionName,omitempty"` + SlavePodRequest *PodRequest `json:"slavePodRequest,omitempty"` } // artifact request body with test artifacts diff --git a/api/testsuiteexecution/v1/zz_generated.deepcopy.go b/api/testsuiteexecution/v1/zz_generated.deepcopy.go index 5e2c1176..027a52f4 100644 --- a/api/testsuiteexecution/v1/zz_generated.deepcopy.go +++ b/api/testsuiteexecution/v1/zz_generated.deepcopy.go @@ -121,6 +121,11 @@ func (in *Execution) DeepCopyInto(out *Execution) { *out = new(RunningContext) **out = **in } + if in.SlavePodRequest != nil { + in, out := &in.SlavePodRequest, &out.SlavePodRequest + *out = new(PodRequest) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Execution. @@ -215,6 +220,51 @@ func (in *ObjectRef) DeepCopy() *ObjectRef { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodRequest) DeepCopyInto(out *PodRequest) { + *out = *in + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = new(PodResourcesRequest) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodRequest. +func (in *PodRequest) DeepCopy() *PodRequest { + if in == nil { + return nil + } + out := new(PodRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodResourcesRequest) DeepCopyInto(out *PodResourcesRequest) { + *out = *in + if in.Requests != nil { + in, out := &in.Requests, &out.Requests + *out = new(ResourceRequest) + **out = **in + } + if in.Limits != nil { + in, out := &in.Limits, &out.Limits + *out = new(ResourceRequest) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodResourcesRequest. +func (in *PodResourcesRequest) DeepCopy() *PodResourcesRequest { + if in == nil { + return nil + } + out := new(PodResourcesRequest) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Repository) DeepCopyInto(out *Repository) { *out = *in @@ -255,6 +305,21 @@ func (in *RepositoryParameters) DeepCopy() *RepositoryParameters { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceRequest) DeepCopyInto(out *ResourceRequest) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceRequest. +func (in *ResourceRequest) DeepCopy() *ResourceRequest { + if in == nil { + return nil + } + out := new(ResourceRequest) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RunningContext) DeepCopyInto(out *RunningContext) { *out = *in diff --git a/config/crd/bases/tests.testkube.io_templates.yaml b/config/crd/bases/tests.testkube.io_templates.yaml index e951fd4b..4572d684 100644 --- a/config/crd/bases/tests.testkube.io_templates.yaml +++ b/config/crd/bases/tests.testkube.io_templates.yaml @@ -47,6 +47,7 @@ spec: - scraper - pvc - webhook + - pod type: string required: - body diff --git a/config/crd/bases/tests.testkube.io_testexecutions.yaml b/config/crd/bases/tests.testkube.io_testexecutions.yaml index 80082323..e69c6e54 100644 --- a/config/crd/bases/tests.testkube.io_testexecutions.yaml +++ b/config/crd/bases/tests.testkube.io_testexecutions.yaml @@ -235,6 +235,40 @@ spec: description: 'Execution variables passed to executor from secrets. Deprecated: use Secret Variables instead' type: object + slavePodRequest: + description: pod request body + properties: + podTemplate: + description: pod template extensions + type: string + podTemplateReference: + description: name of the template resource + type: string + resources: + description: pod resources request specification + properties: + limits: + description: resource request specification + properties: + cpu: + description: requested cpu units + type: string + memory: + description: requested memory units + type: string + type: object + requests: + description: resource request specification + properties: + cpu: + description: requested cpu units + type: string + memory: + description: requested memory units + type: string + type: object + type: object + type: object sync: description: whether to start execution sync or async type: boolean @@ -630,6 +664,40 @@ spec: required: - type type: object + slavePodRequest: + description: pod request body + properties: + podTemplate: + description: pod template extensions + type: string + podTemplateReference: + description: name of the template resource + type: string + resources: + description: pod resources request specification + properties: + limits: + description: resource request specification + properties: + cpu: + description: requested cpu units + type: string + memory: + description: requested memory units + type: string + type: object + requests: + description: resource request specification + properties: + cpu: + description: requested cpu units + type: string + memory: + description: requested memory units + type: string + type: object + type: object + type: object startTime: description: test start time format: date-time diff --git a/config/crd/bases/tests.testkube.io_tests.yaml b/config/crd/bases/tests.testkube.io_tests.yaml index 62a47d6d..2995e13b 100644 --- a/config/crd/bases/tests.testkube.io_tests.yaml +++ b/config/crd/bases/tests.testkube.io_tests.yaml @@ -625,6 +625,40 @@ spec: description: 'Execution variables passed to executor from secrets. Deprecated: use Secret Variables instead' type: object + slavePodRequest: + description: pod request body + properties: + podTemplate: + description: pod template extensions + type: string + podTemplateReference: + description: name of the template resource + type: string + resources: + description: pod resources request specification + properties: + limits: + description: resource request specification + properties: + cpu: + description: requested cpu units + type: string + memory: + description: requested memory units + type: string + type: object + requests: + description: resource request specification + properties: + cpu: + description: requested cpu units + type: string + memory: + description: requested memory units + type: string + type: object + type: object + type: object sync: description: whether to start execution sync or async type: boolean diff --git a/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml b/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml index 1017e0f2..205a0f18 100644 --- a/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml +++ b/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml @@ -549,6 +549,40 @@ spec: required: - type type: object + slavePodRequest: + description: pod request body + properties: + podTemplate: + description: pod template extensions + type: string + podTemplateReference: + description: name of the template resource + type: string + resources: + description: pod resources request specification + properties: + limits: + description: resource request specification + properties: + cpu: + description: requested cpu units + type: string + memory: + description: requested memory units + type: string + type: object + requests: + description: resource request specification + properties: + cpu: + description: requested cpu units + type: string + memory: + description: requested memory units + type: string + type: object + type: object + type: object startTime: description: test start time format: date-time @@ -1055,6 +1089,40 @@ spec: required: - type type: object + slavePodRequest: + description: pod request body + properties: + podTemplate: + description: pod template extensions + type: string + podTemplateReference: + description: name of the template resource + type: string + resources: + description: pod resources request specification + properties: + limits: + description: resource request specification + properties: + cpu: + description: requested cpu units + type: string + memory: + description: requested memory units + type: string + type: object + requests: + description: resource request specification + properties: + cpu: + description: requested cpu units + type: string + memory: + description: requested memory units + type: string + type: object + type: object + type: object startTime: description: test start time format: date-time From 0b0eb5b9820f123f654046e4342f5ea15612e848 Mon Sep 17 00:00:00 2001 From: Dawid Rusnak Date: Mon, 27 Nov 2023 16:22:33 +0100 Subject: [PATCH 53/57] feat: install controller-gen 0.8.0 (#202) --- Makefile | 2 +- api/testsuite/v3/zz_generated.deepcopy.go | 6 ++---- api/testtriggers/v1/zz_generated.deepcopy.go | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 88b3cd2d..2aaac390 100644 --- a/Makefile +++ b/Makefile @@ -102,7 +102,7 @@ undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/confi CONTROLLER_GEN = $(shell pwd)/bin/controller-gen controller-gen: ## Download controller-gen locally if necessary. - $(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.4.1) + $(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.8.0) KUSTOMIZE = $(shell pwd)/bin/kustomize kustomize: ## Download kustomize locally if necessary. diff --git a/api/testsuite/v3/zz_generated.deepcopy.go b/api/testsuite/v3/zz_generated.deepcopy.go index 6b5bdd83..d39c0360 100644 --- a/api/testsuite/v3/zz_generated.deepcopy.go +++ b/api/testsuite/v3/zz_generated.deepcopy.go @@ -98,9 +98,7 @@ func (in *TestSuiteBatchStep) DeepCopyInto(out *TestSuiteBatchStep) { if in.Execute != nil { in, out := &in.Execute, &out.Execute *out = make([]TestSuiteStepSpec, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } + copy(*out, *in) } } @@ -273,7 +271,7 @@ func (in *TestSuiteStatus) DeepCopy() *TestSuiteStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TestSuiteStepSpec) DeepCopyInto(out *TestSuiteStepSpec) { *out = *in - in.Delay.DeepCopyInto(&out.Delay) + out.Delay = in.Delay } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteStepSpec. diff --git a/api/testtriggers/v1/zz_generated.deepcopy.go b/api/testtriggers/v1/zz_generated.deepcopy.go index ac2c588b..de6b839b 100644 --- a/api/testtriggers/v1/zz_generated.deepcopy.go +++ b/api/testtriggers/v1/zz_generated.deepcopy.go @@ -209,7 +209,7 @@ func (in *TestTriggerSpec) DeepCopyInto(out *TestTriggerSpec) { if in.Delay != nil { in, out := &in.Delay, &out.Delay *out = new(metav1.Duration) - (*in).DeepCopyInto(*out) + **out = **in } } From 2fc74ceb3639d69313508caa548ce2576557b987 Mon Sep 17 00:00:00 2001 From: Dejan Zele Pejchev Date: Thu, 30 Nov 2023 15:58:58 +0100 Subject: [PATCH 54/57] chore: update dependencies to latest (#203) --- Makefile | 15 ++++--- api/template/v1/template_types.go | 2 +- go.mod | 34 +++++++-------- go.sum | 72 +++++++++++++++---------------- 4 files changed, 63 insertions(+), 60 deletions(-) diff --git a/Makefile b/Makefile index 2aaac390..6f4af259 100644 --- a/Makefile +++ b/Makefile @@ -72,18 +72,20 @@ docker-build-local: build-local-linux kind-load-local: docker-build-local kind load docker-image controller:latest --name testkube -run: manifests generate fmt vet ## Run a controller from your host. - go run ./cmd/main.go - -run-no-webhook: manifests generate fmt vet ## Run a controller from your host. - ENABLE_WEBHOOKS=false go run ./cmd/main.go - docker-build: test ## Build docker image with the manager. docker build -t ${IMG} . docker-push: ## Push docker image with the manager. docker push ${IMG} +##@ Build + +run: manifests generate fmt vet ## Run a controller from your host. + go run ./cmd/main.go + +run-no-webhook: manifests generate fmt vet ## Run a controller from your host. + ENABLE_WEBHOOKS=false go run ./cmd/main.go + ##@ Deployment install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. @@ -99,6 +101,7 @@ deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. $(KUSTOMIZE) build config/default | kubectl delete -f - +##@ Setup CONTROLLER_GEN = $(shell pwd)/bin/controller-gen controller-gen: ## Download controller-gen locally if necessary. diff --git a/api/template/v1/template_types.go b/api/template/v1/template_types.go index 01827cb4..47b8578e 100644 --- a/api/template/v1/template_types.go +++ b/api/template/v1/template_types.go @@ -24,7 +24,7 @@ import ( // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. // TemplateType defines template type by purpose -// +kubebuilder:validation:Enum=job;container;cronjob;scraper;pvc;webhook +// +kubebuilder:validation:Enum=job;container;cronjob;scraper;pvc;webhook;pod type TemplateType string const ( diff --git a/go.mod b/go.mod index 8cc2d928..17dfec7a 100644 --- a/go.mod +++ b/go.mod @@ -4,19 +4,19 @@ go 1.21 require ( github.com/golang/mock v1.6.0 - github.com/google/uuid v1.3.1 + github.com/google/uuid v1.4.0 github.com/kelseyhightower/envconfig v1.4.0 github.com/onsi/ginkgo v1.16.5 - github.com/onsi/ginkgo/v2 v2.12.0 - github.com/onsi/gomega v1.27.10 + github.com/onsi/ginkgo/v2 v2.13.2 + github.com/onsi/gomega v1.30.0 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.4 - go.uber.org/zap v1.25.0 - k8s.io/api v0.28.2 - k8s.io/apimachinery v0.28.2 - k8s.io/client-go v0.28.2 - sigs.k8s.io/controller-runtime v0.16.2 - sigs.k8s.io/kustomize/kyaml v0.14.3 + go.uber.org/zap v1.26.0 + k8s.io/api v0.28.4 + k8s.io/apimachinery v0.28.4 + k8s.io/client-go v0.28.4 + sigs.k8s.io/controller-runtime v0.16.3 + sigs.k8s.io/kustomize/kyaml v0.15.0 ) require ( @@ -28,7 +28,7 @@ require ( github.com/evanphx/json-patch/v5 v5.7.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-errors/errors v1.5.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/zapr v1.2.4 // indirect github.com/go-openapi/jsonpointer v0.20.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect @@ -38,7 +38,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/imdario/mergo v0.3.16 // indirect @@ -58,13 +58,13 @@ require ( github.com/spf13/pflag v1.0.5 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/net v0.15.0 // indirect + golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.12.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/term v0.12.0 // indirect + golang.org/x/sys v0.14.0 // indirect + golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.13.0 // indirect + golang.org/x/tools v0.14.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/protobuf v1.31.0 // indirect @@ -72,8 +72,8 @@ require ( gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.28.2 // indirect - k8s.io/component-base v0.28.2 // indirect + k8s.io/apiextensions-apiserver v0.28.3 // indirect + k8s.io/component-base v0.28.3 // indirect k8s.io/klog/v2 v2.100.1 // indirect k8s.io/kube-openapi v0.0.0-20230918164632-68afd615200d // indirect k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect diff --git a/go.sum b/go.sum index fbe0b46c..56132a55 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,4 @@ github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 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/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= @@ -25,8 +23,9 @@ github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbS 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-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= @@ -63,15 +62,16 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/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-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= @@ -112,12 +112,12 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI= -github.com/onsi/ginkgo/v2 v2.12.0/go.mod h1:ZNEzXISYlqpb8S36iN71ifqLi3vVD1rVJGvWRCJOUpQ= +github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs= +github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +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= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -161,8 +161,8 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-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= @@ -174,8 +174,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -186,8 +186,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -214,12 +214,12 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc 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-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-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.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.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= @@ -237,8 +237,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f 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.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -275,28 +275,28 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw= -k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg= -k8s.io/apiextensions-apiserver v0.28.2 h1:J6/QRWIKV2/HwBhHRVITMLYoypCoPY1ftigDM0Kn+QU= -k8s.io/apiextensions-apiserver v0.28.2/go.mod h1:5tnkxLGa9nefefYzWuAlWZ7RZYuN/765Au8cWLA6SRg= -k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ= -k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU= -k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY= -k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY= -k8s.io/component-base v0.28.2 h1:Yc1yU+6AQSlpJZyvehm/NkJBII72rzlEsd6MkBQ+G0E= -k8s.io/component-base v0.28.2/go.mod h1:4IuQPQviQCg3du4si8GpMrhAIegxpsgPngPRR/zWpzc= +k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY= +k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0= +k8s.io/apiextensions-apiserver v0.28.3 h1:Od7DEnhXHnHPZG+W9I97/fSQkVpVPQx2diy+2EtmY08= +k8s.io/apiextensions-apiserver v0.28.3/go.mod h1:NE1XJZ4On0hS11aWWJUTNkmVB03j9LM7gJSisbRt8Lc= +k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8= +k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg= +k8s.io/client-go v0.28.4 h1:Np5ocjlZcTrkyRJ3+T3PkXDpe4UpatQxj85+xjaD2wY= +k8s.io/client-go v0.28.4/go.mod h1:0VDZFpgoZfelyP5Wqu0/r/TRYcLYuJ2U1KEeoaPa1N4= +k8s.io/component-base v0.28.3 h1:rDy68eHKxq/80RiMb2Ld/tbH8uAE75JdCqJyi6lXMzI= +k8s.io/component-base v0.28.3/go.mod h1:fDJ6vpVNSk6cRo5wmDa6eKIG7UlIQkaFmZN2fYgIUD8= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230918164632-68afd615200d h1:/CFeJBjBrZvHX09rObS2+2iEEDevMWYc1v3aIYAjIYI= k8s.io/kube-openapi v0.0.0-20230918164632-68afd615200d/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= -sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= +sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4= +sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/kyaml v0.14.3 h1:WpabVAKZe2YEp/irTSHwD6bfjwZnTtSDewd2BVJGMZs= -sigs.k8s.io/kustomize/kyaml v0.14.3/go.mod h1:npvh9epWysfQ689Rtt/U+dpOJDTBn8kUnF1O6VzvmZA= +sigs.k8s.io/kustomize/kyaml v0.15.0 h1:ynlLMAxDhrY9otSg5GYE2TcIz31XkGZ2Pkj7SdolD84= +sigs.k8s.io/kustomize/kyaml v0.15.0/go.mod h1:+uMkBahdU1KNOj78Uta4rrXH+iH7wvg+nW7+GULvREA= sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk= sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= From 83394de3b9760336b0f62df54dcfddcc61e0832f Mon Sep 17 00:00:00 2001 From: Lilla Vass Date: Wed, 6 Dec 2023 14:18:56 +0100 Subject: [PATCH 55/57] feat: add executor and webhook listers and informers [TKC-631] (#205) * feat: add listeners and informers * feat: lister and informer for test source * fix: improve resources in groupversion for executor group * fix: fix permission error while testing locally --- api/executor/v1/groupversion_info.go | 20 +- api/testsource/v1/groupversion_info.go | 14 +- pkg/clientset/versioned/clientset.go | 20 +- .../versioned/fake/clientset_generated.go | 15 +- pkg/clientset/versioned/fake/register.go | 2 + pkg/clientset/versioned/scheme/register.go | 2 + .../versioned/typed/executor/v1/doc.go | 17 ++ .../versioned/typed/executor/v1/executor.go | 88 ++++++++ .../typed/executor/v1/executor_client.go | 111 ++++++++++ .../versioned/typed/executor/v1/fake/doc.go | 17 ++ .../typed/executor/v1/fake/fake_executor.go | 72 +++++++ .../executor/v1/fake/fake_tests_client.go | 42 ++++ .../typed/executor/v1/fake/fake_webhook.go | 72 +++++++ .../typed/executor/v1/generated_expansion.go | 21 ++ .../versioned/typed/executor/v1/webhook.go | 88 ++++++++ .../typed/tests/v1/fake/fake_tests_client.go | 4 + .../typed/tests/v1/fake/fake_testsource.go | 171 +++++++++++++++ .../typed/tests/v1/generated_expansion.go | 2 + .../versioned/typed/tests/v1/tests_client.go | 9 +- .../versioned/typed/tests/v1/testsource.go | 194 ++++++++++++++++++ .../externalversions/executor/interface.go | 48 +++++ .../externalversions/executor/v1/executor.go | 94 +++++++++ .../externalversions/executor/v1/interface.go | 52 +++++ .../externalversions/executor/v1/webhook.go | 94 +++++++++ pkg/informers/externalversions/factory.go | 13 +- pkg/informers/externalversions/generic.go | 21 ++ .../externalversions/tests/v1/interface.go | 7 + .../externalversions/tests/v1/testsource.go | 94 +++++++++ pkg/listers/executor/v1/executors.go | 101 +++++++++ .../executor/v1/expansion_generated.go | 31 +++ pkg/listers/executor/v1/webhooks.go | 101 +++++++++ pkg/listers/tests/v1/expansion_generated.go | 7 + pkg/listers/tests/v1/testsource.go | 101 +++++++++ 33 files changed, 1732 insertions(+), 13 deletions(-) create mode 100644 pkg/clientset/versioned/typed/executor/v1/doc.go create mode 100644 pkg/clientset/versioned/typed/executor/v1/executor.go create mode 100644 pkg/clientset/versioned/typed/executor/v1/executor_client.go create mode 100644 pkg/clientset/versioned/typed/executor/v1/fake/doc.go create mode 100644 pkg/clientset/versioned/typed/executor/v1/fake/fake_executor.go create mode 100644 pkg/clientset/versioned/typed/executor/v1/fake/fake_tests_client.go create mode 100644 pkg/clientset/versioned/typed/executor/v1/fake/fake_webhook.go create mode 100644 pkg/clientset/versioned/typed/executor/v1/generated_expansion.go create mode 100644 pkg/clientset/versioned/typed/executor/v1/webhook.go create mode 100644 pkg/clientset/versioned/typed/tests/v1/fake/fake_testsource.go create mode 100644 pkg/clientset/versioned/typed/tests/v1/testsource.go create mode 100644 pkg/informers/externalversions/executor/interface.go create mode 100644 pkg/informers/externalversions/executor/v1/executor.go create mode 100644 pkg/informers/externalversions/executor/v1/interface.go create mode 100644 pkg/informers/externalversions/executor/v1/webhook.go create mode 100644 pkg/informers/externalversions/tests/v1/testsource.go create mode 100644 pkg/listers/executor/v1/executors.go create mode 100644 pkg/listers/executor/v1/expansion_generated.go create mode 100644 pkg/listers/executor/v1/webhooks.go create mode 100644 pkg/listers/tests/v1/testsource.go diff --git a/api/executor/v1/groupversion_info.go b/api/executor/v1/groupversion_info.go index ba892040..92d8edc7 100644 --- a/api/executor/v1/groupversion_info.go +++ b/api/executor/v1/groupversion_info.go @@ -25,8 +25,26 @@ import ( ) var ( + // Group represents the API Group + Group = "executor.testkube.io" + + // Version represents the Resource version + Version = "v1" + + // ExecutorResource corresponds to the CRD Kind + ExecutorResource = "Executor" + + // WebhookResource corresponds to the CRD Kind + WebhookResource = "Webhook" + // GroupVersion is group version used to register these objects - GroupVersion = schema.GroupVersion{Group: "executor.testkube.io", Version: "v1"} + GroupVersion = schema.GroupVersion{Group: Group, Version: Version} + + // ExecutorGroupVersionResource is group, version and resource used to register these objects + ExecutorGroupVersionResource = schema.GroupVersionResource{Group: Group, Version: Version, Resource: ExecutorResource} + + // WebhookGroupVersionResource is group, version and resource used to register these objects + WebhookGroupVersionResource = schema.GroupVersionResource{Group: Group, Version: Version, Resource: WebhookResource} // SchemeBuilder is used to add go types to the GroupVersionKind scheme SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} diff --git a/api/testsource/v1/groupversion_info.go b/api/testsource/v1/groupversion_info.go index c1627d50..eafba8a8 100644 --- a/api/testsource/v1/groupversion_info.go +++ b/api/testsource/v1/groupversion_info.go @@ -25,8 +25,20 @@ import ( ) var ( + // Group represents the API Group + Group = "tests.testkube.io" + + // Version represents the Resource version + Version = "v1" + + // Resource corresponds to the CRD Kind + Resource = "TestSource" + // GroupVersion is group version used to register these objects - GroupVersion = schema.GroupVersion{Group: "tests.testkube.io", Version: "v1"} + GroupVersion = schema.GroupVersion{Group: Group, Version: Version} + + // GroupVersionResource is group, version and resource used to register these objects + GroupVersionResource = schema.GroupVersionResource{Group: Group, Version: Version, Resource: Resource} // SchemeBuilder is used to add go types to the GroupVersionKind scheme SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} diff --git a/pkg/clientset/versioned/clientset.go b/pkg/clientset/versioned/clientset.go index 9098b726..cfa78488 100644 --- a/pkg/clientset/versioned/clientset.go +++ b/pkg/clientset/versioned/clientset.go @@ -20,6 +20,7 @@ import ( "fmt" "net/http" + executorv1 "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/typed/executor/v1" v1 "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/typed/tests/v1" v2 "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/typed/tests/v2" v3 "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/typed/tests/v3" @@ -34,14 +35,16 @@ type Interface interface { TestsV1() v1.TestsV1Interface TestsV2() v2.TestsV2Interface TestsV3() v3.TestsV3Interface + ExecutorV1() executorv1.ExecutorV1Interface } // Clientset contains the clients for groups. Each group has exactly one version included in a Clientset. type Clientset struct { *discovery.DiscoveryClient - testsV1 *v1.TestsV1Client - testsV2 *v2.TestsV2Client - testsV3 *v3.TestsV3Client + testsV1 *v1.TestsV1Client + testsV2 *v2.TestsV2Client + testsV3 *v3.TestsV3Client + executorV1 *executorv1.ExecutorV1Client } // TestsV1 retrieves the TestsV1Client @@ -59,6 +62,11 @@ func (c *Clientset) TestsV3() v3.TestsV3Interface { return c.testsV3 } +// ExecutorV1 retrieves the ExecutorV1Client +func (c *Clientset) ExecutorV1() executorv1.ExecutorV1Interface { + return c.executorV1 +} + // Discovery retrieves the DiscoveryClient func (c *Clientset) Discovery() discovery.DiscoveryInterface { if c == nil { @@ -118,6 +126,11 @@ func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, return nil, err } + cs.executorV1, err = executorv1.NewForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } + cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient) if err != nil { return nil, err @@ -141,6 +154,7 @@ func New(c rest.Interface) *Clientset { cs.testsV1 = v1.New(c) cs.testsV2 = v2.New(c) cs.testsV3 = v3.New(c) + cs.executorV1 = executorv1.New(c) cs.DiscoveryClient = discovery.NewDiscoveryClient(c) return &cs diff --git a/pkg/clientset/versioned/fake/clientset_generated.go b/pkg/clientset/versioned/fake/clientset_generated.go index df064f8d..1cd3bb75 100644 --- a/pkg/clientset/versioned/fake/clientset_generated.go +++ b/pkg/clientset/versioned/fake/clientset_generated.go @@ -18,8 +18,10 @@ package fake import ( "github.com/kubeshop/testkube-operator/pkg/clientset/versioned" - v1 "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/typed/tests/v1" - fakev1 "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/typed/tests/v1/fake" + executorv1 "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/typed/executor/v1" + fakeexecutorv1 "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/typed/executor/v1/fake" + testsv1 "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/typed/tests/v1" + faketestsv1 "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/typed/tests/v1/fake" v2 "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/typed/tests/v2" fakev2 "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/typed/tests/v2/fake" v3 "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/typed/tests/v3" @@ -82,8 +84,8 @@ var ( ) // TestsV1 retrieves the TestsV1Client -func (c *Clientset) TestsV1() v1.TestsV1Interface { - return &fakev1.FakeTestsV1{Fake: &c.Fake} +func (c *Clientset) TestsV1() testsv1.TestsV1Interface { + return &faketestsv1.FakeTestsV1{Fake: &c.Fake} } // TestsV2 retrieves the TestsV2Client @@ -95,3 +97,8 @@ func (c *Clientset) TestsV2() v2.TestsV2Interface { func (c *Clientset) TestsV3() v3.TestsV3Interface { return &fakev3.FakeTestsV3{Fake: &c.Fake} } + +// ExecutorV1 retrieves the ExecutorV1Client +func (c *Clientset) ExecutorV1() executorv1.ExecutorV1Interface { + return &fakeexecutorv1.FakeExecutorV1{Fake: &c.Fake} +} diff --git a/pkg/clientset/versioned/fake/register.go b/pkg/clientset/versioned/fake/register.go index 59f07697..03e23633 100644 --- a/pkg/clientset/versioned/fake/register.go +++ b/pkg/clientset/versioned/fake/register.go @@ -17,6 +17,7 @@ limitations under the License. package fake import ( + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" @@ -34,6 +35,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{ testtriggersv1.AddToScheme, testsuitev3.AddToScheme, testsv3.AddToScheme, + executorv1.AddToScheme, } // AddToScheme adds all types of this clientset into the given scheme. This allows composition diff --git a/pkg/clientset/versioned/scheme/register.go b/pkg/clientset/versioned/scheme/register.go index 440f31bc..91a719c6 100644 --- a/pkg/clientset/versioned/scheme/register.go +++ b/pkg/clientset/versioned/scheme/register.go @@ -17,6 +17,7 @@ limitations under the License. package scheme import ( + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" @@ -34,6 +35,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{ testtriggersv1.AddToScheme, testsuitev3.AddToScheme, testsv3.AddToScheme, + executorv1.AddToScheme, } // AddToScheme adds all types of this clientset into the given scheme. This allows composition diff --git a/pkg/clientset/versioned/typed/executor/v1/doc.go b/pkg/clientset/versioned/typed/executor/v1/doc.go new file mode 100644 index 00000000..f8a9fe1f --- /dev/null +++ b/pkg/clientset/versioned/typed/executor/v1/doc.go @@ -0,0 +1,17 @@ +/* +Copyright 2021. + +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 v1 diff --git a/pkg/clientset/versioned/typed/executor/v1/executor.go b/pkg/clientset/versioned/typed/executor/v1/executor.go new file mode 100644 index 00000000..98148d72 --- /dev/null +++ b/pkg/clientset/versioned/typed/executor/v1/executor.go @@ -0,0 +1,88 @@ +/* +Copyright 2021. + +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 v1 + +import ( + "context" + "time" + + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" + "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/scheme" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/rest" +) + +// ExecutorGetter has a method to return a ExecutorInterface. +// A group's client should implement this interface. +type ExecutorGetter interface { + Executor(namespace string) ExecutorInterface +} + +// ExecutorInterface has methods to work with Executor resources. +type ExecutorInterface interface { + List(ctx context.Context, opts v1.ListOptions) (*executorv1.ExecutorList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + ExecutorExpansion +} + +// executors implements ExecutorInterface +type executors struct { + client rest.Interface + ns string +} + +// newExecutor returns a Executor +func newExecutor(c *ExecutorV1Client, namespace string) *executors { + return &executors{ + client: c.RESTClient(), + ns: namespace, + } +} + +// List takes label and field selectors, and returns the list of Executor that match those selectors. +func (c *executors) List(ctx context.Context, opts v1.ListOptions) (result *executorv1.ExecutorList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &executorv1.ExecutorList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("executors"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested executors. +func (c *executors) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("executors"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} diff --git a/pkg/clientset/versioned/typed/executor/v1/executor_client.go b/pkg/clientset/versioned/typed/executor/v1/executor_client.go new file mode 100644 index 00000000..0f798848 --- /dev/null +++ b/pkg/clientset/versioned/typed/executor/v1/executor_client.go @@ -0,0 +1,111 @@ +/* +Copyright 2021. + +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 v1 + +import ( + "net/http" + + "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/scheme" + + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" + "k8s.io/client-go/rest" +) + +type ExecutorV1Interface interface { + RESTClient() rest.Interface + ExecutorGetter + WebhookGetter +} + +// ExecutorV1Client is used to interact with features provided by the executor.testkube.io group. +type ExecutorV1Client struct { + restClient rest.Interface +} + +func (c *ExecutorV1Client) Executor(namespace string) ExecutorInterface { + return newExecutor(c, namespace) +} + +func (c *ExecutorV1Client) Webhook(namespace string) WebhookInterface { + return newWebhook(c, namespace) +} + +// NewForConfig creates a new ExecutorV1Client for the given config. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*ExecutorV1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + httpClient, err := rest.HTTPClientFor(&config) + if err != nil { + return nil, err + } + return NewForConfigAndClient(&config, httpClient) +} + +// NewForConfigAndClient creates a new ExecutorV1Client for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +func NewForConfigAndClient(c *rest.Config, h *http.Client) (*ExecutorV1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientForConfigAndClient(&config, h) + if err != nil { + return nil, err + } + return &ExecutorV1Client{client}, nil +} + +// NewForConfigOrDie creates a new ExecutorV1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *ExecutorV1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new ExecutorV1Client for the given RESTClient. +func New(c rest.Interface) *ExecutorV1Client { + return &ExecutorV1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := executorv1.GroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *ExecutorV1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/clientset/versioned/typed/executor/v1/fake/doc.go b/pkg/clientset/versioned/typed/executor/v1/fake/doc.go new file mode 100644 index 00000000..3487a31c --- /dev/null +++ b/pkg/clientset/versioned/typed/executor/v1/fake/doc.go @@ -0,0 +1,17 @@ +/* +Copyright 2021. + +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 fake diff --git a/pkg/clientset/versioned/typed/executor/v1/fake/fake_executor.go b/pkg/clientset/versioned/typed/executor/v1/fake/fake_executor.go new file mode 100644 index 00000000..2fb85924 --- /dev/null +++ b/pkg/clientset/versioned/typed/executor/v1/fake/fake_executor.go @@ -0,0 +1,72 @@ +/* +Copyright 2021. + +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 fake + +import ( + "context" + "fmt" + + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/testing" +) + +// FakeExecutor implements ExecutorInterface +type FakeExecutor struct { + Fake *FakeExecutorV1 + ns string +} + +var executorResource = schema.GroupVersionResource{Group: "executor.testkube.io", Version: "v1", Resource: "Executor"} + +var executorKind = schema.GroupVersionKind{Group: "executor.testkube.io", Version: "v1", Kind: "Executor"} + +// List takes label and field selectors, and returns the list of Executors that match those selectors. +func (c *FakeExecutor) List(ctx context.Context, opts v1.ListOptions) (result *executorv1.ExecutorList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(executorResource, executorKind, c.ns, opts), &executorv1.ExecutorList{}) + + if err != nil { + return nil, err + } + + if obj == nil { + return nil, fmt.Errorf("empty object") + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &executorv1.ExecutorList{ListMeta: obj.(*executorv1.ExecutorList).ListMeta} + for _, item := range obj.(*executorv1.ExecutorList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested Executors. +func (c *FakeExecutor) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(executorResource, c.ns, opts)) +} diff --git a/pkg/clientset/versioned/typed/executor/v1/fake/fake_tests_client.go b/pkg/clientset/versioned/typed/executor/v1/fake/fake_tests_client.go new file mode 100644 index 00000000..a560f7fb --- /dev/null +++ b/pkg/clientset/versioned/typed/executor/v1/fake/fake_tests_client.go @@ -0,0 +1,42 @@ +/* +Copyright 2021. + +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 fake + +import ( + v1 "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/typed/executor/v1" + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeExecutorV1 struct { + *testing.Fake +} + +func (c *FakeExecutorV1) Executor(namespace string) v1.ExecutorInterface { + return &FakeExecutor{c, namespace} +} + +func (c *FakeExecutorV1) Webhook(namespace string) v1.WebhookInterface { + return &FakeWebhook{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeExecutorV1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/clientset/versioned/typed/executor/v1/fake/fake_webhook.go b/pkg/clientset/versioned/typed/executor/v1/fake/fake_webhook.go new file mode 100644 index 00000000..2a847707 --- /dev/null +++ b/pkg/clientset/versioned/typed/executor/v1/fake/fake_webhook.go @@ -0,0 +1,72 @@ +/* +Copyright 2021. + +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 fake + +import ( + "context" + "fmt" + + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/testing" +) + +// FakeWebhook implements WebhookInterface +type FakeWebhook struct { + Fake *FakeExecutorV1 + ns string +} + +var webhookResource = schema.GroupVersionResource{Group: "executor.testkube.io", Version: "v1", Resource: "Webhook"} + +var webhookKind = schema.GroupVersionKind{Group: "executor.testkube.io", Version: "v1", Kind: "Webhook"} + +// List takes label and field selectors, and returns the list of Webhook that match those selectors. +func (c *FakeWebhook) List(ctx context.Context, opts v1.ListOptions) (result *executorv1.WebhookList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(webhookResource, webhookKind, c.ns, opts), &executorv1.WebhookList{}) + + if err != nil { + return nil, err + } + + if obj == nil { + return nil, fmt.Errorf("empty object") + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &executorv1.WebhookList{ListMeta: obj.(*executorv1.WebhookList).ListMeta} + for _, item := range obj.(*executorv1.WebhookList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested Webhooks. +func (c *FakeWebhook) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(webhookResource, c.ns, opts)) +} diff --git a/pkg/clientset/versioned/typed/executor/v1/generated_expansion.go b/pkg/clientset/versioned/typed/executor/v1/generated_expansion.go new file mode 100644 index 00000000..8081a33f --- /dev/null +++ b/pkg/clientset/versioned/typed/executor/v1/generated_expansion.go @@ -0,0 +1,21 @@ +/* +Copyright 2021. + +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 v1 + +type ExecutorExpansion interface{} + +type WebhookExpansion interface{} diff --git a/pkg/clientset/versioned/typed/executor/v1/webhook.go b/pkg/clientset/versioned/typed/executor/v1/webhook.go new file mode 100644 index 00000000..1ac531fc --- /dev/null +++ b/pkg/clientset/versioned/typed/executor/v1/webhook.go @@ -0,0 +1,88 @@ +/* +Copyright 2021. + +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 v1 + +import ( + "context" + "time" + + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" + "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/scheme" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/rest" +) + +// WebhookGetter has a method to return a WebhookInterface. +// A group's client should implement this interface. +type WebhookGetter interface { + Webhook(namespace string) WebhookInterface +} + +// WebhookInterface has methods to work with Webhook resources. +type WebhookInterface interface { + List(ctx context.Context, opts v1.ListOptions) (*executorv1.WebhookList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + WebhookExpansion +} + +// webhooks implements WebhookInterface +type webhooks struct { + client rest.Interface + ns string +} + +// newWebhook returns a Webhook +func newWebhook(c *ExecutorV1Client, namespace string) *webhooks { + return &webhooks{ + client: c.RESTClient(), + ns: namespace, + } +} + +// List takes label and field selectors, and returns the list of Webhook that match those selectors. +func (c *webhooks) List(ctx context.Context, opts v1.ListOptions) (result *executorv1.WebhookList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &executorv1.WebhookList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("webhooks"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested webhooks. +func (c *webhooks) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("webhooks"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} diff --git a/pkg/clientset/versioned/typed/tests/v1/fake/fake_tests_client.go b/pkg/clientset/versioned/typed/tests/v1/fake/fake_tests_client.go index 53b246c9..798d8d8d 100644 --- a/pkg/clientset/versioned/typed/tests/v1/fake/fake_tests_client.go +++ b/pkg/clientset/versioned/typed/tests/v1/fake/fake_tests_client.go @@ -30,6 +30,10 @@ func (c *FakeTestsV1) TestTriggers(namespace string) v1.TestTriggerInterface { return &FakeTestTriggers{c, namespace} } +func (c *FakeTestsV1) TestSource(namespace string) v1.TestSourceInterface { + return &FakeTestSource{c, namespace} +} + // RESTClient returns a RESTClient that is used to communicate // with API server by this client implementation. func (c *FakeTestsV1) RESTClient() rest.Interface { diff --git a/pkg/clientset/versioned/typed/tests/v1/fake/fake_testsource.go b/pkg/clientset/versioned/typed/tests/v1/fake/fake_testsource.go new file mode 100644 index 00000000..b59df96e --- /dev/null +++ b/pkg/clientset/versioned/typed/tests/v1/fake/fake_testsource.go @@ -0,0 +1,171 @@ +/* +Copyright 2021. + +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 fake + +import ( + "context" + "fmt" + + testsourcev1 "github.com/kubeshop/testkube-operator/api/testsource/v1" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/testing" +) + +// FakeTestSource implements TestSourceInterface +type FakeTestSource struct { + Fake *FakeTestsV1 + ns string +} + +var testSourceResource = schema.GroupVersionResource{Group: "tests.testkube.io", Version: "v1", Resource: "TestSource"} + +var testSourceKind = schema.GroupVersionKind{Group: "tests.testkube.io", Version: "v1", Kind: "TestSource"} + +// Get takes name of the testSource, and returns the corresponding testSource object, and an error if there is any. +func (c *FakeTestSource) Get(ctx context.Context, name string, options v1.GetOptions) (result *testsourcev1.TestSource, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(testSourceResource, c.ns, name), &testsourcev1.TestSource{}) + + if err != nil { + return nil, err + } + + if obj == nil { + return nil, fmt.Errorf("empty object %v", name) + } + + return obj.(*testsourcev1.TestSource), err +} + +// List takes label and field selectors, and returns the list of TestSource that match those selectors. +func (c *FakeTestSource) List(ctx context.Context, opts v1.ListOptions) (result *testsourcev1.TestSourceList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(testSourceResource, testSourceKind, c.ns, opts), &testsourcev1.TestSourceList{}) + + if err != nil { + return nil, err + } + + if obj == nil { + return nil, fmt.Errorf("empty object") + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &testsourcev1.TestSourceList{ListMeta: obj.(*testsourcev1.TestSourceList).ListMeta} + for _, item := range obj.(*testsourcev1.TestSourceList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested testSource. +func (c *FakeTestSource) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(testSourceResource, c.ns, opts)) + +} + +// Create takes the representation of a testSource and creates it. Returns the server's representation of the testSource, and an error, if there is any. +func (c *FakeTestSource) Create(ctx context.Context, testSource *testsourcev1.TestSource, opts v1.CreateOptions) (result *testsourcev1.TestSource, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(testSourceResource, c.ns, testSource), &testsourcev1.TestSource{}) + + if err != nil { + return nil, err + } + + if obj == nil { + return nil, fmt.Errorf("empty object") + } + + return obj.(*testsourcev1.TestSource), err +} + +// Update takes the representation of a testSource and updates it. Returns the server's representation of the testSource, and an error, if there is any. +func (c *FakeTestSource) Update(ctx context.Context, testSource *testsourcev1.TestSource, opts v1.UpdateOptions) (result *testsourcev1.TestSource, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(testSourceResource, c.ns, testSource), &testsourcev1.TestSource{}) + + if err != nil { + return nil, err + } + + if obj == nil { + return nil, fmt.Errorf("empty object") + } + + return obj.(*testsourcev1.TestSource), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeTestSource) UpdateStatus(ctx context.Context, testSource *testsourcev1.TestSource, opts v1.UpdateOptions) (*testsourcev1.TestSource, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(testSourceResource, "status", c.ns, testSource), &testsourcev1.TestSource{}) + + if err != nil { + return nil, err + } + + if obj == nil { + return nil, fmt.Errorf("empty object") + } + + return obj.(*testsourcev1.TestSource), err +} + +// Delete takes name of the testSource and deletes it. Returns an error if one occurs. +func (c *FakeTestSource) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(testSourceResource, c.ns, name, opts), &testsourcev1.TestSource{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeTestSource) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(testSourceResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &testsourcev1.TestSourceList{}) + return err +} + +// Patch applies the patch and returns the patched testSource. +func (c *FakeTestSource) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *testsourcev1.TestSource, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(testSourceResource, c.ns, name, pt, data, subresources...), &testsourcev1.TestSource{}) + + if err != nil { + return nil, err + } + + if obj == nil { + return nil, fmt.Errorf("empty object") + } + + return obj.(*testsourcev1.TestSource), err +} diff --git a/pkg/clientset/versioned/typed/tests/v1/generated_expansion.go b/pkg/clientset/versioned/typed/tests/v1/generated_expansion.go index d234e4a7..bfc26d75 100644 --- a/pkg/clientset/versioned/typed/tests/v1/generated_expansion.go +++ b/pkg/clientset/versioned/typed/tests/v1/generated_expansion.go @@ -17,3 +17,5 @@ limitations under the License. package v1 type TestTriggerExpansion interface{} + +type TestSourceExpansion interface{} diff --git a/pkg/clientset/versioned/typed/tests/v1/tests_client.go b/pkg/clientset/versioned/typed/tests/v1/tests_client.go index 291f43ae..df48635c 100644 --- a/pkg/clientset/versioned/typed/tests/v1/tests_client.go +++ b/pkg/clientset/versioned/typed/tests/v1/tests_client.go @@ -17,16 +17,19 @@ limitations under the License. package v1 import ( - "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/scheme" "net/http" + "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/scheme" + testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" + "k8s.io/client-go/rest" ) type TestsV1Interface interface { RESTClient() rest.Interface TestTriggersGetter + TestSourceGetter } // TestsV1Client is used to interact with features provided by the tests.testkube.io group. @@ -38,6 +41,10 @@ func (c *TestsV1Client) TestTriggers(namespace string) TestTriggerInterface { return newTestTriggers(c, namespace) } +func (c *TestsV1Client) TestSource(namespace string) TestSourceInterface { + return newTestSource(c, namespace) +} + // NewForConfig creates a new TestsV1Client for the given config. // NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), // where httpClient was generated with rest.HTTPClientFor(c). diff --git a/pkg/clientset/versioned/typed/tests/v1/testsource.go b/pkg/clientset/versioned/typed/tests/v1/testsource.go new file mode 100644 index 00000000..e1fb073e --- /dev/null +++ b/pkg/clientset/versioned/typed/tests/v1/testsource.go @@ -0,0 +1,194 @@ +/* +Copyright 2021. + +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 v1 + +import ( + "context" + "time" + + testsourcev1 "github.com/kubeshop/testkube-operator/api/testsource/v1" + "github.com/kubeshop/testkube-operator/pkg/clientset/versioned/scheme" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/rest" +) + +// TestSourceGetter has a method to return a TestSourceInterface. +// A group's client should implement this interface. +type TestSourceGetter interface { + TestSource(namespace string) TestSourceInterface +} + +// TestSourceInterface has methods to work with TestSource resources. +type TestSourceInterface interface { + Create(ctx context.Context, testSource *testsourcev1.TestSource, opts v1.CreateOptions) (*testsourcev1.TestSource, error) + Update(ctx context.Context, testSource *testsourcev1.TestSource, opts v1.UpdateOptions) (*testsourcev1.TestSource, error) + UpdateStatus(ctx context.Context, testSource *testsourcev1.TestSource, opts v1.UpdateOptions) (*testsourcev1.TestSource, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*testsourcev1.TestSource, error) + List(ctx context.Context, opts v1.ListOptions) (*testsourcev1.TestSourceList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *testsourcev1.TestSource, err error) + TestSourceExpansion +} + +// testSource implements TestSourceInterface +type testSource struct { + client rest.Interface + ns string +} + +// newTestSource returns a TestSource +func newTestSource(c *TestsV1Client, namespace string) *testSource { + return &testSource{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the testSource, and returns the corresponding testSource object, and an error if there is any. +func (c *testSource) Get(ctx context.Context, name string, options v1.GetOptions) (result *testsourcev1.TestSource, err error) { + result = &testsourcev1.TestSource{} + err = c.client.Get(). + Namespace(c.ns). + Resource("testsources"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of TestSource that match those selectors. +func (c *testSource) List(ctx context.Context, opts v1.ListOptions) (result *testsourcev1.TestSourceList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &testsourcev1.TestSourceList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("testsources"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested testSource. +func (c *testSource) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("testsources"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a testSource and creates it. Returns the server's representation of the testSource, and an error, if there is any. +func (c *testSource) Create(ctx context.Context, testSource *testsourcev1.TestSource, opts v1.CreateOptions) (result *testsourcev1.TestSource, err error) { + result = &testsourcev1.TestSource{} + err = c.client.Post(). + Namespace(c.ns). + Resource("testsources"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(testSource). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a testSource and updates it. Returns the server's representation of the testSource, and an error, if there is any. +func (c *testSource) Update(ctx context.Context, testSource *testsourcev1.TestSource, opts v1.UpdateOptions) (result *testsourcev1.TestSource, err error) { + result = &testsourcev1.TestSource{} + err = c.client.Put(). + Namespace(c.ns). + Resource("testsources"). + Name(testSource.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(testSource). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *testSource) UpdateStatus(ctx context.Context, testSource *testsourcev1.TestSource, opts v1.UpdateOptions) (result *testsourcev1.TestSource, err error) { + result = &testsourcev1.TestSource{} + err = c.client.Put(). + Namespace(c.ns). + Resource("testsources"). + Name(testSource.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(testSource). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the testSource and deletes it. Returns an error if one occurs. +func (c *testSource) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("testsources"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *testSource) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("testsources"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched testSource. +func (c *testSource) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *testsourcev1.TestSource, err error) { + result = &testsourcev1.TestSource{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("testsources"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/informers/externalversions/executor/interface.go b/pkg/informers/externalversions/executor/interface.go new file mode 100644 index 00000000..b8661e35 --- /dev/null +++ b/pkg/informers/externalversions/executor/interface.go @@ -0,0 +1,48 @@ +/* +Copyright 2021. + +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 executor + +import ( + v1 "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/executor/v1" + "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/internalinterfaces" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1 provides access to shared informers for resources in V1 version. + V1() v1.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New( + f internalinterfaces.SharedInformerFactory, + namespace string, + tweakListOptions internalinterfaces.TweakListOptionsFunc, +) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1 returns a new v1.Interface. +func (g *group) V1() v1.Interface { + return v1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/pkg/informers/externalversions/executor/v1/executor.go b/pkg/informers/externalversions/executor/v1/executor.go new file mode 100644 index 00000000..ad6ae051 --- /dev/null +++ b/pkg/informers/externalversions/executor/v1/executor.go @@ -0,0 +1,94 @@ +/* +Copyright 2021. + +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 v1 + +import ( + "context" + "time" + + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" + "github.com/kubeshop/testkube-operator/pkg/clientset/versioned" + "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/internalinterfaces" + executorlisterv1 "github.com/kubeshop/testkube-operator/pkg/listers/executor/v1" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/tools/cache" +) + +// ExecutorInformer provides access to a shared informer and lister for Executor. +type ExecutorInformer interface { + Informer() cache.SharedIndexInformer + Lister() executorlisterv1.ExecutorLister +} + +type executorInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewExecutorInformer constructs a new informer for Executor type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory print and number of connections to the server. +func NewExecutorInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredExecutorInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredExecutorInformer constructs a new informer for Executor type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory print and number of connections to the server. +func NewFilteredExecutorInformer( + client versioned.Interface, + namespace string, + resyncPeriod time.Duration, + indexers cache.Indexers, + tweakListOptions internalinterfaces.TweakListOptionsFunc, +) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ExecutorV1().Executor(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ExecutorV1().Executor(namespace).Watch(context.TODO(), options) + }, + }, + &executorv1.Executor{}, + resyncPeriod, + indexers, + ) +} + +func (f *executorInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredExecutorInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *executorInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&executorv1.Executor{}, f.defaultInformer) +} + +func (f *executorInformer) Lister() executorlisterv1.ExecutorLister { + return executorlisterv1.NewExecutorLister(f.Informer().GetIndexer()) +} diff --git a/pkg/informers/externalversions/executor/v1/interface.go b/pkg/informers/externalversions/executor/v1/interface.go new file mode 100644 index 00000000..71e12744 --- /dev/null +++ b/pkg/informers/externalversions/executor/v1/interface.go @@ -0,0 +1,52 @@ +/* +Copyright 2021. + +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 v1 + +import "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/internalinterfaces" + +// Interface provides access to all the informers in this group version. +type Interface interface { + // Executor returns an ExecutorInformer. + Executor() ExecutorInformer + // Webhook returns a WebhookInformer. + Webhook() WebhookInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New( + f internalinterfaces.SharedInformerFactory, + namespace string, + tweakListOptions internalinterfaces.TweakListOptionsFunc, +) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// Executor returns an ExecutorInformer. +func (v *version) Executor() ExecutorInformer { + return &executorInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// Webhook returns a WebhookInformer. +func (v *version) Webhook() WebhookInformer { + return &webhookInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/informers/externalversions/executor/v1/webhook.go b/pkg/informers/externalversions/executor/v1/webhook.go new file mode 100644 index 00000000..223337c2 --- /dev/null +++ b/pkg/informers/externalversions/executor/v1/webhook.go @@ -0,0 +1,94 @@ +/* +Copyright 2021. + +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 v1 + +import ( + "context" + "time" + + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" + "github.com/kubeshop/testkube-operator/pkg/clientset/versioned" + "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/internalinterfaces" + executorlisterv1 "github.com/kubeshop/testkube-operator/pkg/listers/executor/v1" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/tools/cache" +) + +// WebhookInformer provides access to a shared informer and lister for Webhook. +type WebhookInformer interface { + Informer() cache.SharedIndexInformer + Lister() executorlisterv1.WebhookLister +} + +type webhookInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewWebhookInformer constructs a new informer for Webhook type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory print and number of connections to the server. +func NewWebhookInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredWebhookInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredWebhookInformer constructs a new informer for Webhook type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory print and number of connections to the server. +func NewFilteredWebhookInformer( + client versioned.Interface, + namespace string, + resyncPeriod time.Duration, + indexers cache.Indexers, + tweakListOptions internalinterfaces.TweakListOptionsFunc, +) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ExecutorV1().Webhook(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ExecutorV1().Webhook(namespace).Watch(context.TODO(), options) + }, + }, + &executorv1.Webhook{}, + resyncPeriod, + indexers, + ) +} + +func (f *webhookInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredWebhookInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *webhookInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&executorv1.Webhook{}, f.defaultInformer) +} + +func (f *webhookInformer) Lister() executorlisterv1.WebhookLister { + return executorlisterv1.NewWebhookLister(f.Informer().GetIndexer()) +} diff --git a/pkg/informers/externalversions/factory.go b/pkg/informers/externalversions/factory.go index 5a9c1f9f..4350297e 100644 --- a/pkg/informers/externalversions/factory.go +++ b/pkg/informers/externalversions/factory.go @@ -17,13 +17,15 @@ limitations under the License. package externalversions import ( - "github.com/kubeshop/testkube-operator/pkg/clientset/versioned" - "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/internalinterfaces" - "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/tests" reflect "reflect" sync "sync" time "time" + "github.com/kubeshop/testkube-operator/pkg/clientset/versioned" + "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/executor" + "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/internalinterfaces" + "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/tests" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -169,8 +171,13 @@ type SharedInformerFactory interface { WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool Tests() tests.Interface + Executor() executor.Interface } func (f *sharedInformerFactory) Tests() tests.Interface { return tests.New(f, f.namespace, f.tweakListOptions) } + +func (f *sharedInformerFactory) Executor() executor.Interface { + return executor.New(f, f.namespace, f.tweakListOptions) +} diff --git a/pkg/informers/externalversions/generic.go b/pkg/informers/externalversions/generic.go index 4f39a45f..eb6f2e2a 100644 --- a/pkg/informers/externalversions/generic.go +++ b/pkg/informers/externalversions/generic.go @@ -17,9 +17,12 @@ limitations under the License. package externalversions import ( + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" + testsourcev1 "github.com/kubeshop/testkube-operator/api/testsource/v1" testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" + "github.com/pkg/errors" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -70,6 +73,24 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource resource: resource.GroupResource(), informer: f.Tests().V3().Tests().Informer(), }, nil + // Group=executor.testkube.io, Version=v1 + case executorv1.ExecutorGroupVersionResource: + return &genericInformer{ + resource: resource.GroupResource(), + informer: f.Executor().V1().Executor().Informer(), + }, nil + // Group=executor.testkube.io, Version=v1 + case executorv1.WebhookGroupVersionResource: + return &genericInformer{ + resource: resource.GroupResource(), + informer: f.Executor().V1().Webhook().Informer(), + }, nil + // Group=tests.testkube.io, Version=v1 + case testsourcev1.GroupVersionResource: + return &genericInformer{ + resource: resource.GroupResource(), + informer: f.Tests().V1().TestSource().Informer(), + }, nil } return nil, errors.Errorf("no informer found for %v", resource) diff --git a/pkg/informers/externalversions/tests/v1/interface.go b/pkg/informers/externalversions/tests/v1/interface.go index 8364102a..23432fb8 100644 --- a/pkg/informers/externalversions/tests/v1/interface.go +++ b/pkg/informers/externalversions/tests/v1/interface.go @@ -22,6 +22,8 @@ import "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/int type Interface interface { // TestTriggers returns a TestTriggerInformer. TestTriggers() TestTriggerInformer + // TestSource returns a TestSourceInformer. + TestSource() TestSourceInformer } type version struct { @@ -43,3 +45,8 @@ func New( func (v *version) TestTriggers() TestTriggerInformer { return &testTriggerInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } + +// TestSource returns a TestTriggerInformer. +func (v *version) TestSource() TestSourceInformer { + return &testSourceInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/informers/externalversions/tests/v1/testsource.go b/pkg/informers/externalversions/tests/v1/testsource.go new file mode 100644 index 00000000..682997af --- /dev/null +++ b/pkg/informers/externalversions/tests/v1/testsource.go @@ -0,0 +1,94 @@ +/* +Copyright 2021. + +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 v1 + +import ( + "context" + "time" + + testsourcev1 "github.com/kubeshop/testkube-operator/api/testsource/v1" + "github.com/kubeshop/testkube-operator/pkg/clientset/versioned" + "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/internalinterfaces" + testsourcelisterv1 "github.com/kubeshop/testkube-operator/pkg/listers/tests/v1" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/tools/cache" +) + +// TestSourceInformer provides access to a shared informer and lister for TestSource. +type TestSourceInformer interface { + Informer() cache.SharedIndexInformer + Lister() testsourcelisterv1.TestSourceLister +} + +type testSourceInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewTestSourceInformer constructs a new informer for TestSource type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory print and number of connections to the server. +func NewTestSourceInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredTestSourceInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredTestSourceInformer constructs a new informer for TestSource type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory print and number of connections to the server. +func NewFilteredTestSourceInformer( + client versioned.Interface, + namespace string, + resyncPeriod time.Duration, + indexers cache.Indexers, + tweakListOptions internalinterfaces.TweakListOptionsFunc, +) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TestsV1().TestSource(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TestsV1().TestSource(namespace).Watch(context.TODO(), options) + }, + }, + &testsourcev1.TestSource{}, + resyncPeriod, + indexers, + ) +} + +func (f *testSourceInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredTestSourceInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *testSourceInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&testsourcev1.TestSource{}, f.defaultInformer) +} + +func (f *testSourceInformer) Lister() testsourcelisterv1.TestSourceLister { + return testsourcelisterv1.NewTestSourceLister(f.Informer().GetIndexer()) +} diff --git a/pkg/listers/executor/v1/executors.go b/pkg/listers/executor/v1/executors.go new file mode 100644 index 00000000..2608bbe1 --- /dev/null +++ b/pkg/listers/executor/v1/executors.go @@ -0,0 +1,101 @@ +/* +Copyright 2021. + +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 v1 + +import ( + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/tools/cache" +) + +// ExecutorLister helps list Executors. +// All objects returned here must be treated as read-only. +type ExecutorLister interface { + // List lists all Executors in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*executorv1.Executor, err error) + // Executors returns an object that can list and get Executors. + Executors(namespace string) ExecutorNamespaceLister + ExecutorListerExpansion +} + +// executorLister implements the ExecutorLister interface. +type executorLister struct { + indexer cache.Indexer +} + +// NewExecutorLister returns a new ExecutorLister. +func NewExecutorLister(indexer cache.Indexer) ExecutorLister { + return &executorLister{indexer: indexer} +} + +// List lists all Executors in the indexer. +func (s *executorLister) List(selector labels.Selector) (ret []*executorv1.Executor, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*executorv1.Executor)) + }) + return ret, err +} + +// Executors returns an object that can list and get Executors. +func (s *executorLister) Executors(namespace string) ExecutorNamespaceLister { + return executorNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ExecutorNamespaceLister helps list and get Executors. +// All objects returned here must be treated as read-only. +type ExecutorNamespaceLister interface { + // List lists all Executors in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*executorv1.Executor, err error) + // Get retrieves the Executor from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*executorv1.Executor, error) + ExecutorNamespaceListerExpansion +} + +// executorNamespaceLister implements the ExecutorNamespaceLister +// interface. +type executorNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all Executors in the indexer for a given namespace. +func (s executorNamespaceLister) List(selector labels.Selector) (ret []*executorv1.Executor, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*executorv1.Executor)) + }) + return ret, err +} + +// Get retrieves the Executor from the indexer for a given namespace and name. +func (s executorNamespaceLister) Get(name string) (*executorv1.Executor, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound( + schema.GroupResource{Group: executorv1.GroupVersion.Group, Resource: executorv1.ExecutorResource}, + name, + ) + } + return obj.(*executorv1.Executor), nil +} diff --git a/pkg/listers/executor/v1/expansion_generated.go b/pkg/listers/executor/v1/expansion_generated.go new file mode 100644 index 00000000..30a233f6 --- /dev/null +++ b/pkg/listers/executor/v1/expansion_generated.go @@ -0,0 +1,31 @@ +/* +Copyright 2021. + +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 v1 + +// ExecutorListerExpansion allows custom methods to be added to ExecutorLister. +type ExecutorListerExpansion interface{} + +// ExecutorNamespaceListerExpansion allows custom methods to be added to +// ExecutorNamespaceLister. +type ExecutorNamespaceListerExpansion interface{} + +// WebhookListerExpansion allows custom methods to be added to WebhookLister. +type WebhookListerExpansion interface{} + +// WebhookNamespaceListerExpansion allows custom methods to be added to +// WebhookNamespaceLister. +type WebhookNamespaceListerExpansion interface{} diff --git a/pkg/listers/executor/v1/webhooks.go b/pkg/listers/executor/v1/webhooks.go new file mode 100644 index 00000000..e892185e --- /dev/null +++ b/pkg/listers/executor/v1/webhooks.go @@ -0,0 +1,101 @@ +/* +Copyright 2021. + +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 v1 + +import ( + executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/tools/cache" +) + +// WebhookLister helps list Webhooks. +// All objects returned here must be treated as read-only. +type WebhookLister interface { + // List lists all Webhooks in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*executorv1.Webhook, err error) + // Webhooks returns an object that can list and get Webhooks. + Webhooks(namespace string) WebhookNamespaceLister + WebhookListerExpansion +} + +// webhookLister implements the WebhookLister interface. +type webhookLister struct { + indexer cache.Indexer +} + +// NewWebhookLister returns a new WebhookLister. +func NewWebhookLister(indexer cache.Indexer) WebhookLister { + return &webhookLister{indexer: indexer} +} + +// List lists all Webhooks in the indexer. +func (s *webhookLister) List(selector labels.Selector) (ret []*executorv1.Webhook, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*executorv1.Webhook)) + }) + return ret, err +} + +// Webhooks returns an object that can list and get Webhooks. +func (s *webhookLister) Webhooks(namespace string) WebhookNamespaceLister { + return webhookNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// WebhookNamespaceLister helps list and get Webhooks. +// All objects returned here must be treated as read-only. +type WebhookNamespaceLister interface { + // List lists all Webhooks in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*executorv1.Webhook, err error) + // Get retrieves the Webhook from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*executorv1.Webhook, error) + WebhookNamespaceListerExpansion +} + +// webhookNamespaceLister implements the WebhookNamespaceLister +// interface. +type webhookNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all Webhooks in the indexer for a given namespace. +func (s webhookNamespaceLister) List(selector labels.Selector) (ret []*executorv1.Webhook, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*executorv1.Webhook)) + }) + return ret, err +} + +// Get retrieves the Webhook from the indexer for a given namespace and name. +func (s webhookNamespaceLister) Get(name string) (*executorv1.Webhook, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound( + schema.GroupResource{Group: executorv1.GroupVersion.Group, Resource: executorv1.WebhookResource}, + name, + ) + } + return obj.(*executorv1.Webhook), nil +} diff --git a/pkg/listers/tests/v1/expansion_generated.go b/pkg/listers/tests/v1/expansion_generated.go index 94be48b5..9c22b09d 100644 --- a/pkg/listers/tests/v1/expansion_generated.go +++ b/pkg/listers/tests/v1/expansion_generated.go @@ -22,3 +22,10 @@ type TestTriggerListerExpansion interface{} // TestTriggerNamespaceListerExpansion allows custom methods to be added to // TestTriggerNamespaceLister. type TestTriggerNamespaceListerExpansion interface{} + +// TestSourceListerExpansion allows custom methods to be added to TestSourceLister. +type TestSourceListerExpansion interface{} + +// TestSourceNamespaceListerExpansion allows custom methods to be added to +// TestSourceNamespaceLister. +type TestSourceNamespaceListerExpansion interface{} diff --git a/pkg/listers/tests/v1/testsource.go b/pkg/listers/tests/v1/testsource.go new file mode 100644 index 00000000..109d9fa9 --- /dev/null +++ b/pkg/listers/tests/v1/testsource.go @@ -0,0 +1,101 @@ +/* +Copyright 2021. + +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 v1 + +import ( + testsourcev1 "github.com/kubeshop/testkube-operator/api/testsource/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/tools/cache" +) + +// TestSourceLister helps list TestSources. +// All objects returned here must be treated as read-only. +type TestSourceLister interface { + // List lists all TestSources in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*testsourcev1.TestSource, err error) + // TestSources returns an object that can list and get TestSources. + TestSources(namespace string) TestSourceNamespaceLister + TestSourceListerExpansion +} + +// testSourceLister implements the TestSourceLister interface. +type testSourceLister struct { + indexer cache.Indexer +} + +// NewTestSourceLister returns a new TestSourceLister. +func NewTestSourceLister(indexer cache.Indexer) TestSourceLister { + return &testSourceLister{indexer: indexer} +} + +// List lists all TestSources in the indexer. +func (s *testSourceLister) List(selector labels.Selector) (ret []*testsourcev1.TestSource, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*testsourcev1.TestSource)) + }) + return ret, err +} + +// TestSources returns an object that can list and get TestSources. +func (s *testSourceLister) TestSources(namespace string) TestSourceNamespaceLister { + return testSourceNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// TestSourceNamespaceLister helps list and get TestSources. +// All objects returned here must be treated as read-only. +type TestSourceNamespaceLister interface { + // List lists all TestSources in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*testsourcev1.TestSource, err error) + // Get retrieves the TestSource from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*testsourcev1.TestSource, error) + TestSourceNamespaceListerExpansion +} + +// testSourceNamespaceLister implements the TestSourceNamespaceLister +// interface. +type testSourceNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all TestSources in the indexer for a given namespace. +func (s testSourceNamespaceLister) List(selector labels.Selector) (ret []*testsourcev1.TestSource, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*testsourcev1.TestSource)) + }) + return ret, err +} + +// Get retrieves the TestSource from the indexer for a given namespace and name. +func (s testSourceNamespaceLister) Get(name string) (*testsourcev1.TestSource, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound( + schema.GroupResource{Group: testsourcev1.GroupVersion.Group, Resource: testsourcev1.Resource}, + name, + ) + } + return obj.(*testsourcev1.TestSource), nil +} From 9c1a0e01bc1bab3790f0055e371fde59449e883a Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Sun, 10 Dec 2023 17:14:32 +0300 Subject: [PATCH 56/57] feat: step start and end time (#206) --- api/testsuiteexecution/v1/testsuiteexecution_types.go | 6 ++++++ api/testsuiteexecution/v1/zz_generated.deepcopy.go | 3 ++- .../bases/tests.testkube.io_testsuiteexecutions.yaml | 11 +++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/api/testsuiteexecution/v1/testsuiteexecution_types.go b/api/testsuiteexecution/v1/testsuiteexecution_types.go index f8d623ff..a9637bca 100644 --- a/api/testsuiteexecution/v1/testsuiteexecution_types.go +++ b/api/testsuiteexecution/v1/testsuiteexecution_types.go @@ -412,6 +412,12 @@ const ( type TestSuiteBatchStepExecutionResult struct { Step *TestSuiteBatchStep `json:"step,omitempty"` Execute []TestSuiteStepExecutionResult `json:"execute,omitempty"` + // step start time + StartTime metav1.Time `json:"startTime,omitempty"` + // step end time + EndTime metav1.Time `json:"endTime,omitempty"` + // step duration + Duration string `json:"duration,omitempty"` } // set of steps run in parallel diff --git a/api/testsuiteexecution/v1/zz_generated.deepcopy.go b/api/testsuiteexecution/v1/zz_generated.deepcopy.go index 027a52f4..1bfd05b3 100644 --- a/api/testsuiteexecution/v1/zz_generated.deepcopy.go +++ b/api/testsuiteexecution/v1/zz_generated.deepcopy.go @@ -1,4 +1,3 @@ -//go:build !ignore_autogenerated // +build !ignore_autogenerated /* @@ -492,6 +491,8 @@ func (in *TestSuiteBatchStepExecutionResult) DeepCopyInto(out *TestSuiteBatchSte (*in)[i].DeepCopyInto(&(*out)[i]) } } + in.StartTime.DeepCopyInto(&out.StartTime) + in.EndTime.DeepCopyInto(&out.EndTime) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestSuiteBatchStepExecutionResult. diff --git a/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml b/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml index 205a0f18..2802c827 100644 --- a/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml +++ b/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml @@ -277,6 +277,13 @@ spec: items: description: execution result returned from executor properties: + duration: + description: step duration + type: string + endTime: + description: step end time + format: date-time + type: string execute: items: description: execution result returned from executor @@ -752,6 +759,10 @@ spec: type: object type: object type: array + startTime: + description: step start time + format: date-time + type: string step: description: set of steps run in parallel properties: From 483fef2d873142e5466da3dbaac6d92a0d0ec057 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 14 Dec 2023 12:56:24 +0300 Subject: [PATCH 57/57] feat: artifact enhancement (#207) * feat: artifact enhancement * fix: previous testnames --- api/testexecution/v1/testexecution_types.go | 4 ++++ api/testexecution/v1/zz_generated.deepcopy.go | 5 +++++ api/tests/v3/test_types.go | 4 ++++ api/tests/v3/zz_generated.deepcopy.go | 5 +++++ api/testsuite/v3/testsuite_types.go | 2 ++ api/testsuite/v3/zz_generated.deepcopy.go | 5 +++++ .../v1/testsuiteexecution_types.go | 4 ++++ .../v1/zz_generated.deepcopy.go | 6 ++++++ .../tests.testkube.io_testexecutions.yaml | 18 ++++++++++++++++++ config/crd/bases/tests.testkube.io_tests.yaml | 9 +++++++++ ...tests.testkube.io_testsuiteexecutions.yaml | 19 +++++++++++++++++++ .../bases/tests.testkube.io_testsuites.yaml | 15 +++++++++++++++ 12 files changed, 96 insertions(+) diff --git a/api/testexecution/v1/testexecution_types.go b/api/testexecution/v1/testexecution_types.go index 0a7df57b..4bf821c9 100644 --- a/api/testexecution/v1/testexecution_types.go +++ b/api/testexecution/v1/testexecution_types.go @@ -36,10 +36,14 @@ type ArtifactRequest struct { VolumeMountPath string `json:"volumeMountPath"` // artifact directories for scraping Dirs []string `json:"dirs,omitempty"` + // regexp to filter scraped artifacts, single or comma separated + Masks []string `json:"masks,omitempty"` // artifact bucket storage StorageBucket string `json:"storageBucket,omitempty"` // don't use a separate folder for execution artifacts OmitFolderPerExecution bool `json:"omitFolderPerExecution,omitempty"` + // whether to share volume between pods + SharedBetweenPods bool `json:"sharedBetweenPods,omitempty"` } // running context for test or test suite execution diff --git a/api/testexecution/v1/zz_generated.deepcopy.go b/api/testexecution/v1/zz_generated.deepcopy.go index 737425e0..0c22513c 100644 --- a/api/testexecution/v1/zz_generated.deepcopy.go +++ b/api/testexecution/v1/zz_generated.deepcopy.go @@ -34,6 +34,11 @@ func (in *ArtifactRequest) DeepCopyInto(out *ArtifactRequest) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.Masks != nil { + in, out := &in.Masks, &out.Masks + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArtifactRequest. diff --git a/api/tests/v3/test_types.go b/api/tests/v3/test_types.go index 3cca982b..913e84d1 100644 --- a/api/tests/v3/test_types.go +++ b/api/tests/v3/test_types.go @@ -126,10 +126,14 @@ type ArtifactRequest struct { VolumeMountPath string `json:"volumeMountPath,omitempty"` // artifact directories for scraping Dirs []string `json:"dirs,omitempty"` + // regexp to filter scraped artifacts, single or comma separated + Masks []string `json:"masks,omitempty"` // artifact bucket storage StorageBucket string `json:"storageBucket,omitempty"` // don't use a separate folder for execution artifacts OmitFolderPerExecution bool `json:"omitFolderPerExecution,omitempty"` + // whether to share volume between pods + SharedBetweenPods bool `json:"sharedBetweenPods,omitempty"` } // RunningContext for test or test suite execution diff --git a/api/tests/v3/zz_generated.deepcopy.go b/api/tests/v3/zz_generated.deepcopy.go index bf9950b0..9098fd5e 100644 --- a/api/tests/v3/zz_generated.deepcopy.go +++ b/api/tests/v3/zz_generated.deepcopy.go @@ -34,6 +34,11 @@ func (in *ArtifactRequest) DeepCopyInto(out *ArtifactRequest) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.Masks != nil { + in, out := &in.Masks, &out.Masks + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArtifactRequest. diff --git a/api/testsuite/v3/testsuite_types.go b/api/testsuite/v3/testsuite_types.go index ef51f212..70668660 100644 --- a/api/testsuite/v3/testsuite_types.go +++ b/api/testsuite/v3/testsuite_types.go @@ -60,6 +60,8 @@ type DownloadArtifactOptions struct { AllPreviousSteps bool `json:"allPreviousSteps,omitempty"` // previous step numbers starting from 1 PreviousStepNumbers []int32 `json:"previousStepNumbers,omitempty"` + // previous test names + PreviousTestNames []string `json:"previousTestNames,omitempty"` } // TestSuiteBatchStep is set of steps run in parallel diff --git a/api/testsuite/v3/zz_generated.deepcopy.go b/api/testsuite/v3/zz_generated.deepcopy.go index d39c0360..d079906c 100644 --- a/api/testsuite/v3/zz_generated.deepcopy.go +++ b/api/testsuite/v3/zz_generated.deepcopy.go @@ -33,6 +33,11 @@ func (in *DownloadArtifactOptions) DeepCopyInto(out *DownloadArtifactOptions) { *out = make([]int32, len(*in)) copy(*out, *in) } + if in.PreviousTestNames != nil { + in, out := &in.PreviousTestNames, &out.PreviousTestNames + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DownloadArtifactOptions. diff --git a/api/testsuiteexecution/v1/testsuiteexecution_types.go b/api/testsuiteexecution/v1/testsuiteexecution_types.go index a9637bca..6c5d27ed 100644 --- a/api/testsuiteexecution/v1/testsuiteexecution_types.go +++ b/api/testsuiteexecution/v1/testsuiteexecution_types.go @@ -290,10 +290,14 @@ type ArtifactRequest struct { VolumeMountPath string `json:"volumeMountPath"` // artifact directories for scraping Dirs []string `json:"dirs,omitempty"` + // regexp to filter scraped artifacts, single or comma separated + Masks []string `json:"masks,omitempty"` // artifact bucket storage StorageBucket string `json:"storageBucket,omitempty"` // don't use a separate folder for execution artifacts OmitFolderPerExecution bool `json:"omitFolderPerExecution,omitempty"` + // whether to share volume between pods + SharedBetweenPods bool `json:"sharedBetweenPods,omitempty"` } // TestContent defines test content diff --git a/api/testsuiteexecution/v1/zz_generated.deepcopy.go b/api/testsuiteexecution/v1/zz_generated.deepcopy.go index 1bfd05b3..6c20b875 100644 --- a/api/testsuiteexecution/v1/zz_generated.deepcopy.go +++ b/api/testsuiteexecution/v1/zz_generated.deepcopy.go @@ -1,3 +1,4 @@ +//go:build !ignore_autogenerated // +build !ignore_autogenerated /* @@ -32,6 +33,11 @@ func (in *ArtifactRequest) DeepCopyInto(out *ArtifactRequest) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.Masks != nil { + in, out := &in.Masks, &out.Masks + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArtifactRequest. diff --git a/config/crd/bases/tests.testkube.io_testexecutions.yaml b/config/crd/bases/tests.testkube.io_testexecutions.yaml index e69c6e54..0987106b 100644 --- a/config/crd/bases/tests.testkube.io_testexecutions.yaml +++ b/config/crd/bases/tests.testkube.io_testexecutions.yaml @@ -64,9 +64,18 @@ spec: items: type: string type: array + masks: + description: regexp to filter scraped artifacts, single or + comma separated + items: + type: string + type: array omitFolderPerExecution: description: don't use a separate folder for execution artifacts type: boolean + sharedBetweenPods: + description: whether to share volume between pods + type: boolean storageBucket: description: artifact bucket storage type: string @@ -431,9 +440,18 @@ spec: items: type: string type: array + masks: + description: regexp to filter scraped artifacts, single or + comma separated + items: + type: string + type: array omitFolderPerExecution: description: don't use a separate folder for execution artifacts type: boolean + sharedBetweenPods: + description: whether to share volume between pods + type: boolean storageBucket: description: artifact bucket storage type: string diff --git a/config/crd/bases/tests.testkube.io_tests.yaml b/config/crd/bases/tests.testkube.io_tests.yaml index 2995e13b..4c6e6127 100644 --- a/config/crd/bases/tests.testkube.io_tests.yaml +++ b/config/crd/bases/tests.testkube.io_tests.yaml @@ -462,9 +462,18 @@ spec: items: type: string type: array + masks: + description: regexp to filter scraped artifacts, single or + comma separated + items: + type: string + type: array omitFolderPerExecution: description: don't use a separate folder for execution artifacts type: boolean + sharedBetweenPods: + description: whether to share volume between pods + type: boolean storageBucket: description: artifact bucket storage type: string diff --git a/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml b/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml index 2802c827..dddae6d9 100644 --- a/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml +++ b/config/crd/bases/tests.testkube.io_testsuiteexecutions.yaml @@ -311,10 +311,20 @@ spec: items: type: string type: array + masks: + description: regexp to filter scraped artifacts, + single or comma separated + items: + type: string + type: array omitFolderPerExecution: description: don't use a separate folder for execution artifacts type: boolean + sharedBetweenPods: + description: whether to share volume between + pods + type: boolean storageBucket: description: artifact bucket storage type: string @@ -860,10 +870,19 @@ spec: items: type: string type: array + masks: + description: regexp to filter scraped artifacts, + single or comma separated + items: + type: string + type: array omitFolderPerExecution: description: don't use a separate folder for execution artifacts type: boolean + sharedBetweenPods: + description: whether to share volume between pods + type: boolean storageBucket: description: artifact bucket storage type: string diff --git a/config/crd/bases/tests.testkube.io_testsuites.yaml b/config/crd/bases/tests.testkube.io_testsuites.yaml index f39bafaa..26a77640 100644 --- a/config/crd/bases/tests.testkube.io_testsuites.yaml +++ b/config/crd/bases/tests.testkube.io_testsuites.yaml @@ -576,6 +576,11 @@ spec: format: int32 type: integer type: array + previousTestNames: + description: previous test names + items: + type: string + type: array type: object execute: items: @@ -614,6 +619,11 @@ spec: format: int32 type: integer type: array + previousTestNames: + description: previous test names + items: + type: string + type: array type: object execute: items: @@ -818,6 +828,11 @@ spec: format: int32 type: integer type: array + previousTestNames: + description: previous test names + items: + type: string + type: array type: object execute: items: