diff --git a/.golangci.yml b/.golangci.yml index 4c90e8e..84073c4 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -3,7 +3,7 @@ run: output: # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" - format: colored-line-number + formats: colored-line-number linters-settings: errcheck: @@ -18,7 +18,7 @@ linters-settings: # [deprecated] comma-separated list of pairs of the form pkg:regex # the regex is used to ignore names within pkg. (default "fmt:.*"). # see https://github.com/kisielk/errcheck#the-deprecated-method for details - ignore: fmt:.*,io/ioutil:^Read.* + exclude-functions: fmt:.*,io/ioutil:^Read.* govet: # report about shadowed variables @@ -101,11 +101,12 @@ linters-settings: linters: enable: - - megacheck + - gosimple + - staticcheck + - unused - govet - gocyclo - gocritic - - interfacer - goconst - goimports - gofmt # We enable this as well as goimports for its simplify mode. diff --git a/Makefile b/Makefile index b1b1d40..db0d527 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,6 @@ NPROCS ?= 1 # parallel can lead to high CPU utilization. by default we reduce the parallelism # to half the number of CPU cores. GO_TEST_PARALLEL := $(shell echo $$(( $(NPROCS) / 2 ))) - GO_STATIC_PACKAGES = $(GO_PROJECT)/cmd/angryjet GO_LDFLAGS += -X $(GO_PROJECT)/pkg/version.Version=$(VERSION) GO_SUBDIRS += cmd internal diff --git a/build b/build index 231258d..1ed1933 160000 --- a/build +++ b/build @@ -1 +1 @@ -Subproject commit 231258db281237379d8ec0c6e4af9d7c1ae5cc4a +Subproject commit 1ed19332b947c449795fd016f3c21ee0a64930fd diff --git a/cmd/angryjet/main.go b/cmd/angryjet/main.go index cea6c25..02c973d 100644 --- a/cmd/angryjet/main.go +++ b/cmd/angryjet/main.go @@ -17,11 +17,10 @@ limitations under the License. package main import ( - "io/ioutil" "os" "path/filepath" - "github.com/alecthomas/kingpin/v2" + kingpin "github.com/alecthomas/kingpin/v2" "github.com/pkg/errors" "golang.org/x/tools/go/packages" @@ -50,6 +49,9 @@ const ( ClientAlias = "client" ClientImport = "sigs.k8s.io/controller-runtime/pkg/client" + HelperAlias = "helper" + HelperImport = "github.com/crossplane/crossplane-tools/pkg/helpers" + RuntimeAlias = "xpv1" RuntimeImport = "github.com/crossplane/crossplane-runtime/apis/common/v1" @@ -58,6 +60,9 @@ const ( ReferenceAlias = "reference" ReferenceImport = "github.com/crossplane/crossplane-runtime/pkg/reference" + + PtrAlias = "ptr" + PtrImport = "k8s.io/utils/ptr" ) func main() { @@ -81,7 +86,7 @@ func main() { header := "" if *headerFile != "" { - h, err := ioutil.ReadFile(*headerFile) + h, err := os.ReadFile(*headerFile) kingpin.FatalIfError(err, "cannot read header file %s", *headerFile) header = string(h) } @@ -228,14 +233,16 @@ func GenerateReferences(filename, header string, p *packages.Package) error { comm := comments.In(p) methods := method.Set{ - "ResolveReferences": method.NewResolveReferences(types.NewTraverser(comm), receiver, ClientImport, ReferenceImport), + "ResolveReferences": method.NewResolveReferences(types.NewTraverser(comm), receiver, ClientImport, ReferenceImport, HelperImport, PtrImport), } err := generate.WriteMethods(p, methods, filepath.Join(filepath.Dir(p.GoFiles[0]), filename), generate.WithHeaders(header), generate.WithImportAliases(map[string]string{ ClientImport: ClientAlias, + HelperImport: HelperAlias, ReferenceImport: ReferenceAlias, + PtrAlias: PtrImport, }), generate.WithMatcher(match.AllOf( match.Managed(), diff --git a/go.mod b/go.mod index 871ecff..0289351 100644 --- a/go.mod +++ b/go.mod @@ -1,35 +1,34 @@ module github.com/crossplane/crossplane-tools -go 1.18 +go 1.23.6 require ( github.com/alecthomas/kingpin/v2 v2.4.0 - github.com/dave/jennifer v1.7.0 + github.com/dave/jennifer v1.7.1 github.com/google/go-cmp v0.6.0 github.com/pkg/errors v0.9.1 - golang.org/x/tools v0.6.0 + golang.org/x/tools v0.31.0 k8s.io/apiextensions-apiserver v0.25.0 k8s.io/apimachinery v0.25.0 + k8s.io/utils v0.0.0-20241210054802-24370beab758 ) require ( - github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect - github.com/go-logr/logr v1.2.3 // indirect + github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/google/gofuzz v1.1.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/xhit/go-str2duration/v2 v2.1.0 // indirect - golang.org/x/mod v0.8.0 // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/mod v0.24.0 // indirect + golang.org/x/net v0.37.0 // indirect + golang.org/x/sync v0.12.0 // indirect + golang.org/x/text v0.23.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/klog/v2 v2.70.1 // indirect - k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect - sigs.k8s.io/yaml v1.2.0 // indirect + k8s.io/klog/v2 v2.130.1 // indirect + sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index 43be9ee..bea3c00 100644 --- a/go.sum +++ b/go.sum @@ -1,44 +1,51 @@ github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= -github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/dave/jennifer v1.7.0 h1:uRbSBH9UTS64yXbh4FrMHfgfY762RD+C7bUPKODpSJE= -github.com/dave/jennifer v1.7.0/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= +github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0= +github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= +github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo= +github.com/dave/jennifer v1.7.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= 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/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v1.2.0/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/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +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.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= -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/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 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 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 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/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= 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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 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.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +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.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -48,58 +55,56 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= +golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= golang.org/x/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= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= k8s.io/apiextensions-apiserver v0.25.0 h1:CJ9zlyXAbq0FIW8CD7HHyozCMBpDSiH7EdrSTCZcZFY= k8s.io/apiextensions-apiserver v0.25.0/go.mod h1:3pAjZiN4zw7R8aZC5gR0y3/vCkGlAjCazcg1me8iB/E= k8s.io/apimachinery v0.25.0 h1:MlP0r6+3XbkUG2itd6vp3oxbtdQLQI94fD5gCS+gnoU= k8s.io/apimachinery v0.25.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ= -k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4= -k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/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 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= +k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc= +sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/internal/generate/generate.go b/internal/generate/generate.go index 0f5eba7..b4f1ac0 100644 --- a/internal/generate/generate.go +++ b/internal/generate/generate.go @@ -22,12 +22,13 @@ import ( "go/parser" "go/token" "go/types" - "io/ioutil" "github.com/dave/jennifer/jen" "github.com/pkg/errors" "golang.org/x/tools/go/packages" + "os" + "github.com/crossplane/crossplane-tools/internal/match" "github.com/crossplane/crossplane-tools/internal/method" ) @@ -120,7 +121,7 @@ func WriteMethods(p *packages.Package, ms method.Set, file string, wo ...WriteOp // gosec would prefer this to be written as 0600, but we're comfortable with // it being world readable. - return errors.Wrap(ioutil.WriteFile(file, b.Bytes(), 0644), "cannot write Go file") // nolint:gosec + return errors.Wrap(os.WriteFile(file, b.Bytes(), 0644), "cannot write Go file") // nolint:gosec } diff --git a/internal/method/resolver.go b/internal/method/resolver.go index cf66d96..0c6e88c 100644 --- a/internal/method/resolver.go +++ b/internal/method/resolver.go @@ -30,7 +30,7 @@ import ( // NewResolveReferences returns a NewMethod that writes a ResolveReferences for // given managed resource, if needed. -func NewResolveReferences(traverser *xptypes.Traverser, receiver, clientPath, referencePkgPath string) New { +func NewResolveReferences(traverser *xptypes.Traverser, receiver, clientPath, referencePkgPath string, helpersPkgPath string, ptrPkgPath string) New { return func(f *jen.File, o types.Object) { n, ok := o.Type().(*types.Named) if !ok { @@ -56,10 +56,10 @@ func NewResolveReferences(traverser *xptypes.Traverser, receiver, clientPath, re for i, ref := range refs { if ref.IsSlice { hasMultiResolution = true - resolverCalls[i] = encapsulate(0, multiResolutionCall(ref, referencePkgPath), ref.GoValueFieldPath...).Line() + resolverCalls[i] = encapsulate(0, multiResolutionCall(ref, referencePkgPath, helpersPkgPath), ref.GoValueFieldPath...).Line() } else { hasSingleResolution = true - resolverCalls[i] = encapsulate(0, singleResolutionCall(ref, referencePkgPath), ref.GoValueFieldPath...).Line() + resolverCalls[i] = encapsulate(0, singleResolutionCall(ref, referencePkgPath, ptrPkgPath), ref.GoValueFieldPath...).Line() } } var initStatements jen.Statement @@ -118,7 +118,7 @@ func encapsulate(index int, callFn resolutionCallFn, fields ...string) *jen.Stat } } -func singleResolutionCall(ref Reference, referencePkgPath string) resolutionCallFn { +func singleResolutionCall(ref Reference, referencePkgPath string, ptrPkgPath string) resolutionCallFn { return func(fields ...string) *jen.Statement { prefixPath := jen.Id(fields[0]) for i := 1; i < len(fields)-1; i++ { @@ -129,15 +129,15 @@ func singleResolutionCall(ref Reference, referencePkgPath string) resolutionCall selectorFieldPath := prefixPath.Clone().Dot(ref.GoSelectorFieldName) setResolvedValue := currentValuePath.Clone().Op("=").Id("rsp").Dot("ResolvedValue") - toPointerFunction := "ToPtrValue" - fromPointerFunction := "FromPtrValue" + toPointerFunction := "To" + fromPointerFunction := "Deref" if ref.IsFloatPointer { toPointerFunction = "ToFloatPtrValue" fromPointerFunction = "FromFloatPtrValue" } if ref.IsPointer { - setResolvedValue = currentValuePath.Clone().Op("=").Qual(referencePkgPath, toPointerFunction).Call(jen.Id("rsp").Dot("ResolvedValue")) - currentValuePath = jen.Qual(referencePkgPath, fromPointerFunction).Call(currentValuePath) + setResolvedValue = currentValuePath.Clone().Op("=").Qual(ptrPkgPath, toPointerFunction).Call(jen.Id("rsp").Dot("ResolvedValue")) + currentValuePath = jen.Qual(ptrPkgPath, fromPointerFunction).Call(currentValuePath, jen.Op(`""`)) } return &jen.Statement{ jen.List(jen.Id("rsp"), jen.Err()).Op("=").Id("r").Dot("Resolve").Call( @@ -167,7 +167,7 @@ func singleResolutionCall(ref Reference, referencePkgPath string) resolutionCall } } -func multiResolutionCall(ref Reference, referencePkgPath string) resolutionCallFn { +func multiResolutionCall(ref Reference, referencePkgPath string, helpersPkgPath string) resolutionCallFn { return func(fields ...string) *jen.Statement { prefixPath := jen.Id(fields[0]) for i := 1; i < len(fields)-1; i++ { @@ -186,8 +186,8 @@ func multiResolutionCall(ref Reference, referencePkgPath string) resolutionCallF } if ref.IsPointer { - setResolvedValues = currentValuePath.Clone().Op("=").Qual(referencePkgPath, toPointersFunction).Call(jen.Id("mrsp").Dot("ResolvedValues")) - currentValuePath = jen.Qual(referencePkgPath, fromPointersFunction).Call(currentValuePath) + setResolvedValues = currentValuePath.Clone().Op("=").Qual(helpersPkgPath, toPointersFunction).Call(jen.Id("mrsp").Dot("ResolvedValues")) + currentValuePath = jen.Qual(helpersPkgPath, fromPointersFunction).Call(currentValuePath) } return &jen.Statement{ diff --git a/internal/method/resolver_test.go b/internal/method/resolver_test.go index 354fe99..3c61bed 100644 --- a/internal/method/resolver_test.go +++ b/internal/method/resolver_test.go @@ -106,10 +106,12 @@ type Model struct { import ( "context" client "example.org/client" + helpers "example.org/helpers" reference "example.org/reference" v1beta11 "github.com/crossplane/provider-aws/apis/ec2/v1beta1" v1beta1 "github.com/crossplane/provider-aws/apis/identity/v1beta1" errors "github.com/pkg/errors" + ptr "k8s.io/utils/ptr" ) // ResolveReferences of this Model. @@ -137,7 +139,7 @@ func (mg *Model) ResolveReferences(ctx context.Context, c client.Reader) error { mg.Spec.ForProvider.APIIDRef = rsp.ResolvedReference rsp, err = r.Resolve(ctx, reference.ResolutionRequest{ - CurrentValue: reference.FromPtrValue(mg.Spec.ForProvider.SecurityGroupID), + CurrentValue: ptr.Deref(mg.Spec.ForProvider.SecurityGroupID, ""), Extract: reference.ExternalName(), Reference: mg.Spec.ForProvider.SecurityGroupIDRef, Selector: mg.Spec.ForProvider.SecurityGroupIDSelector, @@ -149,11 +151,11 @@ func (mg *Model) ResolveReferences(ctx context.Context, c client.Reader) error { if err != nil { return errors.Wrap(err, "mg.Spec.ForProvider.SecurityGroupID") } - mg.Spec.ForProvider.SecurityGroupID = reference.ToPtrValue(rsp.ResolvedValue) + mg.Spec.ForProvider.SecurityGroupID = ptr.To(rsp.ResolvedValue) mg.Spec.ForProvider.SecurityGroupIDRef = rsp.ResolvedReference rsp, err = r.Resolve(ctx, reference.ResolutionRequest{ - CurrentValue: reference.FromPtrValue(mg.Spec.ForProvider.IAMRoleARN), + CurrentValue: ptr.Deref(mg.Spec.ForProvider.IAMRoleARN, ""), Extract: v1beta1.IAMRoleARN(), Reference: mg.Spec.ForProvider.IAMRoleARNRef, Selector: mg.Spec.ForProvider.IAMRoleARNSelector, @@ -165,11 +167,11 @@ func (mg *Model) ResolveReferences(ctx context.Context, c client.Reader) error { if err != nil { return errors.Wrap(err, "mg.Spec.ForProvider.IAMRoleARN") } - mg.Spec.ForProvider.IAMRoleARN = reference.ToPtrValue(rsp.ResolvedValue) + mg.Spec.ForProvider.IAMRoleARN = ptr.To(rsp.ResolvedValue) mg.Spec.ForProvider.IAMRoleARNRef = rsp.ResolvedReference rsp, err = r.Resolve(ctx, reference.ResolutionRequest{ - CurrentValue: reference.FromPtrValue(mg.Spec.ForProvider.NestedTargetWithPath), + CurrentValue: ptr.Deref(mg.Spec.ForProvider.NestedTargetWithPath, ""), Extract: v1beta1.IAMRoleARN("a.b.c"), Reference: mg.Spec.ForProvider.NestedTargetWithPathRef, Selector: mg.Spec.ForProvider.NestedTargetWithPathSelector, @@ -181,11 +183,11 @@ func (mg *Model) ResolveReferences(ctx context.Context, c client.Reader) error { if err != nil { return errors.Wrap(err, "mg.Spec.ForProvider.NestedTargetWithPath") } - mg.Spec.ForProvider.NestedTargetWithPath = reference.ToPtrValue(rsp.ResolvedValue) + mg.Spec.ForProvider.NestedTargetWithPath = ptr.To(rsp.ResolvedValue) mg.Spec.ForProvider.NestedTargetWithPathRef = rsp.ResolvedReference rsp, err = r.Resolve(ctx, reference.ResolutionRequest{ - CurrentValue: reference.FromPtrValue(mg.Spec.ForProvider.NestedTargetNoPath), + CurrentValue: ptr.Deref(mg.Spec.ForProvider.NestedTargetNoPath, ""), Extract: IAMRoleARN("a.b.c"), Reference: mg.Spec.ForProvider.NestedTargetNoPathRef, Selector: mg.Spec.ForProvider.NestedTargetNoPathSelector, @@ -197,11 +199,11 @@ func (mg *Model) ResolveReferences(ctx context.Context, c client.Reader) error { if err != nil { return errors.Wrap(err, "mg.Spec.ForProvider.NestedTargetNoPath") } - mg.Spec.ForProvider.NestedTargetNoPath = reference.ToPtrValue(rsp.ResolvedValue) + mg.Spec.ForProvider.NestedTargetNoPath = ptr.To(rsp.ResolvedValue) mg.Spec.ForProvider.NestedTargetNoPathRef = rsp.ResolvedReference rsp, err = r.Resolve(ctx, reference.ResolutionRequest{ - CurrentValue: reference.FromPtrValue(mg.Spec.ForProvider.NoArgNoPath), + CurrentValue: ptr.Deref(mg.Spec.ForProvider.NoArgNoPath, ""), Extract: IAMRoleARN(), Reference: mg.Spec.ForProvider.NoArgNoPathRef, Selector: mg.Spec.ForProvider.NoArgNoPathSelector, @@ -213,7 +215,7 @@ func (mg *Model) ResolveReferences(ctx context.Context, c client.Reader) error { if err != nil { return errors.Wrap(err, "mg.Spec.ForProvider.NoArgNoPath") } - mg.Spec.ForProvider.NoArgNoPath = reference.ToPtrValue(rsp.ResolvedValue) + mg.Spec.ForProvider.NoArgNoPath = ptr.To(rsp.ResolvedValue) mg.Spec.ForProvider.NoArgNoPathRef = rsp.ResolvedReference if mg.Spec.ForProvider.Network != nil { @@ -269,7 +271,7 @@ func (mg *Model) ResolveReferences(ctx context.Context, c client.Reader) error { mg.Spec.ForProvider.SubnetIDRefs = mrsp.ResolvedReferences mrsp, err = r.ResolveMultiple(ctx, reference.MultiResolutionRequest{ - CurrentValues: reference.FromPtrValues(mg.Spec.ForProvider.RouteTableIDs), + CurrentValues: helpers.FromPtrValues(mg.Spec.ForProvider.RouteTableIDs), Extract: reference.ExternalName(), References: mg.Spec.ForProvider.RouteTableIDsRefs, Selector: mg.Spec.ForProvider.RouteTableIDsSelector, @@ -281,11 +283,11 @@ func (mg *Model) ResolveReferences(ctx context.Context, c client.Reader) error { if err != nil { return errors.Wrap(err, "mg.Spec.ForProvider.RouteTableIDs") } - mg.Spec.ForProvider.RouteTableIDs = reference.ToPtrValues(mrsp.ResolvedValues) + mg.Spec.ForProvider.RouteTableIDs = helpers.ToPtrValues(mrsp.ResolvedValues) mg.Spec.ForProvider.RouteTableIDsRefs = mrsp.ResolvedReferences rsp, err = r.Resolve(ctx, reference.ResolutionRequest{ - CurrentValue: reference.FromPtrValue(mg.Spec.ForProvider.CustomConfiguration), + CurrentValue: ptr.Deref(mg.Spec.ForProvider.CustomConfiguration, ""), Extract: Configuration(), Reference: mg.Spec.ForProvider.CustomConfigurationRef, Selector: mg.Spec.ForProvider.CustomConfigurationSelector, @@ -297,7 +299,7 @@ func (mg *Model) ResolveReferences(ctx context.Context, c client.Reader) error { if err != nil { return errors.Wrap(err, "mg.Spec.ForProvider.CustomConfiguration") } - mg.Spec.ForProvider.CustomConfiguration = reference.ToPtrValue(rsp.ResolvedValue) + mg.Spec.ForProvider.CustomConfiguration = ptr.To(rsp.ResolvedValue) mg.Spec.ForProvider.CustomConfigurationRef = rsp.ResolvedReference return nil @@ -319,7 +321,7 @@ func TestNewResolveReferences(t *testing.T) { t.Error(err) } f := jen.NewFilePath("golang.org/fake/v1alpha1") - NewResolveReferences(xptypes.NewTraverser(comments.In(pkgs[0])), "mg", "example.org/client", "example.org/reference")(f, pkgs[0].Types.Scope().Lookup("Model")) + NewResolveReferences(xptypes.NewTraverser(comments.In(pkgs[0])), "mg", "example.org/client", "example.org/reference", "example.org/helpers", "k8s.io/utils/ptr")(f, pkgs[0].Types.Scope().Lookup("Model")) if diff := cmp.Diff(generated, fmt.Sprintf("%#v", f)); diff != "" { t.Errorf("NewResolveReferences(): -want, +got\n%s", diff) } diff --git a/pkg/helpers/helpers.go b/pkg/helpers/helpers.go new file mode 100644 index 0000000..22f8058 --- /dev/null +++ b/pkg/helpers/helpers.go @@ -0,0 +1,127 @@ +package helpers + +import ( + "strconv" + + "k8s.io/utils/ptr" +) + +// NOTE(negz): There are many equivalents of FromPtrValue and ToPtrValue +// throughout the Crossplane codebase. We duplicate them here to reduce the +// number of packages our API types have to import to support references. + +// FromPtrValue adapts a string pointer field for use as a CurrentValue. +// +// Deprecated: Use ptr.Deref from k8s.io/utils/ptr. +func FromPtrValue(v *string) string { + return ptr.Deref(v, "") +} + +// FromFloatPtrValue adapts a float pointer field for use as a CurrentValue. +func FromFloatPtrValue(v *float64) string { + if v == nil { + return "" + } + return strconv.FormatFloat(*v, 'f', 0, 64) +} + +// FromIntPtrValue adapts an int pointer field for use as a CurrentValue. +func FromIntPtrValue(v *int64) string { + if v == nil { + return "" + } + return strconv.FormatInt(*v, 10) +} + +// ToPtrValue adapts a ResolvedValue for use as a string pointer field. +// +// Deprecated: Use ptr.To from k8s.io/utils/ptr +func ToPtrValue(v string) *string { + return ptr.To(v) +} + +// ToFloatPtrValue adapts a ResolvedValue for use as a float64 pointer field. +func ToFloatPtrValue(v string) *float64 { + if v == "" { + return nil + } + vParsed, err := strconv.ParseFloat(v, 64) + if err != nil { + return nil + } + return &vParsed +} + +// ToIntPtrValue adapts a ResolvedValue for use as an int pointer field. +func ToIntPtrValue(v string) *int64 { + if v == "" { + return nil + } + vParsed, err := strconv.ParseInt(v, 10, 64) + if err != nil { + return nil + } + return &vParsed +} + +// FromPtrValues adapts a slice of string pointer fields for use as CurrentValues. +// NOTE: Do not use this utility function unless you have to. +// Using pointer slices does not adhere to our current API practices. +// The current use case is where generated code creates reference-able fields in a provider which are +// string pointers and need to be resolved as part of `ResolveMultiple`. +func FromPtrValues(v []*string) []string { + res := make([]string, len(v)) + for i := range v { + res[i] = FromPtrValue(v[i]) + } + return res +} + +// FromFloatPtrValues adapts a slice of float64 pointer fields for use as CurrentValues. +func FromFloatPtrValues(v []*float64) []string { + res := make([]string, len(v)) + for i := range v { + res[i] = FromFloatPtrValue(v[i]) + } + return res +} + +// FromIntPtrValues adapts a slice of int64 pointer fields for use as CurrentValues. +func FromIntPtrValues(v []*int64) []string { + res := make([]string, len(v)) + for i := range v { + res[i] = FromIntPtrValue(v[i]) + } + return res +} + +// ToPtrValues adapts ResolvedValues for use as a slice of string pointer fields. +// NOTE: Do not use this utility function unless you have to. +// Using pointer slices does not adhere to our current API practices. +// The current use case is where generated code creates reference-able fields in a provider which are +// string pointers and need to be resolved as part of `ResolveMultiple`. +func ToPtrValues(v []string) []*string { + res := make([]*string, len(v)) + for i := range v { + res[i] = ToPtrValue(v[i]) + } + return res +} + +// ToFloatPtrValues adapts ResolvedValues for use as a slice of float64 pointer fields. +func ToFloatPtrValues(v []string) []*float64 { + res := make([]*float64, len(v)) + for i := range v { + res[i] = ToFloatPtrValue(v[i]) + } + return res +} + +// ToIntPtrValues adapts ResolvedValues for use as a slice of int64 pointer fields. +func ToIntPtrValues(v []string) []*int64 { + res := make([]*int64, len(v)) + for i := range v { + res[i] = ToIntPtrValue(v[i]) + } + return res +} diff --git a/pkg/helpers/helpers_test.go b/pkg/helpers/helpers_test.go new file mode 100644 index 0000000..6ee76d6 --- /dev/null +++ b/pkg/helpers/helpers_test.go @@ -0,0 +1,98 @@ +package helpers + +import ( + "testing" + + "github.com/google/go-cmp/cmp" +) + +func TestToAndFromPtr(t *testing.T) { + cases := map[string]struct { + want string + }{ + "Zero": {want: ""}, + "NonZero": {want: "pointy"}, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + got := FromPtrValue(ToPtrValue(tc.want)) + if diff := cmp.Diff(tc.want, got); diff != "" { + t.Errorf("FromPtrValue(ToPtrValue(%s): -want, +got: %s", tc.want, diff) + } + }) + } +} + +func TestToAndFromFloatPtr(t *testing.T) { + cases := map[string]struct { + want string + }{ + "Zero": {want: ""}, + "NonZero": {want: "1123581321"}, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + got := FromFloatPtrValue(ToFloatPtrValue(tc.want)) + if diff := cmp.Diff(tc.want, got); diff != "" { + t.Errorf("FromPtrValue(ToPtrValue(%s): -want, +got: %s", tc.want, diff) + } + }) + } +} + +func TestToAndFromPtrValues(t *testing.T) { + cases := map[string]struct { + want []string + }{ + "Nil": {want: []string{}}, + "Zero": {want: []string{""}}, + "NonZero": {want: []string{"pointy"}}, + "Multiple": {want: []string{"pointy", "pointers"}}, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + got := FromPtrValues(ToPtrValues(tc.want)) + if diff := cmp.Diff(tc.want, got); diff != "" { + t.Errorf("FromPtrValues(ToPtrValues(%s): -want, +got: %s", tc.want, diff) + } + }) + } +} + +func TestToAndFromFloatPtrValues(t *testing.T) { + cases := map[string]struct { + want []string + }{ + "Nil": {want: []string{}}, + "Zero": {want: []string{""}}, + "NonZero": {want: []string{"1123581321"}}, + "Multiple": {want: []string{"1123581321", "1234567890"}}, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + got := FromFloatPtrValues(ToFloatPtrValues(tc.want)) + if diff := cmp.Diff(tc.want, got); diff != "" { + t.Errorf("FromPtrValues(ToPtrValues(%s): -want, +got: %s", tc.want, diff) + } + }) + } +} + +func TestToAndFromIntPtrValues(t *testing.T) { + cases := map[string]struct { + want []string + }{ + "Nil": {want: []string{}}, + "Zero": {want: []string{""}}, + "NonZero": {want: []string{"1123581321"}}, + "Multiple": {want: []string{"1123581321", "1234567890"}}, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + got := FromIntPtrValues(ToIntPtrValues(tc.want)) + if diff := cmp.Diff(tc.want, got); diff != "" { + t.Errorf("FromIntPtrValues(ToIntPtrValues(%s): -want, +got: %s", tc.want, diff) + } + }) + } +}