From 1786f7d38b0f41c9d477161b11b639225e34f411 Mon Sep 17 00:00:00 2001 From: Tamal Saha Date: Fri, 13 Sep 2024 14:13:15 -0800 Subject: [PATCH] Log unverified certs and curl command (#141) Signed-off-by: Tamal Saha --- go.mod | 3 +- go.sum | 11 +- pkg/controllers/prometheus/client.go | 36 ++ vendor/kmodules.xyz/client-go/Makefile | 2 +- .../kmodules.xyz/client-go/api/v1/object.go | 4 +- .../client-go/api/v1/object_enum.go | 5 - .../client-go/apiextensions/controller.go | 4 +- .../client-go/client/retryclient.go | 234 ++++++++++++ .../kmodules.xyz/client-go/cluster/rancher.go | 2 + .../client-go/conditions/getter.go | 2 +- .../client-go/conditions/merge.go | 4 +- .../client-go/meta/preconditions.go | 4 +- vendor/modules.txt | 5 +- vendor/moul.io/http2curl/v2/.gitattributes | 12 + vendor/moul.io/http2curl/v2/.gitignore | 28 ++ vendor/moul.io/http2curl/v2/.releaserc.js | 8 + vendor/moul.io/http2curl/v2/AUTHORS | 15 + vendor/moul.io/http2curl/v2/COPYRIGHT | 22 ++ vendor/moul.io/http2curl/v2/LICENSE-APACHE | 201 ++++++++++ vendor/moul.io/http2curl/v2/LICENSE-MIT | 19 + vendor/moul.io/http2curl/v2/Makefile | 5 + vendor/moul.io/http2curl/v2/README.md | 59 +++ vendor/moul.io/http2curl/v2/doc.go | 1 + vendor/moul.io/http2curl/v2/http2curl.go | 85 +++++ vendor/moul.io/http2curl/v2/rules.mk | 361 ++++++++++++++++++ 25 files changed, 1114 insertions(+), 18 deletions(-) create mode 100644 vendor/kmodules.xyz/client-go/client/retryclient.go create mode 100644 vendor/moul.io/http2curl/v2/.gitattributes create mode 100644 vendor/moul.io/http2curl/v2/.gitignore create mode 100644 vendor/moul.io/http2curl/v2/.releaserc.js create mode 100644 vendor/moul.io/http2curl/v2/AUTHORS create mode 100644 vendor/moul.io/http2curl/v2/COPYRIGHT create mode 100644 vendor/moul.io/http2curl/v2/LICENSE-APACHE create mode 100644 vendor/moul.io/http2curl/v2/LICENSE-MIT create mode 100644 vendor/moul.io/http2curl/v2/Makefile create mode 100644 vendor/moul.io/http2curl/v2/README.md create mode 100644 vendor/moul.io/http2curl/v2/doc.go create mode 100644 vendor/moul.io/http2curl/v2/http2curl.go create mode 100644 vendor/moul.io/http2curl/v2/rules.mk diff --git a/go.mod b/go.mod index fe762f759..b733de000 100644 --- a/go.mod +++ b/go.mod @@ -32,9 +32,10 @@ require ( k8s.io/klog/v2 v2.130.1 k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 kmodules.xyz/authorizer v0.29.1 - kmodules.xyz/client-go v0.30.11 + kmodules.xyz/client-go v0.30.14 kmodules.xyz/custom-resources v0.30.0 kmodules.xyz/monitoring-agent-api v0.30.0 + moul.io/http2curl/v2 v2.3.1-0.20221024080105-10c404f653f7 sigs.k8s.io/controller-runtime v0.18.4 x-helm.dev/apimachinery v0.0.16 ) diff --git a/go.sum b/go.sum index dc513c427..02985b5d3 100644 --- a/go.sum +++ b/go.sum @@ -331,6 +331,7 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -370,6 +371,7 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf 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/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -407,6 +409,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ 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/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8= 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-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= @@ -515,6 +518,7 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -630,6 +634,7 @@ golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/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-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= @@ -762,14 +767,16 @@ kmodules.xyz/apiversion v0.2.0 h1:vAQYqZFm4xu4pbB1cAdHbFEPES6EQkcR4wc06xdTOWk= kmodules.xyz/apiversion v0.2.0/go.mod h1:oPX8g8LvlPdPX3Yc5YvCzJHQnw3YF/X4/jdW0b1am80= kmodules.xyz/authorizer v0.29.1 h1:uByGGoryKbZcfiEAhjcK/Y345I9mygNQP7DVpkMbNQQ= kmodules.xyz/authorizer v0.29.1/go.mod h1:kZRhclL8twzyt2bQuJQJbpYww2sc+qFr8I5PPoq/sWY= -kmodules.xyz/client-go v0.30.11 h1:2UFIu18O5xwKyKbmAn+vs8CIcnfogu0IACurgR2HAmU= -kmodules.xyz/client-go v0.30.11/go.mod h1:XL3PDQIXG4s3xNRL2SSxIvi8b2WyMGpn26dFnOBz0j4= +kmodules.xyz/client-go v0.30.14 h1:Zi3hoIoJOeEYXzafrbwN8ql+L1I5/pKCjcjRHuwiNfU= +kmodules.xyz/client-go v0.30.14/go.mod h1:XL3PDQIXG4s3xNRL2SSxIvi8b2WyMGpn26dFnOBz0j4= kmodules.xyz/crd-schema-fuzz v0.29.1 h1:zJTlWYOrT5dsVVHW8HGcnR/vaWfxQfNh11QwTtkYpcs= kmodules.xyz/crd-schema-fuzz v0.29.1/go.mod h1:n708z9YQqLMP2KNLQVgBcRJw1QpSWLvpNCEi+KJDOYE= kmodules.xyz/custom-resources v0.30.0 h1:vR3CbseHMLwR4GvtcJJuRuwIV8voKqFqNii27rMcm1o= kmodules.xyz/custom-resources v0.30.0/go.mod h1:ZsTuI2mLG2s3byre7bHmpxJ9w0HDqAkRTL1+izGFI24= kmodules.xyz/monitoring-agent-api v0.30.0 h1:b3TQwGAZr+Bd5Roqf943az7AntysjIlQBNMHnDq38c0= kmodules.xyz/monitoring-agent-api v0.30.0/go.mod h1:RUtg5cdynS7LjRr30BsfbVekjvklECLi8E3ZCbGnBTU= +moul.io/http2curl/v2 v2.3.1-0.20221024080105-10c404f653f7 h1:NykkTlRB+X40z86cLHdEmuoTxhNKhQebLT379b1EumA= +moul.io/http2curl/v2 v2.3.1-0.20221024080105-10c404f653f7/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 h1:/U5vjBbQn3RChhv7P11uhYvCSm5G2GaIi5AIGBS6r4c= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0/go.mod h1:z7+wmGM2dfIiLRfrC6jb5kV2Mq/sK1ZP303cxzkV5Y4= diff --git a/pkg/controllers/prometheus/client.go b/pkg/controllers/prometheus/client.go index d88c1054a..06b0ad197 100644 --- a/pkg/controllers/prometheus/client.go +++ b/pkg/controllers/prometheus/client.go @@ -20,6 +20,8 @@ import ( "bytes" "crypto/tls" "crypto/x509" + "encoding/pem" + "errors" "io" "net" "net/http" @@ -33,7 +35,9 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/json" + "k8s.io/klog/v2" mona "kmodules.xyz/monitoring-agent-api/api/v1" + "moul.io/http2curl/v2" ) type GrafanaDatasourceResponse struct { @@ -129,8 +133,20 @@ func (c *Client) Register(ctx mona.PrometheusContext, cfg mona.PrometheusConfig) if c.token != "" { req.Header.Add("Authorization", "Bearer "+c.token) } + if klog.V(8).Enabled() { + command, _ := http2curl.GetCurlCommand(req) + klog.V(8).Infoln(command.String()) + } + resp, err := c.client.Do(req) if err != nil { + var ce *tls.CertificateVerificationError + if errors.As(err, &ce) { + klog.ErrorS(err, "UnverifiedCertificates") + for _, cert := range ce.UnverifiedCertificates { + klog.Errorln(string(encodeCertPEM(cert))) + } + } return nil, err } defer resp.Body.Close() @@ -179,8 +195,20 @@ func (c *Client) Unregister(ctx mona.PrometheusContext) error { if c.token != "" { req.Header.Add("Authorization", "Bearer "+c.token) } + if klog.V(8).Enabled() { + command, _ := http2curl.GetCurlCommand(req) + klog.V(8).Infoln(command.String()) + } + resp, err := c.client.Do(req) if err != nil { + var ce *tls.CertificateVerificationError + if errors.As(err, &ce) { + klog.ErrorS(err, "UnverifiedCertificates") + for _, cert := range ce.UnverifiedCertificates { + klog.Errorln(string(encodeCertPEM(cert))) + } + } return err } defer resp.Body.Close() @@ -202,3 +230,11 @@ func (c *Client) Unregister(ctx mona.PrometheusContext) error { func (c *Client) CACert() []byte { return c.caCert } + +func encodeCertPEM(cert *x509.Certificate) []byte { + block := pem.Block{ + Type: "CERTIFICATE", + Bytes: cert.Raw, + } + return pem.EncodeToMemory(&block) +} diff --git a/vendor/kmodules.xyz/client-go/Makefile b/vendor/kmodules.xyz/client-go/Makefile index 83988a83f..4ff50bd7c 100644 --- a/vendor/kmodules.xyz/client-go/Makefile +++ b/vendor/kmodules.xyz/client-go/Makefile @@ -58,7 +58,7 @@ ARCH := $(if $(GOARCH),$(GOARCH),$(shell go env GOARCH)) BASEIMAGE_PROD ?= gcr.io/distroless/static-debian12 BASEIMAGE_DBG ?= debian:bookworm -GO_VERSION ?= 1.22 +GO_VERSION ?= 1.23 BUILD_IMAGE ?= ghcr.io/appscode/golang-dev:$(GO_VERSION) OUTBIN = bin/$(OS)_$(ARCH)/$(BIN) diff --git a/vendor/kmodules.xyz/client-go/api/v1/object.go b/vendor/kmodules.xyz/client-go/api/v1/object.go index 419d3cab3..073c8141e 100644 --- a/vendor/kmodules.xyz/client-go/api/v1/object.go +++ b/vendor/kmodules.xyz/client-go/api/v1/object.go @@ -216,8 +216,8 @@ type ObjectInfo struct { Ref ObjectReference `json:"ref" protobuf:"bytes,2,opt,name=ref"` } -// +kubebuilder:validation:Enum=authn;authz;auth_secret;backup_via;catalog;cert_issuer;config;connect_via;exposed_by;event;located_on;monitored_by;ocm_bind;offshoot;ops;placed_into;policy;recommended_for;restore_into;scaled_by;source;storage;view -// ENUM(authn,authz,auth_secret,backup_via,catalog,cert_issuer,config,connect_via,exposed_by,event,located_on,monitored_by,ocm_bind,offshoot,ops,placed_into,policy,recommended_for,restore_into,scaled_by,source,storage,view) +// +kubebuilder:validation:Enum=authn;authz;auth_secret;backup_via;catalog;cert_issuer;config;connect_via;exposed_by;event;located_on;monitored_by;ocm_bind;offshoot;ops;policy;recommended_for;restore_into;scaled_by;source;storage;view +// ENUM(authn,authz,auth_secret,backup_via,catalog,cert_issuer,config,connect_via,exposed_by,event,located_on,monitored_by,ocm_bind,offshoot,ops,policy,recommended_for,restore_into,scaled_by,source,storage,view) type EdgeLabel string func (e EdgeLabel) Direct() bool { diff --git a/vendor/kmodules.xyz/client-go/api/v1/object_enum.go b/vendor/kmodules.xyz/client-go/api/v1/object_enum.go index 65792ec2b..954a1ef8b 100644 --- a/vendor/kmodules.xyz/client-go/api/v1/object_enum.go +++ b/vendor/kmodules.xyz/client-go/api/v1/object_enum.go @@ -42,8 +42,6 @@ const ( EdgeLabelOffshoot EdgeLabel = "offshoot" // EdgeLabelOps is a EdgeLabel of type ops. EdgeLabelOps EdgeLabel = "ops" - // EdgeLabelPlacedInto is a EdgeLabel of type placed_into. - EdgeLabelPlacedInto EdgeLabel = "placed_into" // EdgeLabelPolicy is a EdgeLabel of type policy. EdgeLabelPolicy EdgeLabel = "policy" // EdgeLabelRecommendedFor is a EdgeLabel of type recommended_for. @@ -78,7 +76,6 @@ var _EdgeLabelNames = []string{ string(EdgeLabelOcmBind), string(EdgeLabelOffshoot), string(EdgeLabelOps), - string(EdgeLabelPlacedInto), string(EdgeLabelPolicy), string(EdgeLabelRecommendedFor), string(EdgeLabelRestoreInto), @@ -113,7 +110,6 @@ func EdgeLabelValues() []EdgeLabel { EdgeLabelOcmBind, EdgeLabelOffshoot, EdgeLabelOps, - EdgeLabelPlacedInto, EdgeLabelPolicy, EdgeLabelRecommendedFor, EdgeLabelRestoreInto, @@ -152,7 +148,6 @@ var _EdgeLabelValue = map[string]EdgeLabel{ "ocm_bind": EdgeLabelOcmBind, "offshoot": EdgeLabelOffshoot, "ops": EdgeLabelOps, - "placed_into": EdgeLabelPlacedInto, "policy": EdgeLabelPolicy, "recommended_for": EdgeLabelRecommendedFor, "restore_into": EdgeLabelRestoreInto, diff --git a/vendor/kmodules.xyz/client-go/apiextensions/controller.go b/vendor/kmodules.xyz/client-go/apiextensions/controller.go index 6d3d66a66..771374ffb 100644 --- a/vendor/kmodules.xyz/client-go/apiextensions/controller.go +++ b/vendor/kmodules.xyz/client-go/apiextensions/controller.go @@ -38,11 +38,13 @@ type setupGroup struct { fn SetupFn } +type crdParamKey struct{} + var ( setupFns = make(map[schema.GroupKind]setupGroup) testFns = make(map[schema.GroupKind]TestFn) setupDone = map[schema.GroupKind]bool{} - CRDParam = struct{}{} + CRDParam = crdParamKey{} mu sync.Mutex ) diff --git a/vendor/kmodules.xyz/client-go/client/retryclient.go b/vendor/kmodules.xyz/client-go/client/retryclient.go new file mode 100644 index 000000000..d25c02930 --- /dev/null +++ b/vendor/kmodules.xyz/client-go/client/retryclient.go @@ -0,0 +1,234 @@ +/* +Copyright AppsCode Inc. and Contributors + +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 client + +import ( + "context" + "errors" + "io" + "time" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/wait" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type retryClient struct { + d client.Client + interval time.Duration + timeout time.Duration +} + +var _ client.Client = &retryClient{} + +func NewRetryClient(d client.Client) client.Client { + return &retryClient{d: d, interval: 500 * time.Millisecond, timeout: 5 * time.Minute} +} + +func NewRetryClientWithOptions(d client.Client, interval time.Duration, timeout time.Duration) client.Client { + return &retryClient{d: d, interval: interval, timeout: timeout} +} + +func (r *retryClient) Scheme() *runtime.Scheme { + return r.d.Scheme() +} + +func (r *retryClient) RESTMapper() meta.RESTMapper { + return r.d.RESTMapper() +} + +func (r *retryClient) GroupVersionKindFor(obj runtime.Object) (schema.GroupVersionKind, error) { + return r.d.GroupVersionKindFor(obj) +} + +func (r *retryClient) IsObjectNamespaced(obj runtime.Object) (bool, error) { + return r.d.IsObjectNamespaced(obj) +} + +func (r *retryClient) Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) (apierror error) { + _ = wait.PollUntilContextTimeout(ctx, r.interval, r.timeout, true, func(ctx context.Context) (done bool, err error) { + apierror = r.d.Get(ctx, key, obj, opts...) + err = apierror + done = err == nil || !errors.Is(err, io.EOF) + return + }) + return +} + +func (r *retryClient) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) (apierror error) { + _ = wait.PollUntilContextTimeout(ctx, r.interval, r.timeout, true, func(ctx context.Context) (done bool, err error) { + apierror = r.d.List(ctx, list, opts...) + err = apierror + done = err == nil || !errors.Is(err, io.EOF) + return + }) + return +} + +func (r *retryClient) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) (apierror error) { + _ = wait.PollUntilContextTimeout(ctx, r.interval, r.timeout, true, func(ctx context.Context) (done bool, err error) { + apierror = r.d.Create(ctx, obj, opts...) + err = apierror + done = err == nil || !errors.Is(err, io.EOF) + return + }) + return +} + +func (r *retryClient) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) (apierror error) { + _ = wait.PollUntilContextTimeout(ctx, r.interval, r.timeout, true, func(ctx context.Context) (done bool, err error) { + apierror = r.d.Delete(ctx, obj, opts...) + err = apierror + done = err == nil || !errors.Is(err, io.EOF) + return + }) + return +} + +func (r *retryClient) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) (apierror error) { + _ = wait.PollUntilContextTimeout(ctx, r.interval, r.timeout, true, func(ctx context.Context) (done bool, err error) { + apierror = r.d.Update(ctx, obj, opts...) + err = apierror + done = err == nil || !errors.Is(err, io.EOF) + return + }) + return +} + +func (r *retryClient) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) (apierror error) { + _ = wait.PollUntilContextTimeout(ctx, r.interval, r.timeout, true, func(ctx context.Context) (done bool, err error) { + apierror = r.d.Patch(ctx, obj, patch, opts...) + err = apierror + done = err == nil || !errors.Is(err, io.EOF) + return + }) + return +} + +func (r *retryClient) DeleteAllOf(ctx context.Context, obj client.Object, opts ...client.DeleteAllOfOption) (apierror error) { + _ = wait.PollUntilContextTimeout(ctx, r.interval, r.timeout, true, func(ctx context.Context) (done bool, err error) { + apierror = r.d.DeleteAllOf(ctx, obj, opts...) + err = apierror + done = err == nil || !errors.Is(err, io.EOF) + return + }) + return +} + +func (r *retryClient) Status() client.SubResourceWriter { + return &retrySubResourceWriter{ + d: r.d.Status(), + interval: r.interval, + timeout: r.timeout, + } +} + +func (r *retryClient) SubResource(subResource string) client.SubResourceClient { + return &retrySubResourceClient{ + d: r.d.SubResource(subResource), + interval: r.interval, + timeout: r.timeout, + } +} + +type retrySubResourceWriter struct { + d client.SubResourceWriter + interval time.Duration + timeout time.Duration +} + +var _ client.SubResourceWriter = &retrySubResourceWriter{} + +func (r *retrySubResourceWriter) Create(ctx context.Context, obj client.Object, subResource client.Object, opts ...client.SubResourceCreateOption) (apierror error) { + _ = wait.PollUntilContextTimeout(ctx, r.interval, r.timeout, true, func(ctx context.Context) (done bool, err error) { + apierror = r.d.Create(ctx, obj, subResource, opts...) + err = apierror + done = err == nil || !errors.Is(err, io.EOF) + return + }) + return +} + +func (r *retrySubResourceWriter) Update(ctx context.Context, obj client.Object, opts ...client.SubResourceUpdateOption) (apierror error) { + _ = wait.PollUntilContextTimeout(ctx, r.interval, r.timeout, true, func(ctx context.Context) (done bool, err error) { + apierror = r.d.Update(ctx, obj, opts...) + err = apierror + done = err == nil || !errors.Is(err, io.EOF) + return + }) + return +} + +func (r *retrySubResourceWriter) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.SubResourcePatchOption) (apierror error) { + _ = wait.PollUntilContextTimeout(ctx, r.interval, r.timeout, true, func(ctx context.Context) (done bool, err error) { + apierror = r.d.Patch(ctx, obj, patch, opts...) + err = apierror + done = err == nil || !errors.Is(err, io.EOF) + return + }) + return +} + +type retrySubResourceClient struct { + d client.SubResourceClient + interval time.Duration + timeout time.Duration +} + +var _ client.SubResourceClient = &retrySubResourceClient{} + +func (r *retrySubResourceClient) Get(ctx context.Context, obj client.Object, subResource client.Object, opts ...client.SubResourceGetOption) (apierror error) { + _ = wait.PollUntilContextTimeout(ctx, r.interval, r.timeout, true, func(ctx context.Context) (done bool, err error) { + apierror = r.d.Get(ctx, obj, subResource, opts...) + err = apierror + done = err == nil || !errors.Is(err, io.EOF) + return + }) + return +} + +func (r *retrySubResourceClient) Create(ctx context.Context, obj client.Object, subResource client.Object, opts ...client.SubResourceCreateOption) (apierror error) { + _ = wait.PollUntilContextTimeout(ctx, r.interval, r.timeout, true, func(ctx context.Context) (done bool, err error) { + apierror = r.d.Create(ctx, obj, subResource, opts...) + err = apierror + done = err == nil || !errors.Is(err, io.EOF) + return + }) + return +} + +func (r *retrySubResourceClient) Update(ctx context.Context, obj client.Object, opts ...client.SubResourceUpdateOption) (apierror error) { + _ = wait.PollUntilContextTimeout(ctx, r.interval, r.timeout, true, func(ctx context.Context) (done bool, err error) { + apierror = r.d.Update(ctx, obj, opts...) + err = apierror + done = err == nil || !errors.Is(err, io.EOF) + return + }) + return +} + +func (r *retrySubResourceClient) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.SubResourcePatchOption) (apierror error) { + _ = wait.PollUntilContextTimeout(ctx, r.interval, r.timeout, true, func(ctx context.Context) (done bool, err error) { + apierror = r.d.Patch(ctx, obj, patch, opts...) + err = apierror + done = err == nil || !errors.Is(err, io.EOF) + return + }) + return +} diff --git a/vendor/kmodules.xyz/client-go/cluster/rancher.go b/vendor/kmodules.xyz/client-go/cluster/rancher.go index df2a7e69d..8a824fe9c 100644 --- a/vendor/kmodules.xyz/client-go/cluster/rancher.go +++ b/vendor/kmodules.xyz/client-go/cluster/rancher.go @@ -32,6 +32,8 @@ const ( LabelKeyRancherHelmProjectId = "helm.cattle.io/projectId" LabelKeyRancherHelmProjectOperated = "helm.cattle.io/helm-project-operated" + FakeRancherProjectId = "p-fake" + NamespaceRancherMonitoring = "cattle-monitoring-system" PrometheusRancherMonitoring = "rancher-monitoring-prometheus" ) diff --git a/vendor/kmodules.xyz/client-go/conditions/getter.go b/vendor/kmodules.xyz/client-go/conditions/getter.go index 86649a6d5..b915573eb 100644 --- a/vendor/kmodules.xyz/client-go/conditions/getter.go +++ b/vendor/kmodules.xyz/client-go/conditions/getter.go @@ -223,7 +223,7 @@ func mirror(from Getter, targetCondition kmapi.ConditionType, options ...MirrorO case true: condition = TrueCondition(targetCondition) case false: - condition = FalseCondition(targetCondition, mirrorOpt.fallbackReason, mirrorOpt.fallbackSeverity, mirrorOpt.fallbackMessage) + condition = FalseCondition(targetCondition, mirrorOpt.fallbackReason, mirrorOpt.fallbackSeverity, mirrorOpt.fallbackMessage) //nolint:govet } } diff --git a/vendor/kmodules.xyz/client-go/conditions/merge.go b/vendor/kmodules.xyz/client-go/conditions/merge.go index 44290e85f..e1ab6bc6e 100644 --- a/vendor/kmodules.xyz/client-go/conditions/merge.go +++ b/vendor/kmodules.xyz/client-go/conditions/merge.go @@ -65,9 +65,9 @@ func merge(conditions []localizedCondition, targetCondition kmapi.ConditionType, targetMessage := getMessage(g, options) if g.TopGroup().status == metav1.ConditionFalse { - return FalseCondition(targetCondition, targetReason, g.TopGroup().severity, targetMessage) + return FalseCondition(targetCondition, targetReason, g.TopGroup().severity, targetMessage) //nolint:govet } - return UnknownCondition(targetCondition, targetReason, targetMessage) + return UnknownCondition(targetCondition, targetReason, targetMessage) //nolint:govet } // getConditionGroups groups a list of conditions according to status, severity values. diff --git a/vendor/kmodules.xyz/client-go/meta/preconditions.go b/vendor/kmodules.xyz/client-go/meta/preconditions.go index 5a5f597a5..5dddddb48 100644 --- a/vendor/kmodules.xyz/client-go/meta/preconditions.go +++ b/vendor/kmodules.xyz/client-go/meta/preconditions.go @@ -17,7 +17,7 @@ limitations under the License. package meta import ( - "fmt" + "errors" "strings" "k8s.io/apimachinery/pkg/util/mergepatch" @@ -46,7 +46,7 @@ func (s PreConditionSet) PreconditionFunc() []mergepatch.PreconditionFunc { func (s PreConditionSet) Error() error { strList := strings.Join(sets.List[string](s.Set), "\n\t") - return fmt.Errorf(strings.Join([]string{`At least one of the following was changed: + return errors.New(strings.Join([]string{`At least one of the following was changed: apiVersion kind name diff --git a/vendor/modules.txt b/vendor/modules.txt index 3e315eee3..04ce2aaca 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1388,7 +1388,7 @@ kmodules.xyz/authorizer/apiserver kmodules.xyz/authorizer/rbac kmodules.xyz/authorizer/rbac/helpers kmodules.xyz/authorizer/rbac/validation -# kmodules.xyz/client-go v0.30.11 +# kmodules.xyz/client-go v0.30.14 ## explicit; go 1.22.0 kmodules.xyz/client-go kmodules.xyz/client-go/api/v1 @@ -1412,6 +1412,9 @@ kmodules.xyz/custom-resources/crds # kmodules.xyz/monitoring-agent-api v0.30.0 ## explicit; go 1.22.0 kmodules.xyz/monitoring-agent-api/api/v1 +# moul.io/http2curl/v2 v2.3.1-0.20221024080105-10c404f653f7 +## explicit; go 1.13 +moul.io/http2curl/v2 # sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 ## explicit; go 1.20 sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client diff --git a/vendor/moul.io/http2curl/v2/.gitattributes b/vendor/moul.io/http2curl/v2/.gitattributes new file mode 100644 index 000000000..9a0d71ac4 --- /dev/null +++ b/vendor/moul.io/http2curl/v2/.gitattributes @@ -0,0 +1,12 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Collapse vendored and generated files on GitHub +vendor/* linguist-vendored +rules.mk linguest-vendored +*/vendor/* linguist-vendored +*.gen.* linguist-generated +*.pb.go linguist-generated + +# Reduce conflicts on markdown files +*.md merge=union diff --git a/vendor/moul.io/http2curl/v2/.gitignore b/vendor/moul.io/http2curl/v2/.gitignore new file mode 100644 index 000000000..6f74a6986 --- /dev/null +++ b/vendor/moul.io/http2curl/v2/.gitignore @@ -0,0 +1,28 @@ +# Temporary files +*~ +*# +.#* +coverage.txt + +# Vendors +package-lock.json +node_modules/ +vendor/ + +# Binaries for programs and plugins +dist/ +gin-bin +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# IDE settings +.idea \ No newline at end of file diff --git a/vendor/moul.io/http2curl/v2/.releaserc.js b/vendor/moul.io/http2curl/v2/.releaserc.js new file mode 100644 index 000000000..566642fc0 --- /dev/null +++ b/vendor/moul.io/http2curl/v2/.releaserc.js @@ -0,0 +1,8 @@ +module.exports = { + branch: 'master', + plugins: [ + '@semantic-release/commit-analyzer', + '@semantic-release/release-notes-generator', + '@semantic-release/github', + ], +}; diff --git a/vendor/moul.io/http2curl/v2/AUTHORS b/vendor/moul.io/http2curl/v2/AUTHORS new file mode 100644 index 000000000..31e7bebb4 --- /dev/null +++ b/vendor/moul.io/http2curl/v2/AUTHORS @@ -0,0 +1,15 @@ +# This file lists all individuals having contributed content to the repository. +# For how it is generated, see 'https://github.com/moul/rules.mk' + +Darko Djalevski +Drew LeSueur +Elliot Chance +Hani Zakher +Jay Taylor +Manfred Touron <94029+moul@users.noreply.github.com> +Manfred Touron +psaffrey +Quentin Perez +Renovate Bot +Richardson Lima +Th3Whit3D3ath <49405908+Th3Whit3D3ath@users.noreply.github.com> diff --git a/vendor/moul.io/http2curl/v2/COPYRIGHT b/vendor/moul.io/http2curl/v2/COPYRIGHT new file mode 100644 index 000000000..db9d0bb0d --- /dev/null +++ b/vendor/moul.io/http2curl/v2/COPYRIGHT @@ -0,0 +1,22 @@ +Copyright 2015-2021 Manfred Touron and other http2curl Developers. + +Intellectual Property Notice +---------------------------- + +http2curl is licensed under the Apache License, Version 2.0 +(see LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or +the MIT license (see LICENSE-MIT or http://opensource.org/licenses/MIT), +at your option. + +Copyrights and patents in the http2curls project are retained +by contributors. +No copyright assignment is required to contribute to http2curl. + + SPDX-License-Identifier: (Apache-2.0 OR MIT) + +SPDX usage +---------- + +Individual files may contain SPDX tags instead of the full license text. +This enables machine processing of license information based on the SPDX +License Identifiers that are available here: https://spdx.org/licenses/ diff --git a/vendor/moul.io/http2curl/v2/LICENSE-APACHE b/vendor/moul.io/http2curl/v2/LICENSE-APACHE new file mode 100644 index 000000000..55b841758 --- /dev/null +++ b/vendor/moul.io/http2curl/v2/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2015-2021 Manfred Touron (manfred.life) + + 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. diff --git a/vendor/moul.io/http2curl/v2/LICENSE-MIT b/vendor/moul.io/http2curl/v2/LICENSE-MIT new file mode 100644 index 000000000..b6bc77722 --- /dev/null +++ b/vendor/moul.io/http2curl/v2/LICENSE-MIT @@ -0,0 +1,19 @@ +Copyright (c) 2015-2021 Manfred Touron (manfred.life) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/moul.io/http2curl/v2/Makefile b/vendor/moul.io/http2curl/v2/Makefile new file mode 100644 index 000000000..52b5be5b8 --- /dev/null +++ b/vendor/moul.io/http2curl/v2/Makefile @@ -0,0 +1,5 @@ +GOPKG ?= moul.io/http2curl + +all: test + +include rules.mk diff --git a/vendor/moul.io/http2curl/v2/README.md b/vendor/moul.io/http2curl/v2/README.md new file mode 100644 index 000000000..971880826 --- /dev/null +++ b/vendor/moul.io/http2curl/v2/README.md @@ -0,0 +1,59 @@ +# http2curl + +:triangular_ruler: Convert Golang's http.Request to CURL command line + +[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white)](https://pkg.go.dev/moul.io/http2curl) +[![License](https://img.shields.io/badge/license-Apache--2.0%20%2F%20MIT-%2397ca00.svg)](https://github.com/moul/http2curl/blob/master/COPYRIGHT) +[![GitHub release](https://img.shields.io/github/release/moul/http2curl.svg)](https://github.com/moul/http2curl/releases) +[![Docker Metrics](https://images.microbadger.com/badges/image/moul/http2curl.svg)](https://microbadger.com/images/moul/http2curl) +[![Made by Manfred Touron](https://img.shields.io/badge/made%20by-Manfred%20Touron-blue.svg?style=flat)](https://manfred.life/) + +[![Go](https://github.com/moul/http2curl/workflows/Go/badge.svg)](https://github.com/moul/http2curl/actions?query=workflow%3AGo) +[![Release](https://github.com/moul/http2curl/workflows/Release/badge.svg)](https://github.com/moul/http2curl/actions?query=workflow%3ARelease) +[![PR](https://github.com/moul/http2curl/workflows/PR/badge.svg)](https://github.com/moul/http2curl/actions?query=workflow%3APR) +[![GolangCI](https://golangci.com/badges/github.com/moul/http2curl.svg)](https://golangci.com/r/github.com/moul/http2curl) +[![codecov](https://codecov.io/gh/moul/http2curl/branch/master/graph/badge.svg)](https://codecov.io/gh/moul/http2curl) +[![Go Report Card](https://goreportcard.com/badge/moul.io/http2curl)](https://goreportcard.com/report/moul.io/http2curl) +[![CodeFactor](https://www.codefactor.io/repository/github/moul/http2curl/badge)](https://www.codefactor.io/repository/github/moul/http2curl) + +To do the reverse operation, check out [mholt/curl-to-go](https://github.com/mholt/curl-to-go). + +## Example + +```go +import ( + "http" + "moul.io/http2curl" +) + +data := bytes.NewBufferString(`{"hello":"world","answer":42}`) +req, _ := http.NewRequest("PUT", "http://www.example.com/abc/def.ghi?jlk=mno&pqr=stu", data) +req.Header.Set("Content-Type", "application/json") + +command, _ := http2curl.GetCurlCommand(req) +fmt.Println(command) +// Output: curl -X PUT -d "{\"hello\":\"world\",\"answer\":42}" -H "Content-Type: application/json" http://www.example.com/abc/def.ghi?jlk=mno&pqr=stu +``` + +## Install + +```bash +go get moul.io/http2curl +``` + +## Usages + +- https://github.com/parnurzeal/gorequest +- https://github.com/scaleway/scaleway-cli +- https://github.com/nmonterroso/cowsay-slackapp +- https://github.com/moul/as-a-service +- https://github.com/gavv/httpexpect +- https://github.com/smallnest/goreq + +## License + +© 2019-2021 [Manfred Touron](https://manfred.life) + +Licensed under the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) ([`LICENSE-APACHE`](LICENSE-APACHE)) or the [MIT license](https://opensource.org/licenses/MIT) ([`LICENSE-MIT`](LICENSE-MIT)), at your option. See the [`COPYRIGHT`](COPYRIGHT) file for more details. + +`SPDX-License-Identifier: (Apache-2.0 OR MIT)` diff --git a/vendor/moul.io/http2curl/v2/doc.go b/vendor/moul.io/http2curl/v2/doc.go new file mode 100644 index 000000000..6820facab --- /dev/null +++ b/vendor/moul.io/http2curl/v2/doc.go @@ -0,0 +1 @@ +package http2curl diff --git a/vendor/moul.io/http2curl/v2/http2curl.go b/vendor/moul.io/http2curl/v2/http2curl.go new file mode 100644 index 000000000..df21c1936 --- /dev/null +++ b/vendor/moul.io/http2curl/v2/http2curl.go @@ -0,0 +1,85 @@ +package http2curl + +import ( + "bytes" + "fmt" + "io/ioutil" + "net/http" + "sort" + "strings" +) + +// CurlCommand contains exec.Command compatible slice + helpers +type CurlCommand []string + +// append appends a string to the CurlCommand +func (c *CurlCommand) append(newSlice ...string) { + *c = append(*c, newSlice...) +} + +// String returns a ready to copy/paste command +func (c *CurlCommand) String() string { + return strings.Join(*c, " ") +} + +func bashEscape(str string) string { + return `'` + strings.Replace(str, `'`, `'\''`, -1) + `'` +} + +// GetCurlCommand returns a CurlCommand corresponding to an http.Request +func GetCurlCommand(req *http.Request) (*CurlCommand, error) { + if req.URL == nil { + return nil, fmt.Errorf("getCurlCommand: invalid request, req.URL is nil") + } + + command := CurlCommand{} + + command.append("curl") + + schema := req.URL.Scheme + requestURL := req.URL.String() + if schema == "" { + schema = "http" + if req.TLS != nil { + schema = "https" + } + requestURL = schema + "://" + req.Host + req.URL.Path + } + + if schema == "https" { + command.append("-k") + } + + command.append("-X", bashEscape(req.Method)) + + if req.Body != nil { + var buff bytes.Buffer + _, err := buff.ReadFrom(req.Body) + if err != nil { + return nil, fmt.Errorf("getCurlCommand: buffer read from body error: %w", err) + } + // reset body for potential re-reads + req.Body = ioutil.NopCloser(bytes.NewBuffer(buff.Bytes())) + if len(buff.String()) > 0 { + bodyEscaped := bashEscape(buff.String()) + command.append("-d", bodyEscaped) + } + } + + var keys []string + + for k := range req.Header { + keys = append(keys, k) + } + sort.Strings(keys) + + for _, k := range keys { + command.append("-H", bashEscape(fmt.Sprintf("%s: %s", k, strings.Join(req.Header[k], " ")))) + } + + command.append(bashEscape(requestURL)) + + command.append("--compressed") + + return &command, nil +} diff --git a/vendor/moul.io/http2curl/v2/rules.mk b/vendor/moul.io/http2curl/v2/rules.mk new file mode 100644 index 000000000..cc1fe6177 --- /dev/null +++ b/vendor/moul.io/http2curl/v2/rules.mk @@ -0,0 +1,361 @@ +# +--------------------------------------------------------------+ +# | * * * moul.io/rules.mk | +# +--------------------------------------------------------------+ +# | | +# | ++ ______________________________________ | +# | ++++ / \ | +# | ++++ | | | +# | ++++++++++ | https://moul.io/rules.mk is a set | | +# | +++ | | of common Makefile rules that can | | +# | ++ | | be configured from the Makefile | | +# | + -== ==| | or with environment variables. | | +# | ( <*> <*> | | | +# | | | /| Manfred Touron | | +# | | _) / | manfred.life | | +# | | +++ / \______________________________________/ | +# | \ =+ / | +# | \ + | +# | |\++++++ | +# | | ++++ ||// | +# | ___| |___ _||/__ __| +# | / --- \ \| ||| __ _ ___ __ __/ /| +# |/ | | \ \ / / ' \/ _ \/ // / / | +# || | | | | | /_/_/_/\___/\_,_/_/ | +# +--------------------------------------------------------------+ + +.PHONY: _default_entrypoint +_default_entrypoint: help + +## +## Common helpers +## + +rwildcard = $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)) +check-program = $(foreach exec,$(1),$(if $(shell PATH="$(PATH)" which $(exec)),,$(error "No $(exec) in PATH"))) +my-filter-out = $(foreach v,$(2),$(if $(findstring $(1),$(v)),,$(v))) +novendor = $(call my-filter-out,vendor/,$(1)) + +## +## rules.mk +## +ifneq ($(wildcard rules.mk),) +.PHONY: rulesmk.bumpdeps +rulesmk.bumpdeps: + wget -O rules.mk https://raw.githubusercontent.com/moul/rules.mk/master/rules.mk +BUMPDEPS_STEPS += rulesmk.bumpdeps +endif + +## +## Maintainer +## + +ifneq ($(wildcard .git/HEAD),) +.PHONY: generate.authors +generate.authors: AUTHORS +AUTHORS: .git/ + echo "# This file lists all individuals having contributed content to the repository." > AUTHORS + echo "# For how it is generated, see 'https://github.com/moul/rules.mk'" >> AUTHORS + echo >> AUTHORS + git log --format='%aN <%aE>' | LC_ALL=C.UTF-8 sort -uf >> AUTHORS +GENERATE_STEPS += generate.authors +endif + +## +## Golang +## + +ifndef GOPKG +ifneq ($(wildcard go.mod),) +GOPKG = $(shell sed '/module/!d;s/^omdule\ //' go.mod) +endif +endif +ifdef GOPKG +GO ?= go +GOPATH ?= $(HOME)/go +GO_INSTALL_OPTS ?= +GO_TEST_OPTS ?= -test.timeout=30s +GOMOD_DIRS ?= $(sort $(call novendor,$(dir $(call rwildcard,*,*/go.mod go.mod)))) +GOCOVERAGE_FILE ?= ./coverage.txt +GOTESTJSON_FILE ?= ./go-test.json +GOBUILDLOG_FILE ?= ./go-build.log +GOINSTALLLOG_FILE ?= ./go-install.log + +ifdef GOBINS +.PHONY: go.install +go.install: +ifeq ($(CI),true) + @rm -f /tmp/goinstall.log + @set -e; for dir in $(GOBINS); do ( set -xe; \ + cd $$dir; \ + $(GO) install -v $(GO_INSTALL_OPTS) .; \ + ); done 2>&1 | tee $(GOINSTALLLOG_FILE) + +else + @set -e; for dir in $(GOBINS); do ( set -xe; \ + cd $$dir; \ + $(GO) install $(GO_INSTALL_OPTS) .; \ + ); done +endif +INSTALL_STEPS += go.install + +.PHONY: go.release +go.release: + $(call check-program, goreleaser) + goreleaser --snapshot --skip-publish --rm-dist + @echo -n "Do you want to release? [y/N] " && read ans && \ + if [ $${ans:-N} = y ]; then set -xe; goreleaser --rm-dist; fi +RELEASE_STEPS += go.release +endif + +.PHONY: go.unittest +go.unittest: +ifeq ($(CI),true) + @echo "mode: atomic" > /tmp/gocoverage + @rm -f $(GOTESTJSON_FILE) + @set -e; for dir in $(GOMOD_DIRS); do (set -e; (set -euf pipefail; \ + cd $$dir; \ + (($(GO) test ./... $(GO_TEST_OPTS) -cover -coverprofile=/tmp/profile.out -covermode=atomic -race -json && touch $@.ok) | tee -a $(GOTESTJSON_FILE) 3>&1 1>&2 2>&3 | tee -a $(GOBUILDLOG_FILE); \ + ); \ + rm $@.ok 2>/dev/null || exit 1; \ + if [ -f /tmp/profile.out ]; then \ + cat /tmp/profile.out | sed "/mode: atomic/d" >> /tmp/gocoverage; \ + rm -f /tmp/profile.out; \ + fi)); done + @mv /tmp/gocoverage $(GOCOVERAGE_FILE) +else + @echo "mode: atomic" > /tmp/gocoverage + @set -e; for dir in $(GOMOD_DIRS); do (set -e; (set -xe; \ + cd $$dir; \ + $(GO) test ./... $(GO_TEST_OPTS) -cover -coverprofile=/tmp/profile.out -covermode=atomic -race); \ + if [ -f /tmp/profile.out ]; then \ + cat /tmp/profile.out | sed "/mode: atomic/d" >> /tmp/gocoverage; \ + rm -f /tmp/profile.out; \ + fi); done + @mv /tmp/gocoverage $(GOCOVERAGE_FILE) +endif + +.PHONY: go.checkdoc +go.checkdoc: + go doc $(first $(GOMOD_DIRS)) + +.PHONY: go.coverfunc +go.coverfunc: go.unittest + go tool cover -func=$(GOCOVERAGE_FILE) | grep -v .pb.go: | grep -v .pb.gw.go: + +.PHONY: go.lint +go.lint: + @set -e; for dir in $(GOMOD_DIRS); do ( set -xe; \ + cd $$dir; \ + golangci-lint run --verbose ./...; \ + ); done + +.PHONY: go.tidy +go.tidy: + @# tidy dirs with go.mod files + @set -e; for dir in $(GOMOD_DIRS); do ( set -xe; \ + cd $$dir; \ + $(GO) mod tidy; \ + ); done + +.PHONY: go.depaware-update +go.depaware-update: go.tidy + @# gen depaware for bins + @set -e; for dir in $(GOBINS); do ( set -xe; \ + cd $$dir; \ + $(GO) run github.com/tailscale/depaware --update .; \ + ); done + @# tidy unused depaware deps if not in a tools_test.go file + @set -e; for dir in $(GOMOD_DIRS); do ( set -xe; \ + cd $$dir; \ + $(GO) mod tidy; \ + ); done + +.PHONY: go.depaware-check +go.depaware-check: go.tidy + @# gen depaware for bins + @set -e; for dir in $(GOBINS); do ( set -xe; \ + cd $$dir; \ + $(GO) run github.com/tailscale/depaware --check .; \ + ); done + + +.PHONY: go.build +go.build: + @set -e; for dir in $(GOMOD_DIRS); do ( set -xe; \ + cd $$dir; \ + $(GO) build ./...; \ + ); done + +.PHONY: go.bump-deps +go.bumpdeps: + @set -e; for dir in $(GOMOD_DIRS); do ( set -xe; \ + cd $$dir; \ + $(GO) get -u ./...; \ + ); done + +.PHONY: go.bump-deps +go.fmt: + @set -e; for dir in $(GOMOD_DIRS); do ( set -xe; \ + cd $$dir; \ + $(GO) run golang.org/x/tools/cmd/goimports -w `go list -f '{{.Dir}}' ./...` \ + ); done + +VERIFY_STEPS += go.depaware-check +BUILD_STEPS += go.build +BUMPDEPS_STEPS += go.bumpdeps go.depaware-update +TIDY_STEPS += go.tidy +LINT_STEPS += go.lint +UNITTEST_STEPS += go.unittest +FMT_STEPS += go.fmt + +# FIXME: disabled, because currently slow +# new rule that is manually run sometimes, i.e. `make pre-release` or `make maintenance`. +# alternative: run it each time the go.mod is changed +#GENERATE_STEPS += go.depaware-update +endif + +## +## Gitattributes +## + +ifneq ($(wildcard .gitattributes),) +.PHONY: _linguist-ignored +_linguist-kept: + @git check-attr linguist-vendored $(shell git check-attr linguist-generated $(shell find . -type f | grep -v .git/) | grep unspecified | cut -d: -f1) | grep unspecified | cut -d: -f1 | sort + +.PHONY: _linguist-kept +_linguist-ignored: + @git check-attr linguist-vendored linguist-ignored `find . -not -path './.git/*' -type f` | grep '\ set$$' | cut -d: -f1 | sort -u +endif + +## +## Node +## + +ifndef NPM_PACKAGES +ifneq ($(wildcard package.json),) +NPM_PACKAGES = . +endif +endif +ifdef NPM_PACKAGES +.PHONY: npm.publish +npm.publish: + @echo -n "Do you want to npm publish? [y/N] " && read ans && \ + @if [ $${ans:-N} = y ]; then \ + set -e; for dir in $(NPM_PACKAGES); do ( set -xe; \ + cd $$dir; \ + npm publish --access=public; \ + ); done; \ + fi +RELEASE_STEPS += npm.publish +endif + +## +## Docker +## + +docker_build = docker build \ + --build-arg VCS_REF=`git rev-parse --short HEAD` \ + --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \ + --build-arg VERSION=`git describe --tags --always` \ + -t "$2" -f "$1" "$(dir $1)" + +ifndef DOCKERFILE_PATH +DOCKERFILE_PATH = ./Dockerfile +endif +ifndef DOCKER_IMAGE +ifneq ($(wildcard Dockerfile),) +DOCKER_IMAGE = $(notdir $(PWD)) +endif +endif +ifdef DOCKER_IMAGE +ifneq ($(DOCKER_IMAGE),none) +.PHONY: docker.build +docker.build: + $(call check-program, docker) + $(call docker_build,$(DOCKERFILE_PATH),$(DOCKER_IMAGE)) + +BUILD_STEPS += docker.build +endif +endif + +## +## Common +## + +TEST_STEPS += $(UNITTEST_STEPS) +TEST_STEPS += $(LINT_STEPS) +TEST_STEPS += $(TIDY_STEPS) + +ifneq ($(strip $(TEST_STEPS)),) +.PHONY: test +test: $(PRE_TEST_STEPS) $(TEST_STEPS) +endif + +ifdef INSTALL_STEPS +.PHONY: install +install: $(PRE_INSTALL_STEPS) $(INSTALL_STEPS) +endif + +ifdef UNITTEST_STEPS +.PHONY: unittest +unittest: $(PRE_UNITTEST_STEPS) $(UNITTEST_STEPS) +endif + +ifdef LINT_STEPS +.PHONY: lint +lint: $(PRE_LINT_STEPS) $(FMT_STEPS) $(LINT_STEPS) +endif + +ifdef TIDY_STEPS +.PHONY: tidy +tidy: $(PRE_TIDY_STEPS) $(TIDY_STEPS) +endif + +ifdef BUILD_STEPS +.PHONY: build +build: $(PRE_BUILD_STEPS) $(BUILD_STEPS) +endif + +ifdef VERIFY_STEPS +.PHONY: verify +verify: $(PRE_VERIFY_STEPS) $(VERIFY_STEPS) +endif + +ifdef RELEASE_STEPS +.PHONY: release +release: $(PRE_RELEASE_STEPS) $(RELEASE_STEPS) +endif + +ifdef BUMPDEPS_STEPS +.PHONY: bumpdeps +bumpdeps: $(PRE_BUMDEPS_STEPS) $(BUMPDEPS_STEPS) +endif + +ifdef FMT_STEPS +.PHONY: fmt +fmt: $(PRE_FMT_STEPS) $(FMT_STEPS) +endif + +ifdef GENERATE_STEPS +.PHONY: generate +generate: $(PRE_GENERATE_STEPS) $(GENERATE_STEPS) +endif + +.PHONY: help +help:: + @echo "General commands:" + @[ "$(BUILD_STEPS)" != "" ] && echo " build" || true + @[ "$(BUMPDEPS_STEPS)" != "" ] && echo " bumpdeps" || true + @[ "$(FMT_STEPS)" != "" ] && echo " fmt" || true + @[ "$(GENERATE_STEPS)" != "" ] && echo " generate" || true + @[ "$(INSTALL_STEPS)" != "" ] && echo " install" || true + @[ "$(LINT_STEPS)" != "" ] && echo " lint" || true + @[ "$(RELEASE_STEPS)" != "" ] && echo " release" || true + @[ "$(TEST_STEPS)" != "" ] && echo " test" || true + @[ "$(TIDY_STEPS)" != "" ] && echo " tidy" || true + @[ "$(UNITTEST_STEPS)" != "" ] && echo " unittest" || true + @[ "$(VERIFY_STEPS)" != "" ] && echo " verify" || true + @# FIXME: list other commands + +print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true