From 12d125cfba0da4917c9f6e22a0e40630707d4b2b Mon Sep 17 00:00:00 2001 From: qingliu Date: Mon, 25 Jul 2022 17:01:41 +0800 Subject: [PATCH 1/4] feat: add generic methods * get secret by ref or labels * patch status and record event --- apis/meta/v1alpha1/resource_object_types.go | 19 ++++ apis/meta/v1alpha1/zz_generated.deepcopy.go | 25 +++++ errors/errors.go | 25 +++++ go.mod | 21 ++-- go.sum | 17 ++- patchstatus/doc.go | 18 +++ patchstatus/patch_and_record.go | 75 +++++++++++++ patchstatus/patch_and_record_test.go | 116 ++++++++++++++++++++ patchstatus/patchstatus_suite_test.go | 44 ++++++++ secret/get_secret.go | 87 +++++++++++++++ secret/get_secret_test.go | 110 +++++++++++++++++++ secret/secret_suite_test.go | 65 +++++++++++ secret/testdata/secret.has.labels.yaml | 13 +++ secret/testdata/secret.has.sync.labels.yaml | 14 +++ secret/testdata/secret.no.labels.yaml | 9 ++ testing/convert.go | 63 +++++++++++ testing/kubernetes.go | 2 + 17 files changed, 712 insertions(+), 11 deletions(-) create mode 100644 errors/errors.go create mode 100644 patchstatus/doc.go create mode 100644 patchstatus/patch_and_record.go create mode 100644 patchstatus/patch_and_record_test.go create mode 100644 patchstatus/patchstatus_suite_test.go create mode 100644 secret/get_secret.go create mode 100644 secret/get_secret_test.go create mode 100644 secret/secret_suite_test.go create mode 100644 secret/testdata/secret.has.labels.yaml create mode 100644 secret/testdata/secret.has.sync.labels.yaml create mode 100644 secret/testdata/secret.no.labels.yaml create mode 100644 testing/convert.go diff --git a/apis/meta/v1alpha1/resource_object_types.go b/apis/meta/v1alpha1/resource_object_types.go index 920d89af..1e40d7b2 100644 --- a/apis/meta/v1alpha1/resource_object_types.go +++ b/apis/meta/v1alpha1/resource_object_types.go @@ -42,3 +42,22 @@ func (r *ResourceURI) Validate(path *field.Path) field.ErrorList { errs = append(errs, kvalidation.ValidateObjectReference(r.SecretRef, false, false, path.Child("secretRef"))...) return errs } + +// ResourceURL stores a resource URL together with secret references +// for usage +type ResourceURL struct { + // url can be a specific code repository or a group + URL *apis.URL `json:"url"` + + // SecretRef stores a reference to a secret object + // that contain authentication data for the described resource + SecretRef *corev1.ObjectReference `json:"secretRef"` +} + +// Validate basic validation for ResourceURL +func (r *ResourceURL) Validate(path *field.Path) field.ErrorList { + errs := field.ErrorList{} + errs = append(errs, kvalidation.ValidateURL(r.URL, path.Child("url"))...) + errs = append(errs, kvalidation.ValidateObjectReference(r.SecretRef, false, false, path.Child("secretRef"))...) + return errs +} diff --git a/apis/meta/v1alpha1/zz_generated.deepcopy.go b/apis/meta/v1alpha1/zz_generated.deepcopy.go index ba12ffdf..43da2f7d 100644 --- a/apis/meta/v1alpha1/zz_generated.deepcopy.go +++ b/apis/meta/v1alpha1/zz_generated.deepcopy.go @@ -2776,6 +2776,31 @@ func (in *ResourceURI) DeepCopy() *ResourceURI { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceURL) DeepCopyInto(out *ResourceURL) { + *out = *in + if in.URL != nil { + in, out := &in.URL, &out.URL + *out = new(apis.URL) + (*in).DeepCopyInto(*out) + } + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + *out = new(corev1.ObjectReference) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceURL. +func (in *ResourceURL) DeepCopy() *ResourceURL { + if in == nil { + return nil + } + out := new(ResourceURL) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SortOptions) DeepCopyInto(out *SortOptions) { *out = *in diff --git a/errors/errors.go b/errors/errors.go new file mode 100644 index 00000000..7590d90c --- /dev/null +++ b/errors/errors.go @@ -0,0 +1,25 @@ +/* +Copyright 2021 The Katanomi Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package errors + +import ( + apierrors "k8s.io/apimachinery/pkg/api/errors" +) + +// ErrInvalidInputNilPoint invalid input parameters, specifically a nil point +// Although unlikely just in case +var ErrInvalidInputNilPoint = apierrors.NewBadRequest("Invalid input parameters - nil point") diff --git a/go.mod b/go.mod index e4817e01..ab0cec4f 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,6 @@ require ( github.com/opencontainers/image-spec v1.0.2 github.com/opentracing/opentracing-go v1.1.0 github.com/prometheus/client_golang v1.11.0 - github.com/sirupsen/logrus v1.8.1 // indirect github.com/uber/jaeger-client-go v2.29.1+incompatible github.com/uber/jaeger-lib v2.4.1+incompatible go.uber.org/zap v1.18.1 @@ -47,15 +46,12 @@ require ( go.opentelemetry.io/otel v1.2.0 go.opentelemetry.io/otel/exporters/jaeger v1.2.0 go.opentelemetry.io/otel/exporters/zipkin v1.2.0 - go.opentelemetry.io/otel/metric v0.25.0 // indirect go.opentelemetry.io/otel/sdk v1.2.0 go.opentelemetry.io/otel/trace v1.2.0 ) require golang.org/x/net v0.0.0-20220225172249-27dd8689420f -require github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 // indirect - require ( contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200907061046-05415f1de66d // indirect contrib.go.opencensus.io/exporter/prometheus v0.3.0 // indirect @@ -67,6 +63,7 @@ require ( github.com/blang/semver/v4 v4.0.0 // indirect github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 // indirect github.com/evanphx/json-patch v4.9.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.5.0 // indirect github.com/felixge/httpsnoop v1.0.2 // indirect @@ -75,7 +72,6 @@ require ( github.com/go-openapi/jsonreference v0.19.5 // indirect github.com/go-openapi/swag v0.19.15 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/gofuzz v1.2.0 // indirect @@ -93,20 +89,21 @@ require ( github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.1 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/openzipkin/zipkin-go v0.4.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.26.0 // indirect github.com/prometheus/procfs v0.6.0 // indirect github.com/prometheus/statsd_exporter v0.20.0 // indirect + github.com/sirupsen/logrus v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect go.opencensus.io v0.23.0 // indirect go.opentelemetry.io/otel/internal/metric v0.25.0 // indirect + go.opentelemetry.io/otel/metric v0.25.0 // indirect go.uber.org/atomic v1.8.0 // indirect go.uber.org/automaxprocs v1.4.0 // indirect go.uber.org/multierr v1.6.0 // indirect - golang.org/x/crypto v0.0.0-20210920023735-84f357641f63 // indirect + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect + golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914 // indirect golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect @@ -124,10 +121,16 @@ require ( k8s.io/apiextensions-apiserver v0.20.7 // indirect k8s.io/component-base v0.20.7 // indirect k8s.io/klog v1.0.0 // indirect - k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 sigs.k8s.io/structured-merge-diff/v4 v4.0.3 // indirect ) +require ( + github.com/golang-jwt/jwt v3.2.2+incompatible + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/openzipkin/zipkin-go v0.4.0 // indirect + k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 +) + replace ( github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283 go.uber.org/zap => github.com/katanomi/zap v1.18.2 // indirect diff --git a/go.sum b/go.sum index 32b97670..f10e83cd 100644 --- a/go.sum +++ b/go.sum @@ -93,6 +93,7 @@ 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 v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= @@ -107,6 +108,7 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -156,6 +158,7 @@ github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaB github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= 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 h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful-openapi/v2 v2.3.0 h1:tDgSCzQrkk4N+Isos0zGBYX/GTINjmQuP9BvITbEe38= github.com/emicklei/go-restful-openapi/v2 v2.3.0/go.mod h1:bs67E3SEVgSmB3qDuRLqpS0NcpheqtsCCMhW2/jml1E= @@ -319,6 +322,7 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf 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-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -511,6 +515,7 @@ github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k 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.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= 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= @@ -520,6 +525,7 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= 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/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= @@ -670,6 +676,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de 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.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= @@ -727,8 +734,9 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.0.0-20210920023735-84f357641f63 h1:kETrAMYZq6WVGPa8IIixL0CaEcIUNi+1WX7grUoi3y8= golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -765,8 +773,9 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= +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/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -814,6 +823,7 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -900,6 +910,8 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/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-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -986,6 +998,7 @@ 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.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/patchstatus/doc.go b/patchstatus/doc.go new file mode 100644 index 00000000..2c9600f2 --- /dev/null +++ b/patchstatus/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2021 The Katanomi Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package patchstatus contains patch status related functions. +package patchstatus diff --git a/patchstatus/patch_and_record.go b/patchstatus/patch_and_record.go new file mode 100644 index 00000000..d414b5eb --- /dev/null +++ b/patchstatus/patch_and_record.go @@ -0,0 +1,75 @@ +/* +Copyright 2021 The Katanomi Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package patchstatus + +import ( + "context" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/record" + "knative.dev/pkg/apis" + "knative.dev/pkg/logging" + "sigs.k8s.io/controller-runtime/pkg/client" + + metav1alpha1 "github.com/katanomi/pkg/apis/meta/v1alpha1" + kclient "github.com/katanomi/pkg/client" +) + +// PatchStatusAndRecordEvent patch status and record event +func PatchStatusAndRecordEvent( + ctx context.Context, + eventRecorder record.EventRecorder, + obj, old runtime.Object, err error, + isConditionChanged func() bool, + getTopLevelConditon func() *apis.Condition) { + + log := logging.FromContext(ctx) + clt := kclient.Client(ctx) + + patch := client.MergeFrom(old) + patchData, _ := patch.Data(obj) + clientObj, _ := obj.(client.Object) + patchErr := clt.Status().Patch(ctx, clientObj, patch) + log.Debugw("object patch result", "err", patchErr, "patchData", string(patchData)) + + if err != nil { + reason := metav1alpha1.ReasonForError(err) + if reason == "" { + reason = metav1alpha1.ErrorReason + } + eventRecorder.Eventf(obj, corev1.EventTypeWarning, reason, "error: %s", err) + return + } + + if !isConditionChanged() { + return + } + + top := getTopLevelConditon() + if top == nil { + return + } + switch top.Status { + case corev1.ConditionTrue, corev1.ConditionUnknown: + eventRecorder.Eventf(obj, corev1.EventTypeNormal, top.Reason, top.Message) + case corev1.ConditionFalse: + eventRecorder.Eventf(obj, corev1.EventTypeWarning, top.Reason, top.Message) + default: + logging.FromContext(ctx).Warnw("unknown top condition status", "status", top.Status) + } +} diff --git a/patchstatus/patch_and_record_test.go b/patchstatus/patch_and_record_test.go new file mode 100644 index 00000000..68a323d0 --- /dev/null +++ b/patchstatus/patch_and_record_test.go @@ -0,0 +1,116 @@ +/* +Copyright 2021 The Katanomi Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package patchstatus + +import ( + "context" + "errors" + + kclient "github.com/katanomi/pkg/client" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/record" + "knative.dev/pkg/apis" + "knative.dev/pkg/logging" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +var _ = Describe("Test.PatchStatusAndRecordEvent", func() { + var ( + ctx context.Context + clt client.Client + configmap *corev1.ConfigMap + recorder record.EventRecorder + fakeRecorder *record.FakeRecorder + err error + isConditionChanged func() bool + getTopLevelConditon func() *apis.Condition + ) + + BeforeEach(func() { + err = nil + ctx = context.TODO() + configmap = &corev1.ConfigMap{} + clt = fake.NewClientBuilder().WithScheme(scheme).Build() + ctx = kclient.WithClient(ctx, clt) + ctx = logging.WithLogger(ctx, logger) + recorder = record.NewFakeRecorder(100) + fakeRecorder, _ = recorder.(*record.FakeRecorder) + isConditionChanged = func() bool { return false } + getTopLevelConditon = func() *apis.Condition { return nil } + }) + + JustBeforeEach(func() { + PatchStatusAndRecordEvent(ctx, recorder, configmap, configmap, err, isConditionChanged, getTopLevelConditon) + }) + + When("err is not nil", func() { + BeforeEach(func() { + err = errors.New("test error") + }) + It("should record event", func() { + msg := <-fakeRecorder.Events + Expect(msg).To(Equal("Warning Error error: test error")) + }) + }) + + Describe("condition changed", func() { + BeforeEach(func() { + isConditionChanged = func() bool { return true } + }) + + When("condition status is unknown", func() { + BeforeEach(func() { + isConditionChanged = func() bool { return true } + getTopLevelConditon = func() *apis.Condition { + return &apis.Condition{ + Type: apis.ConditionSucceeded, + Status: corev1.ConditionUnknown, + Message: "test message", + Reason: string(metav1.StatusReasonBadRequest), + } + } + }) + It("should record event", func() { + msg := <-fakeRecorder.Events + Expect(msg).To(Equal("Normal BadRequest test message")) + }) + }) + + When("condition status is false", func() { + BeforeEach(func() { + isConditionChanged = func() bool { return true } + getTopLevelConditon = func() *apis.Condition { + return &apis.Condition{ + Type: apis.ConditionSucceeded, + Status: corev1.ConditionFalse, + Message: "test message", + Reason: string(metav1.StatusReasonBadRequest), + } + } + }) + It("should record event", func() { + msg := <-fakeRecorder.Events + Expect(msg).To(Equal("Warning BadRequest test message")) + }) + }) + }) + +}) diff --git a/patchstatus/patchstatus_suite_test.go b/patchstatus/patchstatus_suite_test.go new file mode 100644 index 00000000..198716c1 --- /dev/null +++ b/patchstatus/patchstatus_suite_test.go @@ -0,0 +1,44 @@ +/* +Copyright 2021 The Katanomi Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package patchstatus + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + uberzap "go.uber.org/zap" + "k8s.io/apimachinery/pkg/runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" +) + +var ( + scheme = runtime.NewScheme() + logger *uberzap.SugaredLogger +) + +func init() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + logger = zap.NewRaw(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)).Sugar() +} + +func TestPatchstatus(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Patchstatus Suite") +} diff --git a/secret/get_secret.go b/secret/get_secret.go new file mode 100644 index 00000000..1b54aa13 --- /dev/null +++ b/secret/get_secret.go @@ -0,0 +1,87 @@ +/* +Copyright 2021 The Katanomi Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package secret + +import ( + "context" + "fmt" + + pkgnamespace "github.com/katanomi/pkg/namespace" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/logging" + "sigs.k8s.io/controller-runtime/pkg/client" + + metav1alpha1 "github.com/katanomi/pkg/apis/meta/v1alpha1" + kerrors "github.com/katanomi/pkg/errors" +) + +// GetSecretByRefOrLabel retrieves an secret +// If the ref.namespace is empty, it will use the namespace from the ctx. +// If the resource does not exist, it will try to match according to the label. +func GetSecretByRefOrLabel(ctx context.Context, clt client.Client, ref *corev1.ObjectReference) (obj *corev1.Secret, err error) { + if clt == nil || ref == nil { + return nil, kerrors.ErrInvalidInputNilPoint + } + + log := logging.FromContext(ctx) + obj = &corev1.Secret{} + objKey := client.ObjectKey{Namespace: ref.Namespace, Name: ref.Name} + if objKey.Namespace == "" { + objKey.Namespace = pkgnamespace.NamespaceValue(ctx) + } + if err = clt.Get(ctx, objKey, obj); err == nil { + return obj, nil + } else if !apierrors.IsNotFound(err) { + return nil, err + } + + // not found secret, we should find secret by labels + matchingLabels := map[string]string{ + metav1alpha1.NamespaceLabelKey: objKey.Namespace, + metav1alpha1.SecretLabelKey: objKey.Name, + } + + // label selector to select secret matching ns and name matched and the original secret + labelSelector := &metav1.LabelSelector{ + MatchLabels: matchingLabels, + MatchExpressions: []metav1.LabelSelectorRequirement{{ + Key: metav1alpha1.SecretSyncMutationLabelKey, + Operator: metav1.LabelSelectorOpDoesNotExist, + }}, + } + selector, err := metav1.LabelSelectorAsSelector(labelSelector) + if err != nil { + return nil, err + } + + secretList := &corev1.SecretList{} + if err = clt.List(ctx, secretList, client.InNamespace(objKey.Namespace), client.MatchingLabelsSelector{Selector: selector}); err != nil { + return nil, err + } + + if len(secretList.Items) == 0 { + log.Errorw("not found any secret by labels", "labels", matchingLabels, "secretRef", ref) + err = fmt.Errorf("secret %s not exist or matching by labels '%v'", objKey.String(), matchingLabels) + return nil, err + } + if len(secretList.Items) > 1 { + log.Infow("found multiple secrets by labels", "labels", matchingLabels, "#secretList.Items", len(secretList.Items)) + } + return &secretList.Items[0], nil +} diff --git a/secret/get_secret_test.go b/secret/get_secret_test.go new file mode 100644 index 00000000..3e4064c6 --- /dev/null +++ b/secret/get_secret_test.go @@ -0,0 +1,110 @@ +/* +Copyright 2021 The Katanomi Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package secret + +import ( + "context" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + + pkgClient "github.com/katanomi/pkg/client" + kerrors "github.com/katanomi/pkg/errors" + pkgnamespace "github.com/katanomi/pkg/namespace" + "github.com/katanomi/pkg/testing" +) + +var _ = Describe("Test.GetSecretByRefOrLabel", func() { + var ( + ctx context.Context + clt client.Client + secret *corev1.Secret + ref *corev1.ObjectReference + err error + ) + + BeforeEach(func() { + ctx = context.TODO() + ref = &corev1.ObjectReference{ + Namespace: testNamespace, + Name: "secret-name", + } + clt = fake.NewClientBuilder().WithScheme(testK8sClient.Scheme()).Build() + ctx = pkgClient.WithClient(context.Background(), clt) + }) + + JustBeforeEach(func() { + secret, err = GetSecretByRefOrLabel(ctx, clt, ref) + }) + + When("clt is empty", func() { + BeforeEach(func() { + clt = nil + }) + It("should return error", func() { + Expect(err).ShouldNot(BeNil()) + Expect(err).Should(Equal(kerrors.ErrInvalidInputNilPoint)) + Expect(secret).Should(BeNil()) + }) + }) + + Context("get secret by ref", func() { + BeforeEach(func() { + Expect(testing.LoadKubeResources("testdata/secret.no.labels.yaml", clt)).To(Succeed()) + }) + When("ref namespace is not empty", func() { + It("should return secret", func() { + Expect(err).Should(BeNil()) + Expect(secret.GetName()).Should(Equal("secret-name")) + }) + }) + When("ref namespace is empty", func() { + BeforeEach(func() { + ref.Namespace = "" + ctx = pkgnamespace.WithNamespace(ctx, testNamespace) + }) + It("should return secret", func() { + Expect(err).Should(BeNil()) + Expect(secret.GetName()).Should(Equal("secret-name")) + }) + }) + }) + + Context("get secret by labels", func() { + BeforeEach(func() { + Expect(testing.LoadKubeResources("testdata/secret.has.sync.labels.yaml", clt)).To(Succeed()) + }) + When("there is only one secret but has sync label", func() { + It("should not found any secret", func() { + Expect(err).ShouldNot(BeNil()) + }) + }) + When("there are two secret and one of them meets the requirements", func() { + BeforeEach(func() { + Expect(testing.LoadKubeResources("testdata/secret.has.labels.yaml", clt)).To(Succeed()) + }) + It("should return secret", func() { + Expect(err).Should(BeNil()) + Expect(secret.GetName()).Should(Equal("secret-has-labels")) + }) + }) + }) +}) diff --git a/secret/secret_suite_test.go b/secret/secret_suite_test.go new file mode 100644 index 00000000..f7136fcc --- /dev/null +++ b/secret/secret_suite_test.go @@ -0,0 +1,65 @@ +/* +Copyright 2022 The Katanomi Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package secret + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/kubernetes/scheme" + "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" +) + +func TestSecret(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Secret Suite") +} + +var testNamespace = "default" +var testK8sClient client.Client +var testEnv *envtest.Environment +var testLogger = zap.NewRaw(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)).Sugar() + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{} + + cfg, err := testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + err = corev1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + // +kubebuilder:scaffold:scheme + testK8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(testK8sClient).NotTo(BeNil()) +}) + +var _ = AfterSuite(func() { + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) diff --git a/secret/testdata/secret.has.labels.yaml b/secret/testdata/secret.has.labels.yaml new file mode 100644 index 00000000..93435ae6 --- /dev/null +++ b/secret/testdata/secret.has.labels.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Secret +type: kubernetes.io/basic-auth +metadata: + labels: + core.katanomi.dev/integrationClass: gitlab + core.kubernetes.io/namespace: default + core.kubernetes.io/secret: secret-name + name: secret-has-labels + namespace: default +data: + password: "" + username: "" diff --git a/secret/testdata/secret.has.sync.labels.yaml b/secret/testdata/secret.has.sync.labels.yaml new file mode 100644 index 00000000..a25a804f --- /dev/null +++ b/secret/testdata/secret.has.sync.labels.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Secret +type: kubernetes.io/basic-auth +metadata: + labels: + core.katanomi.dev/integrationClass: gitlab + core.kubernetes.io/namespace: default + core.kubernetes.io/secret: secret-name + integrations.katanomi.dev/integration.mutation: "true" + name: secret-has-sync-labels + namespace: default +data: + password: "" + username: "" diff --git a/secret/testdata/secret.no.labels.yaml b/secret/testdata/secret.no.labels.yaml new file mode 100644 index 00000000..53d84fb9 --- /dev/null +++ b/secret/testdata/secret.no.labels.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +type: kubernetes.io/basic-auth +metadata: + name: secret-name + namespace: default +data: + password: "" + username: "" diff --git a/testing/convert.go b/testing/convert.go new file mode 100644 index 00000000..f75e2784 --- /dev/null +++ b/testing/convert.go @@ -0,0 +1,63 @@ +/* +Copyright 2021 The Katanomi Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package testing + +import ( + "fmt" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// ConvertCorev1Resouces convert runtime.Object to client.Object +// be similar to convertFromUnstructuredIfNecessary +func ConvertCorev1Resouces(runtimeObj runtime.Object) (obj client.Object, err error) { + switch v := runtimeObj.(type) { + case *corev1.PersistentVolume: + obj = v + case *corev1.PersistentVolumeClaim: + obj = v + case *corev1.Pod: + obj = v + case *corev1.ReplicationController: + obj = v + case *corev1.Service: + obj = v + case *corev1.ServiceAccount: + obj = v + case *corev1.Endpoints: + obj = v + case *corev1.Node: + obj = v + case *corev1.Namespace: + obj = v + case *corev1.Binding: + obj = v + case *corev1.LimitRange: + obj = v + case *corev1.ResourceQuota: + obj = v + case *corev1.Secret: + obj = v + case *corev1.ConfigMap: + obj = v + default: + err = fmt.Errorf("Unsupported gvk: %s", runtimeObj.GetObjectKind().GroupVersionKind()) + } + return +} diff --git a/testing/kubernetes.go b/testing/kubernetes.go index 355ec7c2..15c846f4 100644 --- a/testing/kubernetes.go +++ b/testing/kubernetes.go @@ -62,6 +62,8 @@ func LoadKubeResources(file string, clt client.Client, converts ...ConvertRuntim if err != nil { return } + // Automatically convert corev1 resources, such as Secret, Configmap, Service, Pod, etc + converts = append(converts, ConvertCorev1Resouces) OUTER: for _, obj := range objs { runtimeObj, err := convertFromUnstructuredIfNecessary(clt.Scheme(), &obj) From ef68262952caceaa08ae3a1b4da43c36bfa3ed2a Mon Sep 17 00:00:00 2001 From: qingliu Date: Tue, 26 Jul 2022 10:11:16 +0800 Subject: [PATCH 2/4] chore: adjust based on comments --- errors/errors.go | 6 +++--- secret/get_secret.go | 2 +- secret/get_secret_test.go | 2 +- testing/convert.go | 37 ++++--------------------------------- testing/kubernetes.go | 4 ++-- 5 files changed, 11 insertions(+), 40 deletions(-) diff --git a/errors/errors.go b/errors/errors.go index 7590d90c..41dafd36 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -17,9 +17,9 @@ limitations under the License. package errors import ( - apierrors "k8s.io/apimachinery/pkg/api/errors" + "errors" ) -// ErrInvalidInputNilPoint invalid input parameters, specifically a nil point +// ErrNilPoint indicates nil point, avoid panic. // Although unlikely just in case -var ErrInvalidInputNilPoint = apierrors.NewBadRequest("Invalid input parameters - nil point") +var ErrNilPoint = errors.New("nil point") diff --git a/secret/get_secret.go b/secret/get_secret.go index 1b54aa13..3f735dbc 100644 --- a/secret/get_secret.go +++ b/secret/get_secret.go @@ -36,7 +36,7 @@ import ( // If the resource does not exist, it will try to match according to the label. func GetSecretByRefOrLabel(ctx context.Context, clt client.Client, ref *corev1.ObjectReference) (obj *corev1.Secret, err error) { if clt == nil || ref == nil { - return nil, kerrors.ErrInvalidInputNilPoint + return nil, kerrors.ErrNilPoint } log := logging.FromContext(ctx) diff --git a/secret/get_secret_test.go b/secret/get_secret_test.go index 3e4064c6..e486c7fa 100644 --- a/secret/get_secret_test.go +++ b/secret/get_secret_test.go @@ -61,7 +61,7 @@ var _ = Describe("Test.GetSecretByRefOrLabel", func() { }) It("should return error", func() { Expect(err).ShouldNot(BeNil()) - Expect(err).Should(Equal(kerrors.ErrInvalidInputNilPoint)) + Expect(err).Should(Equal(kerrors.ErrNilPoint)) Expect(secret).Should(BeNil()) }) }) diff --git a/testing/convert.go b/testing/convert.go index f75e2784..a8dddc45 100644 --- a/testing/convert.go +++ b/testing/convert.go @@ -19,44 +19,15 @@ package testing import ( "fmt" - corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client" ) -// ConvertCorev1Resouces convert runtime.Object to client.Object +// DefaultConvertRuntimeToClientobjectFunc convert runtime.Object to client.Object // be similar to convertFromUnstructuredIfNecessary -func ConvertCorev1Resouces(runtimeObj runtime.Object) (obj client.Object, err error) { - switch v := runtimeObj.(type) { - case *corev1.PersistentVolume: - obj = v - case *corev1.PersistentVolumeClaim: - obj = v - case *corev1.Pod: - obj = v - case *corev1.ReplicationController: - obj = v - case *corev1.Service: - obj = v - case *corev1.ServiceAccount: - obj = v - case *corev1.Endpoints: - obj = v - case *corev1.Node: - obj = v - case *corev1.Namespace: - obj = v - case *corev1.Binding: - obj = v - case *corev1.LimitRange: - obj = v - case *corev1.ResourceQuota: - obj = v - case *corev1.Secret: - obj = v - case *corev1.ConfigMap: - obj = v - default: +func DefaultConvertRuntimeToClientobjectFunc(runtimeObj runtime.Object) (obj client.Object, err error) { + obj, ok := runtimeObj.(client.Object) + if !ok { err = fmt.Errorf("Unsupported gvk: %s", runtimeObj.GetObjectKind().GroupVersionKind()) } return diff --git a/testing/kubernetes.go b/testing/kubernetes.go index 15c846f4..6e5171b0 100644 --- a/testing/kubernetes.go +++ b/testing/kubernetes.go @@ -62,8 +62,8 @@ func LoadKubeResources(file string, clt client.Client, converts ...ConvertRuntim if err != nil { return } - // Automatically convert corev1 resources, such as Secret, Configmap, Service, Pod, etc - converts = append(converts, ConvertCorev1Resouces) + // Automatically convert runtime object to client object + converts = append(converts, DefaultConvertRuntimeToClientobjectFunc) OUTER: for _, obj := range objs { runtimeObj, err := convertFromUnstructuredIfNecessary(clt.Scheme(), &obj) From 28de9e45ada4b2ff15303a5746c98818d19ca362 Mon Sep 17 00:00:00 2001 From: qingliu Date: Tue, 26 Jul 2022 10:25:36 +0800 Subject: [PATCH 3/4] chore: adjust based on comments --- errors/errors.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/errors/errors.go b/errors/errors.go index 41dafd36..56564de5 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -20,6 +20,6 @@ import ( "errors" ) -// ErrNilPoint indicates nil point, avoid panic. +// ErrNilPointer indicates nil pointer, avoid panic. // Although unlikely just in case -var ErrNilPoint = errors.New("nil point") +var ErrNilPointer = errors.New("nil pointer") From 754182d2c5d9a43c854a81b9c57fac9f5ac70e40 Mon Sep 17 00:00:00 2001 From: qingliu Date: Tue, 26 Jul 2022 10:32:50 +0800 Subject: [PATCH 4/4] chore: fix unit tests --- secret/get_secret.go | 2 +- secret/get_secret_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/secret/get_secret.go b/secret/get_secret.go index 3f735dbc..8fc171f0 100644 --- a/secret/get_secret.go +++ b/secret/get_secret.go @@ -36,7 +36,7 @@ import ( // If the resource does not exist, it will try to match according to the label. func GetSecretByRefOrLabel(ctx context.Context, clt client.Client, ref *corev1.ObjectReference) (obj *corev1.Secret, err error) { if clt == nil || ref == nil { - return nil, kerrors.ErrNilPoint + return nil, kerrors.ErrNilPointer } log := logging.FromContext(ctx) diff --git a/secret/get_secret_test.go b/secret/get_secret_test.go index e486c7fa..65872ebc 100644 --- a/secret/get_secret_test.go +++ b/secret/get_secret_test.go @@ -61,7 +61,7 @@ var _ = Describe("Test.GetSecretByRefOrLabel", func() { }) It("should return error", func() { Expect(err).ShouldNot(BeNil()) - Expect(err).Should(Equal(kerrors.ErrNilPoint)) + Expect(err).Should(Equal(kerrors.ErrNilPointer)) Expect(secret).Should(BeNil()) }) })